diff --git a/src/email/dto/email.dto.ts b/src/email/dto/email.dto.ts index acde50c..7199a13 100644 --- a/src/email/dto/email.dto.ts +++ b/src/email/dto/email.dto.ts @@ -5,6 +5,7 @@ export enum EmailScene { register = 'register', updatePassword = 'updatePassword', updateEmail = 'updateEmail', + deleteUser = 'deleteUser', } export class EmailSendDto { diff --git a/src/email/email.service.ts b/src/email/email.service.ts index 2b25a86..68b2ca8 100644 --- a/src/email/email.service.ts +++ b/src/email/email.service.ts @@ -11,6 +11,7 @@ export class EmailService { [EmailScene.register]: '注册账号', [EmailScene.updatePassword]: '修改密码', [EmailScene.updateEmail]: '修改邮箱', + [EmailScene.deleteUser]: '删除用户', } constructor( private prismaService: PrismaService, @@ -31,11 +32,8 @@ export class EmailService { } break case EmailScene.updatePassword: - await this.prismaService.user.findUniqueOrThrow({ - where: { email }, - }) - break case EmailScene.updateEmail: + case EmailScene.deleteUser: await this.prismaService.user.findUniqueOrThrow({ where: { email }, }) diff --git a/src/users/dto/delete-user.dto.ts b/src/users/dto/delete-user.dto.ts new file mode 100644 index 0000000..4d377a8 --- /dev/null +++ b/src/users/dto/delete-user.dto.ts @@ -0,0 +1,17 @@ +import { IsEmail, IsNotEmpty, IsStrongPassword } from 'class-validator' + +export class DeleteUserDto { + @IsNotEmpty() + @IsEmail() + email: string + + @IsNotEmpty() + verifyCode: string + + @IsNotEmpty() + token: string + + @IsNotEmpty() + @IsStrongPassword() + password: string +} diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 9ebce58..0c90c43 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -2,6 +2,7 @@ import { Controller, Get, Post, + Delete, Patch, Body, UseInterceptors, @@ -15,6 +16,7 @@ import { PrismaService } from 'nestjs-prisma' import { UserEntity } from './entities/user.entity' import { CreateUserDto } from './dto/create-user.dto' import { UpdatePassword } from './dto/update-password.dto' +import { DeleteUserDto } from './dto/delete-user.dto' @ApiTags('User') @Controller('api/users') @@ -38,6 +40,13 @@ export class UsersController { return this.userService.register(userData) } + @NeedAuth() + @ApiOperation({ summary: '删除用户' }) + @Delete('me') + async deleteUser(@Body() userData: DeleteUserDto) { + return this.userService.deleteUser(userData) + } + @ApiOperation({ summary: '修改密码' }) @UseInterceptors(PasswordInterceptor) @Patch('me/password') diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 3a85ff8..dad61d4 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -8,6 +8,8 @@ import { EmailSendDto, EmailScene } from 'src/email/dto/email.dto' import { EmailService } from 'src/email/email.service' import { TokenService } from './token.service' import { UpdatePassword } from './dto/update-password.dto' +import { DeleteUserDto } from './dto/delete-user.dto' + @Injectable() export class UsersService { constructor( @@ -40,6 +42,24 @@ export class UsersService { return this.tokenService.generateTokens({ userId: user.id }) } + async deleteUser(userData: DeleteUserDto) { + await this.verifyEmail( + userData.email, + userData.token, + userData.verifyCode, + EmailScene.deleteUser, + ) + const user = await this.prismaService.user.findUnique({ + where: { email: userData.email }, + }) + const passwordValid = await bcrypt.compare(user.password, userData.password) + if (!passwordValid) { + throw new ForbiddenException('Invalid password') + } + + return this.prismaService.user.delete({ where: { email: userData.email } }) + } + async updatePassword(payload: UpdatePassword) { await this.verifyEmail( payload.email,