mirror of
https://github.com/hknsh/project-knedita.git
synced 2024-11-28 09:31:16 +00:00
feat: added update email and password routes
This commit is contained in:
parent
e6718ca54f
commit
8af84b7cfa
4 changed files with 124 additions and 3 deletions
14
src/users/dto/update-email.dto.ts
Normal file
14
src/users/dto/update-email.dto.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { createZodDto } from "nestjs-zod";
|
||||
import { z } from "nestjs-zod/z";
|
||||
|
||||
export const UpdateEmailSchema = z
|
||||
.object({
|
||||
email: z
|
||||
.string({
|
||||
required_error: "Email is required",
|
||||
})
|
||||
.email("Invalid email"),
|
||||
})
|
||||
.required();
|
||||
|
||||
export class UpdateEmailDTO extends createZodDto(UpdateEmailSchema) {}
|
33
src/users/dto/update-password.dto.ts
Normal file
33
src/users/dto/update-password.dto.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { createZodDto } from "nestjs-zod";
|
||||
import { z } from "nestjs-zod/z";
|
||||
|
||||
// TODO: see if it can be refactored
|
||||
|
||||
export const UpdatePasswordSchema = z
|
||||
.object({
|
||||
old_password: z
|
||||
.password({
|
||||
required_error: "Password is required",
|
||||
})
|
||||
.min(8)
|
||||
.max(32)
|
||||
.atLeastOne("digit")
|
||||
.atLeastOne("uppercase")
|
||||
.atLeastOne("lowercase")
|
||||
.atLeastOne("special")
|
||||
.transform((value) => value.replace(/\s+/g, "")),
|
||||
new_password: z
|
||||
.password({
|
||||
required_error: "Password is required",
|
||||
})
|
||||
.min(8)
|
||||
.max(32)
|
||||
.atLeastOne("digit")
|
||||
.atLeastOne("uppercase")
|
||||
.atLeastOne("lowercase")
|
||||
.atLeastOne("special")
|
||||
.transform((value) => value.replace(/\s+/g, "")),
|
||||
})
|
||||
.required();
|
||||
|
||||
export class UpdatePasswordDTO extends createZodDto(UpdatePasswordSchema) {}
|
|
@ -23,6 +23,8 @@ import { CreateUserDTO } from "./dto/create-user.dto";
|
|||
import { Public } from "src/public.decorator";
|
||||
import { UpdateNameDTO } from "./dto/update-name.dto";
|
||||
import { User } from "./types/user.type";
|
||||
import { UpdateEmailDTO } from "./dto/update-email.dto";
|
||||
import { UpdatePasswordDTO } from "./dto/update-password.dto";
|
||||
|
||||
@ApiTags("Users")
|
||||
@Controller("users")
|
||||
|
@ -49,7 +51,7 @@ export class UserController {
|
|||
description: "Not authenticated / Invalid JWT Token",
|
||||
})
|
||||
me(@Request() req) {
|
||||
return req.user; // TODO: Add typing to req.user
|
||||
return req.user;
|
||||
}
|
||||
|
||||
@Public()
|
||||
|
@ -74,12 +76,23 @@ export class UserController {
|
|||
@Patch("/email")
|
||||
@ApiOperation({ summary: "Updates the email of a logged user" })
|
||||
@ApiBearerAuth("JWT")
|
||||
updateEmail() {}
|
||||
updateEmail(@Body() body: UpdateEmailDTO, @Request() req) {
|
||||
return this.userService.updateEmail(req.user as User, body.email);
|
||||
}
|
||||
|
||||
@Patch("/password")
|
||||
@ApiOperation({ summary: "Updates the password of a logged user" })
|
||||
@ApiBearerAuth("JWT")
|
||||
updatePassword() {}
|
||||
updatePassword(
|
||||
@Body() { old_password, new_password }: UpdatePasswordDTO,
|
||||
@Request() req,
|
||||
) {
|
||||
return this.userService.updatePassword(
|
||||
req.user as User,
|
||||
old_password,
|
||||
new_password,
|
||||
);
|
||||
}
|
||||
|
||||
@Patch("/image")
|
||||
@ApiOperation({ summary: "Add a profile image" })
|
||||
|
|
|
@ -101,6 +101,35 @@ export class UserService {
|
|||
return user;
|
||||
}
|
||||
|
||||
async updateEmail(
|
||||
loggedUser: User,
|
||||
email: string,
|
||||
): Promise<{ message: string }> {
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: { id: loggedUser.id },
|
||||
});
|
||||
|
||||
if (email !== undefined && email.trim() !== user.email) {
|
||||
const isAlreadyInUse = await this.prisma.user.findFirst({
|
||||
where: { email },
|
||||
});
|
||||
if (isAlreadyInUse != null && isAlreadyInUse.email !== user.email) {
|
||||
throw new BadRequestException("Email already in use");
|
||||
}
|
||||
|
||||
await this.prisma.user.update({
|
||||
where: {
|
||||
id: loggedUser.id,
|
||||
},
|
||||
data: {
|
||||
email: email ?? user.email,
|
||||
},
|
||||
});
|
||||
|
||||
return { message: "Email updated successfully" };
|
||||
}
|
||||
}
|
||||
|
||||
async updateName(
|
||||
loggedUser: User,
|
||||
username: string | undefined,
|
||||
|
@ -133,4 +162,36 @@ export class UserService {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
async updatePassword(
|
||||
loggedUser: User,
|
||||
old_password: string,
|
||||
new_password: string,
|
||||
): Promise<{ message: string }> {
|
||||
const id = loggedUser.id;
|
||||
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
const validatePassword = await bcrypt.compare(old_password, user.password);
|
||||
|
||||
if (!validatePassword) {
|
||||
throw new BadRequestException("Wrong password");
|
||||
}
|
||||
|
||||
const salt = await bcrypt.genSalt(15);
|
||||
const hash = await bcrypt.hash(new_password, salt);
|
||||
|
||||
await this.prisma.user.update({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
data: {
|
||||
password: hash,
|
||||
},
|
||||
});
|
||||
|
||||
return { message: "Password updated successfully" };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue