diff --git a/api/src/modules/auth/authentication/authentication.controller.ts b/api/src/modules/auth/authentication/authentication.controller.ts index 1683bef6..913c3f10 100644 --- a/api/src/modules/auth/authentication/authentication.controller.ts +++ b/api/src/modules/auth/authentication/authentication.controller.ts @@ -5,6 +5,7 @@ import { UseInterceptors, ClassSerializerInterceptor, HttpStatus, + UnauthorizedException, } from '@nestjs/common'; import { User } from '@shared/entities/users/user.entity'; import { AuthenticationService } from '@api/modules/auth/authentication/authentication.service'; @@ -80,7 +81,9 @@ export class AuthenticationController { return tsRestHandler( authContract.validateToken, async ({ headers: { authorization }, query: { tokenType } }) => { - await this.authService.verifyToken(authorization, tokenType); + if (!(await this.authService.isTokenValid(authorization, tokenType))) { + throw new UnauthorizedException(); + } return { body: null, status: HttpStatus.OK, diff --git a/api/src/modules/auth/authentication/authentication.service.ts b/api/src/modules/auth/authentication/authentication.service.ts index 2badf47a..0e6a50ce 100644 --- a/api/src/modules/auth/authentication/authentication.service.ts +++ b/api/src/modules/auth/authentication/authentication.service.ts @@ -53,13 +53,19 @@ export class AuthenticationService { return { user, accessToken }; } - async verifyToken(token: string, type: TOKEN_TYPE_ENUM): Promise { + async isTokenValid(token: string, type: TOKEN_TYPE_ENUM): Promise { const { secret } = this.apiConfig.getJWTConfigByType(type); try { - await this.jwt.verify(token, { secret }); + const { id } = await this.jwt.verify(token, { secret }); + switch (type) { + case TOKEN_TYPE_ENUM.EMAIL_CONFIRMATION: + return !(await this.usersService.isUserActive(id)); + default: + break; + } return true; } catch (error) { - throw new UnauthorizedException(); + return false; } } diff --git a/api/src/modules/users/users.service.ts b/api/src/modules/users/users.service.ts index 68569011..f8cf45b0 100644 --- a/api/src/modules/users/users.service.ts +++ b/api/src/modules/users/users.service.ts @@ -33,4 +33,9 @@ export class UsersService { async delete(user: User) { return this.repo.remove(user); } + + async isUserActive(id: string) { + const user = await this.repo.findOneBy({ id }); + return user.isActive; + } } diff --git a/api/test/integration/auth/sign-up.spec.ts b/api/test/integration/auth/sign-up.spec.ts new file mode 100644 index 00000000..7168c2d5 --- /dev/null +++ b/api/test/integration/auth/sign-up.spec.ts @@ -0,0 +1,55 @@ +import { ROLES } from '@api/modules/auth/authorisation/roles.enum'; +import { TestManager } from '../../utils/test-manager'; +import { HttpStatus } from '@nestjs/common'; +import { ApiConfigService } from '@api/modules/config/app-config.service'; +import { JwtService } from '@nestjs/jwt'; +import { TOKEN_TYPE_ENUM } from '@shared/schemas/auth/token-type.schema'; +import { authContract } from '@shared/contracts/auth.contract'; + +//create-user.feature + +describe('Create Users', () => { + let testManager: TestManager; + let apiConfig: ApiConfigService; + let jwtService: JwtService; + + beforeAll(async () => { + testManager = await TestManager.createTestManager(); + apiConfig = testManager.getModule(ApiConfigService); + jwtService = testManager.getModule(JwtService); + }); + + afterEach(async () => { + await testManager.clearDatabase(); + }); + + afterAll(async () => { + await testManager.close(); + }); + + test('A sign-up token should not be valid if the user bound to that token has already been activated', async () => { + // Given a user exists with valid credentials + // But the user has the role partner + + const user = await testManager.mocks().createUser({ + role: ROLES.PARTNER, + email: 'random@test.com', + isActive: true, + }); + const { secret, expiresIn } = apiConfig.getJWTConfigByType( + TOKEN_TYPE_ENUM.EMAIL_CONFIRMATION, + ); + + const token = jwtService.sign({ id: user.id }, { secret, expiresIn }); + + // When the user creates a new user + + const response = await testManager + .request() + .get(authContract.validateToken.path) + .set('Authorization', `Bearer ${token}`) + .query({ tokenType: TOKEN_TYPE_ENUM.EMAIL_CONFIRMATION }); + + expect(response.status).toBe(HttpStatus.UNAUTHORIZED); + }); +});