diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index b9a3e1216..be6a4a463 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -48,15 +48,6 @@ class AuthenticationController extends ActionController */ protected $requiresAuthentication = false; - /** - * This controller modifies the session - * - * @var bool - * - * @see \Icinga\Web\Controller\ActionController::$modifiesSession - */ - protected $modifiesSession = true; - /** * Log into the application */ @@ -69,9 +60,7 @@ class AuthenticationController extends ActionController $this->view->form->setRequest($this->_request); $this->view->title = "Icinga Web Login"; try { - $auth = AuthManager::getInstance(null, array( - 'writeSession' => $this->modifiesSession - )); + $auth = AuthManager::getInstance(); if ($auth->isAuthenticated()) { $this->redirectNow('index?_render=body'); @@ -104,9 +93,7 @@ class AuthenticationController extends ActionController public function logoutAction() { $this->_helper->layout->setLayout('inline'); - $auth = AuthManager::getInstance(null, array( - 'writeSession' => $this->modifiesSession - )); + $auth = AuthManager::getInstance(); $auth->removeAuthorization(); $this->redirectToLogin(); } diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index 93b655090..edee923fa 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -5,7 +5,6 @@ * This file is part of Icinga Web 2. * * Icinga Web 2 - Head for multiple monitoring backends. - * Copyright (C) 2013 Icinga Development Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,13 +29,15 @@ use \Icinga\Web\Controller\BaseConfigController; use \Icinga\Web\Widget\Tab; +use \Icinga\Web\Widget\AlertMessageBox; use \Icinga\Web\Url; -use \Icinga\Web\Widget\Tabs; use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder; +use \Icinga\User\Message; use \Icinga\Application\Icinga; use \Icinga\Application\Config as IcingaConfig; use \Icinga\Data\ResourceFactory; use \Icinga\Form\Config\GeneralForm; +use \Icinga\Authentication\Manager as AuthenticationManager; use \Icinga\Form\Config\Authentication\ReorderForm; use \Icinga\Form\Config\Authentication\LdapBackendForm; use \Icinga\Form\Config\Authentication\DbBackendForm; @@ -110,17 +111,17 @@ class ConfigController extends BaseConfigController */ public function indexAction() { + $this->view->messageBox = new AlertMessageBox(true); $form = new GeneralForm(); - $form->setConfiguration(IcingaConfig::app()); $form->setRequest($this->_request); if ($form->isSubmittedAndValid()) { if (!$this->writeConfigFile($form->getConfig(), 'config')) { return; } - $this->view->successMessage = "Config Sucessfully Updated"; + $this->addSuccessMessage("Configuration Sucessfully Updated"); $form->setConfiguration(IcingaConfig::app(), true); - + $this->redirectNow('config/index'); } $this->view->form = $form; } @@ -130,6 +131,8 @@ class ConfigController extends BaseConfigController */ public function loggingAction() { + $this->view->messageBox = new AlertMessageBox(true); + $form = new LoggingForm(); $form->setConfiguration(IcingaConfig::app()); $form->setRequest($this->_request); @@ -137,8 +140,9 @@ class ConfigController extends BaseConfigController if (!$this->writeConfigFile($form->getConfig(), 'config')) { return; } - $this->view->successMessage = "Config Sucessfully Updated"; + $this->addSuccessMessage("Configuration Sucessfully Updated"); $form->setConfiguration(IcingaConfig::app(), true); + $this->redirectNow('config/logging'); } $this->view->form = $form; } @@ -148,6 +152,8 @@ class ConfigController extends BaseConfigController */ public function moduleoverviewAction() { + $this->view->messageBox = new AlertMessageBox(true); + $this->view->modules = Icinga::app()->getModuleManager()->select() ->from('modules') ->order('name'); @@ -164,10 +170,11 @@ class ConfigController extends BaseConfigController try { $manager->enableModule($module); $manager->loadModule($module); - $this->view->successMessage = 'Module "' . $module . '" enabled'; - $this->moduleoverviewAction(); + $this->addSuccessMessage('Module "' . $module . '" enabled'); + $this->redirectNow('config/moduleoverview'); + return; } catch (Exception $e) { - $this->view->exceptionMessage = $e->getMessage(); + $this->view->exceptionMesssage = $e->getMessage(); $this->view->moduleName = $module; $this->view->action = 'enable'; $this->render('module-configuration-error'); @@ -183,8 +190,9 @@ class ConfigController extends BaseConfigController $manager = Icinga::app()->getModuleManager(); try { $manager->disableModule($module); - $this->view->successMessage = 'Module "' . $module . '" disabled'; - $this->moduleoverviewAction(); + $this->addSuccessMessage('Module "' . $module . '" disabled'); + $this->redirectNow('config/moduleoverview'); + return; } catch (Exception $e) { $this->view->exceptionMessage = $e->getMessage(); $this->view->moduleName = $module; @@ -201,6 +209,7 @@ class ConfigController extends BaseConfigController $config = IcingaConfig::app('authentication', true); $order = array_keys($config->toArray()); $this->view->backends = array(); + $this->view->messageBox = new AlertMessageBox(true); foreach ($config as $backend=>$backendConfig) { $form = new ReorderForm(); @@ -211,8 +220,8 @@ class ConfigController extends BaseConfigController if (!$showOnly && $form->isSubmittedAndValid()) { if ($this->writeAuthenticationFile($form->getReorderedConfig($config))) { - $this->view->successMessage = 'Authentication Order Updated'; - $this->authenticationAction(true); + $this->addSuccessMessage('Authentication Order Updated'); + $this->redirectNow('config/authentication'); } return; } @@ -230,6 +239,8 @@ class ConfigController extends BaseConfigController */ public function createauthenticationbackendAction() { + $this->view->messageBox = new AlertMessageBox(true); + if ($this->getRequest()->getParam('type') === 'ldap') { $form = new LdapBackendForm(); } else { @@ -248,7 +259,7 @@ class ConfigController extends BaseConfigController foreach ($form->getConfig() as $backendName => $settings) { unset($settings->{'name'}); if (isset($backendCfg[$backendName])) { - $this->view->errorMessage = 'Backend name already exists'; + $this->addErrorMessage('Backend name already exists'); $this->view->form = $form; $this->render('authentication/create'); return; @@ -257,11 +268,13 @@ class ConfigController extends BaseConfigController } if ($this->writeAuthenticationFile($backendCfg)) { // redirect to overview with success message - $this->view->successMessage = 'Backend Modification Written'; - $this->authenticationAction(true); + $this->addSuccessMessage('Backend Modification Written.'); + $this->redirectNow("config/authentication"); } return; } + + $this->view->messageBox->addForm($form); $this->view->form = $form; $this->render('authentication/create'); } @@ -275,16 +288,18 @@ class ConfigController extends BaseConfigController */ public function editauthenticationbackendAction() { + $this->view->messageBox = new AlertMessageBox(true); + $configArray = IcingaConfig::app('authentication', true)->toArray(); $authBackend = $this->getParam('auth_backend'); if (!isset($configArray[$authBackend])) { - $this->view->errorMessage = 'Can\'t edit: Unknown Authentication Backend Provided'; - $this->authenticationAction(true); + $this->addErrorMessage('Can\'t edit: Unknown Authentication Backend Provided'); + $this->configurationerrorAction(); return; } if (!array_key_exists('resource', $configArray[$authBackend])) { - $this->view->errorMessage = 'Configuration error: Backend "' . $authBackend . '" has no Resource'; - $this->authenticationAction(true); + $this->addErrorMessage('Configuration error: Backend "' . $authBackend . '" has no Resource'); + $this->configurationerrorAction(); return; } @@ -297,8 +312,8 @@ class ConfigController extends BaseConfigController $form = new DbBackendForm(); break; default: - $this->view->errorMessage = 'Can\'t edit: backend type "' . $type . '" of given resource not supported.'; - $this->authenticationAction(true); + $this->addErrorMessage('Can\'t edit: backend type "' . $type . '" of given resource not supported.'); + $this->configurationerrorAction(); return; } @@ -318,12 +333,13 @@ class ConfigController extends BaseConfigController } if ($this->writeAuthenticationFile($backendCfg)) { // redirect to overview with success message - $this->view->successMessage = 'Backend "' . $authBackend . '" created'; - $this->authenticationAction(true); + $this->addSuccessMessage('Backend "' . $authBackend . '" created'); + $this->redirectNow("config/authentication"); } return; } + $this->view->messageBox->addForm($form); $this->view->name = $authBackend; $this->view->form = $form; $this->render('authentication/modify'); @@ -336,16 +352,13 @@ class ConfigController extends BaseConfigController */ public function removeauthenticationbackendAction() { + $this->view->messageBox = new AlertMessageBox(true); + $configArray = IcingaConfig::app('authentication', true)->toArray(); $authBackend = $this->getParam('auth_backend'); if (!isset($configArray[$authBackend])) { - $this->view->errorMessage = 'Can\'t perform removal: Unknown Authentication Backend Provided'; - $this->authenticationAction(true); - return; - } - if (!array_key_exists('resource', $configArray[$authBackend])) { - $this->view->errorMessage = 'Configuration error: Backend "' . $authBackend . '" has no Resource'; - $this->authenticationAction(true); + $this->addSuccessMessage('Can\'t perform removal: Unknown Authentication Backend Provided'); + $this->render('authentication/remove'); return; } @@ -356,8 +369,8 @@ class ConfigController extends BaseConfigController if ($form->isSubmittedAndValid()) { unset($configArray[$authBackend]); if ($this->writeAuthenticationFile($configArray)) { - $this->view->successMessage = 'Authentication Backend "' . $authBackend . '" Removed'; - $this->authenticationAction(true); + $this->addSuccessMessage('Authentication Backend "' . $authBackend . '" Removed'); + $this->redirectNow("config/authentication"); } return; } @@ -369,7 +382,7 @@ class ConfigController extends BaseConfigController public function resourceAction($showOnly = false) { - + $this->view->messageBox = new AlertMessageBox(true); $this->view->resources = IcingaConfig::app('resources', true)->toArray(); $this->render('resource'); } @@ -383,29 +396,31 @@ class ConfigController extends BaseConfigController if ($form->isSubmittedAndValid()) { $name = $form->getName(); if (isset($resources->{$name})) { - $this->view->errorMessage = 'Resource name "' . $name .'" already in use.'; - $this->view->form = $form; - $this->render('resource/create'); - return; + $this->addErrorMessage('Resource name "' . $name .'" already in use.'); + } else { + $resources->{$name} = $form->getConfig(); + if ($this->writeConfigFile($resources, 'resources')) { + $this->addSuccessMessage('Resource "' . $name . '" created.'); + $this->redirectNow("config/resource"); + } } - $resources->{$name} = $form->getConfig(); - if ($this->writeConfigFile($resources, 'resources')) { - $this->view->successMessage = 'Resource "' . $name . '" created.'; - $this->resourceAction(true); - } - return; } + + $this->view->messageBox = new AlertMessageBox(true); + $this->view->messageBox->addForm($form); $this->view->form = $form; $this->render('resource/create'); } public function editresourceAction() { + $this->view->messageBox = new AlertMessageBox(true); + $resources = ResourceFactory::getResourceConfigs(); $name = $this->getParam('resource'); if ($resources->get($name) === null) { - $this->view->errorMessage = 'Can\'t edit: Unknown Resource Provided'; - $this->resourceAction(true); + $this->addErrorMessage('Can\'t edit: Unknown Resource Provided'); + $this->render('resource/modify'); return; } $form = new EditResourceForm(); @@ -423,11 +438,13 @@ class ConfigController extends BaseConfigController } $resources->{$name} = $form->getConfig(); if ($this->writeConfigFile($resources, 'resources')) { - $this->view->successMessage = 'Resource "' . $name . '" created.'; - $this->resourceAction(true); + $this->addSuccessMessage('Resource "' . $name . '" edited.'); + $this->redirectNow("config/resource"); } return; } + + $this->view->messageBox->addForm($form); $this->view->form = $form; $this->view->name = $name; $this->render('resource/modify'); @@ -435,22 +452,36 @@ class ConfigController extends BaseConfigController public function removeresourceAction() { + $this->view->messageBox = new AlertMessageBox(true); + $resources = ResourceFactory::getResourceConfigs()->toArray(); $name = $this->getParam('resource'); if (!isset($resources[$name])) { - $this->view->errorMessage = 'Can\'t remove: Unknown resource provided'; - $this->resourceAction(true); + $this->addSuccessMessage('Can\'t remove: Unknown resource provided'); + $this->render('resource/remove'); return; } $form = new ConfirmRemovalForm(); $form->setRequest($this->getRequest()); $form->setRemoveTarget('resource', $name); + + // Check if selected resource is currently used for authentication + $authConfig = IcingaConfig::app('authentication', true)->toArray(); + foreach ($authConfig as $backendName => $config) { + if (array_key_exists('resource', $config) && $config['resource'] === $name) { + $this->addErrorMessage( + 'Warning: The resource "' . $name . '" is currently used for user authentication by "' . $backendName . '". ' . + ' Deleting it could eventally make login impossible.' + ); + } + } + if ($form->isSubmittedAndValid()) { unset($resources[$name]); if ($this->writeConfigFile($resources, 'resources')) { - $this->view->successMessage = 'Resource "' . $name . '" removed'; - $this->resourceAction(true); + $this->addSuccessMessage('Resource "' . $name . '" removed.'); + $this->redirectNow('config/resource'); } return; } @@ -460,6 +491,19 @@ class ConfigController extends BaseConfigController $this->render('resource/remove'); } + + /** + * Redirect target only for error-states + * + * When an error is opened in the side-pane, redirecting this request to the index or the overview will look + * weird. This action returns a clear page containing only an AlertMessageBox. + */ + public function configurationerrorAction() + { + $this->view->messageBox = new AlertMessageBox(true); + $this->render('error/error'); + } + /** * Write changes to an authentication file * diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php index b7d64ec4f..a8245e136 100644 --- a/application/controllers/PreferenceController.php +++ b/application/controllers/PreferenceController.php @@ -40,15 +40,6 @@ use \Icinga\Form\Preference\GeneralForm; class PreferenceController extends BasePreferenceController { - /** - * This controller modifies the session - * - * @var bool - * - * @see \Icinga\Web\Controller\ActionController::$modifiesSession - */ - protected $modifiesSession = true; - /** * Create tabs for this preference controller * diff --git a/application/forms/Config/Resource/EditResourceForm.php b/application/forms/Config/Resource/EditResourceForm.php index 800720097..a70263efe 100644 --- a/application/forms/Config/Resource/EditResourceForm.php +++ b/application/forms/Config/Resource/EditResourceForm.php @@ -390,6 +390,9 @@ class EditResourceForm extends Form !file_exists($config->object_file) || !file_exists($config->status_file) ) { + $this->addErrorMessage( + 'Connectivity validation failed, the provided file or socket does not exist.' + ); return false; } break; @@ -402,6 +405,7 @@ class EditResourceForm extends Form break; } } catch (\Exception $exc) { + $this->addErrorMessage('Connectivity validation failed, connection to the given resource not possible.'); return false; } return true; diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml index 4bb8d947d..ab96e4f13 100644 --- a/application/views/scripts/config/authentication.phtml +++ b/application/views/scripts/config/authentication.phtml @@ -6,20 +6,9 @@ $createDbBackend = $this->href('/config/createAuthenticationBackend', array('typ tabs->render($this); ?> -errorMessage): ?> -
- - escape($this->errorMessage); ?> -
- - - -successMessage): ?> -
- - escape($this->successMessage); ?> -
- +messageBox)): ?> + messageBox->render() ?> +
diff --git a/application/views/scripts/config/authentication/create.phtml b/application/views/scripts/config/authentication/create.phtml index 69e0b4bd3..fd329b63a 100644 --- a/application/views/scripts/config/authentication/create.phtml +++ b/application/views/scripts/config/authentication/create.phtml @@ -3,11 +3,10 @@ Create New Authentication Backend -errorMessage): ?> -
- escape($this->errorMessage); ?> -
- + +messageBox)): ?> + messageBox->render() ?> +

Create a new backend for authenticating your users. This backend will be added at the end of your authentication order. diff --git a/application/views/scripts/config/authentication/modify.phtml b/application/views/scripts/config/authentication/modify.phtml index 298cbdd6e..ce7ca8a0a 100644 --- a/application/views/scripts/config/authentication/modify.phtml +++ b/application/views/scripts/config/authentication/modify.phtml @@ -3,11 +3,14 @@ Edit Backend "escape($this->name); ?>" -errorMessage || $this->form->getErrorMessages()): ?> +messageBox)): ?> + messageBox->render() ?> + + +form->getErrorMessages()): ?>

