Skip to content

Commit b634fb3

Browse files
Andrew Farriesroboquat
Andrew Farries
authored andcommitted
Add subscribeToStripe server method
Generalize the `subscribeTeamToStripe` method so that it works for user attribution ids too. Implement the `subscribeTeamToStripe` method in terms of the new general method.
1 parent 5f24cb2 commit b634fb3

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

components/gitpod-protocol/src/gitpod-service.ts

+1
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
289289
findStripeSubscriptionIdForTeam(teamId: string): Promise<string | undefined>;
290290
createOrUpdateStripeCustomerForTeam(teamId: string, currency: string): Promise<void>;
291291
createOrUpdateStripeCustomerForUser(currency: string): Promise<void>;
292+
subscribeToStripe(attributionId: string, setupIntentId: string): Promise<void>;
292293
subscribeTeamToStripe(teamId: string, setupIntentId: string): Promise<void>;
293294
getStripePortalUrl(attributionId: string): Promise<string>;
294295
getStripePortalUrlForTeam(teamId: string): Promise<string>;

components/server/ee/src/workspace/gitpod-server-impl.ts

+31-13
Original file line numberDiff line numberDiff line change
@@ -2124,32 +2124,50 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
21242124
}
21252125

21262126
protected defaultSpendingLimit = 100;
2127-
async subscribeTeamToStripe(ctx: TraceContext, teamId: string, setupIntentId: string): Promise<void> {
2128-
this.checkAndBlockUser("subscribeTeamToStripe");
2129-
const team = await this.guardTeamOperation(teamId, "update");
2130-
await this.ensureStripeApiIsAllowed({ team });
2127+
async subscribeToStripe(ctx: TraceContext, attributionId: string, setupIntentId: string): Promise<void> {
2128+
const attrId = AttributionId.parse(attributionId);
2129+
if (attrId === undefined) {
2130+
log.error(`Invalid attribution id: ${attributionId}`);
2131+
throw new ResponseError(ErrorCodes.BAD_REQUEST, `Invalid attibution id: ${attributionId}`);
2132+
}
2133+
2134+
const user = this.checkAndBlockUser("subscribeToStripe");
2135+
2136+
let customer: Stripe.Customer | undefined;
21312137
try {
2132-
let customer = await this.stripeService.findCustomerByTeamId(team!.id);
2138+
if (attrId.kind === "team") {
2139+
const team = await this.guardTeamOperation(attrId.teamId, "update");
2140+
await this.ensureStripeApiIsAllowed({ team });
2141+
customer = await this.stripeService.findCustomerByTeamId(team!.id);
2142+
} else {
2143+
await this.ensureStripeApiIsAllowed({ user });
2144+
customer = await this.stripeService.findCustomerByUserId(user.id);
2145+
}
21332146
if (!customer) {
2134-
throw new Error(`No Stripe customer profile for team '${team.id}'`);
2147+
throw new Error(`No Stripe customer profile for '${attributionId}'`);
21352148
}
2149+
21362150
await this.stripeService.setDefaultPaymentMethodForCustomer(customer, setupIntentId);
21372151
await this.stripeService.createSubscriptionForCustomer(customer);
2138-
2139-
const attributionId: AttributionId = { kind: "team", teamId };
2140-
2141-
// Creating a cost center for this team
21422152
await this.usageServiceClientProvider.getDefault().setCostCenter({
2143-
id: attributionId,
2153+
id: attrId,
21442154
spendingLimit: this.defaultSpendingLimit,
21452155
billingStrategy: "stripe",
21462156
});
21472157
} catch (error) {
2148-
log.error(`Failed to subscribe team '${teamId}' to Stripe`, error);
2149-
throw new ResponseError(ErrorCodes.INTERNAL_SERVER_ERROR, `Failed to subscribe team '${teamId}' to Stripe`);
2158+
log.error(`Failed to subscribe '${attributionId}' to Stripe`, error);
2159+
throw new ResponseError(
2160+
ErrorCodes.INTERNAL_SERVER_ERROR,
2161+
`Failed to subscribe '${attributionId}' to Stripe`,
2162+
);
21502163
}
21512164
}
21522165

2166+
async subscribeTeamToStripe(ctx: TraceContext, teamId: string, setupIntentId: string): Promise<void> {
2167+
const attributionId: AttributionId = { kind: "team", teamId: teamId };
2168+
return this.subscribeToStripe(ctx, AttributionId.render(attributionId), setupIntentId);
2169+
}
2170+
21532171
async getStripePortalUrl(ctx: TraceContext, attributionId: string): Promise<string> {
21542172
const attrId = AttributionId.parse(attributionId);
21552173
if (attrId === undefined) {

components/server/src/auth/rate-limiter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ const defaultFunctions: FunctionsConfig = {
205205
findStripeSubscriptionIdForTeam: { group: "default", points: 1 },
206206
createOrUpdateStripeCustomerForTeam: { group: "default", points: 1 },
207207
createOrUpdateStripeCustomerForUser: { group: "default", points: 1 },
208+
subscribeToStripe: { group: "default", points: 1 },
208209
subscribeTeamToStripe: { group: "default", points: 1 },
209210
getStripePortalUrl: { group: "default", points: 1 },
210211
getStripePortalUrlForTeam: { group: "default", points: 1 },

components/server/src/workspace/gitpod-server-impl.ts

+3
Original file line numberDiff line numberDiff line change
@@ -3144,6 +3144,9 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
31443144
async subscribeTeamToStripe(ctx: TraceContext, teamId: string, setupIntentId: string): Promise<void> {
31453145
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
31463146
}
3147+
async subscribeToStripe(ctx: TraceContext, attributionId: string, setupIntentId: string): Promise<void> {
3148+
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
3149+
}
31473150
async getStripePortalUrlForTeam(ctx: TraceContext, teamId: string): Promise<string> {
31483151
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
31493152
}

0 commit comments

Comments
 (0)