CASL (Code Access Security Layer) es una librería de autorización para JavaScript que te permite definir permisos y reglas de acceso en tus aplicaciones de forma sencilla. Se utiliza comúnmente en aplicaciones Node.js para controlar qué acciones pueden realizar los usuarios en diferentes recursos, lo que es esencial para construir sistemas con múltiples niveles de roles y permisos.
Para utilizar CASL en tu proyecto, primero debes instalarlo:
npm install @casl/ability
CASL se basa en la creación de una habilidad (Ability
), que define lo que un usuario puede o no hacer. Se define una habilidad con reglas que determinan las acciones permitidas para un recurso específico.
Aquí un ejemplo básico:
const { AbilityBuilder, Ability } = require('@casl/ability');
// Definir las habilidades de un usuario
function defineAbilitiesFor(role) {
const { can, cannot, build } = new AbilityBuilder(Ability);
if (role === 'admin') {
can('manage', 'all'); // Un administrador puede gestionar todo
} else {
can('read', 'Post'); // Un usuario normal solo puede leer posts
cannot('delete', 'Post'); // Pero no puede eliminarlos
}
return build();
}
// Crear habilidades para un usuario 'admin'
const ability = defineAbilitiesFor('admin');
// Verificar permisos
console.log(ability.can('delete', 'Post')); // true
console.log(ability.can('read', 'Post')); // true
En este ejemplo, se definen las habilidades para dos roles: admin, que tiene acceso completo, y un usuario normal, que solo puede leer publicaciones pero no puede eliminarlas.
Para usar CASL en una aplicación Express y proteger rutas según los roles de los usuarios, se podría usar algo como lo siguiente:
const express = require('express');
const { AbilityBuilder, Ability } = require('@casl/ability');
const app = express();
// Definir habilidades según el rol
function defineAbilitiesFor(role) {
const { can, build } = new AbilityBuilder(Ability);
if (role === 'admin') {
can('manage', 'all'); // Admin puede hacer todo
} else {
can('read', 'Post'); // Usuarios pueden leer posts
}
return build();
}
// Middleware de autorización
function checkAbility(action, subject) {
return (req, res, next) => {
const role = req.user.role; // Supongamos que el rol está en req.user
const ability = defineAbilitiesFor(role);
if (ability.can(action, subject)) {
return next(); // Permitir acceso
}
return res.status(403).json({ message: 'Acceso denegado' });
};
}
// Ruta protegida
app.get('/posts', checkAbility('read', 'Post'), (req, res) => {
res.send('Lista de publicaciones');
});
app.listen(3000, () => {
console.log('Servidor ejecutándose en http://localhost:3000');
});
CASL también permite definir permisos basados en condiciones, como permitir que un usuario edite solo sus propios recursos:
const { AbilityBuilder, Ability } = require('@casl/ability');
function defineAbilitiesFor(user) {
const { can, build } = new AbilityBuilder(Ability);
if (user.role === 'admin') {
can('manage', 'all');
} else {
can('read', 'Post');
can('update', 'Post', { authorId: user.id }); // Puede actualizar solo sus posts
}
return build();
}
const ability = defineAbilitiesFor({ role: 'user', id: 1 });
console.log(ability.can('update', 'Post', { authorId: 1 })); // true
console.log(ability.can('update', 'Post', { authorId: 2 })); // false
En este ejemplo, el usuario solo puede actualizar publicaciones donde el authorId
coincide con su propio id
.
CASL no solo se limita al backend. Puedes utilizar CASL también en el frontend para gestionar la visibilidad de botones o acciones basadas en los permisos del usuario:
import { Ability } from '@casl/ability';
const ability = new Ability([
{ action: 'read', subject: 'Post' },
{ action: 'delete', subject: 'Post', conditions: { authorId: 1 } }
]);
if (ability.can('delete', 'Post', { authorId: 1 })) {
// Mostrar botón de eliminar
}
Para obtener más información y detalles avanzados sobre el uso de CASL, puedes consultar la documentación oficial de CASL.
Jorge García
Fullstack developer