- escape($this->errorMessage); ?> form->getErrorMessages() as $error): ?> - escape($error); ?>
+ escape($error); ?>
diff --git a/application/views/scripts/config/authentication/remove.phtml b/application/views/scripts/config/authentication/remove.phtml index 9187195d5..ed478d24b 100644 --- a/application/views/scripts/config/authentication/remove.phtml +++ b/application/views/scripts/config/authentication/remove.phtml @@ -2,4 +2,9 @@ Remove Backend "escape($this->name); ?>" + +messageBox)): ?> + messageBox->render() ?> + + form ?> \ No newline at end of file diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml index 98e227f7d..d307c73eb 100644 --- a/application/views/scripts/config/index.phtml +++ b/application/views/scripts/config/index.phtml @@ -1,10 +1,7 @@ tabs->render($this); ?> -successMessage): ?> -
- - escape($this->successMessage); ?> -
- +messageBox)): ?> + messageBox->render() ?> + form ?> \ No newline at end of file diff --git a/application/views/scripts/config/logging.phtml b/application/views/scripts/config/logging.phtml index 6b0b7cca3..d8129ff62 100644 --- a/application/views/scripts/config/logging.phtml +++ b/application/views/scripts/config/logging.phtml @@ -2,6 +2,10 @@ form->getErrorMessages(); ?> +messageBox)): ?> + messageBox->render() ?> + + successMessage): ?>
diff --git a/application/views/scripts/config/module/overview.phtml b/application/views/scripts/config/module/overview.phtml index e7330c9c3..f50b2e30d 100644 --- a/application/views/scripts/config/module/overview.phtml +++ b/application/views/scripts/config/module/overview.phtml @@ -9,12 +9,9 @@ $modules = $this->modules->paginate();

