Skip to content

Commit

Permalink
[server] don't allow more than three usages
Browse files Browse the repository at this point in the history
  • Loading branch information
svenefftinge committed Sep 21, 2022
1 parent c5c5be9 commit 2430319
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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 D_B_USER = "d_b_user";
const COL_PHONE_NUMBER = "verificationPhoneNumber";

export class IndexPhoneNumber1663784254956 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
if (!(await columnExists(queryRunner, D_B_USER, COL_PHONE_NUMBER))) {
await queryRunner.query(
`ALTER TABLE ${D_B_USER} ADD INDEX (${COL_PHONE_NUMBER}), ALGORITHM=INPLACE, LOCK=NONE `,
);
}
}

public async down(queryRunner: QueryRunner): Promise<void> {}
}
16 changes: 16 additions & 0 deletions components/gitpod-db/src/typeorm/user-db-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,22 @@ export class TypeORMUserDBImpl implements UserDB {
async getByRefreshToken(refreshTokenToken: string): Promise<OAuthToken> {
throw new Error("Not implemented");
}

async countUsagesOfPhoneNumber(phoneNumber: string): Promise<number> {
return (await this.getUserRepo())
.createQueryBuilder()
.where("verificationPhoneNumber = :phoneNumber", { phoneNumber })
.getCount();
}

async isBlockedPhoneNumber(phoneNumber: string): Promise<boolean> {
const blockedUsers = await (await this.getUserRepo())
.createQueryBuilder()
.where("verificationPhoneNumber = :phoneNumber", { phoneNumber })
.andWhere("blocked = true")
.getCount();
return blockedUsers > 0;
}
}

export class TransactionalUserDBImpl extends TypeORMUserDBImpl {
Expand Down
2 changes: 2 additions & 0 deletions components/gitpod-db/src/user-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ export interface UserDB extends OAuthUserRepository, OAuthTokenRepository {
storeGitpodToken(token: GitpodToken & { user: DBUser }): Promise<void>;
deleteGitpodToken(tokenHash: string): Promise<void>;
deleteGitpodTokensNamedLike(userId: string, namePattern: string): Promise<void>;
countUsagesOfPhoneNumber(phoneNumber: string): Promise<number>;
isBlockedPhoneNumber(phoneNumber: string): Promise<boolean>;
}
export type PartialUserUpdate = Partial<Omit<User, "identities">> & Pick<User, "id">;

Expand Down
11 changes: 10 additions & 1 deletion components/server/src/auth/verification-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import { inject, injectable, postConstruct } from "inversify";
import { Config } from "../config";
import { Twilio } from "twilio";
import { ServiceContext } from "twilio/lib/rest/verify/v2/service";
import { WorkspaceDB } from "@gitpod/gitpod-db/lib";
import { UserDB, WorkspaceDB } from "@gitpod/gitpod-db/lib";
import { ConfigCatClientFactory } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server";

@injectable()
export class VerificationService {
@inject(Config) protected config: Config;
@inject(WorkspaceDB) protected workspaceDB: WorkspaceDB;
@inject(UserDB) protected userDB: UserDB;
@inject(ConfigCatClientFactory) protected readonly configCatClientFactory: ConfigCatClientFactory;

protected verifyService: ServiceContext;
Expand Down Expand Up @@ -59,6 +60,14 @@ export class VerificationService {
if (!this.verifyService) {
throw new Error("No verification service configured.");
}
const isBlockedNumber = this.userDB.countUsagesOfPhoneNumber(phoneNumber);
const usages = await this.userDB.countUsagesOfPhoneNumber(phoneNumber);
if (usages > 3) {
throw new Error("The given phone number has been used more than three times.");
}
if (await isBlockedNumber) {
throw new Error("The given phone number is blocked due to abuse.");
}
const verification = await this.verifyService.verifications.create({ to: phoneNumber, channel: "sms" });
log.info("Verification code sent", { phoneNumber, status: verification.status });
}
Expand Down

0 comments on commit 2430319

Please sign in to comment.