86400 * 7, // 7 days 'path' => '/', 'secure' => request_is_https(), 'httponly' => true, 'samesite' => 'Lax' ]); session_start(); } require_once __DIR__ . '/db.php'; function is_authenticated(): bool { return !empty($_SESSION['admin_user_id']); } function require_auth(): void { if (!is_authenticated()) { header('Location: login.php'); exit; } // A user disabled or re-roled mid-session should be affected // immediately rather than when their session expires — re-check against // the DB instead of trusting the session's now-possibly-stale copy. $pdo = get_db(); $stmt = $pdo->prepare("SELECT is_enabled, role FROM users WHERE id = ?"); $stmt->execute([$_SESSION['admin_user_id']]); $row = $stmt->fetch(); if ($row === false || (int) $row['is_enabled'] !== 1) { logout_user(); header('Location: login.php'); exit; } $_SESSION['admin_role'] = $row['role']; } /** * Like require_auth(), but also requires a specific role. Checked against * the role require_auth() just re-read from the DB, not the login-time copy. */ function require_role(string $role): void { require_auth(); if (($_SESSION['admin_role'] ?? '') !== $role) { http_response_code(403); exit('Forbidden'); } } function get_logged_in_user(): ?array { if (!is_authenticated()) { return null; } return [ 'id' => $_SESSION['admin_user_id'], 'username' => $_SESSION['admin_username'] ?? 'admin', 'role' => $_SESSION['admin_role'] ?? 'admin' ]; } function authenticate_user(string $username, string $password): bool { $pdo = get_db(); $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([trim($username)]); $user = $stmt->fetch(); if ($user && (int) $user['is_enabled'] === 1 && password_verify($password, $user['password_hash'])) { session_regenerate_id(true); $_SESSION['admin_user_id'] = $user['id']; $_SESSION['admin_username'] = $user['username']; $_SESSION['admin_role'] = $user['role']; return true; } return false; } function logout_user(): void { $_SESSION = []; if (ini_get("session.use_cookies")) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] ); } session_destroy(); } function get_csrf_token(): string { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } function verify_csrf_token(?string $token): bool { if (empty($_SESSION['csrf_token']) || empty($token)) { return false; } return hash_equals($_SESSION['csrf_token'], $token); }