diff --git a/app/modules/web/Controllers/BootstrapController.php b/app/modules/web/Controllers/BootstrapController.php index 431d8fd7..1867b370 100644 --- a/app/modules/web/Controllers/BootstrapController.php +++ b/app/modules/web/Controllers/BootstrapController.php @@ -145,4 +145,12 @@ final class BootstrapController extends SimpleControllerBase return ''; } } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/app/modules/web/Controllers/ControllerBase.php b/app/modules/web/Controllers/ControllerBase.php index 4743a0df..d8199c30 100644 --- a/app/modules/web/Controllers/ControllerBase.php +++ b/app/modules/web/Controllers/ControllerBase.php @@ -30,6 +30,7 @@ use DI\Container; use Psr\Container\ContainerInterface; use SP\Core\Crypt\Hash; use SP\Core\Exceptions\FileNotFoundException; +use SP\Core\Exceptions\SessionTimeout; use SP\Core\Exceptions\SPException; use SP\DataModel\ProfileData; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; @@ -55,7 +56,6 @@ abstract class ControllerBase const ERR_UPDATE_MPASS = 3; const ERR_OPERATION_NO_PERMISSION = 4; const ERR_EXCEPTION = 5; - /** * @var Template Instancia del motor de plantillas a utilizar */ @@ -89,6 +89,7 @@ abstract class ControllerBase * * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface + * @throws SessionTimeout */ public final function __construct(Container $container, $actionName) { @@ -112,8 +113,12 @@ abstract class ControllerBase $this->setViewVars($loggedIn); - if (method_exists($this, 'initialize')) { + try { $this->initialize(); + } catch (SessionTimeout $sessionTimeout) { + $this->handleSessionTimeout(); + + throw $sessionTimeout; } } @@ -143,6 +148,27 @@ abstract class ControllerBase $this->view->assign($this->actionName, true); } + /** + * @return void + */ + protected abstract function initialize(); + + /** + * @return void + */ + private function handleSessionTimeout() + { + $this->sessionLogout( + $this->request, + $this->configData, + function ($redirect) { + $this->router->response() + ->redirect($redirect) + ->send(true); + } + ); + } + /** * Mostrar los datos de la plantilla */ @@ -219,11 +245,19 @@ abstract class ControllerBase * @throws AuthException * @throws \DI\DependencyException * @throws \DI\NotFoundException + * @throws \SP\Core\Exceptions\SessionTimeout */ protected function checkLoggedIn($requireAuthCompleted = true) { + if ($this->session->isLoggedIn() === false + || $this->session->getAuthCompleted() !== $requireAuthCompleted + ) { + throw new SessionTimeout(); + } + if ($this->session->isLoggedIn() && $this->session->getAuthCompleted() === $requireAuthCompleted + && $this->configData->isAuthBasicEnabled() ) { $browser = $this->dic->get(Browser::class); @@ -234,18 +268,6 @@ abstract class ControllerBase throw new AuthException('Invalid browser auth'); } } - - $this->checkLoggedInSession( - $this->session, - $this->request, - $this->configData, - function ($redirect) { - $this->router->response() - ->redirect($redirect) - ->send(true); - }, - $requireAuthCompleted - ); } /** diff --git a/app/modules/web/Controllers/IndexController.php b/app/modules/web/Controllers/IndexController.php index ab129fee..dff147aa 100644 --- a/app/modules/web/Controllers/IndexController.php +++ b/app/modules/web/Controllers/IndexController.php @@ -52,4 +52,12 @@ final class IndexController extends ControllerBase $this->view(); } } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/app/modules/web/Controllers/InstallController.php b/app/modules/web/Controllers/InstallController.php index d036c98e..db50d41f 100644 --- a/app/modules/web/Controllers/InstallController.php +++ b/app/modules/web/Controllers/InstallController.php @@ -93,4 +93,12 @@ final class InstallController extends ControllerBase return $this->returnJsonResponseException($e); } } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index 9c21c811..57205d0f 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -155,4 +155,12 @@ final class LoginController extends ControllerBase $this->view(); } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/app/modules/web/Controllers/SimpleControllerBase.php b/app/modules/web/Controllers/SimpleControllerBase.php index 51ee862c..3b24dfb1 100644 --- a/app/modules/web/Controllers/SimpleControllerBase.php +++ b/app/modules/web/Controllers/SimpleControllerBase.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers; use DI\Container; use Psr\Container\ContainerInterface; use SP\Core\Acl\UnauthorizedPageException; +use SP\Core\Exceptions\SessionTimeout; use SP\Modules\Web\Controllers\Traits\WebControllerTrait; /** @@ -53,8 +54,7 @@ abstract class SimpleControllerBase * @param Container $container * @param $actionName * - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws SessionTimeout */ public function __construct(Container $container, $actionName) { @@ -65,18 +65,26 @@ abstract class SimpleControllerBase $this->previousSk = $this->session->getSecurityKey(); - if (method_exists($this, 'initialize')) { + try { $this->initialize(); + } catch (SessionTimeout $sessionTimeout) { + $this->handleSessionTimeout(); + + throw $sessionTimeout; } } /** - * Comprobaciones + * @return void */ - protected function checks() + protected abstract function initialize(); + + /** + * @return void + */ + public function handleSessionTimeout() { - $this->checkLoggedInSession( - $this->session, + $this->sessionLogout( $this->request, $this->configData, function ($redirect) { @@ -85,6 +93,21 @@ abstract class SimpleControllerBase ->send(true); } ); + } + + /** + * Comprobaciones + * + * @throws SessionTimeout + */ + protected function checks() + { + if ($this->session->isLoggedIn() === false + || $this->session->getAuthCompleted() !== true + ) { + throw new SessionTimeout(); + } + // $this->checkSecurityToken($this->session, $this->request); } diff --git a/app/modules/web/Controllers/StatusController.php b/app/modules/web/Controllers/StatusController.php index 8de0621c..8aa9c109 100644 --- a/app/modules/web/Controllers/StatusController.php +++ b/app/modules/web/Controllers/StatusController.php @@ -146,4 +146,12 @@ final class StatusController extends SimpleControllerBase return $this->returnJsonResponseException($e); } } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/app/modules/web/Controllers/UpgradeController.php b/app/modules/web/Controllers/UpgradeController.php index d24be396..a0e52b27 100644 --- a/app/modules/web/Controllers/UpgradeController.php +++ b/app/modules/web/Controllers/UpgradeController.php @@ -107,4 +107,12 @@ final class UpgradeController extends ControllerBase return $this->returnJsonResponseException($e); } } + + /** + * @return void + */ + protected function initialize() + { + // TODO: Implement initialize() method. + } } \ No newline at end of file diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index dd8ceebd..63e3558b 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -35,6 +35,7 @@ use SP\Config\ConfigData; use SP\Config\ConfigUtil; use SP\Core\Exceptions\ConfigException; use SP\Core\Exceptions\InitializationException; +use SP\Core\Exceptions\SessionTimeout; use SP\Core\Language; use SP\Core\PhpExtensionChecker; use SP\Http\Request; @@ -203,16 +204,16 @@ final class Bootstrap } // $app = $matches['app'][0] ?: 'web'; - $controller = $matches['controller'][0]; - $method = !empty($matches['action'][0]) ? $matches['action'][0] . 'Action' : 'indexAction'; - $params = !empty($matches['params'][0]) ? Filter::getArray(explode('/', trim($matches['params'][0], '/'))) : []; + $controllerName = $matches['controller'][0]; + $methodName = !empty($matches['action'][0]) ? $matches['action'][0] . 'Action' : 'indexAction'; + $methodParams = !empty($matches['params'][0]) ? Filter::getArray(explode('/', trim($matches['params'][0], '/'))) : []; - $controllerClass = 'SP\\Modules\\' . ucfirst(APP_MODULE) . '\\Controllers\\' . ucfirst($controller) . 'Controller'; + $controllerClass = 'SP\\Modules\\' . ucfirst(APP_MODULE) . '\\Controllers\\' . ucfirst($controllerName) . 'Controller'; $this->initializePluginClasses(); - if (!method_exists($controllerClass, $method)) { - logger($controllerClass . '::' . $method); + if (!method_exists($controllerClass, $methodName)) { + logger($controllerClass . '::' . $methodName); /** @var Response $response */ $response->code(404); @@ -225,13 +226,17 @@ final class Bootstrap switch (APP_MODULE) { case 'web': self::$container->get(InitWeb::class) - ->initialize($controller); + ->initialize($controllerName); break; } - logger('Routing call: ' . $controllerClass . '::' . $method . '::' . print_r($params, true)); + logger('Routing call: ' . $controllerClass . '::' . $methodName . '::' . print_r($methodParams, true)); - return call_user_func_array([new $controllerClass(self::$container, $method), $method], $params); + $controller = new $controllerClass(self::$container, $methodName); + + return call_user_func_array([$controller, $methodName], $methodParams); + } catch (SessionTimeout $sessionTimeout) { + logger('Session timeout', 'DEBUG'); } catch (\Exception $e) { processException($e); diff --git a/lib/SP/Core/Exceptions/SessionTimeout.php b/lib/SP/Core/Exceptions/SessionTimeout.php new file mode 100644 index 00000000..8b2dcfc9 --- /dev/null +++ b/lib/SP/Core/Exceptions/SessionTimeout.php @@ -0,0 +1,35 @@ +. + */ + +namespace SP\Core\Exceptions; + +/** + * Class SessionTimeout + * + * @package SP\Core\Exceptions + */ +final class SessionTimeout extends \Exception +{ + +} \ No newline at end of file diff --git a/lib/SP/Mvc/Controller/ControllerTrait.php b/lib/SP/Mvc/Controller/ControllerTrait.php index 659e5371..696c3d94 100644 --- a/lib/SP/Mvc/Controller/ControllerTrait.php +++ b/lib/SP/Mvc/Controller/ControllerTrait.php @@ -26,7 +26,6 @@ namespace SP\Mvc\Controller; use SP\Bootstrap; use SP\Config\ConfigData; -use SP\Core\Context\SessionContext; use SP\Core\Exceptions\SPException; use SP\Http\Json; use SP\Http\JsonResponse; @@ -54,54 +53,44 @@ trait ControllerTrait } /** - * Comprobar si la sesión está activa + * Logout from current session * - * @param SessionContext $context - * @param Request $request - * @param ConfigData $configData - * @param \Closure $onRedirect - * @param bool $requireAuthCompleted + * @param Request $request + * @param ConfigData $configData + * @param \Closure $onRedirect */ - protected function checkLoggedInSession(SessionContext $context, - Request $request, - ConfigData $configData, - \Closure $onRedirect, - $requireAuthCompleted = true) + protected function sessionLogout(Request $request, ConfigData $configData, \Closure $onRedirect) { - if ($context->isLoggedIn() === false - || $context->getAuthCompleted() !== $requireAuthCompleted - ) { - if ($request->isJson()) { - $jsonResponse = new JsonResponse(__u('Session not started or timed out')); - $jsonResponse->setStatus(10); + if ($request->isJson()) { + $jsonResponse = new JsonResponse(__u('Session not started or timed out')); + $jsonResponse->setStatus(10); - Json::fromDic()->returnJson($jsonResponse); - } elseif ($request->isAjax()) { - Util::logout(); - } else { - try { - // Analyzes if there is any direct route within the URL - // then it computes the route HMAC to build a signed URI - // which would be used during logging in - $route = $request->analyzeString('r'); - $hash = $request->analyzeString('h'); + Json::fromDic()->returnJson($jsonResponse); + } elseif ($request->isAjax()) { + Util::logout(); + } else { + try { + // Analyzes if there is any direct route within the URL + // then it computes the route HMAC to build a signed URI + // which would be used during logging in + $route = $request->analyzeString('r'); + $hash = $request->analyzeString('h'); - $uri = new Uri(Bootstrap::$WEBROOT . Bootstrap::$SUBURI); - $uri->addParam('_r', 'login'); + $uri = new Uri(Bootstrap::$WEBROOT . Bootstrap::$SUBURI); + $uri->addParam('_r', 'login'); - if ($route && $hash) { - $key = $configData->getPasswordSalt(); - $request->verifySignature($key); + if ($route && $hash) { + $key = $configData->getPasswordSalt(); + $request->verifySignature($key); - $uri->addParam('from', $route); + $uri->addParam('from', $route); - $onRedirect->call($this, $uri->getUriSigned($key)); - } else { - $onRedirect->call($this, $uri->getUri()); - } - } catch (SPException $e) { - processException($e); + $onRedirect->call($this, $uri->getUriSigned($key)); + } else { + $onRedirect->call($this, $uri->getUri()); } + } catch (SPException $e) { + processException($e); } } } diff --git a/lib/SP/Services/Install/Installer.php b/lib/SP/Services/Install/Installer.php index 97c1206a..207a571c 100644 --- a/lib/SP/Services/Install/Installer.php +++ b/lib/SP/Services/Install/Installer.php @@ -54,9 +54,9 @@ final class Installer extends Service /** * sysPass' version and build number */ - const VERSION = [3, 0, 3]; + const VERSION = [3, 0, 4]; const VERSION_TEXT = '3.0'; - const BUILD = 19012402; + const BUILD = 19012601; /** * @var DatabaseSetupInterface