undo change

This commit is contained in:
Brandon Thomas committed 2026-01-29 02:39:54 -05:00
1 parent dffc831ce1
commit 6face4ab4f
5 files changed
+142 -45

No files matched your search

@@ -24,6 +24,7 @@ use user_traits_component::traits::internal_session_cache_purge::InternalSession
//use utoipa::ToSchema;
// /// Create a Stripe Checkout session and return the redirect URL in Json.
// #[utoipa::path(
// get,
// tag = "Stripe (Artcraft)",
@@ -35,10 +36,6 @@ use user_traits_component::traits::internal_session_cache_purge::InternalSession
// (status = 200, description = "Success Delete", body = CreateCheckoutSessionSuccessResponse),
// ),
// )]
/// Create a Stripe Checkout session *with* user signup and return the redirect URL in Json.
/// If the user is already logged in, we just attach it to that record instead.
pub async fn stripe_artcraft_create_subscription_session_handler(
http_request: HttpRequest,
request: Json<StripeArtcraftCreateSubscriptionCheckoutRequest>,
@@ -85,10 +82,145 @@ pub async fn stripe_artcraft_create_subscription_session_handler(
// NB: Our integration relies on an internal user token being present.
let user_metadata = match maybe_user_metadata {
None => return Err(CommonWebError::NotAuthorized),
Some(user_metadata) => {
user_exists_case
},
Some(user_metadata) => user_metadata,
};
// NB: Currently the stripe customer id field in the `users` table is only for FakeYou subscriptions,
// so we need to look up any existing Artcraft subscription separately. This is needed to pre-fill
// the Stripe billing form.
let maybe_active_subscription = find_subscription_for_owner_user_using_connection(
&user_metadata.user_token_typed,
PaymentsNamespace::Artcraft,
&mut mysql_connection
).await.map_err(|err| {
error!("Error looking up user's ({}) existing subscription: {:?}", &user_metadata.user_token_typed, err);
CommonWebError::ServerError // NB: This was probably *our* fault.
})?;
if maybe_active_subscription.is_some() {
return Err(CommonWebError::BadInputWithSimpleMessage(
"user already has an active subscription plan; use the portal to update the plan"
.to_string()))
}
// NB: This works, but it feels really weird to have the customer's old email shown in a
// completely immutable state in the stripe checkout form.
//
// let maybe_inactive_subscription = find_possibly_inactive_first_subscription_for_owner_user_using_connection(
// &user_metadata.user_token_typed,
// PaymentsNamespace::Artcraft,
// &mut mysql_connection
// ).await.map_err(|err| {
// error!("Error looking up user's ({}) possibly existing inactive subscription: {:?}",
// &user_metadata.user_token_typed, err);
// CommonWebError::ServerError // NB: This was probably *our* fault.
// })?;
// let maybe_existing_inactive_stripe_customer_id = maybe_inactive_subscription.as_ref()
// .map(|sub| sub.stripe_customer_id.as_str());
let mut maybe_existing_stripe_customer_id = None;
let result = find_user_stripe_customer_link_using_connection(
&user_metadata.user_token_typed,
PaymentsNamespace::Artcraft,
&mut mysql_connection
).await;
// NB: Fail silently.
if let Ok(Some(link)) = result {
maybe_existing_stripe_customer_id = CustomerId::from_str(&link.stripe_customer_id).ok();
} else if let Err(err) = result {
warn!("Error looking up user's ({}) existing stripe customer link: {:?}", &user_metadata.user_token_typed, err);
}
let success_url = stripe_config.checkout_success_url.clone();
let cancel_url = stripe_config.checkout_cancel_url.clone();
let checkout_session = {
// `client_reference_id`
// Stripe Docs:
// A unique string to reference the Checkout Session.
// This can be a customer ID, a cart ID, or similar, and can be used to reconcile the session
// with your internal systems.
//
// Our Notes:
// This gets reported back in the Checkout Session (and related webhooks) as
// `client_reference_id`. Passing the same ID on multiple checkouts does not unify or
// cross-correlate customers and only seems to be metadata for the checkout session itself.
// This is probably only useful for tracking checkout session engagement.
//params.client_reference_id = Some("SOME_INTERNAL_ID");
// `customer_email`
// Stripe Docs:
// If provided, this value will be used when the Customer object is created. If not provided,
// customers will be asked to enter their email address. Use this parameter to prefill
// customer data if you already have an email on file. To access information about the
// customer once a session is complete, use the customer field.
//
// Our Notes:
// This does not look up previous customers with the same email and will not unify or
// cross-correlate customers. By default the field will be un-editable in the checkout flow
// if this is specified.
//params.customer_email = Some("email@example.com");
let mut metadata = HashMap::new();
metadata.insert(STRIPE_ARTCRAFT_METADATA_USER_TOKEN.to_string(), user_metadata.user_token.to_string());
if let Some(username) = user_metadata.username.as_deref() {
metadata.insert(STRIPE_ARTCRAFT_METADATA_USERNAME.to_string(), username.to_string());
}
if let Some(user_email) = user_metadata.user_email.as_deref() {
metadata.insert(STRIPE_ARTCRAFT_METADATA_EMAIL.to_string(), user_email.to_string());
}
let mut checkout_builder = CreateCheckoutSession::new()
.success_url(&success_url)
.cancel_url(&cancel_url)
.mode(CheckoutSessionMode::Subscription)
.line_items(vec![
CreateCheckoutSessionLineItems {
price: Some(price_id.to_string()),
quantity: Some(1),
..Default::default()
}
])
.saved_payment_method_options(CreateCheckoutSessionSavedPaymentMethodOptions {
allow_redisplay_filters: Some(vec![
CreateCheckoutSessionSavedPaymentMethodOptionsAllowRedisplayFilters::Always,
CreateCheckoutSessionSavedPaymentMethodOptionsAllowRedisplayFilters::Limited,
CreateCheckoutSessionSavedPaymentMethodOptionsAllowRedisplayFilters::Unspecified,
]),
// The user can choose to tick a checkbox that saves their card for redisplay later.
payment_method_save: Some(CreateCheckoutSessionSavedPaymentMethodOptionsPaymentMethodSave::Enabled),
})
.allow_promotion_codes(true) // Allow promo codes / coupons
.automatic_tax(CreateCheckoutSessionAutomaticTax {
enabled: true, // This will ask for the customer's location
liability: None,
})
.metadata(metadata.clone())
.subscription_data(CreateCheckoutSessionSubscriptionData {
metadata: Some(metadata),
..Default::default()
})
;
if let Some(customer_id) = maybe_existing_stripe_customer_id {
info!("Adding existing stripe customer id to checkout session: {}", customer_id.as_str());
checkout_builder = checkout_builder.customer(customer_id);
}
let checkout_session = checkout_builder
.send(&stripe_config.client)
.await
.map_err(|err| {
error!("Stripe Error: {:?}", err);
CommonWebError::ServerError
})?;
checkout_session
};
let url = checkout_session.url.ok_or(CommonWebError::ServerError)?;
@@ -12,7 +12,6 @@ use crate::http_server::session::http::http_user_session_manager::HttpUserSessio
use crate::http_server::validations::is_reserved_username::is_reserved_username;
use crate::http_server::validations::validate_passwords::validate_passwords;
use crate::http_server::validations::validate_username::validate_username;
use crate::util::email_to_gravatar::email_to_gravatar;
use crate::util::enroll_in_studio::enroll_in_studio;
use actix_web::error::ResponseError;
use actix_web::http::StatusCode;
@@ -29,6 +28,7 @@ use password::bcrypt_hash_password::bcrypt_hash_password;
use sqlx::MySqlPool;
use tokens::tokens::user_sessions::UserSessionToken;
use user_input_common::check_for_slurs::contains_slurs;
use users::email::email_to_gravatar::email_to_gravatar;
use utoipa::ToSchema;
#[derive(ToSchema, Deserialize)]
@@ -2,7 +2,6 @@ use crate::http_server::endpoints::users::google_sso::google_sso_handler::Google
use crate::http_server::endpoints::users::google_sso::handle_new_sso_account::NewSsoAccountInfo;
use crate::http_server::requests::get_request_signup_source::{get_request_signup_source, get_request_signup_source_enum};
use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
use crate::util::email_to_gravatar::email_to_gravatar;
use actix_web::HttpRequest;
use enums::by_table::users::user_feature_flag::UserFeatureFlag;
use google_sign_in::claims::claims::Claims;
@@ -14,6 +13,7 @@ use mysql_queries::queries::users::user::create::create_account_from_google_sso:
use mysql_queries::utils::transactor::Transactor;
use sqlx::pool::PoolConnection;
use sqlx::{Acquire, MySql};
use users::email::email_to_gravatar::email_to_gravatar;
use users::username::generate_random_username::generate_random_username;
pub struct CreateArgs<'a> {
@@ -1,34 +0,0 @@
use md5::{Digest, Md5};
pub fn email_to_gravatar(email_address: &str) -> String {
let email = email_address.trim().to_lowercase();
let mut hasher = Md5::new();
hasher.update(email);
let hash = hasher.finalize();
let gravatar_hash = format!("{:x}", hash);
gravatar_hash
}
#[cfg(test)]
pub mod tests {
use crate::util::email_to_gravatar::email_to_gravatar;
#[test]
fn test_gravatar() {
// Email 1
assert_eq!(email_to_gravatar("example@example.com"), "23463b99b62a72f26ed677cc556c44e8".to_string());
assert_eq!(email_to_gravatar("EXAMPLE@EXAMPLE.COM"), "23463b99b62a72f26ed677cc556c44e8".to_string());
assert_eq!(email_to_gravatar(" example@example.com \n "), "23463b99b62a72f26ed677cc556c44e8".to_string());
// Email 2
assert_eq!(email_to_gravatar("echelon@gmail.com"), "37e7e18f19d8f654a1ace405c846a9de".to_string());
assert_eq!(email_to_gravatar("ECHELON@GMAIL.COM"), "37e7e18f19d8f654a1ace405c846a9de".to_string());
assert_eq!(email_to_gravatar(" ECHELON@GMAIL.COM "), "37e7e18f19d8f654a1ace405c846a9de".to_string());
// Misc
assert_eq!(email_to_gravatar(""), "d41d8cd98f00b204e9800998ecf8427e".to_string());
assert_eq!(email_to_gravatar(" "), "d41d8cd98f00b204e9800998ecf8427e".to_string());
}
}
@@ -5,7 +5,6 @@ pub mod canonicalize_email_for_users_table;
pub mod check_creator_tokens;
pub mod cleaners;
pub mod delete_role_disambiguation;
pub mod email_to_gravatar;
pub mod encrypted_sort_id;
pub mod enroll_in_studio;
pub mod http_download_url_to_bytes;