196 lines
4.4 KiB
TypeScript
196 lines
4.4 KiB
TypeScript
import bcrypt from "bcrypt";
|
|
import jwt from "jsonwebtoken";
|
|
import userModel from "../user/user.model";
|
|
import auditLogModel from "../auditLogs/auditLog.model";
|
|
|
|
import { IChangePassword } from "./changePassword.interface";
|
|
|
|
import { RolePermissionService } from '../role-permissions/rolePermission.service';
|
|
|
|
const service = new RolePermissionService();
|
|
|
|
export class AuthService {
|
|
|
|
async login (
|
|
userName:string,
|
|
password:string
|
|
){
|
|
const user =
|
|
await userModel.findOne({
|
|
userName
|
|
}).populate("roleId");
|
|
|
|
//Validador de usuario existente
|
|
if (!user) {
|
|
throw new Error("Usuario no encontrado");
|
|
}
|
|
|
|
//Validar si el usuario está activo
|
|
if(!user.active){
|
|
throw new Error("Usuario inactivo")
|
|
}
|
|
|
|
//Validar contraseña
|
|
const validPassword =await bcrypt.compare(
|
|
password,
|
|
user.passwordHash
|
|
);
|
|
|
|
if (!validPassword){
|
|
throw new Error("Contraseña incorrecta");
|
|
}
|
|
|
|
user.lastLogin = new Date();
|
|
await user.save();
|
|
|
|
//Registrar login en auditoría
|
|
|
|
await auditLogModel.create({
|
|
userId: user._id,
|
|
module:"Authentication",
|
|
action:"LOGIN",
|
|
description:"El usuario inició sesión.",
|
|
status:"EXITOSO"
|
|
|
|
});
|
|
|
|
const role = user.roleId as any;
|
|
|
|
const rolePermissions = await service.getByRole(
|
|
role._id.toString()
|
|
);
|
|
|
|
const permissions = rolePermissions ?
|
|
(rolePermissions.permissions as any []).map(
|
|
permission => ({
|
|
name:permission.name,
|
|
module:permission.module,
|
|
action:permission.action
|
|
})
|
|
)
|
|
:[]
|
|
|
|
const token = jwt.sign(
|
|
{
|
|
|
|
id:user._id,
|
|
roleId: role._id,
|
|
roleName: role.roleName,
|
|
permissions
|
|
},
|
|
|
|
process.env.JWT_SECRET as string,
|
|
{
|
|
expiresIn:"8h"
|
|
}
|
|
);
|
|
|
|
return {
|
|
token,
|
|
user:{
|
|
id: user._id,
|
|
|
|
employeeId:user.employeeId,
|
|
|
|
userName:user.userName,
|
|
|
|
roleId: role._id,
|
|
|
|
roleName: role.roleName,
|
|
|
|
permissions,
|
|
|
|
active: user.active
|
|
}
|
|
};
|
|
}
|
|
|
|
async logout (
|
|
userId:string
|
|
){
|
|
|
|
if(!userId){
|
|
|
|
throw new Error("Usuario no autenticado.");
|
|
|
|
}
|
|
await auditLogModel.create({
|
|
userId,
|
|
module:"Authentication",
|
|
action:"LOGOUT",
|
|
description:"El usuario cerró sesión.",
|
|
status:"EXITOSO"
|
|
});
|
|
|
|
return{
|
|
message:"Sesión cerrada exitosamente"
|
|
};
|
|
}
|
|
|
|
async changePassword(
|
|
userId: string,
|
|
data: IChangePassword
|
|
) {
|
|
|
|
// Buscar usuario
|
|
const user = await userModel.findById(userId);
|
|
|
|
if (!user) {
|
|
throw new Error("Usuario no encontrado.");
|
|
}
|
|
|
|
// Validar contraseña actual
|
|
const validPassword = await bcrypt.compare(
|
|
data.currentPassword,
|
|
user.passwordHash
|
|
);
|
|
|
|
if (!validPassword) {
|
|
throw new Error("La contraseña actual es incorrecta.");
|
|
}
|
|
|
|
// Validar que la nueva contraseña sea diferente
|
|
if (data.currentPassword === data.newPassword) {
|
|
throw new Error(
|
|
"La nueva contraseña debe ser diferente a la actual."
|
|
);
|
|
}
|
|
|
|
// Validar longitud mínima
|
|
if (data.newPassword.length < 8) {
|
|
throw new Error(
|
|
"La nueva contraseña debe tener al menos 8 caracteres."
|
|
);
|
|
}
|
|
|
|
// Encriptar nueva contraseña
|
|
user.passwordHash = await bcrypt.hash(
|
|
data.newPassword,
|
|
10
|
|
);
|
|
|
|
await user.save();
|
|
|
|
// Registrar en auditoría
|
|
await auditLogModel.create({
|
|
|
|
userId: user._id,
|
|
|
|
module: "Authentication",
|
|
|
|
action: "CHANGE_PASSWORD",
|
|
|
|
description: "El usuario cambió su contraseña.",
|
|
|
|
status: "EXITOSO"
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
message: "Contraseña actualizada correctamente."
|
|
|
|
};
|
|
|
|
}
|
|
} |