Installed Modules

-successMessage): ?> -
- - escape($this->successMessage); ?> -
- +messageBox)): ?> + messageBox->render() ?> + paginationControl($modules, null, null, array( 'preserve' => $this->preserve diff --git a/application/views/scripts/config/resource.phtml b/application/views/scripts/config/resource.phtml index 4c167aeef..cb6f9542c 100644 --- a/application/views/scripts/config/resource.phtml +++ b/application/views/scripts/config/resource.phtml @@ -2,28 +2,11 @@ use Icinga\Web\Url; $createResource = $this->href('/config/createresource'); ?> - tabs->render($this); ?> -errorMessage): ?> -
- - escape($this->errorMessage); ?> -
- - -successMessage): ?> -
- - escape($this->successMessage); ?> -
-flashMessages): ?> -
- - escape($this->flashMessages); ?> -
- - +messageBox)): ?> + messageBox->render() ?> +
diff --git a/application/views/scripts/config/resource/create.phtml b/application/views/scripts/config/resource/create.phtml index 6ad1bcb4c..f82354557 100644 --- a/application/views/scripts/config/resource/create.phtml +++ b/application/views/scripts/config/resource/create.phtml @@ -3,14 +3,12 @@ Create New Resource -errorMessage): ?> -
- escape($this->errorMessage); ?> -
- +messageBox)): ?> + messageBox->render() ?> +

