Actualización módulo de roles e implementación de permission middleware

This commit is contained in:
2026-07-10 14:56:18 +00:00
parent 8248389269
commit 06b4ab7166
7 changed files with 146 additions and 41 deletions

View File

@ -9,8 +9,7 @@ export class AuthService {
userName:string, userName:string,
password:string password:string
){ ){
const user = const user = await userModel.findOne({
await userModel.findOne({
userName userName
}).populate("roleId"); }).populate("roleId");

View File

@ -0,0 +1,74 @@
import { Request, Response, NextFunction } from "express";
export const permissionMiddleware = (
module: string,
action: string
) => {
return (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const user = (req as any).user;
if (!user) {
return res.status(401).json({
message: "Usuario no autenticado."
});
}
if (!user.permissions) {
return res.status(403).json({
message: "El usuario no tiene permisos asignados."
});
}
const hasPermission = user.permissions.some(
(permission: any) =>
permission.module === module &&
permission.action === action
);
if (!hasPermission) {
return res.status(403).json({
message: "No tiene permisos para realizar esta acción."
});
}
next();
} catch (error) {
return res.status(500).json({
message: "Error al validar permisos.",
error
});
}
};
};

View File

@ -57,9 +57,10 @@ export class RoleController {
res.status(201).json(role); res.status(201).json(role);
} catch(error){ } catch(error:any){
res.status(500).json({ res.status(500).json({
message:"Error al crear role" message:error.message,
error
}); });
} }

View File

@ -1,29 +0,0 @@
import { Request, Response, NextFunction } from "express";
export const roleMiddleware =
(allowedRoles: string[]) => {
return (
req: any,
res: Response,
next: NextFunction
) => {
const userRole =
req.user.roleName;
if (
!allowedRoles.includes(
userRole
)
) {
return res.status(403).json({
message:
"No tiene permisos para realizar esta acción"
});
}
next();
};
};

View File

@ -5,11 +5,13 @@ const roleSchema = new mongoose.Schema({
roleName:{ roleName:{
type:String, type:String,
required:true, required:true,
unique:true unique:true,
trim:true
}, },
description:{ description:{
type:String type:String,
trim:true
}, },
active:{ active:{

View File

@ -1,19 +1,20 @@
import { Router } from "express"; import { Router } from "express";
import { RoleController } from "./role.controller"; import { RoleController } from "./role.controller";
import { authMiddleware } from "../auth/auth.middleware"; import { authMiddleware } from "../auth/auth.middleware";
import { permissionMiddleware } from "../auth/permission.middleware";
const roleRouter = Router(); const roleRouter = Router();
const controller = new RoleController(); const controller = new RoleController();
roleRouter.get("/", authMiddleware, controller.getAll); roleRouter.get("/", authMiddleware, permissionMiddleware("roles", "read"), controller.getAll);
roleRouter.get("/:id", authMiddleware, controller.getById); roleRouter.get("/:id", authMiddleware, permissionMiddleware("roles", "read"), controller.getById);
roleRouter.post("/", authMiddleware, controller.create); roleRouter.post("/", authMiddleware, permissionMiddleware("roles", "create"), controller.create);
roleRouter.put("/:id", authMiddleware, controller.update); roleRouter.put("/:id", authMiddleware, permissionMiddleware("roles", "update"), controller.update);
roleRouter.delete("/:id", authMiddleware, controller.delete); roleRouter.delete("/:id", authMiddleware, permissionMiddleware("roles", "delete"), controller.delete);
export default roleRouter; export default roleRouter ;

View File

@ -1,7 +1,10 @@
import roleModel from "./role.model"; import roleModel from "./role.model";
import userModel from "../user/user.model";
import { IRole } from "./role.interface"; import { IRole } from "./role.interface";
export class RoleService { export class RoleService {
async getAll() { async getAll() {
return await roleModel.find(); return await roleModel.find();
@ -16,6 +19,18 @@ export class RoleService {
async create( async create(
data:IRole data:IRole
) { ) {
const exists = await roleModel.findOne({
roleName:data.roleName
});
if(exists){
throw new Error("Ya existe un rol con ese nombre.");
}
return await roleModel.create(data); return await roleModel.create(data);
} }
@ -23,6 +38,23 @@ export class RoleService {
id:string, id:string,
data:Partial<IRole> data:Partial<IRole>
){ ){
if (data.roleName) {
const exists = await roleModel.findOne({
roleName: data.roleName,
_id: {
$ne: id
}
});
if (exists) {
throw new Error("Ya existe un rol con ese nombre.");
}
}
return await roleModel.findByIdAndUpdate( return await roleModel.findByIdAndUpdate(
id, id,
data, data,
@ -35,6 +67,31 @@ export class RoleService {
async delete( async delete(
id:string id:string
){ ){
// Verificar que el rol exista
const role = await roleModel.findById(id);
if (!role) {
return null;
}
// Verificar si el rol está asignado a usuarios
const usersWithRole = await userModel.countDocuments({
roleId: id
});
if (usersWithRole > 0) {
throw new Error(
"No se puede eliminar el rol porque está asignado a uno o más usuarios."
);
}
if(role.roleName === "ADMINISTRADOR"){
throw new Error(
"No se puede eliminar el rol Administrador.");
}
return await roleModel.findByIdAndDelete(id) return await roleModel.findByIdAndDelete(id)
} }
} }