Skip to content

Commit

Permalink
Merge pull request #745 from PennyDreadfulMTG/sessions
Browse files Browse the repository at this point in the history
Better session handling, (many) fewer logouts
  • Loading branch information
bakert authored Sep 8, 2024
2 parents 58897cb + 53b5e68 commit d87748c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 13 deletions.
74 changes: 74 additions & 0 deletions gatherling/Auth/Session.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Gatherling\Auth;

use Gatherling\Data\DB;

class Session
{
private static $LIFETIME = 60 * 60 * 24 * 60;

public static function start(): void
{
session_start();
self::init();
register_shutdown_function([self::class, 'save']);
}

private static function init(): void
{
if (!empty($_SESSION)) {
return;
}
if (!isset($_COOKIE['remember_me'])) {
return;
}
$token = $_COOKIE['remember_me'];
$_SESSION = self::load($token);
}

private static function load(string $token): array
{
$sql = '
SELECT
details
FROM
sessions
WHERE
token = :token
AND
expiry >= NOW()';
$args = ['token' => $token];
$details = DB::value($sql, $args);
return $details ? json_decode($details, true) : [];
}

private static function save(): void
{
if (isset($_COOKIE['remember_me'])) {
$token = $_COOKIE['remember_me'];
} else {
$token = bin2hex(random_bytes(32));
}
// Force to object so that we get '{}' instead of '[]' when empty
$details = json_encode((object) $_SESSION);
$expiry = time() + self::$LIFETIME;
$sql = '
INSERT INTO
sessions (token, details, expiry)
VALUES
(:token, :details, FROM_UNIXTIME(:expiry))
ON DUPLICATE KEY UPDATE
details = :details,
expiry = FROM_UNIXTIME(:expiry)';
$args = [
'token' => $token,
'details' => $details,
'expiry' => $expiry,
];
DB::execute($sql, $args);
setcookie('remember_me', $token, $expiry, '/');
$sql = 'DELETE FROM sessions WHERE expiry < NOW()';
DB::execute($sql);
}
}
File renamed without changes.
6 changes: 6 additions & 0 deletions gatherling/Data/sql/migrations/55.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS sessions (
id INT AUTO_INCREMENT PRIMARY KEY,
token VARCHAR(64) UNIQUE NOT NULL,
details TEXT NOT NULL,
expiry TIMESTAMP NOT NULL
);
1 change: 0 additions & 1 deletion gatherling/admin/db-upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
function main(): void
{
Setup::setupDatabase();
Setup::setupTestDatabase();
echo 'done';
}

Expand Down
3 changes: 0 additions & 3 deletions gatherling/config.php.docker
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ $CONFIG['style'] = "ChandraNeue";
# A description for the ical calendar which is accessible at calendar.php
$CONFIG['calendar_description'] = "a description for the events calendar";

# How long to store session cookies in seconds
$CONFIG['cookie_lifetime'] = 5184000;

# API Key for Brevo email sending (password reset)
$CONFIG['brevo_api_key'] = 'xkeysib-foobar-baz';

Expand Down
3 changes: 0 additions & 3 deletions gatherling/config.php.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ $CONFIG['style'] = "ChandraNeue";
# A description for the ical calendar which is accessible at calendar.php
$CONFIG['calendar_description'] = "a description for the events calendar";

# How long to store session cookies in seconds
$CONFIG['cookie_lifetime'] = 5184000;

# API Key for Brevo email sending (password reset)
$CONFIG['brevo_api_key'] = 'xkeysib-foobar-baz';

Expand Down
8 changes: 2 additions & 6 deletions gatherling/lib.php
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
<?php

use Gatherling\Auth\Session;
use Gatherling\Models\Database;
use Gatherling\Models\Format;
use Gatherling\Models\Player;

require_once 'bootstrap.php';
ob_start();
if (isset($CONFIG['cookie_lifetime'])) {
ini_set('session.gc_maxlifetime', $CONFIG['cookie_lifetime']);
ini_set('session.cookie_lifetime', $CONFIG['cookie_lifetime']);
session_set_cookie_params($CONFIG['cookie_lifetime']);
}
header('Strict-Transport-Security: max-age=63072000; includeSubDomains; preload');
header('Referrer-Policy: strict-origin-when-cross-origin');

if (php_sapi_name() !== 'cli' && session_status() !== PHP_SESSION_ACTIVE) {
session_start();
Session::start();
}

$HC = '#DDDDDD';
Expand Down

0 comments on commit d87748c

Please sign in to comment.