import { HttpException, HttpStatus, Injectable, UnauthorizedException, BadRequestException, NotFoundException, UseGuards } from "@nestjs/common"; import { InjectModel } from "@nestjs/sequelize"; import { User } from "./entities/user.entity"; import * as bcrypt from "bcrypt"; import { JwtService } from "@nestjs/jwt"; import { ConfigService } from "@nestjs/config"; import { CreateUserDto } from "./dto/create-user.dto"; import { LoginUserDto } from "./dto/login-user.dto"; import { UpdateUserDto } from "./dto/update-user.dto"; @Injectable() export class UsersService { constructor( @InjectModel(User) private readonly userModel: typeof User, private readonly jwtService: JwtService, private readonly configService: ConfigService, ) {} // Register method async register(createUserDto: CreateUserDto): Promise<{ message }> { try { createUserDto.password = await bcrypt.hash(createUserDto.password, parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10)); const userExists = await this.userModel.findOne({ where: { email: createUserDto.email }, }); if (userExists) { throw new BadRequestException("Email is already registered."); } const user = await this.userModel.create(createUserDto); return { message: "user registered successful" }; } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR); } } // Login method async login(loginUserDto: LoginUserDto): Promise<{ token: string }> { try { const user = await this.userModel.findOne({ where: { email: loginUserDto.email }, }); if (!user) { throw new UnauthorizedException("Invalid email or password."); } const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password); if (!passwordMatch) { throw new UnauthorizedException("Invalid email or password."); } const token = this.jwtService.sign( { id: user.id, role: user.role }, { secret: this.configService.get("JWT_SECRET"), expiresIn: this.configService.get("JWT_EXPIRES") || "1h", }, ); return { token }; } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR); } } //get information user method async getProfile(userId: number): Promise { try { const user = await this.userModel.findOne({ where: { id: userId }, attributes: { exclude: ["password"] }, }); if (!user) { throw new HttpException("User not found.", HttpStatus.NOT_FOUND); } return user; } catch (error) { throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR); } } //edit profile user method async editProfile(userId: number, updateUserDto: UpdateUserDto) { try { let user = await this.userModel.findOne({ where: { id: userId } }); if (!user) { throw new NotFoundException('User not found.'); } if (updateUserDto.password) { updateUserDto.password = await bcrypt.hash(updateUserDto.password, 10); } await user.update(updateUserDto); user = await this.userModel.findOne({ where: { id: userId }, attributes: { exclude: ['password'] }, }); return { message: 'User account updated successfully.', user }; } catch (error) { throw new HttpException( 'An unexpected error occurred. Please try again later.', HttpStatus.INTERNAL_SERVER_ERROR, ); } } //get users list async findAll(): Promise { try { return await this.userModel.findAll(); } catch (error) { throw new HttpException( 'An unexpected error occurred while fetching users.', HttpStatus.INTERNAL_SERVER_ERROR, ); } } //get users list async findSpecificUserInfoByUser(userId: number): Promise { try { const user = await this.userModel.findByPk(userId); if (!user) { throw new HttpException('User not found.', HttpStatus.NOT_FOUND); } return user; } catch (error) { throw new HttpException( 'An unexpected error occurred while fetching user information.', HttpStatus.INTERNAL_SERVER_ERROR, ); } } }