From 84681cbf75afae9922c501bc6d7fd8f424bd19f0 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 15 Feb 2026 14:47:26 -0800 Subject: [PATCH] feat(platform-service): add user plan update to auth module for Stripe webhooks - Added auth repository updatePlan(userId, productId, plan) helper - Stripe webhook handlers now sync plan changes into auth users container - Handles checkout completion and cancellation downgrade paths - Keeps existing backend sync behavior intact - Verified: tsc --noEmit clean, 19 test files / 178 tests passing --- .../src/modules/auth/repository.ts | 22 +++++++++++++++++++ .../src/modules/stripe/routes.ts | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/services/platform-service/src/modules/auth/repository.ts b/services/platform-service/src/modules/auth/repository.ts index d7e0c420..863ba7a4 100644 --- a/services/platform-service/src/modules/auth/repository.ts +++ b/services/platform-service/src/modules/auth/repository.ts @@ -37,6 +37,28 @@ export async function create(user: UserDoc): Promise { return resource as UserDoc; } +export async function updatePlan( + id: string, + productId: string, + plan: UserDoc['plan'] +): Promise { + try { + const { resource } = await container().item(id, id).read(); + if (!resource || resource.productId !== productId) return null; + const { resource: updated } = await container() + .item(id, id) + .replace({ + ...resource, + plan, + updatedAt: new Date().toISOString(), + }); + if (!updated) return null; + return updated; + } catch { + return null; + } +} + export async function updateLastLogin(id: string): Promise { try { const { resource } = await container().item(id, id).read(); diff --git a/services/platform-service/src/modules/stripe/routes.ts b/services/platform-service/src/modules/stripe/routes.ts index 2bae5675..689273d7 100644 --- a/services/platform-service/src/modules/stripe/routes.ts +++ b/services/platform-service/src/modules/stripe/routes.ts @@ -16,6 +16,7 @@ import { DEFAULT_PRODUCT_ID } from '../../lib/product-config.js'; import { getRequestProductId } from '../../lib/request-context.js'; import { getStripeForProduct, getPriceIds } from '../../lib/stripe.js'; import { BadRequestError } from '../../lib/errors.js'; +import * as authRepo from '../auth/repository.js'; import * as subRepo from '../subscriptions/repository.js'; import type { SubscriptionDoc } from '../subscriptions/types.js'; @@ -134,6 +135,7 @@ export async function stripeRoutes(app: FastifyInstance) { currentPeriodStart: now.toISOString(), currentPeriodEnd: periodEnd.toISOString(), }); + await authRepo.updatePlan(userId, eventProductId, plan as SubscriptionDoc['plan']); } else { await subRepo.createSubscription({ id: `sub_${userId}_${Date.now()}`, @@ -152,6 +154,7 @@ export async function stripeRoutes(app: FastifyInstance) { createdAt: now.toISOString(), updatedAt: now.toISOString(), }); + await authRepo.updatePlan(userId, eventProductId, plan as SubscriptionDoc['plan']); } // Sync plan to backend users container @@ -190,6 +193,7 @@ export async function stripeRoutes(app: FastifyInstance) { cancelAtPeriodEnd: sub.cancel_at_period_end, currentPeriodEnd: new Date(sub.current_period_end * 1000).toISOString(), }); + await authRepo.updatePlan(existing.userId, eventProductId, existing.plan); // Sync plan to backend users container await syncUserPlan(existing.userId, existing.plan, app.log); } @@ -206,6 +210,7 @@ export async function stripeRoutes(app: FastifyInstance) { plan: 'free', cancelAtPeriodEnd: false, }); + await authRepo.updatePlan(existing.userId, eventProductId, 'free'); // Sync plan downgrade to backend users container await syncUserPlan(existing.userId, 'free', app.log); }