From 37eef6a705ac4181794e0c85972137d6d8c83e59 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 30 Jun 2026 18:42:33 -0500 Subject: [PATCH] fix: persist admin sessions in DB so deploys don't log out users Store PHP sessions in the `sessions` MySQL table (30-day TTL) instead of server files, which disappear on container restart / redeploy. Cookie lifetime also extended to 30 days. Co-Authored-By: Claude Sonnet 4.6 --- middleware/DbSessionHandler.php | 38 +++++++++++++++++++++++++++++++++ middleware/SessionAuth.php | 5 ++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 middleware/DbSessionHandler.php diff --git a/middleware/DbSessionHandler.php b/middleware/DbSessionHandler.php new file mode 100644 index 0000000..08d028e --- /dev/null +++ b/middleware/DbSessionHandler.php @@ -0,0 +1,38 @@ +prepare("SELECT data FROM sessions WHERE id = ? AND updated_at > DATE_SUB(NOW(), INTERVAL " . self::TTL . " SECOND)"); + $stmt->execute([$id]); + $row = $stmt->fetch(); + return $row ? $row['data'] : ''; + } + + public function write(string $id, string $data): bool + { + db()->prepare("INSERT INTO sessions (id, data) VALUES (?, ?) ON DUPLICATE KEY UPDATE data = VALUES(data), updated_at = NOW()") + ->execute([$id, $data]); + return true; + } + + public function destroy(string $id): bool + { + db()->prepare("DELETE FROM sessions WHERE id = ?")->execute([$id]); + return true; + } + + public function gc(int $max_lifetime): int|false + { + $stmt = db()->prepare("DELETE FROM sessions WHERE updated_at < DATE_SUB(NOW(), INTERVAL ? SECOND)"); + $stmt->execute([self::TTL]); + return $stmt->rowCount(); + } +} diff --git a/middleware/SessionAuth.php b/middleware/SessionAuth.php index bc0d036..1c591bc 100644 --- a/middleware/SessionAuth.php +++ b/middleware/SessionAuth.php @@ -1,13 +1,16 @@ 0, + 'lifetime' => 86400 * 30, // 30 days — survives deploys 'path' => '/', 'secure' => isset($_SERVER['HTTPS']), 'httponly' => true,