From bc580cfcacd5a2b3b6dabaa07bb6da83c39f543d Mon Sep 17 00:00:00 2001 From: FerreiroAlberto Date: Fri, 3 May 2024 14:25:07 +0200 Subject: [PATCH 1/2] Fix guards logic --- src/core/auth/logged.guard.ts | 9 ++++++--- src/core/auth/owner.guard.ts | 4 +++- src/core/crypto/crypto.service.ts | 8 +++++--- src/policies/policies.controller.ts | 5 ++--- src/policies/policies.module.ts | 10 +++++++++- src/users/entities/user.entity.ts | 8 ++++++++ src/users/users.service.ts | 1 + 7 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/core/auth/logged.guard.ts b/src/core/auth/logged.guard.ts index 8687223..6d69f7f 100644 --- a/src/core/auth/logged.guard.ts +++ b/src/core/auth/logged.guard.ts @@ -1,5 +1,4 @@ import { - BadRequestException, CanActivate, ExecutionContext, ForbiddenException, @@ -14,12 +13,16 @@ export class LoggedGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); const auth = request.headers.authorization; + if (!auth) { - throw new BadRequestException('Authorization header is required'); + throw new ForbiddenException('Authorization header is required'); } const token = auth.split(' ')[1]; + try { - request.payload = await this.cryptoService.verifyToken(token); + const decodedToken = await this.cryptoService.verifyToken(token); + + request.payload = decodedToken; return true; } catch (error) { throw new ForbiddenException('Invalid token'); diff --git a/src/core/auth/owner.guard.ts b/src/core/auth/owner.guard.ts index b82b127..612b3c0 100644 --- a/src/core/auth/owner.guard.ts +++ b/src/core/auth/owner.guard.ts @@ -13,7 +13,9 @@ export class PolicyOwnerGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); - const user = request.user; + + const user = request.payload; + const policyId = request.params.id; const policy = await this.policiesService.findOne(policyId); diff --git a/src/core/crypto/crypto.service.ts b/src/core/crypto/crypto.service.ts index 1aaacc6..a7d0d6b 100644 --- a/src/core/crypto/crypto.service.ts +++ b/src/core/crypto/crypto.service.ts @@ -2,10 +2,11 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { hash, compare } from 'bcrypt'; -import { SignUser } from 'src/users/entities/user.entity'; +import { LogUser } from '../../users/entities/user.entity'; export type TokenPayload = { email: string; + id: string; }; @Injectable() @@ -23,8 +24,9 @@ export class CryptoService { return compare(value, hash); } - async createToken({ email }: SignUser) { - const payload: TokenPayload = { email }; + async createToken({ email, id }: LogUser) { + console.log('ID en crypto:', id); + const payload: TokenPayload = { email, id }; const token = await this.jwtService.signAsync(payload, { secret: this.configService.get('SECRET_JWT'), }); diff --git a/src/policies/policies.controller.ts b/src/policies/policies.controller.ts index 226085b..3edf59e 100644 --- a/src/policies/policies.controller.ts +++ b/src/policies/policies.controller.ts @@ -40,15 +40,14 @@ export class PoliciesController { findOne(@Param('id') id: string) { return this.policiesService.findOne(id); } - - @UseGuards(LoggedGuard) @UseGuards(PolicyOwnerGuard) + @UseGuards(LoggedGuard) @Patch(':id') update(@Param('id') id: string, @Body() updatePolicyDto: UpdatePolicyDto) { return this.policiesService.update(id, updatePolicyDto); } - @UseGuards(LoggedGuard) @UseGuards(PolicyOwnerGuard) + @UseGuards(LoggedGuard) @Delete(':id') delete(@Param('id') id: string) { return this.policiesService.delete(id); diff --git a/src/policies/policies.module.ts b/src/policies/policies.module.ts index 8d2ecfc..7ebc1a8 100644 --- a/src/policies/policies.module.ts +++ b/src/policies/policies.module.ts @@ -5,9 +5,17 @@ import { PrismaService } from '../prisma/prisma.service'; import { PrismaModule } from '../prisma/prisma.module'; import { CoreModule } from '../core/core.module'; +export const REPO_SERVICE = 'REPO_SERVICE'; @Module({ controllers: [PoliciesController], - providers: [PoliciesService, PrismaService], + providers: [ + PoliciesService, + PrismaService, + { + provide: 'REPO_SERVICE', + useClass: PoliciesService, + }, + ], imports: [PrismaModule, CoreModule], }) export class PoliciesModule {} diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts index 9de1f37..bda639d 100644 --- a/src/users/entities/user.entity.ts +++ b/src/users/entities/user.entity.ts @@ -19,3 +19,11 @@ export class SignUser { @IsString() password: string; } + +export class LogUser { + @IsString() + @IsEmail() + email: string; + @IsString() + id: string; +} diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 5d316be..6d85452 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -59,6 +59,7 @@ export class UsersService { select: { email: true, password: true, + id: true, }, }); From f9f747e981abff9c3c03c1373777547c14a5374e Mon Sep 17 00:00:00 2001 From: FerreiroAlberto Date: Fri, 3 May 2024 14:40:00 +0200 Subject: [PATCH 2/2] Fix guard logic and additional testing --- src/core/auth/owner.guard.spec.ts | 2 +- src/core/crypto/crypto.service.spec.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/auth/owner.guard.spec.ts b/src/core/auth/owner.guard.spec.ts index e9fb9e4..13d013a 100644 --- a/src/core/auth/owner.guard.spec.ts +++ b/src/core/auth/owner.guard.spec.ts @@ -21,7 +21,7 @@ describe('PolicyOwnerGuard', () => { it('should allow access if the user is the owner of the policy', async () => { const request = { - user: { id: 'user5' }, + payload: { id: 'user5' }, params: { id: 'policy1' }, }; const policy = { diff --git a/src/core/crypto/crypto.service.spec.ts b/src/core/crypto/crypto.service.spec.ts index ad7044c..ee02b57 100644 --- a/src/core/crypto/crypto.service.spec.ts +++ b/src/core/crypto/crypto.service.spec.ts @@ -4,7 +4,7 @@ import { JwtService } from '@nestjs/jwt'; import { ConfigService } from '@nestjs/config'; import { hash, compare } from 'bcrypt'; -import { SignUser } from 'src/users/entities/user.entity'; +import { LogUser } from '../../users/entities/user.entity'; jest.mock('bcrypt', () => ({ hash: jest.fn().mockResolvedValue('hashedValue'), compare: jest.fn().mockResolvedValue(true), @@ -59,10 +59,10 @@ describe('CryptoService', () => { describe('When we call createToken method', () => { it('should return a token', async () => { - const user: SignUser = { email: 'id@dominio.com', password: '' }; + const user: LogUser = { email: 'id@dominio.com', id: '4' }; const result = await service.createToken(user); expect(jwtServiceMock.signAsync).toHaveBeenCalledWith( - { email: 'id@dominio.com' }, + { email: 'id@dominio.com', id: '4' }, { secret: 'SECRET_JWT' }, ); expect(result).toBe('token');