- Create a new resource to describes a data sourc + Resources are entities that provide data to Icingaweb.

form ?> \ No newline at end of file diff --git a/application/views/scripts/config/resource/modify.phtml b/application/views/scripts/config/resource/modify.phtml index 9956c3cdf..079c9464d 100644 --- a/application/views/scripts/config/resource/modify.phtml +++ b/application/views/scripts/config/resource/modify.phtml @@ -3,13 +3,16 @@ Edit Resource "escape($this->name); ?>" -errorMessage || $this->form->getErrorMessages()): ?> +messageBox)): ?> + messageBox->render() ?> + + +form->getErrorMessages()): ?>
- escape($this->errorMessage); ?> form->getErrorMessages() as $error): ?> - escape($error); ?>
+ escape($error); ?>
- + form ?> \ No newline at end of file diff --git a/application/views/scripts/config/resource/remove.phtml b/application/views/scripts/config/resource/remove.phtml index 0502cc709..3b5ffbfc1 100644 --- a/application/views/scripts/config/resource/remove.phtml +++ b/application/views/scripts/config/resource/remove.phtml @@ -2,4 +2,9 @@ Remove Resource "escape($this->name); ?>" -form ?> \ No newline at end of file + +messageBox)): ?> + messageBox->render() ?> + + +form ?> diff --git a/application/views/scripts/config/show-configuration.phtml b/application/views/scripts/config/show-configuration.phtml index 79d8edf59..2bf97cbfb 100644 --- a/application/views/scripts/config/show-configuration.phtml +++ b/application/views/scripts/config/show-configuration.phtml @@ -1,4 +1,6 @@ tabs->render($this); ?> + +

WARNING ICONSaving "escape($this->file); ?>.ini" Failed

diff --git a/application/views/scripts/error/error.phtml b/application/views/scripts/error/error.phtml index f9c73e026..c51ab59da 100755 --- a/application/views/scripts/error/error.phtml +++ b/application/views/scripts/error/error.phtml @@ -1,26 +1,9 @@ +tabs->render($this); ?> +

An error occurred

-

- message ?> -

- exception)): ?> -
-

Exception information:

- -

- Message: - exception->getMessage(); ?> -

- -

Stack trace:

-
-      exception->getTraceAsString(); ?>
-    
- -

Request Parameters:

