From 01f4378e11b95c438db0f6cc2c016660b5f2e2cb Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Wed, 17 Jan 2024 17:40:30 +0300 Subject: [PATCH] apps/api: add /reset-password method --- .vscode/settings.json | 4 ++-- apps/api/src/account/account.controller.ts | 16 ++++++++++++++++ apps/api/src/account/account.service.ts | 12 +++++++++++- apps/api/src/account/dto/reset-password.dto.ts | 9 +++++++++ apps/api/src/schemas/account.schema.ts | 14 ++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/account/dto/reset-password.dto.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index f841f25..e7d3a4f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,8 +14,8 @@ "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true, - "source.fixAll.eslint": true, - "source.removeUnusedImports": true + "source.fixAll.eslint": true + // "source.removeUnusedImports": true }, "workbench.editor.labelFormat": "short", "eslint.workingDirectories": [ diff --git a/apps/api/src/account/account.controller.ts b/apps/api/src/account/account.controller.ts index 7faae31..548678a 100644 --- a/apps/api/src/account/account.controller.ts +++ b/apps/api/src/account/account.controller.ts @@ -3,6 +3,7 @@ /* eslint-disable import/no-extraneous-dependencies */ import { AccountService } from './account.service'; import { CreateAccountDto } from './dto/create-account.dto'; +import { ResetPasswordDto } from './dto/reset-password.dto'; import { Body, Controller, @@ -84,6 +85,21 @@ export class AccountController { } } + @Post('/reset-password') + @ApiResponse({ + status: HttpStatus.OK, + type: Account, + }) + async resetPassword(@Body() resetPasswordDto: ResetPasswordDto, @Res() reply: FastifyReply) { + try { + const updatedAccount = await this.accountService.resetPassword(resetPasswordDto); + + return reply.status(HttpStatus.OK).send(updatedAccount); + } catch (error) { + throw new HttpException(error, HttpStatus.BAD_REQUEST); + } + } + @Post('/login') async login(@Body() credentials: Credentials, @Res() reply: FastifyReply) { try { diff --git a/apps/api/src/account/account.service.ts b/apps/api/src/account/account.service.ts index 4918d2a..15988ce 100644 --- a/apps/api/src/account/account.service.ts +++ b/apps/api/src/account/account.service.ts @@ -1,4 +1,5 @@ import type { CreateAccountDto } from './dto/create-account.dto'; +import type { ResetPasswordDto } from './dto/reset-password.dto'; import { BadRequestException, Injectable, UnauthorizedException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { InjectModel } from '@nestjs/mongoose'; @@ -53,11 +54,20 @@ export class AccountService { throw new BadRequestException(`Prop ${field} is not allowed`); }); - this.accountModel.findOneAndUpdate({ username }, props).exec(); + await this.accountModel.findOneAndUpdate({ username }, props).exec(); return this.accountModel.findOne({ username }); } + public async resetPassword({ username }: ResetPasswordDto): Promise { + const account = await this.accountModel.findOne({ username }); + if (!account) throw new UnauthorizedException('Account not found'); + + const new_password = generatePassword(); + + return { password: new_password, username }; + } + public async login({ login, password }: Credentials) { try { const account = await this.accountModel.findOne({ username: login }); diff --git a/apps/api/src/account/dto/reset-password.dto.ts b/apps/api/src/account/dto/reset-password.dto.ts new file mode 100644 index 0000000..d031718 --- /dev/null +++ b/apps/api/src/account/dto/reset-password.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +export class ResetPasswordDto { + @ApiProperty() + @IsString() + @IsNotEmpty() + public readonly username: string; +} diff --git a/apps/api/src/schemas/account.schema.ts b/apps/api/src/schemas/account.schema.ts index 5f922fe..65f9880 100644 --- a/apps/api/src/schemas/account.schema.ts +++ b/apps/api/src/schemas/account.schema.ts @@ -35,3 +35,17 @@ AccountSchema.pre('save', async function (next) { return next(error); } }); + +AccountSchema.pre('findOneAndUpdate', async function (next) { + try { + const password = this.get('password'); + if (password) { + const hash = await bcrypt.hash(password, 10); + this.set('password', hash); + } + + return next(); + } catch (error) { + return next(error); + } +});