From 224297356801046f3d20a3d938f3a61372899f78 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 23 Jan 2014 16:03:47 +0100 Subject: [PATCH] XHR: Force redirect to login if session is expired resolves #5507 --- .../controllers/AuthenticationController.php | 35 +++++++---------- application/controllers/ErrorController.php | 7 ++-- .../Web/Controller/ActionController.php | 25 ++++++------ public/js/icinga/components/container.js | 39 +++++++++++-------- public/js/icinga/components/dashboard.js | 12 +++++- 5 files changed, 65 insertions(+), 53 deletions(-) diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index be6a4a463..2e3f8098f 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -30,11 +30,11 @@ # namespace Icinga\Application\Controllers; -use \Icinga\Web\Controller\ActionController; -use \Icinga\Authentication\Credential; -use \Icinga\Authentication\Manager as AuthManager; -use \Icinga\Form\Authentication\LoginForm; -use \Icinga\Exception\ConfigurationError; +use Icinga\Web\Controller\ActionController; +use Icinga\Authentication\Credential; +use Icinga\Authentication\Manager as AuthManager; +use Icinga\Form\Authentication\LoginForm; +use Icinga\Exception\ConfigurationError; /** * Application wide controller for authentication @@ -42,7 +42,7 @@ use \Icinga\Exception\ConfigurationError; class AuthenticationController extends ActionController { /** - * This controller handles authentication + * This controller does not require authentication * * @var bool */ @@ -53,33 +53,26 @@ class AuthenticationController extends ActionController */ public function loginAction() { - $credentials = new Credential(); $this->_helper->layout->setLayout('login'); $this->view->form = new LoginForm(); - $this->view->form->setRequest($this->_request); - $this->view->title = "Icinga Web Login"; + $this->view->title = 'Icinga Web Login'; try { + $redirectUrl = $this->_request->getParam('redirect', 'index?_render=body'); $auth = AuthManager::getInstance(); - if ($auth->isAuthenticated()) { - $this->redirectNow('index?_render=body'); + $this->redirectNow($redirectUrl); } - if ($this->view->form->isSubmittedAndValid()) { - $credentials->setUsername($this->view->form->getValue('username')); - $credentials->setPassword($this->view->form->getValue('password')); - + $credentials = new Credential( + $this->view->form->getValue('username'), + $this->view->form->getValue('password') + ); if (!$auth->authenticate($credentials)) { $this->view->form->getElement('password') ->addError(t('Please provide a valid username and password')); } else { - $redirectUrl = $this->_request->getParam('redirect'); - if ($redirectUrl == null) { - $this->redirectNow('index?_render=body'); - } else { - $this->redirectNow($redirectUrl); - } + $this->redirectNow($redirectUrl); } } } catch (ConfigurationError $configError) { diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php index b49248d16..5731982c9 100755 --- a/application/controllers/ErrorController.php +++ b/application/controllers/ErrorController.php @@ -42,7 +42,8 @@ class ErrorController extends ActionController */ public function errorAction() { - $error = $this->_getParam('error_handler'); + $error = $this->_getParam('error_handler'); + $exception = $error->exception; switch ($error->type) { case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: @@ -52,11 +53,11 @@ class ErrorController extends ActionController break; default: $this->getResponse()->setHttpResponseCode(500); - $this->view->message = $error->exception->getMessage(); + $this->view->message = $exception->getMessage(); break; } if ($this->getInvokeArg('displayExceptions') == true) { - $this->view->stackTrace = $error->exception->getTraceAsString(); + $this->view->stackTrace = $exception->getTraceAsString(); } $this->view->request = $error->request; } diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index ac1a5caba..cb0b0c951 100755 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -36,13 +36,13 @@ use \Zend_Controller_Front; use \Zend_Controller_Response_Abstract; use \Zend_Controller_Action_HelperBroker; use \Zend_Layout; -use \Icinga\Authentication\Manager as AuthManager; -use \Icinga\Application\Benchmark; -use \Icinga\Application\Config; -use \Icinga\Web\Notification; -use \Icinga\Web\Widget\Tabs; -use \Icinga\Web\Url; -use \Icinga\Web\Request; +use Icinga\Authentication\Manager as AuthManager; +use Icinga\Application\Benchmark; +use Icinga\Application\Config; +use Icinga\Web\Notification; +use Icinga\Web\Widget\Tabs; +use Icinga\Web\Url; +use Icinga\Web\Request; /** * Base class for all core action controllers @@ -173,14 +173,15 @@ class ActionController extends Zend_Controller_Action protected function redirectToLogin($afterLogin = '/index') { if ($this->getRequest()->isXmlHttpRequest()) { - - $this->getResponse()->setHttpResponseCode(401); - $this->getResponse()->sendHeaders(); - throw new Exception("You are not logged in"); + $this->_response->setHttpResponseCode(401); + $this->_helper->json(array( + 'exception' => 'You are not logged in', + 'redirectTo' => Url::fromPath('/authentication/login')->getAbsoluteUrl() + )); } $url = Url::fromPath('/authentication/login'); $url->setParam('redirect', $afterLogin); - $this->redirectNow($url->getRelativeUrl()); + $this->redirectNow($url); } /** diff --git a/public/js/icinga/components/container.js b/public/js/icinga/components/container.js index 9ccf138cd..4f326359c 100644 --- a/public/js/icinga/components/container.js +++ b/public/js/icinga/components/container.js @@ -29,7 +29,7 @@ define(['jquery', 'logging', 'icinga/componentLoader', 'URIjs/URI', 'URIjs/URITemplate', 'icinga/util/url'], function($, logger, componentLoader, URI, Tpl, urlMgr) { - "use strict"; + 'use strict'; var Icinga; @@ -194,22 +194,29 @@ define(['jquery', 'logging', 'icinga/componentLoader', 'URIjs/URI', 'URIjs/URITe cancelPendingRequest(); this.containerDom.trigger('showLoadIndicator'); pendingDetailRequest = $.ajax({ - 'url' : url, - 'data' : { - 'render' : 'detail' - } - }); - pendingDetailRequest.done( - (function(response) { + 'url': url, + 'data': { + 'render': 'detail' + }, + 'context': this + }) + .done(function (response) { pendingDetailRequest = null; this.replaceDom($(response)); - }).bind(this) - ).fail( - (function(response, reason) { + }) + .fail(function (response, reason) { if (reason === 'abort') { return; } - + if (response.statusCode().status === 401) { + var error = JSON.parse(response.responseText); + window.location.replace( + URI(error.redirectTo).search({ + redirect: URI(urlMgr.getUrl()).resource().replace(new RegExp('^' + window.base_url), '') + }) + ); + return; + } var errorReason; if (response.statusCode.toString()[0] === '4') { errorReason = 'The Requested View Couldn\'t Be Found
'; @@ -217,10 +224,10 @@ define(['jquery', 'logging', 'icinga/componentLoader', 'URIjs/URI', 'URIjs/URITe errorReason = response.responseText; } this.replaceDom(response.responseText); - }).bind(this) - ).always((function() { - this.containerDom.trigger('hideLoadIndicator'); - }).bind(this)); + }) + .always(function () { + this.containerDom.trigger('hideLoadIndicator'); + }); }; this.getUrl = function() { diff --git a/public/js/icinga/components/dashboard.js b/public/js/icinga/components/dashboard.js index a63fdb864..758bccbc0 100644 --- a/public/js/icinga/components/dashboard.js +++ b/public/js/icinga/components/dashboard.js @@ -31,7 +31,8 @@ * Dashboard container, uses freetile for layout * */ -define(['jquery', 'logging', 'URIjs/URI', 'icinga/componentLoader'], function($, log, URI, components) { +define(['jquery', 'logging', 'URIjs/URI', 'icinga/componentLoader', 'icinga/util/url'], + function($, log, URI, components, urlMgr) { 'use strict'; return function(parent) { this.dom = $(parent); @@ -55,6 +56,15 @@ define(['jquery', 'logging', 'URIjs/URI', 'icinga/componentLoader'], function($, components.load(); }) .fail(function (response, reason) { + if (response.statusCode().status === 401) { + var error = JSON.parse(response.responseText); + window.location.replace( + URI(error.redirectTo).search({ + redirect: URI(urlMgr.getUrl()).resource().replace(new RegExp('^' + window.base_url), '') + }) + ); + return; + } this.container.html(response.responseText); }) .always(function () {