-
getParams(), true); ?>
-    
-
- + messageBox)) : ?> + messageBox->render() ?> +
diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index a5d5da7d2..756316af8 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -232,12 +232,7 @@ class Web extends ApplicationBootstrap */ private function setupUser() { - $authenticationManager = AuthenticationManager::getInstance( - null, - array( - 'writeSession' => true - ) - ); + $authenticationManager = AuthenticationManager::getInstance(); if ($authenticationManager->isAuthenticated() === true) { $user = $authenticationManager->getUser(); diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index b089ea015..83c9393e3 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -121,16 +121,10 @@ class Manager } if (!isset($options['sessionClass'])) { - $this->session = new PhpSession($config->session); + $this->session = new PhpSession(); } else { $this->session = $options['sessionClass']; } - - if (isset($options['writeSession']) && $options['writeSession'] === true) { - $this->session->read(true); - } else { - $this->session->read(); - } } /** @@ -404,9 +398,9 @@ class Manager } /** - * Returns the current user or null if no user is authenticated + * Returns the current user or null if no user is authenticated * - * @return User + * @return User **/ public function getUser() { diff --git a/library/Icinga/Authentication/PhpSession.php b/library/Icinga/Authentication/PhpSession.php index 14fe12525..fea5b3663 100644 --- a/library/Icinga/Authentication/PhpSession.php +++ b/library/Icinga/Authentication/PhpSession.php @@ -51,21 +51,7 @@ class PhpSession extends Session * * @var string */ - const SESSION_NAME = 'Icinga2Web'; - - /** - * Flag if session is open - * - * @var bool - */ - private $isOpen = false; - - /** - * Flag if session is flushed - * - * @var bool - */ - private $isFlushed = false; + private $sessionName = 'Icingaweb2'; /** * Configuration for cookie options @@ -96,8 +82,12 @@ class PhpSession extends Session } else { $options = PhpSession::$defaultCookieOptions; } + if (array_key_exists('test_session_name', $options)) { + $this->sessionName = $options['test_session_name']; + unset($options['test_session_name']); + } foreach ($options as $sessionVar => $value) { - if (ini_set("session.".$sessionVar, $value) === false) { + if (ini_set("session." . $sessionVar, $value) === false) { Logger::warn( 'Could not set php.ini setting %s = %s. This might affect your sessions behaviour.', $sessionVar, @@ -108,129 +98,38 @@ class PhpSession extends Session if (!is_writable(session_save_path())) { throw new ConfigurationError('Can\'t save session'); } + $this->read(); } /** - * Return true when the session has not yet been closed - * - * @return bool + * Open a PHP session */ - private function sessionCanBeChanged() + private function open() { - if ($this->isFlushed) { - Logger::error('Tried to work on a closed session, session changes will be ignored'); - return false; - } - return true; - } - - /** - * Return true when the session has not yet been opened - * - * @return bool - */ - private function sessionCanBeOpened() - { - if ($this->isOpen) { - Logger::warn('Tried to open a session more than once'); - return false; - } - return $this->sessionCanBeChanged(); - } - - /** - * Open a PHP session when possible - * - * @return bool True on success - */ - public function open() - { - if (!$this->sessionCanBeOpened()) { - return false; - } - - session_name(self::SESSION_NAME); + session_name($this->sessionName); session_start(); - $this->isOpen = true; + } + + /** + * Read all values written to the underling session and make them accessible. + */ + public function read() + { + $this->open(); $this->setAll($_SESSION); - return true; - } - - /** - * Ensure that the session is open modifiable - * - * @return bool True on success - */ - private function ensureOpen() - { - // try to open first - if (!$this->isOpen) { - if (!$this->open()) { - return false; - } - } - return true; - } - - /** - * Read all values written to the underling session and - * makes them accessible. if keepOpen is not set, the session - * is immediately closed again - * - * @param bool $keepOpen Set to true when modifying the session - * - * @return bool True on success - */ - public function read($keepOpen = false) - { - if (!$this->ensureOpen()) { - return false; - } - if ($keepOpen) { - return true; - } - $this->close(); - return true; + session_write_close(); } /** * Write all values of this session object to the underlying session implementation - * - * If keepOpen is not set, the session is closed - * - * @param bool $keepOpen Set to true when modifying the session further - * - * @return bool True on success */ - public function write($keepOpen = false) + public function write() { - if (!$this->ensureOpen()) { - return false; - } + $this->open(); foreach ($this->getAll() as $key => $value) { $_SESSION[$key] = $value; } - if ($keepOpen) { - return null; - } - $this->close(); - - return null; - } - - /** - * Close and writes the session - * - * Only call this if you want the session to be closed without any changes. - * - * @see PHPSession::write - */ - public function close() - { - if (!$this->isFlushed) { - session_write_close(); - } - $this->isFlushed = true; + session_write_close(); } /** @@ -238,12 +137,12 @@ class PhpSession extends Session */ public function purge() { - if ($this->ensureOpen()) { - $_SESSION = array(); - session_destroy(); - $this->clearCookies(); - $this->close(); - } + $this->open(); + $_SESSION = array(); + $this->setAll(array(), true); + session_destroy(); + $this->clearCookies(); + session_write_close(); } /** diff --git a/library/Icinga/Authentication/Session.php b/library/Icinga/Authentication/Session.php index 0cdd5b3bd..8959549a6 100644 --- a/library/Icinga/Authentication/Session.php +++ b/library/Icinga/Authentication/Session.php @@ -41,29 +41,15 @@ abstract class Session */ private $sessionValues = array(); - /** - * Open a session or creates a new one if not exists - */ - abstract public function open(); - /** * Read all values from the underlying session implementation - * - * @param bool $keepOpen True to keep the session open */ - abstract public function read($keepOpen = false); + abstract public function read(); /** * Persists changes to the underlying session implementation - * - * @param bool $keepOpen True to keep the session open */ - abstract public function write($keepOpen = false); - - /** - * Close session - */ - abstract public function close(); + abstract public function write(); /** * Purge session @@ -78,10 +64,13 @@ abstract class Session * @see self::persist * @param string $key Name of value * @param mixed $value Value + * + * @returns PhpSession this */ public function set($key, $value) { $this->sessionValues[$key] = $value; + return $this; } /** diff --git a/library/Icinga/User.php b/library/Icinga/User.php index 9003e9f64..4a35ac721 100644 --- a/library/Icinga/User.php +++ b/library/Icinga/User.php @@ -31,14 +31,16 @@ namespace Icinga; use \DateTimeZone; use \InvalidArgumentException; -use Icinga\User\Preferences; +use \Icinga\User\Preferences; +use \Icinga\User\Message; +use \Icinga\Authentication\PhpSession; + /** * This class represents an authorized user * * You can retrieve authorization information (@TODO: Not implemented yet) or * to retrieve user information - * */ class User { @@ -105,6 +107,13 @@ class User */ private $preferences; + /** + * Queued notifications for this user. + * + * @var array() + */ + private $messages; + /** * Creates a user object given the provided information * @@ -334,4 +343,36 @@ class User } return new DateTimeZone($tz); } + + /** + * Add a message that can be accessed from future requests, to this user. + * + * This function does NOT automatically write to the session, messages will not be persisted until you do. + * + * @param Message $msg The message + */ + public function addMessage(Message $msg) + { + $this->messages[] = $msg; + } + + /** + * Get all currently pending messages + * + * @return array the messages + */ + public function getMessages() + { + return isset($this->messages) ? $this->messages : array(); + } + + /** + * Remove all messages from this user + * + * This function does NOT automatically write the session, messages will not be persisted until you do. + */ + public function clearMessages() + { + $this->messages = null; + } } diff --git a/library/Icinga/User/Message.php b/library/Icinga/User/Message.php new file mode 100644 index 000000000..d10bb09f5 --- /dev/null +++ b/library/Icinga/User/Message.php @@ -0,0 +1,57 @@ +message = $message; + $this->level = $level; + } + + /** + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * @return The + */ + public function getLevel() + { + return $this->level; + } +} \ No newline at end of file diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index b7e2ee826..b153e7411 100755 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -58,17 +58,6 @@ class ActionController extends Zend_Controller_Action */ protected $requiresAuthentication = true; - /** - * Set true when this controller modifies the session - * - * otherwise the session will be written back to disk and closed before the controller - * action is executed, leading to every modification in the session to be lost after - * the response is submitted - * - * @var bool - */ - protected $modifiesSession = false; - /** * The constructor starts benchmarking, loads the configuration and sets * other useful controller properties @@ -114,10 +103,7 @@ class ActionController extends Zend_Controller_Action return false; } - return !AuthManager::getInstance( - null, - array('writeSession' => $this->modifiesSession) - )->isAuthenticated(); + return !AuthManager::getInstance()->isAuthenticated(); } /** diff --git a/library/Icinga/Web/Controller/BaseConfigController.php b/library/Icinga/Web/Controller/BaseConfigController.php index 86e108cbc..5ca93e9aa 100644 --- a/library/Icinga/Web/Controller/BaseConfigController.php +++ b/library/Icinga/Web/Controller/BaseConfigController.php @@ -30,6 +30,9 @@ namespace Icinga\Web\Controller; use \Icinga\Application\Icinga; +use \Icinga\Authentication\Manager as AuthenticationManager; +use \Zend_Log; +use \Icinga\User\Message; /** * Base class for Configuration Controllers @@ -38,14 +41,36 @@ use \Icinga\Application\Icinga; * added to the application's configuration dialog. If you create a subclass of * BasePreferenceController and overwrite @see init(), make sure you call * parent::init(), otherwise you won't have the $tabs property in your view. - * */ class BaseConfigController extends ActionController { /** - * @var Zend_Controller_Action_Helper_FlashMessenger + * Send a message with the logging level Zend_Log::INFO to the current user and + * commit the changes to the underlying session. + * + * @param $msg The message content */ - protected $flashManager; + protected function addSuccessMessage($msg) + { + AuthenticationManager::getInstance()->getUser()->addMessage( + new Message($msg, Zend_Log::INFO) + ); + AuthenticationManager::getInstance()->getSession()->write(); + } + + /** + * Send a message with the logging level Zend_Log::ERR to the current user and + * commit the changes to the underlying session. + * + * @param $msg The message content + */ + protected function addErrorMessage($msg) + { + AuthenticationManager::getInstance()->getUser()->addMessage( + new Message($msg, Zend_Log::ERR) + ); + AuthenticationManager::getInstance()->getSession()->write(); + } /* * Return an array of tabs provided by this configuration controller. @@ -68,6 +93,5 @@ class BaseConfigController extends ActionController { parent::init(); $this->view->tabs = ControllerTabCollector::collectControllerTabs('ConfigController'); - $this->view->flashMessages = $this->_request->getParam('flash_message'); } } diff --git a/library/Icinga/Web/Widget/AlertMessageBox.php b/library/Icinga/Web/Widget/AlertMessageBox.php new file mode 100644 index 000000000..9bf90facf --- /dev/null +++ b/library/Icinga/Web/Widget/AlertMessageBox.php @@ -0,0 +1,128 @@ +user->getMessages(); + $this->user->clearMessages(); + AuthenticationManager::getInstance()->getSession()->write(); + return $messages; + } + + /** + * The displayed alert messages + * + * @var array + */ + private $messages = array(); + + /** + * The user to fetch the messages from + * + * @var User + */ + private $user; + + /** + * The available states. + * + * @var array + */ + private $states = array( + Zend_Log::INFO => array( + 'state' => 'alert-success', + 'icon' => 'icinga-icon-success' + ), + Zend_Log::NOTICE => array( + 'state' => 'alert-info', + 'icon' => 'icinga-icon-info' + ), + Zend_Log::WARN => array( + 'state' => 'alert-warning', + 'icon' => 'icinga-icon-warning' + ), + Zend_Log::ERR => array( + 'state' => 'alert-danger', + 'icon' => 'icinga-icon-danger' + ) + ); + + /** + * Create a new AlertBox + * + * @param boolean showUserMessages If the current user messages should be displayed + * in this AlertMessageBox. Defaults to false + */ + public function __construct($showUserMessages = false) { + if ($showUserMessages) { + $this->user = AuthenticationManager::getInstance()->getUser(); + } + } + + /** + * Add a new error + * + * @param $error + */ + public function addError($error) + { + $this->messages[] = new Message($error, Zend_Log::ERR); + } + + /** + * Add the error messages of the given Zend_Form + */ + public function addForm(Zend_Form $form) + { + foreach ($form->getErrorMessages() as $error) { + $this->addError($error); + } + } + + /** + * Output the HTML of the AlertBox + * + * @return string + */ + public function render(Zend_View_Abstract $view = null) { + $html = ''; + if (isset($this->user)) { + $this->messages = array_merge($this->messages, $this->getAndClearMessages()); + } + foreach ($this->messages as $message) { + $level = $message->getLevel(); + if (!array_key_exists($level, $this->states)) { + continue; + } + $alert = $this->states[$level]; + $html .= '
' . + '' . + '' . htmlspecialchars($message->getMessage()) . '' . + '
'; + } + return $html; + } +} diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index 755a06173..c75a54829 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -34,6 +34,7 @@ use \Icinga\Application\Config as IcingaConfig; use \Icinga\Config\PreservingIniWriter; use \Icinga\Web\Controller\BaseConfigController; use \Icinga\Web\Widget\Tab; +use \Icinga\Web\Widget\AlertMessageBox; use \Icinga\Web\Url; use Icinga\Module\Monitoring\Form\Config\ConfirmRemovalForm; @@ -69,6 +70,7 @@ class Monitoring_ConfigController extends BaseConfigController { */ public function indexAction() { + $this->view->messageBox = new AlertMessageBox(true); $this->view->backends = IcingaConfig::module('monitoring', 'backends')->toArray(); $this->view->instances = IcingaConfig::module('monitoring', 'instances')->toArray(); $this->render('index'); @@ -89,11 +91,11 @@ class Monitoring_ConfigController extends BaseConfigController { $backendForm->setBackendConfiguration(IcingaConfig::module('monitoring', 'backends')->get($backend)); if ($backendForm->isSubmittedAndValid()) { - $newConfig = $backendForm->getConfig(); $config = IcingaConfig::module('monitoring', 'backends'); $config->$backend = $newConfig; if ($this->writeConfiguration($config, 'backends')) { + $this->addSuccessMessage('Backend ' . $backend . ' Modified.'); $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); @@ -116,8 +118,8 @@ class Monitoring_ConfigController extends BaseConfigController { $configArray[$form->getBackendName()] = $form->getConfig(); if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) { - $this->view->successMessage = 'Backend Creation Succeeded'; - $this->indexAction(); + $this->addSuccessMessage('Backend Creation Succeeded'); + $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); } @@ -146,8 +148,8 @@ class Monitoring_ConfigController extends BaseConfigController { unset($configArray[$backend]); if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) { - $this->view->successMessage = 'Backend "' . $backend . '" Removed'; - $this->indexAction(); + $this->addSuccessMessage('Backend "' . $backend . '" Removed'); + $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); } @@ -178,8 +180,8 @@ class Monitoring_ConfigController extends BaseConfigController { unset($configArray[$instance]); if ($this->writeConfiguration(new Zend_Config($configArray), 'instances')) { - $this->view->successMessage = 'Instance "' . $instance . '" Removed'; - $this->indexAction(); + $this->addSuccessMessage('Instance "' . $instance . '" Removed'); + $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); } @@ -207,8 +209,8 @@ class Monitoring_ConfigController extends BaseConfigController { $instanceConfig = IcingaConfig::module('monitoring', 'instances')->toArray(); $instanceConfig[$instance] = $form->getConfig(); if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) { - $this->view->successMessage = 'Instance Modified'; - $this->indexAction(); + $this->addSuccessMessage('Instance Modified'); + $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); return; @@ -228,8 +230,8 @@ class Monitoring_ConfigController extends BaseConfigController { $instanceConfig = IcingaConfig::module('monitoring', 'instances')->toArray(); $instanceConfig[$form->getInstanceName()] = $form->getConfig()->toArray(); if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) { - $this->view->successMessage = 'Instance Creation Succeeded'; - $this->indexAction(); + $this->addSuccessMessage('Instance Creation Succeeded'); + $this->redirectNow('monitoring/config'); } else { $this->render('show-configuration'); } diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index 569500a82..39febc428 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -56,7 +56,6 @@ class Monitoring_ShowController extends MonitoringController */ public function init() { - if ($this->getRequest()->getActionName() === 'host') { $this->view->object = new Host($this->getRequest()); } elseif ($this->getRequest()->getActionName() === 'service' diff --git a/modules/monitoring/application/views/scripts/config/editbackend.phtml b/modules/monitoring/application/views/scripts/config/editbackend.phtml index 4344f9dbe..7ecf69bf0 100644 --- a/modules/monitoring/application/views/scripts/config/editbackend.phtml +++ b/modules/monitoring/application/views/scripts/config/editbackend.phtml @@ -1,8 +1,8 @@ -tabs->render($this); ?> + name): ?> -

{{EDIT_ICON}} Edit Backend "escape($this->name) ?>"

+

Edit Backend "escape($this->name) ?>"

-

{{CREATE_ICON}} Create New Backend

+

Create New Backend

error): ?> diff --git a/modules/monitoring/application/views/scripts/config/editinstance.phtml b/modules/monitoring/application/views/scripts/config/editinstance.phtml index 5b6907c64..1a2f5fe97 100644 --- a/modules/monitoring/application/views/scripts/config/editinstance.phtml +++ b/modules/monitoring/application/views/scripts/config/editinstance.phtml @@ -1,9 +1,8 @@ -tabs->render($this); ?> name)): ?> -

