From 7d8a32e1b02e69b7a1cd13bc1f26721db794f058 Mon Sep 17 00:00:00 2001 From: Jan Keromnes Date: Tue, 31 May 2022 07:55:48 +0000 Subject: [PATCH] [db][payment][server] Implement TeamSubscription2.excludeFromMoreResources --- .../chargebee/team-subscription-handler.ts | 1 + components/gitpod-db/src/team-db.ts | 1 + .../typeorm/entity/db-team-subscription-2.ts | 5 ++++ .../1653983151212-TS2MoreResources.ts | 23 +++++++++++++++++++ .../gitpod-db/src/typeorm/team-db-impl.ts | 9 ++++++++ .../src/team-subscription-protocol.ts | 1 + .../server/ee/src/user/eligibility-service.ts | 15 +++++++++++- 7 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 components/gitpod-db/src/typeorm/migration/1653983151212-TS2MoreResources.ts diff --git a/components/ee/payment-endpoint/src/chargebee/team-subscription-handler.ts b/components/ee/payment-endpoint/src/chargebee/team-subscription-handler.ts index 7f9ba6a2448035..53032b31dba3ee 100644 --- a/components/ee/payment-endpoint/src/chargebee/team-subscription-handler.ts +++ b/components/ee/payment-endpoint/src/chargebee/team-subscription-handler.ts @@ -128,6 +128,7 @@ export class TeamSubscriptionHandler implements EventHandler; findTeamById(teamId: string): Promise; + findTeamByMembershipId(membershipId: string): Promise; findMembersByTeam(teamId: string): Promise; findTeamMembership(userId: string, teamId: string): Promise; findTeamsByUser(userId: string): Promise; diff --git a/components/gitpod-db/src/typeorm/entity/db-team-subscription-2.ts b/components/gitpod-db/src/typeorm/entity/db-team-subscription-2.ts index 8e08e0cc172ef7..08560b6f56295d 100644 --- a/components/gitpod-db/src/typeorm/entity/db-team-subscription-2.ts +++ b/components/gitpod-db/src/typeorm/entity/db-team-subscription-2.ts @@ -46,6 +46,11 @@ export class DBTeamSubscription2 implements TeamSubscription2 { }) cancellationDate?: string; + @Column({ + default: true, + }) + excludeFromMoreResources: boolean; + // This column triggers the db-sync deletion mechanism. It's not intended for public consumption. @Column() deleted: boolean; diff --git a/components/gitpod-db/src/typeorm/migration/1653983151212-TS2MoreResources.ts b/components/gitpod-db/src/typeorm/migration/1653983151212-TS2MoreResources.ts new file mode 100644 index 00000000000000..9c1186646e9aa5 --- /dev/null +++ b/components/gitpod-db/src/typeorm/migration/1653983151212-TS2MoreResources.ts @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2022 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +import { MigrationInterface, QueryRunner } from "typeorm"; +import { columnExists } from "./helper/helper"; + +const TABLE_NAME = "d_b_team_subscription2"; +const COLUMN_NAME = "excludeFromMoreResources"; + +export class TS2MoreResources1653983151212 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + if (!(await columnExists(queryRunner, TABLE_NAME, COLUMN_NAME))) { + await queryRunner.query( + `ALTER TABLE ${TABLE_NAME} ADD COLUMN ${COLUMN_NAME} tinyint(4) NOT NULL DEFAULT '1', ALGORITHM=INPLACE, LOCK=NONE `, + ); + } + } + + public async down(queryRunner: QueryRunner): Promise {} +} diff --git a/components/gitpod-db/src/typeorm/team-db-impl.ts b/components/gitpod-db/src/typeorm/team-db-impl.ts index 6d480baf681a03..0fd28d9b64946d 100644 --- a/components/gitpod-db/src/typeorm/team-db-impl.ts +++ b/components/gitpod-db/src/typeorm/team-db-impl.ts @@ -64,6 +64,15 @@ export class TeamDBImpl implements TeamDB { return teamRepo.findOne({ id: teamId, deleted: false, markedDeleted: false }); } + public async findTeamByMembershipId(membershipId: string): Promise { + const membershipRepo = await this.getMembershipRepo(); + const membership = await membershipRepo.findOne({ id: membershipId, deleted: false }); + if (!membership) { + return; + } + return this.findTeamById(membership.teamId); + } + public async findMembersByTeam(teamId: string): Promise { const membershipRepo = await this.getMembershipRepo(); const userRepo = await this.getUserRepo(); diff --git a/components/gitpod-protocol/src/team-subscription-protocol.ts b/components/gitpod-protocol/src/team-subscription-protocol.ts index deafdf2b557e28..699bf8d09ad155 100644 --- a/components/gitpod-protocol/src/team-subscription-protocol.ts +++ b/components/gitpod-protocol/src/team-subscription-protocol.ts @@ -43,6 +43,7 @@ export interface TeamSubscription2 { /** The Chargebee subscription id */ paymentReference: string; cancellationDate?: string; + excludeFromMoreResources: boolean; } export namespace TeamSubscription2 { diff --git a/components/server/ee/src/user/eligibility-service.ts b/components/server/ee/src/user/eligibility-service.ts index 2b39f7bcb3b051..144e7fb1c06184 100644 --- a/components/server/ee/src/user/eligibility-service.ts +++ b/components/server/ee/src/user/eligibility-service.ts @@ -5,7 +5,7 @@ */ import { inject, injectable } from "inversify"; -import { TeamSubscriptionDB, UserDB } from "@gitpod/gitpod-db/lib"; +import { TeamDB, TeamSubscription2DB, TeamSubscriptionDB, UserDB } from "@gitpod/gitpod-db/lib"; import { TokenProvider } from "../../../src/user/token-provider"; import { User, @@ -50,11 +50,13 @@ export interface GitHubEducationPack { export class EligibilityService { @inject(Config) protected readonly config: Config; @inject(UserDB) protected readonly userDb: UserDB; + @inject(TeamDB) protected readonly teamDb: TeamDB; @inject(SubscriptionService) protected readonly subscriptionService: SubscriptionService; @inject(EMailDomainService) protected readonly domainService: EMailDomainService; @inject(TokenProvider) protected readonly tokenProvider: TokenProvider; @inject(AccountStatementProvider) protected readonly accountStatementProvider: AccountStatementProvider; @inject(TeamSubscriptionDB) protected readonly teamSubscriptionDb: TeamSubscriptionDB; + @inject(TeamSubscription2DB) protected readonly teamSubscription2Db: TeamSubscription2DB; /** * Whether the given user is recognized as a student within Gitpod @@ -303,6 +305,17 @@ export class EligibilityService { // some TeamSubscriptions are marked with 'excludeFromMoreResources' to convey that those are _not_ receiving more resources const excludeFromMoreResources = await Promise.all( relevantSubscriptions.map(async (s): Promise => { + if (s.teamMembershipId) { + const team = await this.teamDb.findTeamByMembershipId(s.teamMembershipId); + if (!team) { + return true; + } + const ts2 = await this.teamSubscription2Db.findForTeam(team.id, new Date().toISOString()); + if (!ts2) { + return true; + } + return ts2.excludeFromMoreResources; + } if (!s.teamSubscriptionSlotId) { return false; }