From 5bf6d379ede1431c775e5f46f0df9187475600cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 4 Jul 2024 10:50:15 -0600 Subject: [PATCH 1/4] agregando auth user guard --- backend/src/admin/admin.controller.ts | 4 +++- backend/src/admin/admin.module.ts | 5 ++++- backend/src/app.module.ts | 2 +- backend/src/auth/admin/authAdmincontroller.ts | 4 +++- backend/src/auth/user/authUser.guard.ts | 21 +++++++++++++++++++ backend/src/auth/user/authUsercontroller.ts | 12 ++++++++++- backend/src/auth/user/authUserservice.ts | 10 +++++++++ .../src/auth/user/interface/customUserReq.ts | 6 ++++++ backend/src/place/place.controller.ts | 4 ++++ backend/src/place/place.module.ts | 18 ++++++++++++++-- .../PointOfInterest.controller.ts | 3 +++ .../pointOfInterest/PointOfInterest.module.ts | 17 +++++++++++++-- backend/src/town/town.controller.ts | 4 ++++ backend/src/town/town.module.ts | 9 ++++++-- 14 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 backend/src/auth/user/authUser.guard.ts create mode 100644 backend/src/auth/user/interface/customUserReq.ts diff --git a/backend/src/admin/admin.controller.ts b/backend/src/admin/admin.controller.ts index 072625aa..9fa23ef2 100644 --- a/backend/src/admin/admin.controller.ts +++ b/backend/src/admin/admin.controller.ts @@ -1,15 +1,17 @@ -import { Controller, Get, Req } from '@nestjs/common'; +import { Controller, Get, Req, UseGuards } from '@nestjs/common'; import { AdminService } from './admin.service'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { ADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; import { Roles } from 'src/auth/role.decorator'; import { CustomAdminRequest } from 'src/auth/admin/interface/customAdminReq'; +import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; @Controller('') @ApiTags('Admin') export class AdminController { constructor(private readonly adminService: AdminService) {} + @UseGuards(AuthAdminGuard) @Roles(ADMIN_ROLES) @ApiBearerAuth('jwt') @Get('admin/whoami') diff --git a/backend/src/admin/admin.module.ts b/backend/src/admin/admin.module.ts index 15c3c09e..59cc1c90 100644 --- a/backend/src/admin/admin.module.ts +++ b/backend/src/admin/admin.module.ts @@ -4,10 +4,13 @@ import { AdminController } from './admin.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Admin } from './entities/admin.entity'; import { Town } from 'src/town/entities/town.entity'; +import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; @Module({ controllers: [AdminController], - providers: [AdminService], + providers: [AdminService, AuthAdminService, JwtService, EncryptionService], imports: [TypeOrmModule.forFeature([Admin, Town])], exports: [AdminService], }) diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 719f3f5c..85d00ffe 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -65,7 +65,7 @@ import { PlaceTraduction } from './place/entities/place-traduction.entity'; PointOfInterestModule, ], controllers: [AppController], - providers: [AppService, DatabaseSeederModule, { provide: APP_GUARD, useClass: AuthAdminGuard }], + providers: [AppService, DatabaseSeederModule], exports: [TypeOrmModule], }) export class AppModule {} diff --git a/backend/src/auth/admin/authAdmincontroller.ts b/backend/src/auth/admin/authAdmincontroller.ts index 6aeadfc9..830fcde3 100644 --- a/backend/src/auth/admin/authAdmincontroller.ts +++ b/backend/src/auth/admin/authAdmincontroller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Post } from '@nestjs/common'; +import { Body, Controller, Post, UseGuards } from '@nestjs/common'; import { AuthAdminService } from './authAdmin.service'; import { CreateAdminDto } from 'src/admin/dto/create-admin.dto'; import { LoginAdminDto } from 'src/auth/admin/dto/login-admin.dto'; @@ -6,6 +6,7 @@ import { ApiBearerAuth, ApiBody, ApiCreatedResponse, ApiTags, ApiUnauthorizedRes import { AdminSigninResDto } from './dto/admin-signin-res.dto'; import { Roles } from '../role.decorator'; import { ADMIN_ROLE, SUPERADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; +import { AuthAdminGuard } from './authAdmin.guard'; @Controller() @ApiTags('Create admin account and sign in as admin') @@ -22,6 +23,7 @@ export class AuthAdminController { }, }, }) + @UseGuards(AuthAdminGuard) @Roles(SUPERADMIN_ROLES) @Post('admin/signup') @ApiBearerAuth('jwt') diff --git a/backend/src/auth/user/authUser.guard.ts b/backend/src/auth/user/authUser.guard.ts new file mode 100644 index 00000000..21603815 --- /dev/null +++ b/backend/src/auth/user/authUser.guard.ts @@ -0,0 +1,21 @@ +import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'; +import { UserService } from 'src/user/user.service'; +import { AuthUserService } from './authUserservice'; + +@Injectable() +export class AuthUserGuard implements CanActivate { + constructor( + private authUserService: AuthUserService, + private userService: UserService, + ) {} + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest(); + let { authorization }: any = request.headers; + if (!authorization) throw new UnauthorizedException('session expired! Please sign In'); + authorization = authorization.split(' ')[1]; + const jwtPayload = await this.authUserService.validateToken(authorization); + const user = await this.userService.findOne(jwtPayload.email); + request.user = { ...user }; + return true; + } +} diff --git a/backend/src/auth/user/authUsercontroller.ts b/backend/src/auth/user/authUsercontroller.ts index f82a1147..e9c709af 100644 --- a/backend/src/auth/user/authUsercontroller.ts +++ b/backend/src/auth/user/authUsercontroller.ts @@ -1,9 +1,11 @@ -import { Body, Controller, Post } from '@nestjs/common'; +import { Body, Controller, Patch, Post, Req, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiBody, ApiCreatedResponse, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; import { AuthUserService } from './authUserservice'; import { CreateUserDto } from 'src/user/dto/create-user.dto'; import { LoginUserDto } from './dto/login-user.dto'; import { UserSigninResDto } from './dto/user-signin-res.dto'; +import { AuthUserGuard } from './authUser.guard'; +import { CustomUserRequest } from './interface/customUserReq'; @Controller('') @ApiTags('Create user account and sign in as user') @@ -38,4 +40,12 @@ export class AuthUserController { throw e; } } + + @UseGuards(AuthUserGuard) + @ApiBearerAuth('jwt') + @Patch('user/change-password') + async changePassword(@Req() req: CustomUserRequest) { + console.log({ user: req.user }); + return true; + } } diff --git a/backend/src/auth/user/authUserservice.ts b/backend/src/auth/user/authUserservice.ts index a3122c86..b025e98f 100644 --- a/backend/src/auth/user/authUserservice.ts +++ b/backend/src/auth/user/authUserservice.ts @@ -8,6 +8,7 @@ import { UserService } from 'src/user/user.service'; import { CreateUserDto } from 'src/user/dto/create-user.dto'; import { LoginUserDto } from './dto/login-user.dto'; import { ALL_ROLES } from 'src/shared/enum/admin-role.enum'; +import { PayloadJwtDto } from 'src/shared/dto/payload-jwt.dto'; @Injectable() export class AuthUserService { @@ -54,4 +55,13 @@ export class AuthUserService { }; return userSigninResDto; } + + async validateToken(token: string): Promise { + try { + const payload: PayloadJwtDto = await this.jwtService.verify(token, { secret: JwtConstants.SECRET }); + return payload; + } catch (error) { + throw new UnauthorizedException('Invalid token'); + } + } } diff --git a/backend/src/auth/user/interface/customUserReq.ts b/backend/src/auth/user/interface/customUserReq.ts new file mode 100644 index 00000000..bccd04dd --- /dev/null +++ b/backend/src/auth/user/interface/customUserReq.ts @@ -0,0 +1,6 @@ +import { Request } from 'express'; +import { User } from 'src/user/entities/user.entity'; + +export interface CustomUserRequest extends Request { + user?: User; +} diff --git a/backend/src/place/place.controller.ts b/backend/src/place/place.controller.ts index 82e5edeb..4e26dcfb 100644 --- a/backend/src/place/place.controller.ts +++ b/backend/src/place/place.controller.ts @@ -10,6 +10,7 @@ import { UnauthorizedException, Req, Patch, + UseGuards, } from '@nestjs/common'; import { PlaceService } from './place.service'; import { CreatePlaceDateTradDto } from './dto/create-place-date.dto'; @@ -21,6 +22,7 @@ import { FileValidationPipe } from 'src/shared/pipe/file-validation.pipe'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { CustomAdminRequest } from 'src/auth/admin/interface/customAdminReq'; import { UpdatePlaceReqDto } from './dto/update-place.req.dto'; +import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; @Controller('place') @ApiTags('Place') @@ -29,6 +31,7 @@ export class PlaceController { @ApiBody({ type: CreatePlaceDateTradDto }) @ApiConsumes('multipart/form-data') + @UseGuards(AuthAdminGuard) @Roles([ALL_ROLES.ADMIN]) @ApiBearerAuth('jwt') @Post() @@ -67,6 +70,7 @@ export class PlaceController { } @Patch(':idPlace') + @UseGuards(AuthAdminGuard) @Roles([ALL_ROLES.ADMIN]) @ApiBearerAuth('jwt') @ApiConsumes('multipart/form-data') diff --git a/backend/src/place/place.module.ts b/backend/src/place/place.module.ts index d32cf55e..dd524b38 100644 --- a/backend/src/place/place.module.ts +++ b/backend/src/place/place.module.ts @@ -10,12 +10,26 @@ import { TownService } from 'src/town/town.service'; import { TownTraduction } from 'src/town/entities/town-traduction.entity'; import { StateService } from 'src/state/state.service'; import { State } from 'src/state/entities/state.entity'; +import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; +import { AdminService } from 'src/admin/admin.service'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; +import { Admin } from 'src/admin/entities/admin.entity'; @Module({ controllers: [PlaceController], - providers: [PlaceService, TownService, StateService], + providers: [ + PlaceService, + TownService, + StateService, + AuthAdminService, + AdminService, + JwtService, + EncryptionService, + TownService, + ], imports: [ - TypeOrmModule.forFeature([Place, AvailableDate, PlaceTraduction, Town, TownTraduction, State]), + TypeOrmModule.forFeature([Place, AvailableDate, PlaceTraduction, Town, TownTraduction, State, Admin]), TypeOrmModule, ], }) diff --git a/backend/src/pointOfInterest/PointOfInterest.controller.ts b/backend/src/pointOfInterest/PointOfInterest.controller.ts index 57c26d37..62ac1bdd 100644 --- a/backend/src/pointOfInterest/PointOfInterest.controller.ts +++ b/backend/src/pointOfInterest/PointOfInterest.controller.ts @@ -8,6 +8,7 @@ import { UploadedFile, Query, StreamableFile, + UseGuards, } from '@nestjs/common'; import { PointOfInterestService } from './PointOfInterest.service'; import { CreatePointAndTradDto } from './dto/create-pointAndTraduction.dto'; @@ -17,6 +18,7 @@ import { ADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; import { fileInterceptor } from 'src/shared/interceptors/file-save.interceptor'; import { FileValidationPipe } from 'src/shared/pipe/file-validation.pipe'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; @Controller('') @ApiTags('Point of interest') @@ -24,6 +26,7 @@ export class PointOfInterestController { constructor(private readonly pointService: PointOfInterestService) {} @ApiConsumes('multipart/form-data') + @UseGuards(AuthAdminGuard) @Roles(ADMIN_ROLES) @ApiBearerAuth('jwt') @Post('point') diff --git a/backend/src/pointOfInterest/PointOfInterest.module.ts b/backend/src/pointOfInterest/PointOfInterest.module.ts index c9223025..aa78034b 100644 --- a/backend/src/pointOfInterest/PointOfInterest.module.ts +++ b/backend/src/pointOfInterest/PointOfInterest.module.ts @@ -9,12 +9,25 @@ import { Place } from 'src/place/entities/place.entity'; import { AvailableDate } from 'src/place/entities/available-date.entity'; import { PlaceTraduction } from 'src/place/entities/place-traduction.entity'; import { Town } from 'src/town/entities/town.entity'; +import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; +import { AdminService } from 'src/admin/admin.service'; +import { Admin } from 'src/admin/entities/admin.entity'; @Module({ controllers: [PointOfInterestController], - providers: [PointOfInterestService, PlaceService], + providers: [PointOfInterestService, PlaceService, AdminService, AuthAdminService, JwtService, EncryptionService], imports: [ - TypeOrmModule.forFeature([PointOfInterest, PointOfInterestTraduction, Place, AvailableDate, PlaceTraduction, Town]), + TypeOrmModule.forFeature([ + PointOfInterest, + PointOfInterestTraduction, + Place, + AvailableDate, + PlaceTraduction, + Town, + Admin, + ]), ], }) export class PointOfInterestModule {} diff --git a/backend/src/town/town.controller.ts b/backend/src/town/town.controller.ts index 34a17eef..f2abda25 100644 --- a/backend/src/town/town.controller.ts +++ b/backend/src/town/town.controller.ts @@ -10,6 +10,7 @@ import { Patch, Req, UnauthorizedException, + UseGuards, } from '@nestjs/common'; import { TownService } from './town.service'; import { ApiBearerAuth, ApiBody, ApiConsumes, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger'; @@ -20,11 +21,13 @@ import { Roles } from 'src/auth/role.decorator'; import { ALL_ROLES, SUPERADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; import { CreateTownReqDto } from './dto/createTownReq.dto'; import { CustomAdminRequest } from 'src/auth/admin/interface/customAdminReq'; +import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; @Controller() @ApiTags('Pueblos') export class TownController { constructor(private readonly townService: TownService) {} + @UseGuards(AuthAdminGuard) @Roles(SUPERADMIN_ROLES) @ApiBearerAuth('jwt') @ApiBody({ type: CreateTownReqDto }) @@ -59,6 +62,7 @@ export class TownController { } } + @UseGuards(AuthAdminGuard) @Roles([ALL_ROLES.ADMIN]) @ApiBearerAuth('jwt') @ApiBody({ type: CreateTownReqDto }) diff --git a/backend/src/town/town.module.ts b/backend/src/town/town.module.ts index 3bcef4a4..401bac47 100644 --- a/backend/src/town/town.module.ts +++ b/backend/src/town/town.module.ts @@ -6,11 +6,16 @@ import { Town } from './entities/town.entity'; import { StateService } from 'src/state/state.service'; import { State } from 'src/state/entities/state.entity'; import { TownTraduction } from './entities/town-traduction.entity'; +import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; +import { AdminService } from 'src/admin/admin.service'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; +import { Admin } from 'src/admin/entities/admin.entity'; @Module({ controllers: [TownController], - providers: [TownService, StateService, TypeOrmModule], - imports: [TypeOrmModule.forFeature([Town, State, TownTraduction]), TypeOrmModule], + providers: [TownService, StateService, TypeOrmModule, AuthAdminService, AdminService, JwtService, EncryptionService], + imports: [TypeOrmModule.forFeature([Town, State, TownTraduction, Admin]), TypeOrmModule], exports: [TownService], }) export class TownModule {} -- GitLab From d2d87795a315cdb6cbd6cc3e07ac2b62f24ce4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:06:28 -0600 Subject: [PATCH 2/4] dto para actualizar password --- backend/src/auth/user/dto/update-pwd.dto.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 backend/src/auth/user/dto/update-pwd.dto.ts diff --git a/backend/src/auth/user/dto/update-pwd.dto.ts b/backend/src/auth/user/dto/update-pwd.dto.ts new file mode 100644 index 00000000..afcb4141 --- /dev/null +++ b/backend/src/auth/user/dto/update-pwd.dto.ts @@ -0,0 +1,8 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class UpdatePwdDto { + @ApiProperty() + prevPassword: string; + @ApiProperty() + newPassword: string; +} -- GitLab From 8af92d7190ad66ffca7a26c55cb217bee643c57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:06:59 -0600 Subject: [PATCH 3/4] =?UTF-8?q?agregando=20endpoint=20para=20cambiar=20con?= =?UTF-8?q?trase=C3=B1a=20para=20un=20usuario?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/auth/user/authUser.guard.ts | 3 +++ backend/src/auth/user/authUsercontroller.ts | 6 +++--- backend/src/auth/user/authUserservice.ts | 12 ++++++++++++ backend/src/user/user.service.ts | 4 ++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/src/auth/user/authUser.guard.ts b/backend/src/auth/user/authUser.guard.ts index 21603815..d8f0b97f 100644 --- a/backend/src/auth/user/authUser.guard.ts +++ b/backend/src/auth/user/authUser.guard.ts @@ -14,7 +14,10 @@ export class AuthUserGuard implements CanActivate { if (!authorization) throw new UnauthorizedException('session expired! Please sign In'); authorization = authorization.split(' ')[1]; const jwtPayload = await this.authUserService.validateToken(authorization); + if (!jwtPayload) throw new UnauthorizedException('session expired! Please sign In'); + const user = await this.userService.findOne(jwtPayload.email); + if (!user) throw new UnauthorizedException('session expired! Please sign In'); request.user = { ...user }; return true; } diff --git a/backend/src/auth/user/authUsercontroller.ts b/backend/src/auth/user/authUsercontroller.ts index e9c709af..8febe05f 100644 --- a/backend/src/auth/user/authUsercontroller.ts +++ b/backend/src/auth/user/authUsercontroller.ts @@ -6,6 +6,7 @@ import { LoginUserDto } from './dto/login-user.dto'; import { UserSigninResDto } from './dto/user-signin-res.dto'; import { AuthUserGuard } from './authUser.guard'; import { CustomUserRequest } from './interface/customUserReq'; +import { UpdatePwdDto } from './dto/update-pwd.dto'; @Controller('') @ApiTags('Create user account and sign in as user') @@ -44,8 +45,7 @@ export class AuthUserController { @UseGuards(AuthUserGuard) @ApiBearerAuth('jwt') @Patch('user/change-password') - async changePassword(@Req() req: CustomUserRequest) { - console.log({ user: req.user }); - return true; + async changePassword(@Req() req: CustomUserRequest, @Body() updatePwdDto: UpdatePwdDto) { + return this.authUserService.changePassword(req.user.email, updatePwdDto); } } diff --git a/backend/src/auth/user/authUserservice.ts b/backend/src/auth/user/authUserservice.ts index b025e98f..b3b5db3b 100644 --- a/backend/src/auth/user/authUserservice.ts +++ b/backend/src/auth/user/authUserservice.ts @@ -9,6 +9,7 @@ import { CreateUserDto } from 'src/user/dto/create-user.dto'; import { LoginUserDto } from './dto/login-user.dto'; import { ALL_ROLES } from 'src/shared/enum/admin-role.enum'; import { PayloadJwtDto } from 'src/shared/dto/payload-jwt.dto'; +import { UpdatePwdDto } from './dto/update-pwd.dto'; @Injectable() export class AuthUserService { @@ -64,4 +65,15 @@ export class AuthUserService { throw new UnauthorizedException('Invalid token'); } } + + async changePassword(email: string, updatePwdDto: UpdatePwdDto) { + const user: User = await this.userService.findOne(email); + const prevPwdHashed = user.password; + const validPwd: boolean = await this.encryptionService.comparePassword(updatePwdDto.prevPassword, prevPwdHashed); + + if (!validPwd) throw new UnauthorizedException('Invalid password'); + + const newPwdHashed = await this.encryptionService.hashPassword(updatePwdDto.newPassword); + await this.userService.updatePassword(email, newPwdHashed); + } } diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 561a0be7..e22805e2 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -24,4 +24,8 @@ export class UserService { if (user) return true; else return false; } + + async updatePassword(email: string, password: string) { + await this.userRepository.update({ email }, { password }); + } } -- GitLab From aefef127b9588501e71cd06d28a270f82b6561de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:15:45 -0600 Subject: [PATCH 4/4] =?UTF-8?q?agregando=20endpoint=20para=20cambiar=20con?= =?UTF-8?q?trase=C3=B1a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/admin/admin.service.ts | 4 ++++ backend/src/auth/admin/authAdmin.service.ts | 11 +++++++++++ backend/src/auth/admin/authAdmincontroller.ts | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/backend/src/admin/admin.service.ts b/backend/src/admin/admin.service.ts index ff36b7a5..793c06a5 100644 --- a/backend/src/admin/admin.service.ts +++ b/backend/src/admin/admin.service.ts @@ -23,4 +23,8 @@ export class AdminService { throw new UnauthorizedException('Admin not found'); } } + + async updatePassword(email: string, password: string) { + await this.adminRepository.update({ email }, { password }); + } } diff --git a/backend/src/auth/admin/authAdmin.service.ts b/backend/src/auth/admin/authAdmin.service.ts index 69e17602..c11613a4 100644 --- a/backend/src/auth/admin/authAdmin.service.ts +++ b/backend/src/auth/admin/authAdmin.service.ts @@ -9,6 +9,7 @@ import { AdminSigninResDto } from './dto/admin-signin-res.dto'; import { Admin } from 'src/admin/entities/admin.entity'; import { ADMIN_ROLE } from 'src/shared/enum/admin-role.enum'; import { PayloadJwtDto } from 'src/shared/dto/payload-jwt.dto'; +import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; @Injectable() export class AuthAdminService { @@ -58,4 +59,14 @@ export class AuthAdminService { throw new UnauthorizedException('Invalid token'); } } + + async changePassword(email: string, updatePwdDto: UpdatePwdDto): Promise { + const admin: Admin = await this.adminService.findOne(email); + const validPwd: boolean = await this.encryptionService.comparePassword(updatePwdDto.prevPassword, admin.password); + if (!validPwd) { + throw new HttpException('Invalid password', HttpStatus.UNAUTHORIZED); + } + const hashedPwd = await this.encryptionService.hashPassword(updatePwdDto.newPassword); + await this.adminService.updatePassword(email, hashedPwd); + } } diff --git a/backend/src/auth/admin/authAdmincontroller.ts b/backend/src/auth/admin/authAdmincontroller.ts index 830fcde3..20ebd5a7 100644 --- a/backend/src/auth/admin/authAdmincontroller.ts +++ b/backend/src/auth/admin/authAdmincontroller.ts @@ -1,12 +1,14 @@ -import { Body, Controller, Post, UseGuards } from '@nestjs/common'; +import { Body, Controller, Post, Req, UseGuards } from '@nestjs/common'; import { AuthAdminService } from './authAdmin.service'; import { CreateAdminDto } from 'src/admin/dto/create-admin.dto'; import { LoginAdminDto } from 'src/auth/admin/dto/login-admin.dto'; import { ApiBearerAuth, ApiBody, ApiCreatedResponse, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; import { AdminSigninResDto } from './dto/admin-signin-res.dto'; import { Roles } from '../role.decorator'; -import { ADMIN_ROLE, SUPERADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; +import { ADMIN_ROLE, ADMIN_ROLES, SUPERADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; import { AuthAdminGuard } from './authAdmin.guard'; +import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; +import { CustomAdminRequest } from './interface/customAdminReq'; @Controller() @ApiTags('Create admin account and sign in as admin') @@ -50,4 +52,13 @@ export class AuthAdminController { throw e; } } + + @UseGuards(AuthAdminGuard) + @Roles(ADMIN_ROLES) + @Post('admin/change-password') + @ApiBearerAuth('jwt') + async changePassword(@Req() req: CustomAdminRequest, @Body() updatePwdDto: UpdatePwdDto) { + const email = req.admin.email; + return this.authAdminService.changePassword(email, updatePwdDto); + } } -- GitLab