import { BadRequestException, HttpStatus, Injectable, Res, UnauthorizedException, } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcrypt'; import { AdminsService } from '../admins/services/admins.service'; import Admin from '../admins/entities/admin.entity'; import { plainToClass } from 'class-transformer'; import { Request, Response } from 'express'; import { Constant } from './ultils/constant'; import { ChangePasswordDto } from './dto/change-password.dto'; import AppResponse from '@/response/app-response'; import { GenerateKeysService } from '../admins/services/generate-key.service'; @Injectable() export class AuthService { constructor( private jwtService: JwtService, private readonly adminService: AdminsService, private readonly generateKeyService: GenerateKeysService, ) {} async validateAdmin( username: string, password: string, message = 'Username or Password is cornet', ) { const user = await this.adminService.adminRepo.findOne({ where: { username }, }); if (!user || !(await bcrypt.compare(password, user.password))) { throw new UnauthorizedException( AppResponse.toResponse(null, { message, status_code: HttpStatus.UNAUTHORIZED, }), ); } return user; } async login(user: Admin, response: Response) { const payload = { _id: user.id }; const accessToken = this.jwtService.sign(payload, { expiresIn: '15m' }); const refreshToken = this.jwtService.sign( { refresh_key: true, ...payload }, { expiresIn: '7d' }, ); response.cookie(Constant.ACCESS_TOKEN, accessToken, { httpOnly: true, maxAge: 15 * 60 * 1000, sameSite: 'lax', }); response.cookie(Constant.REFRESH_TOKEN, refreshToken, { httpOnly: true, maxAge: 7 * 24 * 60 * 60 * 1000, sameSite: 'lax', }); return AppResponse.toResponse(true, { message: 'Login Success' }); } async logout(@Res() response: Response) { response.cookie(Constant.ACCESS_TOKEN, '', { httpOnly: true, maxAge: 0, sameSite: 'lax', }); response.cookie(Constant.REFRESH_TOKEN, '', { httpOnly: true, maxAge: 0, sameSite: 'lax', }); return AppResponse.toResponse(true, { message: 'Logout Success' }); } async changePassword( data: ChangePasswordDto, request: Request, response: Response, ) { const admin = request['admin']; if (!admin) throw new UnauthorizedException(AppResponse.toResponse(false)); await this.validateAdmin( admin.username, data.password, 'Password is invalid !', ); const newPassword = await bcrypt.hash(data.newPassword, 10); const result = await this.adminService.adminRepo.update(admin.id, { password: newPassword, }); if (!result.affected) throw new BadRequestException(AppResponse.toResponse(false)); await this.logout(response); return AppResponse.toResponse(true, { message: 'Change password success. Please re-login !', }); } async me(request: Request) { const admin = request['admin']; if (!admin) throw new UnauthorizedException(AppResponse.toResponse(null)); return AppResponse.toResponse(admin); } }