diff --git a/src/Security/RememberLoginHash.php b/src/Security/RememberLoginHash.php index 1266a31b4..6733b3190 100644 --- a/src/Security/RememberLoginHash.php +++ b/src/Security/RememberLoginHash.php @@ -84,6 +84,42 @@ class RememberLoginHash extends DataObject */ private $token = null; + /** + * Used to override the config value of logout_across_devices + * Tri-state where null denotes an unset override value + * + * @internal + * @var bool|null + */ + protected static $logoutAcrossDevices = null; + + /** + * @internal + * @return bool + */ + public static function getLogoutAcrossDevices(): bool + { + if (is_bool(static::$logoutAcrossDevices)) { + return static::$logoutAcrossDevices; + } + return static::config()->get('logout_across_devices'); + } + + /** + * Override the config value of logout_across_devices for the duration of the request + * Useful if an authenticator is causing the wrong number of devices to loose their tokens + * A value of false will prevent all devices from having their token removed when a single device logs out + * A value of true will remove all devices tokens when a single device logs out + * Use this public API instead of modifying the config value directly + * + * @internal + * @param bool $value + */ + public static function setLogoutAcrossDevices(bool $value): void + { + static::$logoutAcrossDevices = $value; + } + public function getToken() { return $this->token; @@ -181,7 +217,7 @@ class RememberLoginHash extends DataObject return; } - if (static::config()->logout_across_devices) { + if (static::getLogoutAcrossDevices()) { self::get()->filter(['MemberID' => $member->ID])->removeAll(); } elseif ($alcDevice) { self::get()->filter([ diff --git a/tests/php/Security/RememberLoginHashTest.php b/tests/php/Security/RememberLoginHashTest.php index e4987c125..ec5625304 100644 --- a/tests/php/Security/RememberLoginHashTest.php +++ b/tests/php/Security/RememberLoginHashTest.php @@ -72,4 +72,18 @@ class RememberLoginHashTest extends SapphireTest ); } } + + public function testGetSetLogoutAcrossDevices() + { + // set config directly + RememberLoginHash::config()->set('logout_across_devices', true); + $this->assertTrue(RememberLoginHash::getLogoutAcrossDevices()); + RememberLoginHash::config()->set('logout_across_devices', false); + $this->assertFalse(RememberLoginHash::getLogoutAcrossDevices()); + // override using public API + RememberLoginHash::setLogoutAcrossDevices(true); + $this->assertTrue(RememberLoginHash::getLogoutAcrossDevices()); + RememberLoginHash::setLogoutAcrossDevices(false); + $this->assertFalse(RememberLoginHash::getLogoutAcrossDevices()); + } }