' . htmlspecialchars((string)($translations['audite_access_denied'] ?? 'Accès refusé.'), ENT_QUOTES, 'UTF-8') . '
'; return; } require_once __DIR__.'/_lib_audit.php'; // reauth (10 min) $mustReauth=function(int $ttl=600){$t=(int)($_SESSION['admin_reauth_at']??0);return ($t===0||(time()-$t)>$ttl);}; if ($mustReauth()){ $qs=http_build_query(['page'=>'reauth','redir'=>($_SERVER['REQUEST_URI']??'index.php?page=maintenance')]); header('Location:?'.$qs); exit; } if (!isset($pdo)) { $db = realpath(__DIR__.'/../../includes/db.php'); if ($db) require_once $db; } if (!isset($pdo) || !($pdo instanceof PDO)) { echo '
' . htmlspecialchars((string)($translations['audite_db_unavailable'] ?? 'DB indisponible.'), ENT_QUOTES, 'UTF-8') . '
'; return; } try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(Throwable) {} $e = static fn($s)=>htmlspecialchars((string)$s,ENT_QUOTES,'UTF-8'); if (empty($_SESSION['csrf_token'])) $_SESSION['csrf_token']=bin2hex(random_bytes(32)); $CSRF=$_SESSION['csrf_token']; // filtres $qAdmin = (int)($_GET['admin_id'] ?? 0); $qAct = trim($_GET['action'] ?? ''); $qFrom = trim($_GET['from'] ?? ''); $qTo = trim($_GET['to'] ?? ''); $page = max(1, (int)($_GET['p'] ?? 1)); $per = min(200, max(10,(int)($_GET['per'] ?? 50))); $w=[]; $p=[]; if ($qAdmin>0){ $w[]='admin_id=:aid'; $p[':aid']=$qAdmin; } if ($qAct!==''){ $w[]='action=:act'; $p[':act']=$qAct; } if ($qFrom!==''){ $w[]='created_at>=:f'; $p[':f']=$qFrom.' 00:00:00'; } if ($qTo!==''){ $w[]='created_at<=:t'; $p[':t']=$qTo.' 23:59:59'; } $where = $w?('WHERE '.implode(' AND ',$w)):''; $cnt = $pdo->prepare("SELECT COUNT(*) FROM admin_audit $where"); $cnt->execute($p); $total=(int)$cnt->fetchColumn(); $pages = max(1,(int)ceil($total/$per)); $off = ($page-1)*$per; $sql = "SELECT id,admin_id,action,scope,target_table,target_id,meta_json,INET6_NTOA(ip) ip,user_agent,created_at FROM admin_audit $where ORDER BY id DESC LIMIT $per OFFSET $off"; $stmt=$pdo->prepare($sql); $stmt->execute($p); $rows=$stmt->fetchAll(PDO::FETCH_ASSOC); ?>

1): ?>