From d2f61eebcdf768e9266b4f3c836fa45198edf040 Mon Sep 17 00:00:00 2001 From: Emnaghz Date: Mon, 23 Sep 2024 11:17:19 +0100 Subject: [PATCH] fix: use req + update unit tests --- .../user/controllers/role.controller.spec.ts | 43 ++++++++++--------- api/src/user/controllers/role.controller.ts | 24 +++++------ 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/api/src/user/controllers/role.controller.spec.ts b/api/src/user/controllers/role.controller.spec.ts index fae89e6..ce6f786 100644 --- a/api/src/user/controllers/role.controller.spec.ts +++ b/api/src/user/controllers/role.controller.spec.ts @@ -12,7 +12,7 @@ import { ForbiddenException, NotFoundException } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; -import { Session as ExpressSession } from 'express-session'; +import { Request } from 'express'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -191,45 +191,48 @@ describe('RoleController', () => { describe('deleteOne', () => { it("should throw ForbiddenException if the role is part of the user's roles", async () => { - const session = { passport: { user: { id: 'user1' } } } as ExpressSession; + const req = { user: { roles: ['role1'] } } as unknown as Request; const roleId = 'role1'; - userService.findOneAndPopulate = jest.fn().mockResolvedValue({ - roles: [{ id: roleId }], - }); + userService.findOne = jest.fn().mockResolvedValue(null); - await expect(roleController.deleteOne(roleId, session)).rejects.toThrow( + await expect(roleController.deleteOne(roleId, req)).rejects.toThrow( + ForbiddenException, + ); + }); + + it('should throw ForbiddenException if the role is associated with other users', async () => { + const req = { user: { roles: ['role2'] } } as unknown as Request; + const roleId = 'role1'; + + userService.findOne = jest.fn().mockResolvedValue({ id: 'user2' }); + + await expect(roleController.deleteOne(roleId, req)).rejects.toThrow( ForbiddenException, ); }); it('should throw NotFoundException if the role is not found', async () => { - const session = { passport: { user: { id: 'user1' } } } as ExpressSession; - const roleId = 'role2'; - - userService.findOneAndPopulate = jest.fn().mockResolvedValue({ - roles: [{ id: 'role1' }], - }); + const req = { user: { roles: ['role2'] } } as unknown as Request; + const roleId = 'role1'; + userService.findOne = jest.fn().mockResolvedValue(null); roleService.deleteOne = jest.fn().mockResolvedValue({ deletedCount: 0 }); - await expect(roleController.deleteOne(roleId, session)).rejects.toThrow( + await expect(roleController.deleteOne(roleId, req)).rejects.toThrow( NotFoundException, ); }); it('should return the result if the role is successfully deleted', async () => { - const session = { passport: { user: { id: 'user1' } } } as ExpressSession; - const roleId = 'role2'; - - userService.findOneAndPopulate = jest.fn().mockResolvedValue({ - roles: [{ id: 'role1' }], - }); + const req = { user: { roles: ['role2'] } } as unknown as Request; + const roleId = 'role1'; + userService.findOne = jest.fn().mockResolvedValue(null); const deleteResult = { deletedCount: 1 }; roleService.deleteOne = jest.fn().mockResolvedValue(deleteResult); - const result = await roleController.deleteOne(roleId, session); + const result = await roleController.deleteOne(roleId, req); expect(result).toEqual(deleteResult); }); }); diff --git a/api/src/user/controllers/role.controller.ts b/api/src/user/controllers/role.controller.ts index b54b62a..ba92870 100644 --- a/api/src/user/controllers/role.controller.ts +++ b/api/src/user/controllers/role.controller.ts @@ -20,10 +20,10 @@ import { Query, UseInterceptors, ForbiddenException, - Session, + Req, } from '@nestjs/common'; import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; -import { Session as ExpressSession } from 'express-session'; +import { Request } from 'express'; import { TFilterQuery } from 'mongoose'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; @@ -36,6 +36,7 @@ import { SearchFilterPipe } from '@/utils/pipes/search-filter.pipe'; import { RoleCreateDto, RoleUpdateDto } from '../dto/role.dto'; import { Role, RoleFull, RolePopulate, RoleStub } from '../schemas/role.schema'; +import { User } from '../schemas/user.schema'; import { RoleService } from '../services/role.service'; import { UserService } from '../services/user.service'; @@ -152,19 +153,16 @@ export class RoleController extends BaseController< @CsrfCheck(true) @Delete(':id') @HttpCode(204) - async deleteOne(@Param('id') id: string, @Session() session: ExpressSession) { - const currentUser = await this.userService.findOneAndPopulate( - session.passport.user.id, - ['roles'], - ); - if (!currentUser) { - throw new NotFoundException('User not found'); - } + async deleteOne(@Param('id') id: string, @Req() req: Request) { + const userRoles = (req.user as User).roles; - const roles = currentUser.roles.map((role) => role.id); - - if (roles.includes(id)) { + const associatedUser = await this.userService.findOne({ + roles: { $in: [id] }, + }); + if (userRoles.includes(id)) { throw new ForbiddenException("Your account's role can't be deleted"); + } else if (associatedUser) { + throw new ForbiddenException('Role is associated with other users'); } else { try { const result = await this.roleService.deleteOne(id);