→ qué ve/no ve ese usuario * acl_debug.php?usuario=&full=1 → incluye el árbol completo */ require_once 'db.php'; require_once 'ib_acl.php'; // Evitar que el CDN cachee las respuestas de diagnóstico (aprendizaje del 27-jul: // los GET de esta API se sirven cacheados y el parámetro anti-caché se pierde en // el redirect, lo que hizo concluir mal sobre un despliegue). header('Content-Type: application/json'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Expires: 0'); define('AUTH_DB_PREFIX', 'genniux_board.'); // Solo usuarios privilegiados pueden correr el diagnóstico. $PRIVILEGIADOS = array('JoseRojas', 'Alex Rojas534', 'AlexRojas534'); $usuario = ''; if (isset($_GET['usuario']) && trim($_GET['usuario']) != '') { $usuario = trim($_GET['usuario']); } // Quién PIDE el diagnóstico (por default, el mismo que se consulta). $solicitante = isset($_GET['as']) && trim($_GET['as']) != '' ? trim($_GET['as']) : $usuario; if (!in_array($solicitante, $PRIVILEGIADOS)) { http_response_code(403); echo json_encode(array('error' => 'diagnostico restringido a usuarios privilegiados')); exit; } if ($usuario === '') { echo json_encode(array('error' => 'falta ?usuario=')); exit; } $out = array('usuario' => $usuario); try { // --- 1. ¿Existe la tabla? (si no, el motor hace fail-open y no deniega nada) $chk = $pdo->query("SHOW TABLES LIKE 'folder_shares'"); $tablaExiste = ($chk && $chk->fetch()) ? true : false; $out['tabla_folder_shares_existe'] = $tablaExiste; if ($tablaExiste) { $c = $pdo->query("SELECT COUNT(*) AS n FROM folder_shares")->fetch(PDO::FETCH_ASSOC); $out['filas_en_folder_shares'] = (int)$c['n']; $rs = $pdo->query("SELECT folder_id, shared_with, permission FROM folder_shares ORDER BY folder_id"); $out['permisos_definidos'] = $rs->fetchAll(PDO::FETCH_ASSOC); } else { $out['aviso'] = 'La tabla no existe: el motor NO deniega nada (fail-open). Corre folder_shares.sql.'; } // --- 2. Empresa del usuario (el ACL solo resta sobre este scope) $st = $pdo->prepare("SELECT origen FROM " . AUTH_DB_PREFIX . "colaborador WHERE wikiname = ? LIMIT 1"); $st->execute(array($usuario)); $row = $st->fetch(PDO::FETCH_ASSOC); $out['origen_usuario'] = ($row && $row['origen'] !== null) ? (int)$row['origen'] : null; // --- 3. EL MOTOR: carpetas denegadas $t0 = microtime(true); $denied = ib_acl_denied_folders($pdo, $usuario); $out['ms_motor'] = round((microtime(true) - $t0) * 1000, 2); // --- 4. Resolver nombres y rutas para que el resultado sea legible $todas = array(); $rs = $pdo->query("SELECT id, name, parent_id, created_by FROM skill_folders"); while ($r = $rs->fetch(PDO::FETCH_ASSOC)) { $todas[$r['id']] = $r; } $out['total_carpetas'] = count($todas); function ib_dbg_ruta($id, $todas) { $segs = array(); $guard = 0; while ($id !== null && $id !== '' && isset($todas[$id]) && $guard < 200) { array_unshift($segs, $todas[$id]['name']); $id = $todas[$id]['parent_id']; $guard++; } return implode('/', $segs); } $listaDenegadas = array(); foreach ($denied as $fid => $_) { $listaDenegadas[] = array( 'folder_id' => $fid, 'ruta' => isset($todas[$fid]) ? ib_dbg_ruta($fid, $todas) : '(carpeta inexistente)', 'dueno' => isset($todas[$fid]) ? $todas[$fid]['created_by'] : null ); } $out['denegadas_total'] = count($listaDenegadas); $out['denegadas'] = $listaDenegadas; // --- 5. Cuántos skills quedarían ocultos por esas carpetas if (count($denied) > 0) { $ids = array_keys($denied); $ph = implode(',', array_fill(0, count($ids), '?')); $st = $pdo->prepare("SELECT COUNT(*) AS n FROM skills WHERE folder_id IN ($ph)"); $st->execute($ids); $n = $st->fetch(PDO::FETCH_ASSOC); $out['skills_ocultos_por_acl'] = (int)$n['n']; } else { $out['skills_ocultos_por_acl'] = 0; } // --- 6. Árbol completo (opcional) con marca de visible/denegada if (isset($_GET['full']) && $_GET['full'] == '1') { $arbol = array(); foreach ($todas as $fid => $f) { $arbol[] = array( 'folder_id' => $fid, 'ruta' => ib_dbg_ruta($fid, $todas), 'dueno' => $f['created_by'], 'acceso' => isset($denied[$fid]) ? 'DENEGADA' : 'visible' ); } $out['arbol'] = $arbol; } echo json_encode($out); } catch (Exception $e) { http_response_code(500); echo json_encode(array('error' => $e->getMessage())); } ?>