diff --git a/components/dashboard/src/teams/TeamUsageBasedBilling.tsx b/components/dashboard/src/teams/TeamUsageBasedBilling.tsx index 5703066fde374e..36e937ea382e11 100644 --- a/components/dashboard/src/teams/TeamUsageBasedBilling.tsx +++ b/components/dashboard/src/teams/TeamUsageBasedBilling.tsx @@ -36,7 +36,7 @@ export default function TeamUsageBasedBilling() { setStripeCustomerId(undefined); setIsLoading(true); try { - const customerId = await getGitpodService().server.getTeamStripeCustomerId(team.id); + const customerId = await getGitpodService().server.findStripeCustomerIdForTeam(team.id); setStripeCustomerId(customerId); } catch (error) { console.error(error); @@ -102,7 +102,7 @@ export default function TeamUsageBasedBilling() { if (!pollStripeCustomerTimeout) { // Refresh Stripe customer in 5 seconds in order to poll for upgrade confirmation const timeout = setTimeout(async () => { - const customerId = await getGitpodService().server.getTeamStripeCustomerId(team.id); + const customerId = await getGitpodService().server.findStripeCustomerIdForTeam(team.id); setStripeCustomerId(customerId); setPollStripeCustomerTimeout(undefined); }, 5000); @@ -164,7 +164,7 @@ function BillingSetupModal(props: { onClose: () => void }) { useEffect(() => { const { server } = getGitpodService(); Promise.all([ - server.getStripePublishableKey().then((v) => () => setStripePromise(loadStripe(v || ""))), + server.getStripePublishableKey().then((v) => () => setStripePromise(loadStripe(v))), server.getStripeSetupIntentClientSecret().then((v) => () => setStripeSetupIntentClientSecret(v)), ]).then((setters) => setters.forEach((s) => s())); }, []); diff --git a/components/gitpod-protocol/src/gitpod-service.ts b/components/gitpod-protocol/src/gitpod-service.ts index 04a6c5319c6d5a..63e474dd24d7a7 100644 --- a/components/gitpod-protocol/src/gitpod-service.ts +++ b/components/gitpod-protocol/src/gitpod-service.ts @@ -270,9 +270,9 @@ export interface GitpodServer extends JsonRpcServer, AdminServer, getGithubUpgradeUrls(): Promise; - getStripePublishableKey(): Promise; - getStripeSetupIntentClientSecret(): Promise; - getTeamStripeCustomerId(teamId: string): Promise; + getStripePublishableKey(): Promise; + getStripeSetupIntentClientSecret(): Promise; + findStripeCustomerIdForTeam(teamId: string): Promise; subscribeTeamToStripe(teamId: string, setupIntentId: string): Promise; /** diff --git a/components/server/ee/src/workspace/gitpod-server-impl.ts b/components/server/ee/src/workspace/gitpod-server-impl.ts index 4263afa0025433..4704709d9f6938 100644 --- a/components/server/ee/src/workspace/gitpod-server-impl.ts +++ b/components/server/ee/src/workspace/gitpod-server-impl.ts @@ -1848,26 +1848,36 @@ export class GitpodServerEEImpl extends GitpodServerImpl { } } - async getStripePublishableKey(ctx: TraceContext): Promise { + async getStripePublishableKey(ctx: TraceContext): Promise { const user = this.checkAndBlockUser("getStripePublishableKey"); await this.ensureIsUsageBasedFeatureFlagEnabled(user); - return this.config.stripeSettings?.publishableKey; + const publishableKey = this.config.stripeSettings?.publishableKey; + if (!publishableKey) { + throw new ResponseError( + ErrorCodes.INTERNAL_SERVER_ERROR, + "Stripe is not properly configured (no publishable key)", + ); + } + return publishableKey; } - async getStripeSetupIntentClientSecret(ctx: TraceContext): Promise { + async getStripeSetupIntentClientSecret(ctx: TraceContext): Promise { const user = this.checkAndBlockUser("getStripeSetupIntentClientSecret"); await this.ensureIsUsageBasedFeatureFlagEnabled(user); try { const setupIntent = await this.stripeService.createSetupIntent(); - return setupIntent.client_secret || undefined; + if (!setupIntent.client_secret) { + throw new Error("No client secret in the SetupIntent"); + } + return setupIntent.client_secret; } catch (error) { log.error("Failed to create Stripe SetupIntent", error); throw new ResponseError(ErrorCodes.INTERNAL_SERVER_ERROR, "Failed to create Stripe SetupIntent"); } } - async getTeamStripeCustomerId(ctx: TraceContext, teamId: string): Promise { - const user = this.checkAndBlockUser("getTeamStripeCustomerId"); + async findStripeCustomerIdForTeam(ctx: TraceContext, teamId: string): Promise { + const user = this.checkAndBlockUser("findStripeCustomerIdForTeam"); await this.ensureIsUsageBasedFeatureFlagEnabled(user); await this.guardTeamOperation(teamId, "update"); try { diff --git a/components/server/src/auth/rate-limiter.ts b/components/server/src/auth/rate-limiter.ts index 03c5ec8cc70aa0..8c53ba61763647 100644 --- a/components/server/src/auth/rate-limiter.ts +++ b/components/server/src/auth/rate-limiter.ts @@ -198,7 +198,7 @@ function getConfig(config: RateLimiterConfig): RateLimiterConfig { tsReassignSlot: { group: "default", points: 1 }, getStripePublishableKey: { group: "default", points: 1 }, getStripeSetupIntentClientSecret: { group: "default", points: 1 }, - getTeamStripeCustomerId: { group: "default", points: 1 }, + findStripeCustomerIdForTeam: { group: "default", points: 1 }, subscribeTeamToStripe: { group: "default", points: 1 }, trackEvent: { group: "default", points: 1 }, trackLocation: { group: "default", points: 1 }, diff --git a/components/server/src/workspace/gitpod-server-impl.ts b/components/server/src/workspace/gitpod-server-impl.ts index 557d58cfbf6c7d..09cfddef3fa258 100644 --- a/components/server/src/workspace/gitpod-server-impl.ts +++ b/components/server/src/workspace/gitpod-server-impl.ts @@ -3033,13 +3033,13 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable { async getGithubUpgradeUrls(ctx: TraceContext): Promise { throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`); } - async getStripePublishableKey(ctx: TraceContext): Promise { + async getStripePublishableKey(ctx: TraceContext): Promise { throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`); } - async getStripeSetupIntentClientSecret(ctx: TraceContext): Promise { + async getStripeSetupIntentClientSecret(ctx: TraceContext): Promise { throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`); } - async getTeamStripeCustomerId(ctx: TraceContext, teamId: string): Promise { + async findStripeCustomerIdForTeam(ctx: TraceContext, teamId: string): Promise { throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`); } async subscribeTeamToStripe(ctx: TraceContext, teamId: string, setupIntentId: string): Promise {