From 61da63a4a0b31e979e631681357933ca2d61d773 Mon Sep 17 00:00:00 2001 From: Yii Date: Tue, 8 Jul 2025 11:02:08 +0800 Subject: [PATCH] fix(server): separate active subscriptions (#13077) ## Summary by CodeRabbit * **Bug Fixes** * Improved accuracy of subscription management by ensuring only active or trialing subscriptions are considered in all relevant user, workspace, and license actions. * Enhanced consistency in subscription retrieval for workspace member updates and subscription-related operations. * **Refactor** * Updated internal subscription retrieval methods to distinguish between general and active subscriptions for more precise handling across the app. --- .../server/src/plugins/payment/license/controller.ts | 4 ++-- .../server/src/plugins/payment/manager/common.ts | 5 +++++ .../server/src/plugins/payment/manager/selfhost.ts | 8 ++++++++ .../server/src/plugins/payment/manager/user.ts | 9 +++++++++ .../server/src/plugins/payment/manager/workspace.ts | 12 +++++++++++- .../backend/server/src/plugins/payment/resolver.ts | 2 +- .../backend/server/src/plugins/payment/service.ts | 8 ++++---- 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/backend/server/src/plugins/payment/license/controller.ts b/packages/backend/server/src/plugins/payment/license/controller.ts index 652f75422e..04507e8afc 100644 --- a/packages/backend/server/src/plugins/payment/license/controller.ts +++ b/packages/backend/server/src/plugins/payment/license/controller.ts @@ -79,7 +79,7 @@ export class LicenseController { }); } - const subscription = await this.manager.getSubscription({ + const subscription = await this.manager.getActiveSubscription({ key: license.key, plan: SubscriptionPlan.SelfHostedTeam, }); @@ -140,7 +140,7 @@ export class LicenseController { }, }); - const subscription = await this.manager.getSubscription({ + const subscription = await this.manager.getActiveSubscription({ key, plan: SubscriptionPlan.SelfHostedTeam, }); diff --git a/packages/backend/server/src/plugins/payment/manager/common.ts b/packages/backend/server/src/plugins/payment/manager/common.ts index 352cb53ee6..a10d963f74 100644 --- a/packages/backend/server/src/plugins/payment/manager/common.ts +++ b/packages/backend/server/src/plugins/payment/manager/common.ts @@ -84,9 +84,14 @@ export abstract class SubscriptionManager { subscription: KnownStripeSubscription ): Promise; + abstract getActiveSubscription( + identity: z.infer + ): Promise; + abstract getSubscription( identity: z.infer ): Promise; + abstract cancelSubscription( subscription: Subscription ): Promise; diff --git a/packages/backend/server/src/plugins/payment/manager/selfhost.ts b/packages/backend/server/src/plugins/payment/manager/selfhost.ts index 08b95cece1..aa14be5994 100644 --- a/packages/backend/server/src/plugins/payment/manager/selfhost.ts +++ b/packages/backend/server/src/plugins/payment/manager/selfhost.ts @@ -186,6 +186,14 @@ export class SelfhostTeamSubscriptionManager extends SubscriptionManager { } getSubscription(identity: z.infer) { + return this.db.subscription.findFirst({ + where: { targetId: identity.key }, + }); + } + + getActiveSubscription( + identity: z.infer + ) { return this.db.subscription.findFirst({ where: { targetId: identity.key, diff --git a/packages/backend/server/src/plugins/payment/manager/user.ts b/packages/backend/server/src/plugins/payment/manager/user.ts index fb3931fd3d..bd59641932 100644 --- a/packages/backend/server/src/plugins/payment/manager/user.ts +++ b/packages/backend/server/src/plugins/payment/manager/user.ts @@ -198,6 +198,15 @@ export class UserSubscriptionManager extends SubscriptionManager { } async getSubscription(args: z.infer) { + return this.db.subscription.findFirst({ + where: { + targetId: args.userId, + plan: args.plan, + }, + }); + } + + async getActiveSubscription(args: z.infer) { return this.db.subscription.findFirst({ where: { targetId: args.userId, diff --git a/packages/backend/server/src/plugins/payment/manager/workspace.ts b/packages/backend/server/src/plugins/payment/manager/workspace.ts index cc131eb8f7..42602112c6 100644 --- a/packages/backend/server/src/plugins/payment/manager/workspace.ts +++ b/packages/backend/server/src/plugins/payment/manager/workspace.ts @@ -202,6 +202,16 @@ export class WorkspaceSubscriptionManager extends SubscriptionManager { } getSubscription(identity: z.infer) { + return this.db.subscription.findFirst({ + where: { + targetId: identity.workspaceId, + }, + }); + } + + getActiveSubscription( + identity: z.infer + ) { return this.db.subscription.findFirst({ where: { targetId: identity.workspaceId, @@ -277,7 +287,7 @@ export class WorkspaceSubscriptionManager extends SubscriptionManager { @OnEvent('workspace.members.updated') async onMembersUpdated({ workspaceId }: Events['workspace.members.updated']) { const count = await this.models.workspaceUser.chargedCount(workspaceId); - const subscription = await this.getSubscription({ + const subscription = await this.getActiveSubscription({ plan: SubscriptionPlan.Team, workspaceId, }); diff --git a/packages/backend/server/src/plugins/payment/resolver.ts b/packages/backend/server/src/plugins/payment/resolver.ts index 7e27afd2d5..54d5e932db 100644 --- a/packages/backend/server/src/plugins/payment/resolver.ts +++ b/packages/backend/server/src/plugins/payment/resolver.ts @@ -528,7 +528,7 @@ export class WorkspaceSubscriptionResolver { description: 'The team subscription of the workspace, if exists.', }) async subscription(@Parent() workspace: WorkspaceType) { - return this.service.getSubscription({ + return this.service.getActiveSubscription({ plan: SubscriptionPlan.Team, workspaceId: workspace.id, }); diff --git a/packages/backend/server/src/plugins/payment/service.ts b/packages/backend/server/src/plugins/payment/service.ts index f72852255d..a4d13d0871 100644 --- a/packages/backend/server/src/plugins/payment/service.ts +++ b/packages/backend/server/src/plugins/payment/service.ts @@ -159,7 +159,7 @@ export class SubscriptionService { this.assertSubscriptionIdentity(identity); const manager = this.select(identity.plan); - const subscription = await manager.getSubscription(identity); + const subscription = await manager.getActiveSubscription(identity); if (!subscription) { throw new SubscriptionNotExists({ plan: identity.plan }); @@ -205,7 +205,7 @@ export class SubscriptionService { const manager = this.select(identity.plan); - const subscription = await manager.getSubscription(identity); + const subscription = await manager.getActiveSubscription(identity); if (!subscription) { throw new SubscriptionNotExists({ plan: identity.plan }); @@ -252,7 +252,7 @@ export class SubscriptionService { this.assertSubscriptionIdentity(identity); const manager = this.select(identity.plan); - const subscription = await manager.getSubscription(identity); + const subscription = await manager.getActiveSubscription(identity); if (!subscription) { throw new SubscriptionNotExists({ plan: identity.plan }); @@ -304,7 +304,7 @@ export class SubscriptionService { ) { this.assertSubscriptionIdentity(identity); - const subscription = await this.select(identity.plan).getSubscription( + const subscription = await this.select(identity.plan).getActiveSubscription( identity );