Verificar Permisos
Como el sistema verifica si un usuario puede realizar una accion.
Flujo de Verificacion
Request → Respuesta
Usuario hace request (ej: POST /api/events)
-
AUTENTICACION - ¿Usuario logueado?
- NO → 401 Unauthorized
- SI → Continua
-
OBTENER PERMISOS - Buscar en cache (Redis)
- Cache hit → Usa cache
- Cache miss → Busca en DB
-
VERIFICAR PERMISO - ¿Tiene "events.manage"?
- NO → 403 Forbidden
- SI → Continua
-
EJECUTAR ACCION - Procesa el request y retorna resultado
Algoritmo de Verificacion
Pseudocodigo
function hasPermission(userId, permissionKey):
// 1. Admins tienen todo
if user.role === "admin":
return true
// 2. Buscar ACL Object
object = findAclObject(permissionKey)
if not object:
return false
// 3. Verificar rol permitido
if user.role not in object.allowedRoles:
return false
// 4. Buscar permiso asignado
permission = findAclPermission(userId, object.id)
if not permission:
return false
// 5. Retornar valor de allowed
return permission.allowed
Casos Especiales
ADMIN:
- Siempre retorna true
- No necesita buscar en DB
ROL NO PERMITIDO:
- Si el rol del usuario no esta en allowedRoles
- Retorna false sin buscar permission
SIN PERMISO ASIGNADO:
- Si no existe registro en acl_permission
- Retorna false (deny by default)
PERMISO EXPLICITAMENTE DENEGADO:
- Si existe permission pero allowed = false
- Retorna false
Cache de Permisos
Como Funciona
El sistema cachea permisos en Redis:
- Primera consulta: Busca en DB, guarda en Redis
- Siguientes consultas: Lee de Redis (rapido)
- Al modificar permiso: Invalida cache
- TTL expira (5 min): Proxima consulta recarga de DB
Estructura del Cache
Key: acl:permissions:{userId}
Valor (JSON):
{
"process.read": true,
"process.manage": true,
"events.read": true,
"events.manage": false,
"users.read": true,
"users.manage": false
}
TTL: 300 segundos (5 minutos)
Invalidacion
El cache se invalida cuando:
- Se asigna/quita permiso - DELETE acl:permissions:{userId}
- Se cambia rol del usuario - DELETE acl:permissions:{userId}
- Usuario cierra sesion - DELETE acl:permissions:{userId}
- Manualmente (admin) - POST /api/acl/invalidate-cache
Verificacion en Backend
Middleware
En las rutas, se usa middleware:
// Ruta protegida
router.post("/events",
authMiddleware, // Verifica autenticacion
checkPermission("events.manage"), // Verifica permiso
EventController.create // Ejecuta accion
);
Si checkPermission falla: Retorna 403 Forbidden
Ejemplo de Codigo
// middleware/acl.ts
export const checkPermission = (permissionKey: string) => {
return async (req, res, next) => {
const hasAccess = await aclService.hasPermission(
req.user.id,
permissionKey
);
if (!hasAccess) {
return res.status(403).json({
error: "No tienes permiso para esta accion"
});
}
next();
};
};
Verificacion en Frontend
Hook de Permisos
// En React, usar hook:
const { hasPermission } = useAuth();
// Verificar antes de mostrar boton
{hasPermission('events.manage') && (
<Button onClick={createEvent}>
Crear Evento
</Button>
)}
Carga de Permisos
Al iniciar sesion:
- Usuario se autentica
- Backend retorna permisos en response
- Frontend guarda en contexto
- Componentes usan hasPermission()
Actualizacion:
- Cada 5 minutos (polling)
- Al recibir notificacion de cambio
- Al refrescar pagina
Errores de Permiso
401 Unauthorized
Codigo: 401
Mensaje: "No autenticado"
Causa:
- No hay sesion activa
- Token expirado
- Cookie invalida
Solucion: Iniciar sesion nuevamente
403 Forbidden
Codigo: 403
Mensaje: "No tienes permiso para esta accion"
Causa:
- Usuario no tiene el permiso requerido
- Rol no compatible con la accion
- Permiso explicitamente denegado
Solucion:
- Solicitar el permiso a un admin
- O usar cuenta con permisos adecuados
UI sin Permiso
En la interfaz, elementos sin permiso:
- Opcion 1: No se muestran - El boton/menu no aparece
- Opcion 2: Deshabilitados - El boton aparece pero gris/inactivo
- Opcion 3: Mensaje al intentar - Modal: "No tienes permiso..."
Debugging de Permisos
Verificar Permisos de Usuario
Como admin:
- Menu: Administracion → Usuarios
- Buscar usuario
- Click [...] → Ver permisos
- Ver lista de permisos activos
O via API: GET /api/users/{userId}/permissions
Log de Verificacion
En desarrollo, habilitar logs:
[ACL] Checking: events.manage for user 456
[ACL] Cache: HIT
[ACL] Result: allowed = true
Comprobar Manualmente
Como admin, simular usuario:
- Menu: Administracion → Usuarios
- Buscar usuario
- Click [...] → Simular
- Navega como ese usuario
- Verifica que ve/no ve
Nota: Solo para debugging, no produccion.
Permisos Implicitos
Dependencias
Algunos permisos implican otros:
- process.manage implica process.read - Si puedes gestionar, puedes ver (pero NO al reves)
- events.manage implica events.read
- users.manage implica users.read
- ...
El sistema puede verificar automaticamente.
Cascada
Ejemplo:
Si usuario tiene: process.manage Y intenta: process.read
Verificacion:
- ¿Tiene process.read? → NO (no asignado)
- ¿Tiene process.manage? → SI
- process.manage implica process.read
- Resultado: PERMITIDO
Performance
Optimizaciones
El sistema optimiza verificaciones:
- Cache en Redis - Evita queries repetidas
- Carga en lote - Carga todos los permisos de usuario de una vez
- Verificacion local - Frontend verifica localmente cuando posible
- Prefetch - Carga permisos al iniciar sesion
Metricas
Tiempos tipicos:
| Escenario | Tiempo |
|---|---|
| Cache hit | < 1ms |
| Cache miss | 10-50ms |
| Sin cache | 50-100ms |
El 95% de verificaciones son cache hits.
Permisos
Para ver informacion de permisos: acl.read
Para modificar permisos: acl.manage
Proximos Pasos
- Asignar Permisos - Dar acceso a usuarios
- ACL Objects - Ver permisos disponibles
- Introduccion - Conceptos basicos