{{EDIT_ICON}} Edit Instance Configuration for "escape($this->name) ?>"

+

} Edit Instance Configuration for "escape($this->name) ?>"

-

{{CREATE_ICON}} Configure New Icinga Instance

+

Configure New Icinga Instance

error): ?> diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml index a12501f9f..f9e1f0ea8 100644 --- a/modules/monitoring/application/views/scripts/config/index.phtml +++ b/modules/monitoring/application/views/scripts/config/index.phtml @@ -3,16 +3,13 @@

Monitoring Backends

-successMessage): ?> -
- {{OK_ICON}} - escape($this->successMessage); ?> -
- +messageBox)): ?> + messageBox->render() ?> +
@@ -24,8 +21,8 @@ escape($backendName); ?> (Type: escape($config['type'] === 'ido' ? 'IDO' : ucfirst($config['type'])); ?>)

@@ -37,7 +34,7 @@ @@ -50,8 +47,8 @@ (Type: )

diff --git a/modules/monitoring/application/views/scripts/config/removebackend.phtml b/modules/monitoring/application/views/scripts/config/removebackend.phtml index e2a3e0226..bd4a95f3b 100644 --- a/modules/monitoring/application/views/scripts/config/removebackend.phtml +++ b/modules/monitoring/application/views/scripts/config/removebackend.phtml @@ -1,5 +1,5 @@ -tabs->render($this); ?> -

