From e3a185d650f0df27bf40d4c59e86e5b996641bd6 Mon Sep 17 00:00:00 2001 From: sjaanus Date: Tue, 1 Nov 2022 10:38:18 +0100 Subject: [PATCH] Hard cap expiry date of public signup token (#2308) Validate expiry --- .../services/public-signup-token-service.ts | 11 +++++- .../api/admin/public-signup-token.e2e.test.ts | 34 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/lib/services/public-signup-token-service.ts b/src/lib/services/public-signup-token-service.ts index 9d24e951a2..88373ab2a4 100644 --- a/src/lib/services/public-signup-token-service.ts +++ b/src/lib/services/public-signup-token-service.ts @@ -17,6 +17,7 @@ import { import UserService from './user-service'; import { IUser } from '../types/user'; import { URL } from 'url'; +import { add } from 'date-fns'; export class PublicSignupTokenService { private store: IPublicSignupTokenStore; @@ -118,9 +119,13 @@ export class PublicSignupTokenService { const viewerRole = await this.roleStore.getRoleByName(RoleName.VIEWER); const secret = this.generateSecretKey(); const url = this.getUrl(secret); + const cappedDate = this.getMinimumDate( + new Date(tokenCreate.expiresAt), + add(new Date(), { months: 1 }), + ); const newToken: IPublicSignupTokenCreate = { name: tokenCreate.name, - expiresAt: new Date(tokenCreate.expiresAt), + expiresAt: cappedDate, secret: secret, roleId: viewerRole ? viewerRole.id : -1, createdBy: createdBy, @@ -141,6 +146,10 @@ export class PublicSignupTokenService { return crypto.randomBytes(16).toString('hex'); } + private getMinimumDate(date1: Date, date2: Date): Date { + return date1 < date2 ? date1 : date2; + } + destroy(): void { clearInterval(this.timer); this.timer = null; diff --git a/src/test/e2e/api/admin/public-signup-token.e2e.test.ts b/src/test/e2e/api/admin/public-signup-token.e2e.test.ts index e14643e08e..b0b274301e 100644 --- a/src/test/e2e/api/admin/public-signup-token.e2e.test.ts +++ b/src/test/e2e/api/admin/public-signup-token.e2e.test.ts @@ -214,3 +214,37 @@ test('can get a token with users', async () => { await destroy(); }); + +test('should not be able to set expiry further than 1 month', async () => { + const preHook = (app, config, { userService, accessService }) => { + app.use('/api/admin/', async (req, res, next) => { + const role = await accessService.getRootRole(RoleName.ADMIN); + const user = await userService.createUser({ + email: 'admin@example.com', + rootRole: role.id, + }); + req.user = user; + next(); + }); + }; + + const { request, destroy } = await setupAppWithCustomAuth(stores, preHook); + + const tokenCreate: PublicSignupTokenCreateSchema = { + name: 'some-name', + expiresAt: expireAt(100).toISOString(), + }; + + await request + .post('/api/admin/invite-link/tokens') + .send(tokenCreate) + .expect('Content-Type', /json/) + .expect(201) + .expect((res) => { + expect(new Date(res.body.expiresAt).getTime()).toBeLessThan( + expireAt(31).getTime(), + ); + }); + + await destroy(); +});