From acb79f25c7a4c7ee447e4409be25682152b3f739 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Tue, 12 Jan 2021 10:36:41 +0100 Subject: [PATCH] feat: add role guard --- src/users/decorators/roles.decorator.ts | 3 +++ src/users/dto/create-user.dto.ts | 2 +- src/users/guards/roles.guard.ts | 33 +++++++++++++++++++++++++ src/users/users.controller.ts | 15 ++++++----- src/users/users.service.ts | 6 ++--- 5 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 src/users/decorators/roles.decorator.ts create mode 100644 src/users/guards/roles.guard.ts diff --git a/src/users/decorators/roles.decorator.ts b/src/users/decorators/roles.decorator.ts new file mode 100644 index 000000000..b0376727c --- /dev/null +++ b/src/users/decorators/roles.decorator.ts @@ -0,0 +1,3 @@ +import { SetMetadata } from '@nestjs/common'; + +export const Roles = (...roles: string[]) => SetMetadata('roles', roles); diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index acb92be7f..34297e1ca 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -14,5 +14,5 @@ export class CreateUserDto { @IsArray() @IsOptional() - structuresLink?: Array<number>; + pendingStructuresLink?: Array<number>; } diff --git a/src/users/guards/roles.guard.ts b/src/users/guards/roles.guard.ts new file mode 100644 index 000000000..2ad887357 --- /dev/null +++ b/src/users/guards/roles.guard.ts @@ -0,0 +1,33 @@ +import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { UserRole } from '../enum/user-role.enum'; + +@Injectable() +export class RolesGuard implements CanActivate { + constructor(private reflector: Reflector) {} + + canActivate(context: ExecutionContext): boolean { + const roles = this.reflector.get<string[]>('roles', context.getHandler()); + if (!roles) { + return true; + } + const request = context.switchToHttp().getRequest(); + const user = request.user; + return this.matchRoles(user.role, roles[0]); + } + + /** + * Return true if user is admin or if the requested role match the user role. + * @param userRole user role from request + * @param expectedRole role requested by the endpoint + */ + private matchRoles(userRole: number, expectedRole: string): boolean { + if (userRole === UserRole.admin) { + return true; + } else if (userRole === UserRole[expectedRole]) { + return true; + } else { + return false; + } + } +} diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index b5029bbec..d78059dc5 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -7,6 +7,8 @@ import { CreateUserDto } from './dto/create-user.dto'; import { PasswordResetApplyDto } from './dto/reset-password-apply.dto'; import { PasswordResetDto } from './dto/reset-password.dto'; import { UsersService } from './users.service'; +import { RolesGuard } from './guards/roles.guard'; +import { Roles } from './decorators/roles.decorator'; @Controller('users') export class UsersController { @@ -26,9 +28,9 @@ export class UsersController { public async create(@Body() createUserDto: CreateUserDto) { // remove structureId for creation and add structure after let structureId = null; - if (createUserDto.structuresLink.length > 0) { - structureId = createUserDto.structuresLink[0]; - delete createUserDto.structuresLink; + if (createUserDto.pendingStructuresLink.length > 0) { + structureId = createUserDto.pendingStructuresLink[0]; + delete createUserDto.pendingStructuresLink; } const user = await this.usersService.create(createUserDto); if (structureId) { @@ -86,9 +88,10 @@ export class UsersController { return this.usersService.validatePasswordResetToken(passwordResetApplyDto.password, passwordResetApplyDto.token); } - @UseGuards(JwtAuthGuard) - @Get('pendingAttachments') + @UseGuards(JwtAuthGuard, RolesGuard) + @Roles('admin') + @Get('pendingStructures') public getPendingAttachments() { - return this.usersService.getPendingAttachments(); + return this.usersService.getPendingStructures(); } } diff --git a/src/users/users.service.ts b/src/users/users.service.ts index b4d54e274..e5e6b9230 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -244,9 +244,9 @@ export class UsersService { public async updateStructureLinked(userEmail: string, idStructure: number): Promise<any> { const user = await this.findOne(userEmail, true); if (user) { - user.structuresLink.push(idStructure); + user.pendingStructuresLink.push(idStructure); user.save(); - return user.structuresLink; + return user.pendingStructuresLink; } throw new HttpException('Invalid user', HttpStatus.NOT_FOUND); } @@ -254,7 +254,7 @@ export class UsersService { /** * Return all pending attachments of all profiles */ - public async getPendingAttachments(): Promise<{ userEmail: string; structureId: number }[]> { + public async getPendingStructures(): Promise<{ userEmail: string; structureId: number }[]> { const users = await this.userModel.find(); const structuresPending = []; -- GitLab