resources/views/pages/frontend/docs/roles-permisos.md
Última modificación: 24 Oct, 2026

RBAC Aditivo & Capacidades de Negocio

El modelo de autorización de Mañuti implementa un Control de Acceso Basado en Roles (RBAC) evolucionado hacia la arquitectura de Capacidades Atómicas (Capability-Based Security). A diferencia de esquemas rudimentarios que enlazan usuarios directamente a métodos de controlador o endpoints HTTP, Mañuti desacopla las intenciones del usuario de la infraestructura de enrutamiento.

1. Topología Relacional de Control de Acceso

La persistencia del subsistema de seguridad se fundamenta en cuatro tablas relacionales normalizadas en MariaDB/MySQL bajo Tercera Forma Normal (3NF), garantizando integridad referencial estricta y eliminación en cascada de privilegios huérfanos.

flowchart LR
    U["usuarios"]
    RU["role_user"]
    R["roles"]
    PR["permission_role"]
    P["permissions"]

    U <-->|"1"| RU
    RU <-->|"N"| R
    
    R <--> PR
    PR <--> P

Diccionario de Datos del Modelo RBAC

Entidad roles

  • id (BIGINT UNSIGNED, PK, Auto-increment): Identificador único del perfil.
  • name (VARCHAR(255), Unique, Not Null): Identificador legible (e.g., Super Admin, Auditor de Seguridad, Oficial de Cumplimiento).
  • description (VARCHAR(255), Nullable): Alcance funcional del rol.
  • created_at / updated_at / deleted_at: Marcas de auditoría temporal con soporte nativo para Soft Deletes.

Entidad permissions

Representa una capacidad indivisible del dominio de negocio.

  • id (BIGINT UNSIGNED, PK, Auto-increment): Identificador de la capacidad.
  • slug (VARCHAR(255), Unique, Not Null): Clave unívoca indexada para evaluación programática (e.g., users.create, legal.publish, audit.search). Admite la convención estricta con puntos regex:/^[a-zA-Z0-9\.\-_]+$/.
  • name (VARCHAR(255), Not Null): Etiqueta descriptiva para renderizado en matrices administrativas.
  • description (VARCHAR(255), Nullable): Detalle técnico de la operación permitida.
  • module (VARCHAR(255), Index, Not Null): Agrupador taxonómico para interfaces de usuario (e.g., Usuarios, Auditoría, Legal y Compliance).
  • auditable (TINYINT(1), Default 0): Bandera booleana que instruye al Middleware de Auditoría si la ejecución de esta capacidad debe persistirse en MongoDB.

Tablas Pivote Intermedias

  • role_user: Materializa la relación Muchos a Muchos entre usuarios y roles. Posee restricción compuesta UNIQUE('usuario_id', 'role_id').
  • permission_role: Asigna capacidades atómicas a los perfiles funcionales. Posee restricción compuesta UNIQUE('role_id', 'permission_id').

2. Paradigma de Permisos Aditivos

Mañuti descarta la asignación restrictiva de un único rol por usuario. Mediante la relación belongsToMany en App\Models\Usuario, los privilegios operan bajo el principio de Unión de Conjuntos:

$$\text{Capacidades Totales} = \bigcup_{i=1}^{n} \text{Permisos}(\text{Rol}_i)$$

Si el Usuario $U$ posee los roles $\text{Rol}_A$ (sin permiso de exportación) y $\text{Rol}_B$ (con permiso audit.export), el sistema concede el acceso de forma aditiva. Esto erradica la proliferación de roles híbridos artificiales en la organización.


3. Integración con el Kernel de Laravel: Gates & Traversal

La intercepción de seguridad se centraliza en el AppServiceProvider utilizando el gancho global Gate::before, eliminando consultas redundantes tipo $N+1$ mediante eager loading.

// app/Providers/AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Gate::before(function ($user, string $ability) {
            if (method_exists($user, 'hasPermission')) {
                return $user->hasPermission($ability) ?: null;
            }
        });
    }
}

En el modelo App\Models\Usuario, la resolución de capacidades recorre la jerarquía en memoria:

public function hasPermission(string $permissionSlug): bool
{
    return $this->roles()
        ->with('permissions')
        ->get()
        ->pluck('permissions')
        ->flatten()
        ->contains('slug', $permissionSlug);
}

4. Implementación en Capas (Defensa en Profundidad)

Capa de Enrutamiento (routes/web.php y routes/api.php)

Las peticiones HTTP no autenticadas o no autorizadas son abortadas antes de instanciar controladores, invocando el alias can:

Route::middleware(['auth', 'can:users.view'])->group(function () {
    Route::get('/usuarios', [UserController::class, 'index'])->name('admin.users.index');
});

Capa de Presentación (Blade UI Adaptativa)

La interfaz oculta condicionalmente nodos del DOM. Los elementos no concedidos no se imprimen en el HTML, evitando vectores de inspección:

@can('users.create')
    <button class="btn btn-primary" onclick="openCreateModal()">Nuevo Usuario</button>
@endcan

@canany(['roles.view', 'permissions.view', 'users.view'])
    {{-- Renderizado del nodo agrupador Sistema en el Sidebar --}}
    <x-backend.sidebar-accordion title="Sistema" icon="ki-setting-2" />
@endcanany

Enlaces Relacionados

Edita este documento en >> roles-permisos.md
← Volver a la Landing Page