add: developer pass
This commit is contained in:
parent
636ecce9f4
commit
02f3d08926
14 changed files with 355 additions and 101 deletions
|
@ -3,9 +3,9 @@ use std::{str::FromStr, time::Duration};
|
|||
use axum::{http::HeaderMap, response::IntoResponse, Extension, Json};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::{
|
||||
auth::{User, Notification},
|
||||
auth::{Notification, User},
|
||||
moderation::AuditLogEntry,
|
||||
permissions::FinePermission,
|
||||
permissions::{FinePermission, SecondaryPermission},
|
||||
ApiReturn, Error,
|
||||
};
|
||||
use stripe::{EventObject, EventType};
|
||||
|
@ -205,6 +205,43 @@ pub async fn stripe_webhook(
|
|||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
} else if product_id == stripe_cnf.product_ids.dev_pass {
|
||||
// dev pass
|
||||
tracing::info!("found subscription user in {retries} tries");
|
||||
|
||||
if user
|
||||
.secondary_permissions
|
||||
.check(SecondaryPermission::DEVELOPER_PASS)
|
||||
{
|
||||
return Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Already applied".to_string(),
|
||||
payload: (),
|
||||
});
|
||||
}
|
||||
|
||||
tracing::info!("invoice {} (stripe: {})", user.id, customer_id);
|
||||
let new_user_permissions =
|
||||
user.secondary_permissions | SecondaryPermission::DEVELOPER_PASS;
|
||||
|
||||
if let Err(e) = data
|
||||
.update_user_secondary_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
if let Err(e) = data
|
||||
.create_notification(Notification::new(
|
||||
"Welcome new developer!".to_string(),
|
||||
"Thank you for your support! Your account has been updated with your new role."
|
||||
.to_string(),
|
||||
user.id,
|
||||
))
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
} else {
|
||||
tracing::error!(
|
||||
"received an invalid stripe product id, please check config.stripe.product_ids"
|
||||
|
@ -220,34 +257,72 @@ pub async fn stripe_webhook(
|
|||
};
|
||||
|
||||
let customer_id = subscription.customer.id();
|
||||
let product_id = subscription
|
||||
.items
|
||||
.data
|
||||
.get(0)
|
||||
.as_ref()
|
||||
.expect("cancelled nothing?")
|
||||
.plan
|
||||
.as_ref()
|
||||
.expect("no subscription plan?")
|
||||
.product
|
||||
.as_ref()
|
||||
.expect("plan with no product?")
|
||||
.id()
|
||||
.to_string();
|
||||
|
||||
let user = match data.get_user_by_stripe_id(customer_id.as_str()).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
tracing::info!("unsubscribe {} (stripe: {})", user.id, customer_id);
|
||||
let new_user_permissions = user.permissions - FinePermission::SUPPORTER;
|
||||
// handle each subscription item
|
||||
if product_id == stripe_cnf.product_ids.supporter {
|
||||
// supporter
|
||||
tracing::info!("unsubscribe {} (stripe: {})", user.id, customer_id);
|
||||
let new_user_permissions = user.permissions - FinePermission::SUPPORTER;
|
||||
|
||||
if let Err(e) = data
|
||||
.update_user_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
if data.0.0.security.enable_invite_codes && user.was_purchased && user.invite_code == 0
|
||||
{
|
||||
// user doesn't come from an invite code, and is a purchased account
|
||||
// this means their account must be locked if they stop paying
|
||||
if let Err(e) = data
|
||||
.update_user_awaiting_purchased_status(user.id, true, user.clone(), false)
|
||||
.update_user_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
if data.0.0.security.enable_invite_codes
|
||||
&& user.was_purchased
|
||||
&& user.invite_code == 0
|
||||
{
|
||||
// user doesn't come from an invite code, and is a purchased account
|
||||
// this means their account must be locked if they stop paying
|
||||
if let Err(e) = data
|
||||
.update_user_awaiting_purchased_status(user.id, true, user.clone(), false)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
}
|
||||
} else if product_id == stripe_cnf.product_ids.dev_pass {
|
||||
// dev pass
|
||||
tracing::info!("unsubscribe {} (stripe: {})", user.id, customer_id);
|
||||
let new_user_permissions =
|
||||
user.secondary_permissions - SecondaryPermission::DEVELOPER_PASS;
|
||||
|
||||
if let Err(e) = data
|
||||
.update_user_secondary_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
} else {
|
||||
tracing::error!(
|
||||
"received an invalid stripe product id, please check config.stripe.product_ids"
|
||||
);
|
||||
return Json(Error::MiscError("Unknown product ID".to_string()).into());
|
||||
}
|
||||
|
||||
// send notification
|
||||
if let Err(e) = data
|
||||
.create_notification(Notification::new(
|
||||
"Sorry to see you go... :(".to_string(),
|
||||
|
@ -269,46 +344,112 @@ pub async fn stripe_webhook(
|
|||
|
||||
let customer_id = invoice.customer.expect("TETRATTO_STRIPE_NO_CUSTOMER").id();
|
||||
|
||||
let item = match invoice.lines.as_ref().expect("no line items?").data.get(0) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
if let Err(e) = data
|
||||
.create_audit_log_entry(AuditLogEntry::new(
|
||||
0,
|
||||
format!("too few invoice line items: stripe {customer_id}"),
|
||||
))
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
return Json(Error::MiscError("Too few line items".to_string()).into());
|
||||
}
|
||||
};
|
||||
|
||||
let product_id = item
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.product
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.id()
|
||||
.to_string();
|
||||
|
||||
let user = match data.get_user_by_stripe_id(customer_id.as_str()).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
if !user.permissions.check(FinePermission::SUPPORTER) {
|
||||
// the user isn't currently a supporter, there's no reason to send this notification
|
||||
return Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Acceptable".to_string(),
|
||||
payload: (),
|
||||
});
|
||||
}
|
||||
// handle each subscription item
|
||||
if product_id == stripe_cnf.product_ids.supporter {
|
||||
// supporter
|
||||
if !user.permissions.check(FinePermission::SUPPORTER) {
|
||||
// the user isn't currently a supporter, there's no reason to send this notification
|
||||
return Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Acceptable".to_string(),
|
||||
payload: (),
|
||||
});
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"unsubscribe (pay fail) {} (stripe: {})",
|
||||
user.id,
|
||||
customer_id
|
||||
);
|
||||
let new_user_permissions = user.permissions - FinePermission::SUPPORTER;
|
||||
tracing::info!(
|
||||
"unsubscribe (pay fail) {} (stripe: {})",
|
||||
user.id,
|
||||
customer_id
|
||||
);
|
||||
let new_user_permissions = user.permissions - FinePermission::SUPPORTER;
|
||||
|
||||
if let Err(e) = data
|
||||
.update_user_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
if data.0.0.security.enable_invite_codes && user.was_purchased && user.invite_code == 0
|
||||
{
|
||||
// user doesn't come from an invite code, and is a purchased account
|
||||
// this means their account must be locked if they stop paying
|
||||
if let Err(e) = data
|
||||
.update_user_awaiting_purchased_status(user.id, true, user.clone(), false)
|
||||
.update_user_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
|
||||
if data.0.0.security.enable_invite_codes
|
||||
&& user.was_purchased
|
||||
&& user.invite_code == 0
|
||||
{
|
||||
// user doesn't come from an invite code, and is a purchased account
|
||||
// this means their account must be locked if they stop paying
|
||||
if let Err(e) = data
|
||||
.update_user_awaiting_purchased_status(user.id, true, user.clone(), false)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
}
|
||||
} else if product_id == stripe_cnf.product_ids.dev_pass {
|
||||
// dev pass
|
||||
if !user
|
||||
.secondary_permissions
|
||||
.check(SecondaryPermission::DEVELOPER_PASS)
|
||||
{
|
||||
return Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Acceptable".to_string(),
|
||||
payload: (),
|
||||
});
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"unsubscribe (pay fail) {} (stripe: {})",
|
||||
user.id,
|
||||
customer_id
|
||||
);
|
||||
let new_user_permissions =
|
||||
user.secondary_permissions - SecondaryPermission::DEVELOPER_PASS;
|
||||
|
||||
if let Err(e) = data
|
||||
.update_user_secondary_role(user.id, new_user_permissions, user.clone(), true)
|
||||
.await
|
||||
{
|
||||
return Json(e.into());
|
||||
}
|
||||
} else {
|
||||
tracing::error!(
|
||||
"received an invalid stripe product id, please check config.stripe.product_ids"
|
||||
);
|
||||
return Json(Error::MiscError("Unknown product ID".to_string()).into());
|
||||
}
|
||||
|
||||
// send notification
|
||||
if let Err(e) = data
|
||||
.create_notification(Notification::new(
|
||||
"It seems your recent payment has failed :(".to_string(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue