feat: added update email and password routes

This commit is contained in:
Hackntosh 2024-01-26 18:30:34 +00:00
parent e6718ca54f
commit 8af84b7cfa
4 changed files with 124 additions and 3 deletions

View 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) {}

View 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) {}

View file

@ -23,6 +23,8 @@ import { CreateUserDTO } from "./dto/create-user.dto";
import { Public } from "src/public.decorator"; import { Public } from "src/public.decorator";
import { UpdateNameDTO } from "./dto/update-name.dto"; import { UpdateNameDTO } from "./dto/update-name.dto";
import { User } from "./types/user.type"; import { User } from "./types/user.type";
import { UpdateEmailDTO } from "./dto/update-email.dto";
import { UpdatePasswordDTO } from "./dto/update-password.dto";
@ApiTags("Users") @ApiTags("Users")
@Controller("users") @Controller("users")
@ -49,7 +51,7 @@ export class UserController {
description: "Not authenticated / Invalid JWT Token", description: "Not authenticated / Invalid JWT Token",
}) })
me(@Request() req) { me(@Request() req) {
return req.user; // TODO: Add typing to req.user return req.user;
} }
@Public() @Public()
@ -74,12 +76,23 @@ export class UserController {
@Patch("/email") @Patch("/email")
@ApiOperation({ summary: "Updates the email of a logged user" }) @ApiOperation({ summary: "Updates the email of a logged user" })
@ApiBearerAuth("JWT") @ApiBearerAuth("JWT")
updateEmail() {} updateEmail(@Body() body: UpdateEmailDTO, @Request() req) {
return this.userService.updateEmail(req.user as User, body.email);
}
@Patch("/password") @Patch("/password")
@ApiOperation({ summary: "Updates the password of a logged user" }) @ApiOperation({ summary: "Updates the password of a logged user" })
@ApiBearerAuth("JWT") @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") @Patch("/image")
@ApiOperation({ summary: "Add a profile image" }) @ApiOperation({ summary: "Add a profile image" })

View file

@ -101,6 +101,35 @@ export class UserService {
return user; 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( async updateName(
loggedUser: User, loggedUser: User,
username: string | undefined, 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" };
}
} }