diff --git a/api/src/modules/admin/admin.controller.ts b/api/src/modules/admin/admin.controller.ts index abe24419..e62a37e3 100644 --- a/api/src/modules/admin/admin.controller.ts +++ b/api/src/modules/admin/admin.controller.ts @@ -2,7 +2,6 @@ import { Body, Controller, Post, UseGuards } from '@nestjs/common'; import { RolesGuard } from '@api/modules/auth/guards/roles.guard'; import { AuthenticationService } from '@api/modules/auth/authentication/authentication.service'; import { CreateUserDto } from '@shared/schemas/users/create-user.schema'; -import { Public } from '@api/modules/auth/decorators/is-public.decorator'; import { JwtAuthGuard } from '@api/modules/auth/guards/jwt-auth.guard'; import { ROLES } from '@api/modules/auth/authorisation/roles.enum'; import { RequiredRoles } from '@api/modules/auth/decorators/roles.decorator'; @@ -12,7 +11,6 @@ import { RequiredRoles } from '@api/modules/auth/decorators/roles.decorator'; export class AdminController { constructor(private readonly auth: AuthenticationService) {} - @Public() @RequiredRoles(ROLES.ADMIN) @Post('/users') async createUser(@Body() createUserDto: CreateUserDto): Promise { diff --git a/api/test/auth/authorization.spec.ts b/api/test/auth/authorization.spec.ts deleted file mode 100644 index 0c799016..00000000 --- a/api/test/auth/authorization.spec.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { ROLES } from '@api/modules/auth/authorisation/roles.enum'; -import { TestManager } from '../utils/test-manager'; -import { User } from '@shared/entities/users/user.entity'; - -describe('Authorization', () => { - let testManager: TestManager; - - beforeAll(async () => { - testManager = await TestManager.createTestManager(); - }); - - afterEach(async () => { - await testManager.clearDatabase(); - }); - - afterAll(async () => { - await testManager.close(); - }); - - test('a user should have a default general user role when signing up', async () => { - await testManager - .request() - .post('/authentication/signup') - .send({ email: 'test@test.com', password: '123456' }); - - const user = await testManager - .getDataSource() - .getRepository(User) - .findOne({ where: { email: 'test@test.com' } }); - - expect(user.role).toEqual(ROLES.GENERAL_USER); - }); - - describe('ROLE TEST ENDPOINTS, REMOVE!', () => { - test('when role required is GENERAL_USER, all roles should have access', async () => { - const roles = [ROLES.GENERAL_USER, ROLES.PARTNER, ROLES.ADMIN]; - - for (const role of roles) { - const user = await testManager - .mocks() - .createUser({ role, email: `${role}@email.com` }); - const { jwtToken } = await testManager.logUserIn(user); - - const response = await testManager - .request() - .get('/users/user') - .set('Authorization', `Bearer ${jwtToken}`); - - expect(response.status).toBe(200); - expect(response.body).toEqual( - expect.arrayContaining([ - ROLES.GENERAL_USER, - ROLES.PARTNER, - ROLES.ADMIN, - ]), - ); - } - }); - - test('when role required is PARTNER, only PARTNER and ADMIN roles should have access', async () => { - const allowedRoles = [ROLES.PARTNER, ROLES.ADMIN]; - const deniedRoles = [ROLES.GENERAL_USER]; - - for (const role of allowedRoles) { - const user = await testManager - .mocks() - .createUser({ role, email: `${role}@email.com` }); - const { jwtToken } = await testManager.logUserIn(user); - - const response = await testManager - .request() - .get('/users/partner') - .set('Authorization', `Bearer ${jwtToken}`); - - expect(response.status).toBe(200); - expect(response.body).toEqual( - expect.arrayContaining([ROLES.PARTNER, ROLES.ADMIN]), - ); - } - - for (const role of deniedRoles) { - const user = await testManager - .mocks() - .createUser({ role, email: `${role}@email.com` }); - const { jwtToken } = await testManager.logUserIn(user); - - const response = await testManager - .request() - .get('/users/partner') - .set('Authorization', `Bearer ${jwtToken}`); - - expect(response.status).toBe(403); - } - }); - - test('when role required is ADMIN, only ADMIN role should have access', async () => { - const allowedRoles = [ROLES.ADMIN]; - const deniedRoles = [ROLES.GENERAL_USER, ROLES.PARTNER]; - - for (const role of allowedRoles) { - const user = await testManager - .mocks() - .createUser({ role, email: `${role}@email.com` }); - const { jwtToken } = await testManager.logUserIn(user); - - const response = await testManager - .request() - .get('/users/admin') - .set('Authorization', `Bearer ${jwtToken}`); - - expect(response.status).toBe(200); - expect(response.body).toEqual([ROLES.ADMIN]); - } - - for (const role of deniedRoles) { - const user = await testManager - .mocks() - .createUser({ role, email: `${role}@email.com` }); - const { jwtToken } = await testManager.logUserIn(user); - - const response = await testManager - .request() - .get('/users/admin') - .set('Authorization', `Bearer ${jwtToken}`); - - expect(response.status).toBe(403); - } - }); - }); -}); diff --git a/api/test/e2e/features/create-user.feature b/api/test/e2e/features/create-user.feature new file mode 100644 index 00000000..da9e8923 --- /dev/null +++ b/api/test/e2e/features/create-user.feature @@ -0,0 +1,23 @@ +Feature: Create user as Admin + + Scenario: A user can not create a user if it is not an admin + Given a user exists with valid credentials + But the user has the role "partner" + When the user creates a new user + Then the user should receive a 403 status code + + + Scenario: An Admin tries to register a partner with an existing email + Given a admin user exists with valid credentials + When the user creates a new user + But the email is already in use + Then the user should receive a 409 status code + And the user should receive a message containing "Email already exists" + + + Scenario: An Admin registers a new user + Given a admin user exists with valid credentials + When the user creates a new user + Then the user should receive a 201 status code + And the user should not be active + And an email should be sent diff --git a/api/test/e2e/features/sign-up.feature b/api/test/e2e/features/sign-up.feature new file mode 100644 index 00000000..e69de29b diff --git a/api/test/integration/auth/create-user.spec.ts b/api/test/integration/auth/create-user.spec.ts new file mode 100644 index 00000000..0fb702fe --- /dev/null +++ b/api/test/integration/auth/create-user.spec.ts @@ -0,0 +1,96 @@ +import { ROLES } from '@api/modules/auth/authorisation/roles.enum'; +import { TestManager } from '../../utils/test-manager'; +import { User } from '@shared/entities/users/user.entity'; +import { HttpStatus } from '@nestjs/common'; +import { MockEmailService } from '../../utils/mocks/mock-email.service'; +import { IEmailServiceToken } from '@api/modules/notifications/email/email-service.interface'; + +//create-user.feature + +describe('Create Users', () => { + let testManager: TestManager; + let testUser: User; + let jwtToken: string; + let mockEmailService: MockEmailService; + + beforeAll(async () => { + testManager = await TestManager.createTestManager(); + const { user, jwtToken: token } = await testManager.setUpTestUser(); + testUser = user; + jwtToken = token; + mockEmailService = + testManager.getModule(IEmailServiceToken); + }); + + afterEach(async () => { + await testManager.clearDatabase(); + }); + + afterAll(async () => { + await testManager.close(); + }); + + test('A user can not create a user if it is not an admin', async () => { + // Given a user exists with valid credentials + // But the user has the role partner + + const user = await testManager.mocks().createUser({ role: ROLES.PARTNER }); + const { jwtToken } = await testManager.logUserIn(user); + + // When the user creates a new user + + const response = await testManager + .request() + .post('/admin/users') + .set('Authorization', `Bearer ${jwtToken}`); + + expect(response.status).toBe(HttpStatus.FORBIDDEN); + }); + test('An Admin tries to register a partner with an existing email', async () => { + // Given a admin user exists with valid credentials + // beforeAll + + // When the user creates a new user + // But the email is already in use + + const response = await testManager + .request() + .post('/admin/users') + .set('Authorization', `Bearer ${jwtToken}`) + .send({ email: testUser.email, password: '12345678' }); + + // Then the user should receive a 409 status code + expect(response.status).toBe(HttpStatus.CONFLICT); + // And the user should receive a message containing "Email already exists" + expect(response.body.message).toBe( + `Email ${testUser.email} already exists`, + ); + }); + + test('An Admin registers a new user', async () => { + // Given a admin user exists with valid credentials + // beforeAll + const newUser = { + email: 'test@test.com', + password: '12345678', + partnerName: 'test', + }; + + const response = await testManager + .request() + .post('/admin/users') + .set('Authorization', `Bearer ${jwtToken}`) + .send(newUser); + + // Then the user should receive a 201 status code + expect(response.status).toBe(HttpStatus.CREATED); + // And the user should not be active + const createdUser = await testManager + .getDataSource() + .getRepository(User) + .findOne({ where: { email: newUser.email } }); + + expect(createdUser.isActive).toBe(false); + expect(mockEmailService.sendMail).toHaveBeenCalledTimes(1); + }); +}); diff --git a/api/test/jest-config.json b/api/test/jest-config.json index 2b0e1ce8..a3717c69 100644 --- a/api/test/jest-config.json +++ b/api/test/jest-config.json @@ -3,7 +3,7 @@ "rootDir": "../", "roots": ["/src/", "/test/"], "testEnvironment": "node", - "testRegex": ".steps.ts$", + "testRegex": "(.steps.ts|.spec.ts)$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, diff --git a/api/test/utils/test-manager.ts b/api/test/utils/test-manager.ts index f1e94ff2..7665e43a 100644 --- a/api/test/utils/test-manager.ts +++ b/api/test/utils/test-manager.ts @@ -13,6 +13,7 @@ import { createUser } from './mocks/entity-mocks'; import { User } from '@shared/entities/users/user.entity'; import { IEmailServiceToken } from '@api/modules/notifications/email/email-service.interface'; import { MockEmailService } from './mocks/mock-email.service'; +import { ROLES } from '@api/modules/auth/authorisation/roles.enum'; /** * @description: Abstraction for NestJS testing workflow. For now its a basic implementation to create a test app, but can be extended to encapsulate @@ -72,7 +73,7 @@ export class TestManager { } async setUpTestUser() { - const user = await createUser(this.getDataSource()); + const user = await createUser(this.getDataSource(), { role: ROLES.ADMIN }); return logUserIn(this, user); }