193 lines
5.1 KiB
TypeScript
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');
|
|
}
|
|
}
|
|
}
|