diff --git a/backend/src/core/graphql/schema.gql b/backend/src/core/graphql/schema.gql index 3be3ea8..957525f 100644 --- a/backend/src/core/graphql/schema.gql +++ b/backend/src/core/graphql/schema.gql @@ -7,6 +7,15 @@ type AuthModel { user: UserModel } +input ChangeEmailInput { + email: String! +} + +input ChangePasswordInput { + newPassword: String! + oldPassword: String! +} + input CreateUserInput { email: String! name: String! @@ -49,6 +58,8 @@ input LoginInput { } type Mutation { + changeEmail(data: ChangeEmailInput!): UserModel! + changePassword(data: ChangePasswordInput!): UserModel! clearSessionCookie: Boolean! createUser(data: CreateUserInput!): UserModel! deactivateAccount(data: DeactivateAccountInput!): AuthModel! diff --git a/backend/src/module/auth/account/account.resolver.ts b/backend/src/module/auth/account/account.resolver.ts index 5becf63..843a4e7 100644 --- a/backend/src/module/auth/account/account.resolver.ts +++ b/backend/src/module/auth/account/account.resolver.ts @@ -1,5 +1,8 @@ +import { ChangeEmailInput } from '@/src/module/auth/account/inputs/change-email.input' +import { ChangePasswordInput } from '@/src/module/auth/account/inputs/change-password.input' import { Authorization } from '@/src/shared/decorators/auth.decorator' import { Authorized } from '@/src/shared/decorators/authorized.decorator' +import { User } from '@prisma/generated' import { CreateUserInput } from './inputs/create-user.input' import { Args, Mutation, Query, Resolver } from '@nestjs/graphql' import { AccountService } from './account.service' @@ -19,4 +22,22 @@ export class AccountResolver { public async create(@Args('data') input: CreateUserInput) { return this.accountService.create(input) } + + @Authorization() + @Mutation(() => UserModel, { name: 'changeEmail' }) + public async changeEmail( + @Args('data') input: ChangeEmailInput, + @Authorized() user: User, + ) { + return this.accountService.changeEmail(user, input) + } + + @Authorization() + @Mutation(() => UserModel, { name: 'changePassword' }) + public async changePassword( + @Args('data') input: ChangePasswordInput, + @Authorized() user: User, + ) { + return this.accountService.changePassword(user, input) + } } diff --git a/backend/src/module/auth/account/account.service.ts b/backend/src/module/auth/account/account.service.ts index 9d07b17..bb93271 100644 --- a/backend/src/module/auth/account/account.service.ts +++ b/backend/src/module/auth/account/account.service.ts @@ -1,9 +1,11 @@ import { User } from '@/prisma/generated' import { PrismaService } from '@/src/core/prisma/prisma.service' +import { ChangeEmailInput } from '@/src/module/auth/account/inputs/change-email.input' +import { ChangePasswordInput } from '@/src/module/auth/account/inputs/change-password.input' import { CreateUserInput } from '@/src/module/auth/account/inputs/create-user.input' import { VerificationService } from '@/src/module/auth/verification/verification.service' -import { ConflictException, Injectable } from '@nestjs/common' -import { hash } from 'argon2' +import { BadRequestException, ConflictException, Injectable } from '@nestjs/common' +import { hash, verify } from 'argon2' @Injectable() export class AccountService { @@ -56,4 +58,35 @@ export class AccountService { return user } + + public async changeEmail(user: User, input: ChangeEmailInput) { + const { email } = input + + return this.prismaService.user.update({ + where: { + id: user.id, + }, + data: { + email, + }, + }) + } + + public async changePassword(user: User, input: ChangePasswordInput) { + const { newPassword, oldPassword } = input + + const isCorrectPassword = await verify(user.password, oldPassword) + if (!isCorrectPassword) { + throw new BadRequestException('Неверный пароль') + } + + return this.prismaService.user.update({ + where: { + id: user.id, + }, + data: { + password: await hash(newPassword), + }, + }) + } } diff --git a/backend/src/module/auth/account/inputs/change-email.input.ts b/backend/src/module/auth/account/inputs/change-email.input.ts new file mode 100644 index 0000000..c41bef6 --- /dev/null +++ b/backend/src/module/auth/account/inputs/change-email.input.ts @@ -0,0 +1,11 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsEmail, IsNotEmpty, IsString } from 'class-validator' + +@InputType() +export class ChangeEmailInput { + @Field(() => String) + @IsString() + @IsNotEmpty() + @IsEmail() + email: string +} diff --git a/backend/src/module/auth/account/inputs/change-password.input.ts b/backend/src/module/auth/account/inputs/change-password.input.ts new file mode 100644 index 0000000..d902e80 --- /dev/null +++ b/backend/src/module/auth/account/inputs/change-password.input.ts @@ -0,0 +1,17 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsNotEmpty, IsString, MinLength } from 'class-validator' + +@InputType() +export class ChangePasswordInput { + @Field(() => String) + @IsString() + @IsNotEmpty() + @MinLength(8) + oldPassword: string + + @Field(() => String) + @IsString() + @IsNotEmpty() + @MinLength(8) + newPassword: string +}