{{REMOVE_ICON}} Remove Backend "escape($this->name) ?>"

+ +

Remove Backend "escape($this->name) ?>"

Are you sure you want to remove the backend escape($this->name) ?>? diff --git a/modules/monitoring/application/views/scripts/config/removeinstance.phtml b/modules/monitoring/application/views/scripts/config/removeinstance.phtml index 6a9711a44..a278cf9b1 100644 --- a/modules/monitoring/application/views/scripts/config/removeinstance.phtml +++ b/modules/monitoring/application/views/scripts/config/removeinstance.phtml @@ -1,12 +1,12 @@ -tabs->render($this); ?> -

{{REMOVE_ICON}} Remove Instance "escape($this->name) ?>"

+ +

Remove Instance "escape($this->name) ?>"

Are you sure you want to remove the instance escape($this->name) ?>?

- {{WARNING_ICON}} If you have still any environments or views refering to this instance, you won't be able to send commands anymore + If you have still any environments or views refering to this instance, you won't be able to send commands anymore after deletion.

diff --git a/modules/monitoring/application/views/scripts/config/show-configuration.phtml b/modules/monitoring/application/views/scripts/config/show-configuration.phtml index 884a46aac..356c42b7b 100644 --- a/modules/monitoring/application/views/scripts/config/show-configuration.phtml +++ b/modules/monitoring/application/views/scripts/config/show-configuration.phtml @@ -1,7 +1,7 @@ tabs->render($this); ?>
-

