' . htmlspecialchars(($translations['access_denied'] ?? 'Доступ запрещён.'), ENT_QUOTES, 'UTF-8') . '
'; exit; } // 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; } // CSRF if (! isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } $CSRF = $_SESSION['csrf_token']; function e($s) {return htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8');} // Helpers DB : test existence de la table de log function tableExists(PDO $pdo, string $table): bool { $sql = "SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? LIMIT 1"; $st = $pdo->prepare($sql); $st->execute([$table]); return (bool) $st->fetchColumn(); } // ------------ Traitement POST ------------ $flash = null; if (($_POST['do'] ?? '') === 'impersonate') { try { if (! hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf'] ?? '')) { throw new Exception('CSRF'); } $email = trim((string) ($_POST['email'] ?? '')); if ($email === '') { throw new Exception('NO_EMAIL'); } // On cherche dans la table compte (à adapter si le nom diffère) $sql = "SELECT id, email, role, reference_id FROM compte WHERE email = ? LIMIT 1"; $st = $pdo->prepare($sql); $st->execute([$email]); $user = $st->fetch(PDO::FETCH_ASSOC); if (! $user) { throw new Exception('NOT_FOUND'); } $role = (string) ($user['role'] ?? ''); // On autorise seulement certains rôles à être "impersonnés" $allowedRoles = ['praticien', 'client']; if (! in_array($role, $allowedRoles, true)) { throw new Exception('ROLE_FORBIDDEN'); } // Sauvegarder l’admin actuel si ce n’est pas déjà fait if (empty($_SESSION['admin_impersonate']) || ! is_array($_SESSION['admin_impersonate'])) { $_SESSION['admin_impersonate'] = [ 'admin_compte_id' => $_SESSION['compte_id'] ?? null, 'admin_reference_id' => $_SESSION['reference_id'] ?? null, 'admin_role' => $_SESSION['role'] ?? null, 'started_at' => time(), ]; } // Log de l’action si la table existe if (tableExists($pdo, 'admin_impersonation_log')) { $ip = $_SERVER['REMOTE_ADDR'] ?? null; $ua = $_SERVER['HTTP_USER_AGENT'] ?? null; $adminUid = (int) ($_SESSION['compte_id'] ?? 0); $adminRef = (int) ($_SESSION['reference_id'] ?? 0); $targetUid = (int) ($user['id'] ?? 0); $targetRef = (int) ($user['reference_id'] ?? 0); $emailLog = (string) ($user['email'] ?? ''); $logSql = "INSERT INTO admin_impersonation_log (admin_user_id, admin_reference_id, target_user_id, target_reference_id, target_role, email, ip, user_agent) VALUES (?,?,?,?,?,?,?,?)"; $pdo->prepare($logSql)->execute([ $adminUid, $adminRef, $targetUid, $targetRef, $role, $emailLog, $ip, $ua, ]); } // Basculer la session sur l’utilisateur cible session_regenerate_id(true); unset( $_SESSION['client_id'], $_SESSION['praticien_id'], $_SESSION['secretaire_id'], $_SESSION['admin_id'], $_SESSION['compte_id'], $_SESSION['reference_id'], $_SESSION['role'] ); $_SESSION['compte_id'] = (int) $user['id']; $_SESSION['role'] = $role; $_SESSION['reference_id'] = (int) ($user['reference_id'] ?? 0); $_SESSION['last_activity'] = time(); if ($role === 'praticien') { $_SESSION['praticien_id'] = (int) $user['reference_id']; } elseif ($role === 'client') { $_SESSION['client_id'] = (int) $user['reference_id']; } // Redirection selon le rôle if ($role === 'praticien') { header('Location: /public/praticien/agenda.php'); } elseif ($role === 'client') { header('Location: /public/client/mes_rendez_vous.php'); } else { // fallback header('Location: /'); } exit; } catch (Throwable $e) { $code = $e->getMessage(); $msg = ($translations['admin_impersonate_err_default'] ?? 'Ошибка при подключении.'); if ($code === 'CSRF') { $msg = ($translations['admin_impersonate_err_csrf'] ?? 'Ошибка безопасности. Обновите страницу.'); } if ($code === 'NO_EMAIL') { $msg = ($translations['admin_impersonate_err_no_email'] ?? 'Укажите e-mail практикующего или клиента.'); } if ($code === 'NOT_FOUND') { $msg = ($translations['admin_impersonate_err_not_found'] ?? 'Пользователь с таким e-mail не найден.'); } if ($code === 'ROLE_FORBIDDEN') { $msg = ($translations['admin_impersonate_err_role_forbidden'] ?? 'Невозможно подключиться под этим типом пользователя.'); } $flash = ['type' => 'danger', 'msg' => $msg]; } } // Indicateur si on est déjà en mode impersonation (admin_impersonate présent) $isImpersonating = ! empty($_SESSION['admin_impersonate']) && is_array($_SESSION['admin_impersonate']); ?>