This commit is contained in:
Lizandro Guarnizo
2026-04-16 23:07:53 -05:00
parent aa12a87fbb
commit 0164c51c1a
10 changed files with 236 additions and 41 deletions
+61 -10
View File
@@ -20,16 +20,17 @@ class ModuleRegistry
private static ?array $registry = null;
/** Orden de visualización de categorías en el sidebar */
private const CATEGORY_ORDER = ['bot', 'lab', 'turnero', 'clinico', 'reportes', 'sistema'];
private const CATEGORY_ORDER = ['bot', 'lab', 'formularios', 'turnero', 'clinico', 'reportes', 'sistema'];
/** Etiquetas e íconos de cada categoría */
private const CATEGORIES = [
'bot' => ['label' => 'WhatsApp', 'icon' => 'fab fa-whatsapp'],
'lab' => ['label' => 'Laboratorio', 'icon' => 'fas fa-flask'],
'turnero' => ['label' => 'Turnero', 'icon' => 'fas fa-ticket-alt'],
'clinico' => ['label' => 'Clínico', 'icon' => 'fas fa-vials'],
'reportes'=> ['label' => 'Reportes', 'icon' => 'fas fa-chart-bar'],
'sistema' => ['label' => 'Sistema', 'icon' => 'fas fa-cog'],
'bot' => ['label' => 'WhatsApp', 'icon' => 'fab fa-whatsapp'],
'lab' => ['label' => 'Domicilios', 'icon' => 'fas fa-house-medical'],
'formularios'=> ['label' => 'Formulario', 'icon' => 'fas fa-file-invoice'],
'turnero' => ['label' => 'Turnero', 'icon' => 'fas fa-ticket-alt'],
'clinico' => ['label' => 'Clínico', 'icon' => 'fas fa-vials'],
'reportes' => ['label' => 'Reportes', 'icon' => 'fas fa-chart-bar'],
'sistema' => ['label' => 'Sistema', 'icon' => 'fas fa-cog'],
];
// ─── API pública ────────────────────────────────────────────────────────
@@ -47,20 +48,26 @@ class ModuleRegistry
/**
* Retorna solo los módulos ACTIVOS que el usuario actual puede ver.
* Si el usuario es admin sin role_id → todos los activos.
*
* IMPORTANTE: consulta role_modules desde BD en tiempo real para que los
* cambios hechos en lab_usuarios.php se reflejen sin necesidad de re-login.
*
* Excepción: superadmin y admin sin role_id tienen acceso total (retrocompat).
*
* @return array<string, array> Indexado por slug.
*/
public static function forCurrentUser(): array
{
self::load();
$allowed = self::liveUserModules(); // null = acceso total
$result = [];
foreach (self::$registry as $slug => $mod) {
if (!$mod['is_active']) {
continue;
}
// hasModule() definida en config.php / core/Rbac.php (retrocompat)
if (function_exists('hasModule') && !hasModule($slug)) {
// null = superadmin / admin legacy → ve todo
if ($allowed !== null && !in_array($slug, $allowed, true)) {
continue;
}
$result[$slug] = $mod;
@@ -68,6 +75,50 @@ class ModuleRegistry
return $result;
}
/**
* Obtiene los slugs de módulos permitidos para el usuario actual consultando
* role_modules en BD (ignora la caché de sesión para ser siempre fresco).
*
* Retorna null si el usuario tiene acceso total (superadmin / admin legacy).
*
* @return string[]|null
*/
private static function liveUserModules(): ?array
{
$role = $_SESSION['admin_user']['role'] ?? 'admin';
$roleId = $_SESSION['admin_user']['role_id'] ?? null;
// Superadmin → acceso total siempre
if ($role === 'superadmin') {
return null;
}
// Admin sin role_id asignado → retrocompat, acceso total
if ($role === 'admin' && !$roleId) {
return null;
}
// Sin role_id en cualquier otro rol → usar sesión como fallback
if (!$roleId) {
return $_SESSION['admin_user']['modules'] ?? [];
}
// Consulta en tiempo real: reflejan cambios en lab_usuarios.php al instante
try {
$db = Database::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare(
"SELECT module_slug FROM role_modules WHERE role_id = ?"
);
$stmt->execute([(int) $roleId]);
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'module_slug');
} catch (Exception $e) {
error_log("ModuleRegistry::liveUserModules error: " . $e->getMessage());
// Fallback a sesión si la BD no responde
return $_SESSION['admin_user']['modules'] ?? [];
}
}
/**
* Retorna módulos activos agrupados por categoría para el sidebar.
* Solo incluye módulos accesibles por el usuario actual.