From f932e028e83de90fbc32944b1e3ce251d65cab2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Sun, 26 Nov 2023 17:03:47 +0100 Subject: [PATCH] chore(tests): UT for SessionUtil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- .../web/Controllers/Login/IndexController.php | 6 +- .../Controllers/Login/LogoutController.php | 2 +- lib/SP/Core/Context/ContextBase.php | 6 +- lib/SP/Core/Context/SessionContext.php | 150 ++++-------------- lib/SP/Core/Context/SessionUtil.php | 56 +++++++ lib/SP/Core/HttpModuleBase.php | 22 +-- lib/SP/Core/ProvidersHelper.php | 46 ++---- .../Core/Context/SessionContextInterface.php | 8 +- .../SP/Core/Context/SessionUtilTest.php | 31 ++-- 9 files changed, 133 insertions(+), 194 deletions(-) create mode 100644 lib/SP/Core/Context/SessionUtil.php rename lib/SP/Core/SessionUtil.php => tests/SP/Core/Context/SessionUtilTest.php (62%) diff --git a/app/modules/web/Controllers/Login/IndexController.php b/app/modules/web/Controllers/Login/IndexController.php index 866256f8..42970765 100644 --- a/app/modules/web/Controllers/Login/IndexController.php +++ b/app/modules/web/Controllers/Login/IndexController.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -24,7 +24,7 @@ namespace SP\Modules\Web\Controllers\Login; -use SP\Core\SessionUtil; +use SP\Core\Context\SessionUtil; use SP\Modules\Web\Controllers\ControllerBase; final class IndexController extends ControllerBase @@ -44,4 +44,4 @@ final class IndexController extends ControllerBase $this->view(); } -} \ No newline at end of file +} diff --git a/app/modules/web/Controllers/Login/LogoutController.php b/app/modules/web/Controllers/Login/LogoutController.php index df31f96d..9a202678 100644 --- a/app/modules/web/Controllers/Login/LogoutController.php +++ b/app/modules/web/Controllers/Login/LogoutController.php @@ -25,9 +25,9 @@ namespace SP\Modules\Web\Controllers\Login; use SP\Core\Context\ContextBase; +use SP\Core\Context\SessionUtil; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; -use SP\Core\SessionUtil; use SP\Modules\Web\Controllers\ControllerBase; /** diff --git a/lib/SP/Core/Context/ContextBase.php b/lib/SP/Core/Context/ContextBase.php index ad41dfa7..e32052bf 100644 --- a/lib/SP/Core/Context/ContextBase.php +++ b/lib/SP/Core/Context/ContextBase.php @@ -127,7 +127,7 @@ abstract class ContextBase implements ContextInterface * * @throws ContextException */ - protected function getContextKey(string $key, $default = null) + protected function getContextKey(string $key, mixed $default = null) { $this->checkContext(); @@ -150,8 +150,8 @@ abstract class ContextBase implements ContextInterface /** * Establecer una variable de contexto * - * @param string $key El nombre de la variable - * @param mixed $value El valor de la variable + * @param string $key El nombre de la variable + * @param mixed $value El valor de la variable * * @throws ContextException */ diff --git a/lib/SP/Core/Context/SessionContext.php b/lib/SP/Core/Context/SessionContext.php index ecae244c..889c412d 100644 --- a/lib/SP/Core/Context/SessionContext.php +++ b/lib/SP/Core/Context/SessionContext.php @@ -31,6 +31,8 @@ use SP\Domain\Core\Context\SessionContextInterface; use SP\Domain\Core\Crypt\VaultInterface; use SP\Domain\User\Services\UserLoginResponse; +use function SP\__u; +use function SP\getLastCaller; use function SP\logger; use function SP\processException; @@ -72,8 +74,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve el tema visual utilizado en sysPass - * - * @return string */ public function getTheme(): string { @@ -81,14 +81,9 @@ class SessionContext extends ContextBase implements SessionContextInterface } /** - * Devolver una variable de sesión - * - * @param string $key - * @param mixed $default - * - * @return mixed + * Return a context variable's value */ - protected function getContextKey(string $key, $default = null) + protected function getContextKey(string $key, mixed $default = null): mixed { try { return parent::getContextKey($key, $default); @@ -101,27 +96,24 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece el tema visual utilizado en sysPass - * - * @param $theme string El tema visual a utilizar */ - public function setTheme(string $theme) + public function setTheme(string $theme): void { $this->setContextKey('theme', $theme); } /** - * Establecer una variable de sesión + * Set a context variable and its value * - * @param string $key El nombre de la variable - * @param mixed $value El valor de la variable - * - * @return mixed + * @template T + * @param T $value + * @return T|null */ protected function setContextKey(string $key, mixed $value): mixed { try { if (self::$isLocked) { - logger('Session locked; key='.$key); + logger('Session locked; key=' . $key); } else { parent::setContextKey($key, $value); } @@ -136,8 +128,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer la hora de carga de la configuración - * - * @param int $time */ public function setConfigTime(int $time): void { @@ -146,8 +136,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devolver la hora de carga de la configuración - * - * @return int */ public function getConfigTime(): int { @@ -156,18 +144,14 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece los datos del usuario en la sesión. - * - * @param UserLoginResponse|null $userLoginResponse */ - public function setUserData(UserLoginResponse $userLoginResponse = null): void + public function setUserData(?UserLoginResponse $userLoginResponse = null): void { $this->setContextKey('userData', $userLoginResponse); } /** * Obtiene el objeto de perfil de usuario de la sesión. - * - * @return ProfileData|null */ public function getUserProfile(): ?ProfileData { @@ -176,39 +160,29 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece el objeto de perfil de usuario en la sesión. - * - * @param ProfileData $ProfileData */ - public function setUserProfile(ProfileData $ProfileData): void + public function setUserProfile(ProfileData $profileData): void { - $this->setContextKey('userProfile', $ProfileData); + $this->setContextKey('userProfile', $profileData); } - /** - * @return AccountSearchFilter|null - */ public function getSearchFilters(): ?AccountSearchFilter { return $this->getContextKey('searchFilters'); } - /** - * @param AccountSearchFilter $searchFilters - */ public function setSearchFilters(AccountSearchFilter $searchFilters): void { $this->setContextKey('searchFilters', $searchFilters); } - public function resetAccountAcl() + public function resetAccountAcl(): void { $this->setContextKey('accountAcl', null); } /** - * Returns if user is logged in - * - * @return bool + * Returns whether the user is logged in */ public function isLoggedIn(): bool { @@ -218,8 +192,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve los datos del usuario en la sesión. - * - * @return UserLoginResponse */ public function getUserData(): UserLoginResponse { @@ -228,26 +200,22 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer si el usuario está completamente autorizado - * - * @param $bool */ - public function setAuthCompleted($bool): void + public function setAuthCompleted(bool $bool): void { - $this->setContextKey('authCompleted', (bool)$bool); + $this->setContextKey('authCompleted', $bool); } /** * Devolver si el usuario está completamente logeado */ - public function getAuthCompleted() + public function getAuthCompleted(): bool { - return $this->getContextKey('authCompleted', false); + return (bool)$this->getContextKey('authCompleted', false); } /** * Devolver la clave maestra temporal - * - * @return ?string */ public function getTemporaryMasterPass(): ?string { @@ -256,8 +224,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Sets a temporary master password - * - * @param string $password */ public function setTemporaryMasterPass(string $password): void { @@ -266,8 +232,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devolver la clave pública - * - * @return string|null */ public function getPublicKey(): ?string { @@ -276,18 +240,14 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer la clave pública - * - * @param $key */ - public function setPublicKey($key): void + public function setPublicKey(string $key): void { $this->setContextKey('pubkey', $key); } /** * Devuelve el timeout de la sesión - * - * @return int|null El valor en segundos */ public function getSessionTimeout(): ?int { @@ -296,10 +256,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer el timeout de la sesión - * - * @param int $timeout El valor en segundos - * - * @return int */ public function setSessionTimeout(int $timeout): int { @@ -310,8 +266,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve la hora de la última actividad - * - * @return int */ public function getLastActivity(): int { @@ -320,8 +274,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece la hora de la última actividad - * - * @param $time int La marca de hora */ public function setLastActivity(int $time): void { @@ -330,8 +282,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve la hora de inicio de actividad. - * - * @return int */ public function getStartActivity(): int { @@ -348,8 +298,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve el lenguaje de la sesión - * - * @return string|null */ public function getLocale(): ?string { @@ -358,18 +306,14 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devolver el color asociado a una cuenta - * - * @return string */ - public function getAccountColor() + public function getAccountColor(): string { return $this->getContextKey('accountcolor'); } /** * Establece el color asociado a una cuenta - * - * @param array $color */ public function setAccountColor(array $color): void { @@ -386,8 +330,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer el estado de la aplicación - * - * @param string $status */ public function setAppStatus(string $status): void { @@ -396,8 +338,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Return the CSRF key - * - * @return string|null */ public function getCSRF(): ?string { @@ -406,8 +346,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Set the CSRF key - * - * @param string $csrf */ public function setCSRF(string $csrf): void { @@ -416,8 +354,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Reset del estado de la aplicación - * - * @return bool|null */ public function resetAppStatus(): ?bool { @@ -426,8 +362,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve la clave maestra encriptada - * - * @return VaultInterface|null */ public function getVault(): ?VaultInterface { @@ -436,8 +370,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establecer la clave maestra encriptada - * - * @param VaultInterface $vault */ public function setVault(VaultInterface $vault): void { @@ -446,8 +378,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece la cache de cuentas - * - * @param array $accountsCache */ public function setAccountsCache(array $accountsCache): void { @@ -471,8 +401,8 @@ class SessionContext extends ContextBase implements SessionContextInterface { // Si la sesión no puede ser iniciada, devolver un error 500 if (headers_sent($filename, $line) - || @session_start() === false) { - + || @session_start() === false + ) { logger(sprintf('Headers sent in %s:%d file', $filename, $line)); throw new ContextException(__u('Session cannot be initialized')); @@ -488,8 +418,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Devuelve la hora en la que el SID de sesión fue creado - * - * @return int */ public function getSidStartTime(): int { @@ -498,10 +426,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece la hora de creación del SID - * - * @param $time int La marca de hora - * - * @return int */ public function setSidStartTime(int $time): int { @@ -512,10 +436,6 @@ class SessionContext extends ContextBase implements SessionContextInterface /** * Establece la hora de inicio de actividad - * - * @param $time int La marca de hora - * - * @return int */ public function setStartActivity(int $time): int { @@ -524,38 +444,22 @@ class SessionContext extends ContextBase implements SessionContextInterface return $time; } - /** - * @param string $pluginName - * @param string $key - * @param mixed $value - * - * @return mixed - */ - public function setPluginKey(string $pluginName, string $key, mixed $value) + public function setPluginKey(string $pluginName, string $key, mixed $value): mixed { /** @var ContextCollection $ctxKey */ $ctxKey = $this->getContextKey($pluginName, new ContextCollection()); + $ctxKey->set($key, $value); - $this->setContextKey($pluginName, $ctxKey->set($key, $value)); + $this->setContextKey($pluginName, $value); return $value; } - /** - * @param string $pluginName - * @param string $key - * - * @return mixed - */ public function getPluginKey(string $pluginName, string $key): mixed { /** @var ContextCollection $ctxKey */ $ctxKey = $this->getContextKey($pluginName); - if ($ctxKey !== null) { - return $ctxKey->get($key); - } - - return null; + return $ctxKey?->get($key); } } diff --git a/lib/SP/Core/Context/SessionUtil.php b/lib/SP/Core/Context/SessionUtil.php new file mode 100644 index 00000000..f25940e6 --- /dev/null +++ b/lib/SP/Core/Context/SessionUtil.php @@ -0,0 +1,56 @@ +. + */ + +namespace SP\Core\Context; + +/** + * Class SessionUtil + */ +final class SessionUtil +{ + /** + * Limpiar la sesión del usuario + */ + public static function cleanSession(): void + { + session_start(); + + $_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(); + } +} diff --git a/lib/SP/Core/HttpModuleBase.php b/lib/SP/Core/HttpModuleBase.php index 815ce4d4..eb9a0319 100644 --- a/lib/SP/Core/HttpModuleBase.php +++ b/lib/SP/Core/HttpModuleBase.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -24,9 +24,9 @@ namespace SP\Core; +use JsonException; use Klein\Klein; use SP\Core\Bootstrap\BootstrapBase; -use SP\Http\Request; use SP\Http\RequestInterface; use SP\Util\Util; @@ -35,18 +35,12 @@ use SP\Util\Util; */ abstract class HttpModuleBase extends ModuleBase { - protected Request $request; - protected Klein $router; - public function __construct( - Application $application, - ProvidersHelper $providersHelper, - RequestInterface $request, - Klein $router + Application $application, + ProvidersHelper $providersHelper, + protected readonly RequestInterface $request, + protected readonly Klein $router ) { - $this->request = $request; - $this->router = $router; - parent::__construct($application, $providersHelper); } @@ -54,7 +48,7 @@ abstract class HttpModuleBase extends ModuleBase * Comprobar si el modo mantenimiento está activado * Esta función comprueba si el modo mantenimiento está activado. * - * @throws \JsonException + * @throws JsonException */ protected function checkMaintenanceMode(): bool { @@ -70,4 +64,4 @@ abstract class HttpModuleBase extends ModuleBase return false; } -} \ No newline at end of file +} diff --git a/lib/SP/Core/ProvidersHelper.php b/lib/SP/Core/ProvidersHelper.php index b27b06f6..158a085d 100644 --- a/lib/SP/Core/ProvidersHelper.php +++ b/lib/SP/Core/ProvidersHelper.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -39,37 +39,16 @@ use SP\Providers\ProviderInterface; */ final class ProvidersHelper { - private FileLogHandler $fileLogHandler; - private ?DatabaseLogHandler $databaseLogHandler; - private ?MailHandler $mailHandler; - private ?SyslogHandler $syslogHandler; - private ?RemoteSyslogHandler $remoteSyslogHandler; - private ?AclHandler $aclHandler; - private ?NotificationHandler $notificationHandler; public function __construct( - FileLogHandler $fileLogHandler, - ?DatabaseLogHandler $databaseLogHandler = null, - ?MailHandler $mailHandler = null, - ?SyslogHandler $syslogHandler = null, - ?RemoteSyslogHandler $remoteSyslogHandler = null, - ?AclHandler $aclHandler = null, - ?NotificationHandler $notificationHandler = null + private readonly FileLogHandler $fileLogHandler, + private readonly ?DatabaseLogHandler $databaseLogHandler = null, + private readonly ?MailHandler $mailHandler = null, + private readonly ?SyslogHandler $syslogHandler = null, + private readonly ?RemoteSyslogHandler $remoteSyslogHandler = null, + private readonly ?AclHandler $aclHandler = null, + private readonly ?NotificationHandler $notificationHandler = null ) { - $this->fileLogHandler = $fileLogHandler; - $this->databaseLogHandler = $databaseLogHandler; - $this->mailHandler = $mailHandler; - $this->syslogHandler = $syslogHandler; - $this->remoteSyslogHandler = $remoteSyslogHandler; - $this->aclHandler = $aclHandler; - $this->notificationHandler = $notificationHandler; - } - - private static function ensureIsInitialized(?ProviderInterface $provider = null): void - { - if ($provider !== null && !$provider->isInitialized()) { - $provider->initialize(); - } } public function getFileLogHandler(): FileLogHandler @@ -79,6 +58,13 @@ final class ProvidersHelper return $this->fileLogHandler; } + private static function ensureIsInitialized(?ProviderInterface $provider = null): void + { + if ($provider !== null && !$provider->isInitialized()) { + $provider->initialize(); + } + } + public function getDatabaseLogHandler(): DatabaseLogHandler { self::ensureIsInitialized($this->databaseLogHandler); @@ -120,4 +106,4 @@ final class ProvidersHelper return $this->notificationHandler; } -} \ No newline at end of file +} diff --git a/lib/SP/Domain/Core/Context/SessionContextInterface.php b/lib/SP/Domain/Core/Context/SessionContextInterface.php index a9e4ea9c..a83fa99b 100644 --- a/lib/SP/Domain/Core/Context/SessionContextInterface.php +++ b/lib/SP/Domain/Core/Context/SessionContextInterface.php @@ -60,10 +60,8 @@ interface SessionContextInterface extends ContextInterface /** * Establecer si el usuario está completamente autorizado - * - * @param $bool */ - public function setAuthCompleted($bool): void; + public function setAuthCompleted(bool $bool): void; /** * Devolver si el usuario está completamente logeado @@ -86,10 +84,8 @@ interface SessionContextInterface extends ContextInterface /** * Establecer la clave pública - * - * @param $key */ - public function setPublicKey($key): void; + public function setPublicKey(string $key): void; /** * Devuelve el timeout de la sesión diff --git a/lib/SP/Core/SessionUtil.php b/tests/SP/Core/Context/SessionUtilTest.php similarity index 62% rename from lib/SP/Core/SessionUtil.php rename to tests/SP/Core/Context/SessionUtilTest.php index 17c9e147..536e9e90 100644 --- a/lib/SP/Core/SessionUtil.php +++ b/tests/SP/Core/Context/SessionUtilTest.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -22,24 +22,27 @@ * along with sysPass. If not, see . */ -namespace SP\Core; +namespace SP\Tests\Core\Context; -defined('APP_ROOT') || die(); +use SP\Core\Context\SessionUtil; +use SP\Tests\UnitaryTestCase; /** - * Class SessionUtil para las utilidades de la sesión + * Class SessionUtilTest * - * @package SP + * @group unitary */ -final class SessionUtil +class SessionUtilTest extends UnitaryTestCase { - /** - * Limpiar la sesión del usuario - */ - public static function cleanSession(): void + + public function testCleanSession() { - foreach ($_SESSION as $key => $value) { - unset($_SESSION[$key]); - } + session_start(); + + $_SESSION['test'] = self::$faker->colorName; + + SessionUtil::cleanSession(); + + $this->assertArrayNotHasKey('test', $_SESSION); } -} \ No newline at end of file +}