import * as bcrypt from 'bcryptjs'; import { Injectable, NotFoundException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { ConfigService } from '@nestjs/config'; import UsersService from '@v1/users/users.service'; import { RolesEnum } from '@decorators/roles.decorator'; import { DecodedUser } from './interfaces/decoded-user.interface'; import JwtTokensDto from './dto/jwt-tokens.dto'; import { ValidateUserOutput } from './interfaces/validate-user-output.interface'; import { LoginPayload } from './interfaces/login-payload.interface'; import authConstants from './auth-constants'; import AuthRepository from './auth.repository'; @Injectable() export default class AuthService { constructor( private readonly usersService: UsersService, private readonly jwtService: JwtService, private readonly authRepository: AuthRepository, private readonly configService: ConfigService, ) { } async validateUser( email: string, password: string, ): Promise { const user = await this.usersService.getVerifiedUserByEmail(email); if (!user) { throw new NotFoundException('The item does not exist'); } const passwordCompared = await bcrypt.compare(password, user.password); if (passwordCompared) { const roles = user.roles.map((role) => role.name as RolesEnum); return { id: user.id, email: user.email, roles, }; } return null; } async login(data: LoginPayload): Promise { const payload: LoginPayload = { id: data.id, email: data.email, roles: data.roles, }; const accessToken = this.jwtService.sign(payload, { expiresIn: authConstants.jwt.expirationTime.accessToken, secret: this.configService.get('ACCESS_TOKEN') || '<%= config.accessTokenSecret %>', }); const refreshToken = this.jwtService.sign(payload, { expiresIn: authConstants.jwt.expirationTime.refreshToken, secret: this.configService.get('REFRESH_TOKEN') || '<%= config.refreshTokenSecret %>', }); await this.authRepository.addRefreshToken( payload.email as string, refreshToken, ); return { accessToken, refreshToken, }; } getRefreshTokenByEmail(email: string): Promise { return this.authRepository.getToken(email); } deleteTokenByEmail(email: string): Promise { return this.authRepository.removeToken(email); } deleteAllTokens(): Promise { return this.authRepository.removeAllTokens(); } async verifyToken(token: string, secret: string): Promise { try { const user = await this.jwtService.verifyAsync(token, { secret }); return user; } catch (error) { return null; } } }