{{ERROR_ICON}} Saving escape($this->file); ?>failed

+

Saving escape($this->file); ?>failed


Your escape($this->file); ?> configuration couldn't be stored (error: "exceptionMessage; ?>").
diff --git a/test/php/library/Icinga/Authentication/ManagerTest.php b/test/php/library/Icinga/Authentication/ManagerTest.php index 73fc430d4..18e58ff9f 100644 --- a/test/php/library/Icinga/Authentication/ManagerTest.php +++ b/test/php/library/Icinga/Authentication/ManagerTest.php @@ -179,17 +179,6 @@ class ManagerTest extends BaseTestCase $this->assertTrue($auth->isAuthenticated()); } - /** - * @expectedException Exception - * @expectedExceptionMessage Session write after close - */ - public function testWriteSessionTwice() - { - $auth = $this->getManagerInstance($session, false); - $this->assertFalse($auth->isAuthenticated(true)); - $auth->authenticate(new Credential("jdoe", "passjdoe")); - } - /** * @expectedException Icinga\Exception\ConfigurationError * @expectedExceptionMessage No authentication backend set diff --git a/test/php/library/Icinga/Authentication/PhpSessionTest.php b/test/php/library/Icinga/Authentication/PhpSessionTest.php index 793293980..cf7e2fee9 100644 --- a/test/php/library/Icinga/Authentication/PhpSessionTest.php +++ b/test/php/library/Icinga/Authentication/PhpSessionTest.php @@ -49,67 +49,54 @@ class PhpSessionTest extends BaseTestCase { private function getSession() { - if (!is_writable('/tmp')) { $this->markTestSkipped('Could not write to session directory'); } return new PhpSession( array( 'use_cookies' => false, - 'save_path' => '/tmp' + 'save_path' => '/tmp', + 'test_session_name' => 'IcingawebUnittest' ) ); - } /** - * Test the creation of a PhpSession object - * - * @runInSeparateProcess - **/ + * Test the creation of a PhpSession object + * + * @runInSeparateProcess + */ public function testSessionCreation() { $this->getSession(); } /** - * Test PhpSession::open() + * Test PhpSession::open() * - * @runInSeparateProcess + * @runInSeparateProcess */ - public function testOpenSession() + public function testSessionReadWrite() { - $this->assertEquals(session_id(), '', 'Asserting test precondition: session not being setup yet '); $session = $this->getSession(); - $session->open(); - $this->assertNotEquals(session_id(), '', 'Asserting a Session ID being available after PhpSession::open()'); + $session->purge(); + $this->assertEquals(null, $session->get('key')); + $session->set('key', 'value'); + $session->write(); + $session->read(); + $this->assertEquals('value', $session->get('key')); } /** - * Test a session being closed by PhpSession::close() + * Test a session being closed by PhpSession::close() * - * @runInSeparateProcess - **/ - public function testCloseSession() - { - $this->assertEquals(session_id(), '', 'Asserting test precondition: session not being setup yet '); - $session = $this->getSession(); - $session->open(); - $this->assertNotEquals(session_id(), '', 'Asserting a Session ID being available after PhpSession::open()'); - $session->close(); - } - - /** - * Test if a session is correctly purged when calling PhpSession::purge() - * - * @runInSeparateProcess + * @runInSeparateProcess */ public function testPurgeSession() { - $this->assertEquals(session_id(), '', 'Asserting test precondition: session not being setup yet '); $session = $this->getSession(); - $session->open(); - $this->assertNotEquals(session_id(), '', 'Asserting a Session ID being available after PhpSession::open()'); + $session->set('key2', 'value2'); $session->purge(); - $this->assertEquals(session_id(), '', 'Asserting no Session ID being available after PhpSession::purge()'); + $session->read(); + $this->assertEquals(null, $session->get('key2')); } }