fase 2.1: roles editables (modelo skeen.role) y permisos por accion (43 claves, 9 grupos) con enforcement en backend y gating en frontend; editor de roles/permisos/menus en Configuracion

This commit is contained in:
2026-10-11 07:32:29 +00:00
parent 75736967ef
commit 28a690aa0f
24 changed files with 1637 additions and 157 deletions

View File

@@ -43,17 +43,24 @@ const SUBCATALOGOS = [
const LEGACY_STORAGE_KEY = 'skeen_clinic_settings';
const Configuracion: FC = () => {
const { user, brand, setBrand } = useAuth();
const { user, brand, setBrand, can } = useAuth();
// Gerencia gestiona catálogos, usuarios y roles; la sección "Clínica" (datos
// de contacto, tipo de cambio y comisiones) queda para administración del sistema.
const esAdmin = user?.role === 'admin';
// Cada pestaña requiere su permiso por acción (Configuración › Roles › Permisos).
const TABS_PERM: Record<string, string> = {
usuarios: 'config.usuarios',
roles: 'config.roles',
auditoria: 'config.auditoria',
};
const tabsVisibles = useMemo(
() => (esAdmin ? TABS : TABS.filter((t) => TABS_GERENCIA.includes(t.key))),
[esAdmin],
() => (esAdmin ? TABS : TABS.filter((t) => TABS_GERENCIA.includes(t.key)))
.filter((t) => can(TABS_PERM[t.key] || 'config.editar')),
[esAdmin, can],
);
const [searchParams, setSearchParams] = useSearchParams();
const tabPedida = searchParams.get('tab') || 'clinica';
const tab = tabsVisibles.some((t) => t.key === tabPedida) ? tabPedida : tabsVisibles[0].key;
const tab = tabsVisibles.some((t) => t.key === tabPedida) ? tabPedida : (tabsVisibles[0]?.key || 'clinica');
const setTab = (t: string) => setSearchParams({ tab: t });
const [subcatalogo, setSubcatalogo] = useState<string>(() => {
const sub = searchParams.get('sub');
@@ -284,7 +291,13 @@ const Configuracion: FC = () => {
))}
</div>
{tab === 'usuarios' ? (
{tabsVisibles.length === 0 ? (
<Card>
<Card.Body>
<p className="text-sm text-theme-muted">No tienes permiso para ninguna sección de Configuración.</p>
</Card.Body>
</Card>
) : tab === 'usuarios' ? (
<Card>
<Card.Body>
<UsuariosPanel />