Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[server] Implement EntitlementServiceUBP.hasPaidSubscription #12305

Merged
merged 2 commits into from
Sep 1, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions components/server/ee/src/billing/entitlement-service-ubp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* See License-AGPL.txt in the project root for license information.
*/

import { UserDB } from "@gitpod/gitpod-db/lib";
import { TeamDB, UserDB } from "@gitpod/gitpod-db/lib";
import {
Team,
User,
WorkspaceInstance,
WorkspaceTimeoutDuration,
Expand All @@ -20,6 +21,7 @@ import {
MayStartWorkspaceResult,
} from "../../../src/billing/entitlement-service";
import { Config } from "../../../src/config";
import { StripeService } from "../user/stripe-service";
import { BillingModes } from "./billing-mode";
import { BillingService } from "./billing-service";

Expand All @@ -35,6 +37,8 @@ export class EntitlementServiceUBP implements EntitlementService {
@inject(UserDB) protected readonly userDb: UserDB;
@inject(BillingModes) protected readonly billingModes: BillingModes;
@inject(BillingService) protected readonly billingService: BillingService;
@inject(StripeService) protected readonly stripeService: StripeService;
@inject(TeamDB) protected readonly teamDB: TeamDB;

async mayStartWorkspace(
user: User,
Expand Down Expand Up @@ -91,8 +95,12 @@ export class EntitlementServiceUBP implements EntitlementService {
}
}

/**
* DEPRECATED: With usage-based billing, users can choose exactly how many resources they want to get.
* Thus, we no longer need to "force" extra resources via the `userGetsMoreResources` mechanism.
*/
async userGetsMoreResources(user: User, date: Date = new Date()): Promise<boolean> {
return this.hasPaidSubscription(user, date);
return false;
}

/**
Expand All @@ -105,7 +113,40 @@ export class EntitlementServiceUBP implements EntitlementService {
}

protected async hasPaidSubscription(user: User, date: Date): Promise<boolean> {
// TODO(gpl) UBP personal: implement!
return true;
// Paid user?
const customer = await this.stripeService.findCustomerByUserId(user.id);
jankeromnes marked this conversation as resolved.
Show resolved Hide resolved
if (customer) {
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customer.id);
if (subscriptionId) {
return true;
}
}
// Member of paid team?
const teams = await this.teamDB.findTeamsByUser(user.id);
const isTeamSubscribedPromises = teams.map(async (team: Team) => {
const customer = await this.stripeService.findCustomerByTeamId(team.id);
if (!customer) {
return false;
}
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customer.id);
return !!subscriptionId;
});
// Return the first truthy promise, or false if all the promises were falsy.
// Source: https://gist.github.com/jbreckmckye/66364021ebaa0785e426deec0410a235
return new Promise((resolve, reject) => {
// If any promise returns true, immediately resolve with true
isTeamSubscribedPromises.forEach(async (isTeamSubscribedPromise: Promise<boolean>) => {
const isTeamSubscribed = await isTeamSubscribedPromise;
if (isTeamSubscribed) resolve(true);
});

// If neither of the above fires, resolve with false
// Check truthiness just in case callbacks fire out-of-band
Promise.all(isTeamSubscribedPromises)
.then((areTeamsSubscribed) => {
resolve(!!areTeamsSubscribed.find((isTeamSubscribed: boolean) => !!isTeamSubscribed));
})
.catch(reject);
});
}
}