From f60dbe656d7e9334cd42295334ad39d68cb8ecc1 Mon Sep 17 00:00:00 2001 From: Rick Klomp Date: Tue, 20 Dec 2022 18:38:21 +0100 Subject: [PATCH 1/5] add optionally applied address whitelist --- src/index.ts | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/index.ts b/src/index.ts index 7c8ab44..6a00f31 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,6 +42,8 @@ export class TokenGate { urlFromReq: (req: Request) => string; tzAddrFromReq: (req: Request) => string | undefined; + applyAddressWhitelist: boolean; + constructor({ dbPool }: { dbPool: DbPool }) { this.db = dbPool; @@ -59,6 +61,8 @@ export class TokenGate { this.urlFromReq = (req) => req.baseUrl; this.tzAddrFromReq = (req: any) => req.auth?.userAddress; + + this.applyAddressWhitelist = false; } loadSpecFromFile(filepath: string, overwrite: boolean = true): this { @@ -172,6 +176,11 @@ export class TokenGate { return this; } + enableAddressWhitelist(): this { + this.applyAddressWhitelist = true; + return this; + } + getSpec(): TokenGateSpec { return Object.keys(this.rules).reduce((res, endpoint) => { res[endpoint] = { @@ -194,12 +203,23 @@ export class TokenGate { use(req: Request, resp: Response, next: NextFunction): void { const url = this.urlFromReq(req); const tzAddr = this.tzAddrFromReq(req); + this.hasAccess(url, tzAddr) .then((access) => { if (!access) { resp.sendStatus(403); return; } + if (this.applyAddressWhitelist) { + this.isAddressInWhitelist(tzAddr).then((isAllowed) => { + if (!isAllowed) { + resp.status(403).send('{"error": "not in address enable list"}'); + return; + } + next(); + }); + return; + } next(); }) .catch((err) => { @@ -208,6 +228,25 @@ export class TokenGate { }); } + async isAddressInWhitelist(userAddress?: string): Promise { + if (typeof userAddress === "undefined") { + return false; + } + const qryResp = await this.db.query( + ` +SELECT 1 +FROM addresses_enabled +WHERE address = $1 + AND NOT claimed + `, + [userAddress] + ); + if (qryResp.rowCount === 0) { + return false; + } + return true; + } + async hasAccess( endpoint: Endpoint, tzAddr: string | undefined From 270bc99e73cda8b561db66f1d1c0d22168a60ffa Mon Sep 17 00:00:00 2001 From: Rick Klomp Date: Tue, 20 Dec 2022 19:01:39 +0100 Subject: [PATCH 2/5] bugfix --- src/index.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6a00f31..27426ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -210,16 +210,6 @@ export class TokenGate { resp.sendStatus(403); return; } - if (this.applyAddressWhitelist) { - this.isAddressInWhitelist(tzAddr).then((isAllowed) => { - if (!isAllowed) { - resp.status(403).send('{"error": "not in address enable list"}'); - return; - } - next(); - }); - return; - } next(); }) .catch((err) => { @@ -260,6 +250,12 @@ WHERE address = $1 if (typeof tzAddr === "undefined") { return false; } + if ( + this.applyAddressWhitelist && + !(await this.isAddressInWhitelist(tzAddr)) + ) { + return false; + } return await this.#ownsOneOf(tzAddr, rule.allowedTokens); } From fac231de1efef0994606f308ad5db4c1a0d17873 Mon Sep 17 00:00:00 2001 From: Rick Klomp Date: Tue, 20 Dec 2022 19:24:58 +0100 Subject: [PATCH 3/5] update address whitelist table name --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 27426ce..af1aa4b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -225,7 +225,7 @@ export class TokenGate { const qryResp = await this.db.query( ` SELECT 1 -FROM addresses_enabled +FROM whitelisted_wallet_addresses WHERE address = $1 AND NOT claimed `, From 40972a4ff83d0ffc166d20c3f24b87841ea57d06 Mon Sep 17 00:00:00 2001 From: Rick Klomp Date: Tue, 20 Dec 2022 23:27:47 +0100 Subject: [PATCH 4/5] expose whether whitelisted address has already claimed or not --- src/index.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index af1aa4b..ce69fba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -218,23 +218,24 @@ export class TokenGate { }); } - async isAddressInWhitelist(userAddress?: string): Promise { + async isAddressInWhitelist( + userAddress?: string + ): Promise<"allowed" | "claimed" | "forbidden"> { if (typeof userAddress === "undefined") { - return false; + return "forbidden"; } const qryResp = await this.db.query( ` -SELECT 1 +SELECT claimed FROM whitelisted_wallet_addresses WHERE address = $1 - AND NOT claimed `, [userAddress] ); if (qryResp.rowCount === 0) { - return false; + return "forbidden"; } - return true; + return qryResp.rows[0].claimed ? "claimed" : "allowed"; } async hasAccess( @@ -252,7 +253,7 @@ WHERE address = $1 } if ( this.applyAddressWhitelist && - !(await this.isAddressInWhitelist(tzAddr)) + (await this.isAddressInWhitelist(tzAddr)) !== "allowed" ) { return false; } From 82ddefdb26650f9f343d76a4b447a21564e7559b Mon Sep 17 00:00:00 2001 From: Rick Klomp Date: Wed, 21 Dec 2022 12:09:22 +0100 Subject: [PATCH 5/5] add max claims number to whitelist --- src/index.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index ce69fba..afddd92 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ export class TokenGate { tzAddrFromReq: (req: Request) => string | undefined; applyAddressWhitelist: boolean; + maxWhitelistedClaims: number; constructor({ dbPool }: { dbPool: DbPool }) { this.db = dbPool; @@ -63,6 +64,7 @@ export class TokenGate { this.tzAddrFromReq = (req: any) => req.auth?.userAddress; this.applyAddressWhitelist = false; + this.maxWhitelistedClaims = 0; } loadSpecFromFile(filepath: string, overwrite: boolean = true): this { @@ -176,8 +178,9 @@ export class TokenGate { return this; } - enableAddressWhitelist(): this { + enableAddressWhitelist(maxClaims: number = 1): this { this.applyAddressWhitelist = true; + this.maxWhitelistedClaims = maxClaims; return this; } @@ -235,7 +238,9 @@ WHERE address = $1 if (qryResp.rowCount === 0) { return "forbidden"; } - return qryResp.rows[0].claimed ? "claimed" : "allowed"; + return Number(qryResp.rows[0].claimed) >= this.maxWhitelistedClaims + ? "claimed" + : "allowed"; } async hasAccess(