Files
api_directorio/src/auth/auth.service.ts
T
2024-08-18 23:03:28 -06:00

193 lines
5.1 KiB
TypeScript

import {
HttpException,
Inject,
Injectable,
Logger,
UnauthorizedException,
} from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '@nestjs/jwt';
import { registerDto } from './dto/registerDto.dto';
import { User } from 'src/users/entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { hash } from 'bcrypt';
import { compare } from 'bcryptjs';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
private configService: ConfigService,
@InjectRepository(User) private userRepository: Repository<User>,
) {}
//register users
async register(data: registerDto) {
const { usuario, contraseña } = data;
if (await this.usersService.findOne(usuario)) {
throw new HttpException('User already exist', 403);
}
const hashedpassword = await hash(contraseña, 10);
data = { ...data, contraseña: hashedpassword };
return this.userRepository.save(this.userRepository.create(data));
}
//singin
async signIn(data: registerDto, rememberMe: boolean) {
const { usuario, contraseña } = data;
const user = await this.usersService.findOne(usuario);
if (!user) {
throw new UnauthorizedException('Invalid name');
}
const checkPassword = await compare(contraseña, user.contraseña);
if (!checkPassword) {
throw new UnauthorizedException('Invalid password');
}
const payload = {
id_usuario: user.id_usuario,
usuario: user.usuario,
id_tipo_usuario: user.id_tipo_usuario,
};
const token = this.jwtService.sign(payload, {
expiresIn: rememberMe ? '31d' : '7h',
});
const expirationTime = rememberMe ? 31 * 24 * 3600 * 1000 : 7 * 3600 * 1000;
await this.usersService.updateTokenAndDates(
user.id_usuario,
token,
new Date(),
new Date(Date.now() + expirationTime),
);
return { token };
}
//update user
async update(
id_usuario: number,
data: registerDto,
token: string,
): Promise<any> {
const { contraseña, id_tipo_usuario } = data;
const tokenUserId = this.getTokenUserId(token);
if (tokenUserId == id_usuario && id_tipo_usuario !== undefined) {
Logger.debug('Cannot modify id_tipo_usuario')
delete data.id_tipo_usuario;
}
const user = await this.userRepository.findOne({ where: { id_usuario } });
if (!user) {
throw new HttpException('User not found', 404);
}
if (contraseña) {
const hashedpassword = await hash(contraseña, 10);
data = { ...data, contraseña: hashedpassword };
} else {
data = { ...data, contraseña: user.contraseña };
}
return await this.userRepository.update(id_usuario, data);
}
async remove(id_usuario: number): Promise<void> {
await this.userRepository.delete(id_usuario);
}
//validate tojen of users
async validateToken(token: string): Promise<User> {
try {
const decoded = this.jwtService.verify(token, {
secret: this.configService.get<string>('JWT_SECRET'),
});
//verify JWT's username with DB's username
const user = await this.usersService.findOne(decoded.username);
if (!user) {
throw new UnauthorizedException('Invalid token');
}
//verify JWT hasn't expired
const currentTime = Math.floor(Date.now() / 1000);
if (decoded.exp < currentTime) {
throw new UnauthorizedException('Token has expired');
}
return;
} catch (error) {
throw new UnauthorizedException('validation token failed');
}
}
async findAll(): Promise<User[]> {
return this.userRepository.find();
}
async findAllPaginated(
page: number,
limit: number,
filters: any,
): Promise<{ usuarios: User[]; total: number; totalPages: number }> {
const query = this.userRepository.createQueryBuilder('usuario');
if (filters.nombre) {
Logger.debug('fiter by name user');
query.andWhere('usuario.nombre LIKE :nombre', {
nombre: `%${filters.nombre}%`,
});
}
if (filters.id_tipo_usuario) {
Logger.debug('fiter by id user');
query.andWhere('usuario.id_tipo_usuario = :id_tipo_usuario', {
id_tipo_usuario: filters.id_tipo_usuario,
});
}
const [usuarios, total] = await query
.skip((page - 1) * limit)
.take(limit)
.orderBy('usuario.nombre', 'ASC')
.getManyAndCount();
const totalPages = Math.ceil(total / limit);
return { usuarios, total, totalPages };
}
async profile(id_usuario: number) {
const user = await this.userRepository.findOne({
where: { id_usuario },
});
if (!user) {
Logger.debug('user not found');
throw new HttpException('user not found', 404);
}
return user;
}
getTokenUserId(token: string): number {
try {
const decoded = this.jwtService.verify(token);
return decoded['id_usuario'];
} catch (error) {
throw new UnauthorizedException('Invalid token');
}
}
}