Check editor accounts.

A new editor needs a username and a password of at least 12 characters. A persistent login needs an unexpired key and an existing account. Removing an account revokes its persistent logins, and its sessions end.
This commit is contained in:
tim
2026-09-26 15:27:51 +02:00
parent 5d657d7e45
commit 3df88e0b4c
10 changed files with 217 additions and 16 deletions
+49 -2
View File
@@ -127,6 +127,7 @@ class SessionTest extends TestCase {
}
public function testCheckPersistentLoginLogsInAndSwapsTheKey(): void {
SiteData::$tables['editors'][] = array('username' => 'ed', 'password' => '', 'email' => '');
session_start();
$before = session_id();
SiteData::$tables['persistent_sessions'][] = array('username' => 'ed', 'session' => persistent_key_hash('key'), 'created' => gmdate('Y-m-d H:i:s'));
@@ -139,6 +140,52 @@ class SessionTest extends TestCase {
$this->assertNotSame(persistent_key_hash('key'), $rows[0]['session'], 'the used key is gone');
}
public function testCheckPersistentLoginRefusesAnExpiredKey(): void {
SiteData::$tables['editors'][] = array('username' => 'ed', 'password' => '', 'email' => '');
SiteData::$tables['persistent_sessions'][] = array('username' => 'ed', 'session' => persistent_key_hash('key'),
'created' => gmdate('Y-m-d H:i:s', strtotime('-1 year -1 day')));
$_COOKIE['PersistentAuth'] = 'ed|key';
$this->assertFalse(check_persistent_login());
$this->assertArrayNotHasKey('editor', $_SESSION ?? array());
$this->assertSame(array(), SiteData::$tables['persistent_sessions']);
}
public function testCheckPersistentLoginRefusesAKeyWithoutAnAccount(): void {
SiteData::$tables['persistent_sessions'][] = array('username' => 'ed', 'session' => persistent_key_hash('key'), 'created' => gmdate('Y-m-d H:i:s'));
$_COOKIE['PersistentAuth'] = 'ed|key';
$this->assertFalse(check_persistent_login());
$this->assertSame(array(), SiteData::$tables['persistent_sessions']);
}
public function testEditorExists(): void {
SiteData::$tables['editors'][] = array('username' => 'ed', 'password' => '', 'email' => '');
$this->assertTrue(editor_exists('ed'));
$this->assertFalse(editor_exists('ann'));
$this->assertFalse(editor_exists(''));
$this->assertFalse(editor_exists(array('ed')));
$this->assertNull($GLOBALS['db'], 'the connection is closed again');
}
public function testRemoveEditorRevokesItsPersistentLogins(): void {
SiteData::$tables['editors'] = array(array('username' => 'ed', 'password' => '', 'email' => ''),
array('username' => 'ann', 'password' => '', 'email' => ''));
SiteData::$tables['persistent_sessions'] = array(
array('username' => 'ed', 'session' => persistent_key_hash('one'), 'created' => gmdate('Y-m-d H:i:s')),
array('username' => 'ed', 'session' => persistent_key_hash('two'), 'created' => gmdate('Y-m-d H:i:s')),
array('username' => 'ann', 'session' => persistent_key_hash('three'), 'created' => gmdate('Y-m-d H:i:s')));
remove_editor('ed');
$this->assertSame(array('ann'), array_column(SiteData::$tables['editors'], 'username'));
$this->assertSame(array('ann'), array_column(SiteData::$tables['persistent_sessions'], 'username'));
}
public function testARemovedEditorIsLoggedOutOverHttps(): void {
$code = 'Xxx\Tests\Support\SiteData::install(); $_SERVER["HTTPS"] = "on"; session_id("abc123"); session_start(); $_SESSION["editor"] = "ed"; session_write_close();'
. ' $_COOKIE[session_name()] = "abc123"; include XXX_ROOT . "/session.lib.php";'
. ' echo json_encode(array($is_admin, $_SESSION["editor"] ?? NULL));';
$result = PhpProcess::runBare($code, array(), array('session.save_path' => $this->tmp, 'session.use_cookies' => '0', 'session.cache_limiter' => ''));
$this->assertSame('[false,null]', $result['stdout'], $result['stderr']);
}
public function testDeletePersistentLoginRemovesThisKeyAndOldKeys(): void {
SiteData::$tables['persistent_sessions'] = array(
array('username' => 'ed', 'session' => persistent_key_hash('mine'), 'created' => gmdate('Y-m-d H:i:s')),
@@ -160,7 +207,7 @@ class SessionTest extends TestCase {
// The top of session.lib.php runs on every page; it needs HTTPS and a session
public function testSessionStartsOnlyOverHttps(): void {
$code = '$_SERVER["HTTPS"] = %s; session_id("abc123"); session_start(); $_SESSION["editor"] = "ed"; session_write_close();'
$code = 'Xxx\Tests\Support\SiteData::install(array("editors" => array(array("username" => "ed")))); $_SERVER["HTTPS"] = %s; session_id("abc123"); session_start(); $_SESSION["editor"] = "ed"; session_write_close();'
. ' $_COOKIE[session_name()] = "abc123"; include XXX_ROOT . "/session.lib.php";'
. ' echo json_encode(array($is_admin, $username ?? NULL, session_status() === PHP_SESSION_ACTIVE));';
$ini = array('session.save_path' => $this->tmp, 'session.use_cookies' => '0', 'session.cache_limiter' => '');
@@ -176,7 +223,7 @@ class SessionTest extends TestCase {
public function testPersistentCookieLogsInOverHttps(): void {
$store = $this->tmp . '/tables.json';
file_put_contents($store, json_encode(array('persistent_sessions' => array(
file_put_contents($store, json_encode(array('editors' => array(array('username' => 'ed')), 'persistent_sessions' => array(
array('username' => 'ed', 'session' => persistent_key_hash('key'), 'created' => gmdate('Y-m-d H:i:s'))))));
$code = 'Xxx\Tests\Support\SiteData::install(json_decode(file_get_contents(' . var_export($store, TRUE) . '), TRUE));'
. ' $_SERVER["HTTPS"] = "on"; $_COOKIE["PersistentAuth"] = "ed|key"; include XXX_ROOT . "/session.lib.php";'