--- name: Sistema de Permissões (RBAC) — Direção description: RBAC dentro do tipo "direção" — superuser + permissões por módulo. Aplicado no menu lateral e via AuthFilter modulo=X. type: project originSessionId: 86576285-fa7a-44f0-8ed3-9a88bcd27a8e --- ## Sistema de Permissões (RBAC) — implementado 2026-05-05 ### Esquema de banco - **`usuarios.is_superuser`** TINYINT(1) DEFAULT 0 — superuser tem acesso a tudo - **`usuario_permissoes`**: id, usuario_id (FK→usuarios CASCADE), modulo VARCHAR(50), created_at — UNIQUE(usuario_id, modulo) - **Usuário ID 1 (Agnaldo) marcado como superuser** automaticamente na migration ### Código - **`PermissaoModel`** (`app/Models/PermissaoModel.php`): - `static $MODULOS` — lista de 15 módulos: dashboard, alunos, professores, matriculas, cursos, salas, reservas, agenda, monitoramento, financeiro, atendimento, analytics, feriados, configuracoes, usuarios - `getModulosUsuario($id)` — lista módulos do usuário - `setPermissoes($id, [modulos])` — substitui (sync) - **`static pode($modulo)`** — método central. Lê de `session('permissoes_cache')`, fallback no banco se sessão não tem `is_superuser` (suporta usuários logados antes da migration) - `static limparCacheSessao()` — chama após editar permissões do user logado - **`Auth.php`** seta `is_superuser` + `permissoes_cache=null` na sessão no login - **`AuthFilter`** aceita argumento `modulo=alunos` além dos tipos. Bloqueia se `tipo_usuario=direcao` e não tem permissão. Não-direção (aluno/professor) passa direto (escopo natural). - **`UsuarioDirecaoController`** — CRUD acessível só por superuser. Rotas: `/direcao/usuarios-direcao` (UI), `/direcao/api/usuarios-direcao` GET/POST/DELETE. - **`direcao/usuarios_direcao.php`** — UI grid de cards (1/2/3 colunas), 4 KPIs, tags de módulos por usuário. - **Menu lateral** (`layouts/main.php`) — cada `` envolvido em ``. Item "Usuários" ⭐ só pra superuser. Aba "Configurações" do acordeão também check. ### Como adicionar restrição de rota nova Em `app/Config/Routes.php`: ```php $routes->get('financeiro', 'FinanceiroController::index', ['filter' => 'auth:direcao,modulo=financeiro']); ``` **Não migrei todas as rotas** ainda — só o menu. Pra blindar acesso direto via URL, precisa adicionar `modulo=X` em cada rota crítica. ### Pitfalls - **Usuário logado antes da migration** não tinha `is_superuser` na sessão → menu sumia. Resolvido com fallback do banco no `PermissaoModel::pode()`. - Bloqueio de auto-rebaixamento: usuário não pode tirar superuser de si mesmo nem se excluir. **Why:** secretária/financeiro/coordenadores precisam de visões parciais — não podem ver tudo que o admin vê. **How to apply:** ao criar nova feature direção, adicionar nome em `PermissaoModel::$MODULOS`, envolver item de menu com `if ($podeVer('chave'))`, e proteger rotas críticas com filtro `auth:direcao,modulo=chave`.