diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 6026058..bc71857 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Post, Body, UseGuards, Get, Request, Put, Param } from "@nestjs/common"; +import { Controller, Post, Body, UseGuards, Get, Request, Put, Param, HttpException, HttpStatus, Delete } from "@nestjs/common"; import { UsersService } from "./users.service"; import { User } from "./entities/user.entity"; import { CreateUserDto } from "./dto/create-user.dto"; @@ -17,13 +17,15 @@ export class UsersController { } //login as user @Post("login") - async login(@Body() loginUserDto: LoginUserDto): Promise<{ accessToken; refreshToken }> { + async login(@Body() loginUserDto: LoginUserDto): Promise<{ accessToken }> { return this.usersService.login(loginUserDto); } //get access token - @Post("new-token") - async newAccessToken(@Body("refreshToken") refreshToken: string) { - return this.usersService.newAccessToken(refreshToken); + @UseGuards(JwtAuthGuard) + @Get("new-token") + async newAccessToken(@Request() req) { + const userId = req.user.id; + return this.usersService.newAccessToken(userId); } //logout user @UseGuards(JwtAuthGuard) @@ -61,8 +63,11 @@ export class UsersController { } //delete a specific user by admin @UseGuards(RoleGuard) - @Get("users/delete/:id") + @Delete(":id?") async deleteUser(@Param("id") id){ + if (!id) { + throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST); + } return this.usersService.deleteUser(id); } } diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 158b54b..7d43e3d 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -17,17 +17,42 @@ export class UsersService { ) {} // Register method - async register(createUserDto: CreateUserDto): Promise<{ message }> { + async register(createUserDto: CreateUserDto): Promise<{ message: string }> { try { createUserDto.password = await bcrypt.hash(createUserDto.password, parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10)); - const userExists = await this.userModel.findOne({ + + const emailExists = await this.userModel.findOne({ where: { email: createUserDto.email }, }); - if (userExists) { + if (emailExists) { throw new BadRequestException("Email is already registered."); } - const user = await this.userModel.create(createUserDto); - return { message: "user registered successful" }; + + const phoneExists = await this.userModel.findOne({ + where: { phoneNumber: createUserDto.phoneNumber }, + }); + if (phoneExists) { + throw new BadRequestException("Phone number is already registered."); + } + + await this.userModel.create(createUserDto); + const user = await this.userModel.findOne({ + where: { email: createUserDto.email }, + }); + const refreshToken = this.jwtService.sign( + { id: user.id }, + { + secret: this.configService.get("JWT_REFRESH_SECRET"), + expiresIn: this.configService.get("JWT_REFRESH_EXPIRES") || "7d", + }, + ); + + await this.userModel.update( + { refreshToken }, // + { where: { id: user.id } }, + ); + + return { message: "User registered successfully." }; } catch (error) { if (error instanceof HttpException) { throw error; @@ -36,7 +61,7 @@ export class UsersService { } } // Login method - async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string; refreshToken: string }> { + async login(loginUserDto: LoginUserDto): Promise<{ accessToken: string }> { try { const user = await this.userModel.findOne({ where: { email: loginUserDto.email }, @@ -72,7 +97,7 @@ export class UsersService { { where: { id: user.id } }, ); - return { accessToken: accessToken, refreshToken: refreshToken }; + return { accessToken: accessToken }; } catch (error) { if (error instanceof HttpException) { throw error; @@ -81,23 +106,21 @@ export class UsersService { } } // getting access token - async newAccessToken(refreshToken: string) { - if (!refreshToken) { - throw new HttpException({ message: "Refresh token is required." }, HttpStatus.BAD_REQUEST); + async newAccessToken(userId: number) { + const user = await this.userModel.findOne({ where: { id: userId } }); + if (!user || !user.refreshToken) { + throw new HttpException("Refresh token is required.", HttpStatus.BAD_REQUEST); } let decoded; try { - decoded = this.jwtService.verify(refreshToken, { secret: process.env.JWT_REFRESH_SECRET }); + decoded = this.jwtService.verify(user.refreshToken, { secret: process.env.JWT_REFRESH_SECRET }); } catch (error) { - throw new HttpException({ message: "Invalid or expired token." }, HttpStatus.UNAUTHORIZED); + throw new HttpException("Invalid or expired token.", HttpStatus.UNAUTHORIZED); } - const user = await this.userModel.findOne({ - where: { id: decoded.id }, - }); - if (!user) { - throw new HttpException({ message: "User not found." }, HttpStatus.NOT_FOUND); + if (user.id !== decoded.id) { + throw new HttpException("User ID mismatch.", HttpStatus.FORBIDDEN); } const accessToken = this.jwtService.sign( @@ -111,15 +134,23 @@ export class UsersService { return { accessToken }; } //logout (delete refresh token from database) - async logout(userId: number) { - const user = await this.userModel.findOne({ - where: { id: userId }, - }); - if (!user) { - throw new HttpException("User not found.", HttpStatus.NOT_FOUND); + async logout(userId: number): Promise<{ message: string }> { + if (!userId) { + throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST); + } + + try { + const user = await this.userModel.findOne({ where: { id: userId } }); + if (!user) { + throw new HttpException("User not found.", HttpStatus.NOT_FOUND); + } + + await this.userModel.update({ refreshToken: null }, { where: { id: userId } }); + + return { message: "Logout is successful." }; + } catch (error) { + throw new HttpException("An error occurred while logging out.", HttpStatus.INTERNAL_SERVER_ERROR); } - await this.userModel.update({ refreshToken: null }, { where: { id: userId } }); - return { message: "logout is successful" }; } //get information user method async getProfile(userId: number): Promise { @@ -177,16 +208,23 @@ export class UsersService { } } //delete a specific user by admin - async deleteUser(userId: number) { + async deleteUser(userId: number): Promise<{ message: string }> { const user = await this.userModel.findOne({ where: { id: userId }, }); if (!user) { - throw new HttpException("User not found.", HttpStatus.NOT_FOUND); + throw new HttpException("User not found!.", HttpStatus.NOT_FOUND); + } + try { + const deletedCount = await this.userModel.destroy({ where: { id: userId } }); + + if (deletedCount === 0) { + throw new HttpException("User not found.", HttpStatus.NOT_FOUND); + } + + return { message: "User deleted successfully." }; + } catch (error) { + throw new HttpException("An error occurred while deleting the user.", HttpStatus.INTERNAL_SERVER_ERROR); } - await this.userModel.destroy({ - where: { id: userId }, - }); - return { message: "user deleted successful" }; } }