From 1683e2f144674f7b6021e61bce093d28dc373e39 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 23 May 2025 11:48:21 -0400 Subject: [PATCH] collab: Prevent canceling the free plan (#31292) This PR makes it so the Zed Free plan cannot be canceled. We were already preventing this on the zed.dev side, but this will make it more airtight. Release Notes: - N/A --- crates/collab/src/api/billing.rs | 42 ++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/crates/collab/src/api/billing.rs b/crates/collab/src/api/billing.rs index a0912b7a4ffa2810c87f55d59a977e069f8015a6..f1eace8a5b2dd3c5d4b57f47fe31bfd3c8b59975 100644 --- a/crates/collab/src/api/billing.rs +++ b/crates/collab/src/api/billing.rs @@ -269,7 +269,8 @@ async fn list_billing_subscriptions( .and_utc() .to_rfc3339_opts(SecondsFormat::Millis, true) }), - is_cancelable: subscription.stripe_subscription_status.is_cancelable() + is_cancelable: subscription.kind != Some(SubscriptionKind::ZedFree) + && subscription.stripe_subscription_status.is_cancelable() && subscription.stripe_cancel_at.is_none(), }) .collect(), @@ -591,23 +592,32 @@ async fn manage_billing_subscription( }), ..Default::default() }), - ManageSubscriptionIntent::Cancel => Some(CreateBillingPortalSessionFlowData { - type_: CreateBillingPortalSessionFlowDataType::SubscriptionCancel, - after_completion: Some(CreateBillingPortalSessionFlowDataAfterCompletion { - type_: stripe::CreateBillingPortalSessionFlowDataAfterCompletionType::Redirect, - redirect: Some(CreateBillingPortalSessionFlowDataAfterCompletionRedirect { - return_url: format!("{}/account", app.config.zed_dot_dev_url()), + ManageSubscriptionIntent::Cancel => { + if subscription.kind == Some(SubscriptionKind::ZedFree) { + return Err(Error::http( + StatusCode::BAD_REQUEST, + "free subscription cannot be canceled".into(), + )); + } + + Some(CreateBillingPortalSessionFlowData { + type_: CreateBillingPortalSessionFlowDataType::SubscriptionCancel, + after_completion: Some(CreateBillingPortalSessionFlowDataAfterCompletion { + type_: stripe::CreateBillingPortalSessionFlowDataAfterCompletionType::Redirect, + redirect: Some(CreateBillingPortalSessionFlowDataAfterCompletionRedirect { + return_url: format!("{}/account", app.config.zed_dot_dev_url()), + }), + ..Default::default() }), + subscription_cancel: Some( + stripe::CreateBillingPortalSessionFlowDataSubscriptionCancel { + subscription: subscription.stripe_subscription_id, + retention: None, + }, + ), ..Default::default() - }), - subscription_cancel: Some( - stripe::CreateBillingPortalSessionFlowDataSubscriptionCancel { - subscription: subscription.stripe_subscription_id, - retention: None, - }, - ), - ..Default::default() - }), + }) + } ManageSubscriptionIntent::StopCancellation => unreachable!(), };