Merge branch 'bugfix/ajax-requests-override-session-5101'

This commit is contained in:
Matthias Jentsch 2013-11-26 10:43:27 +01:00
commit e229d73038
36 changed files with 504 additions and 424 deletions

View File

@ -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();
}

View File

@ -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
*

View File

@ -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
*

View File

@ -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;

View File

@ -6,20 +6,9 @@ $createDbBackend = $this->href('/config/createAuthenticationBackend', array('typ
<?= $this->tabs->render($this); ?>
<?php if ($this->errorMessage): ?>
<div class="alert alert-danger">
<i class="icinga-icon-error"></i>
<strong><?= $this->escape($this->errorMessage); ?></strong>
</div>
<?php endif; ?>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>
<strong><?= $this->escape($this->successMessage); ?></strong>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<div class="panel panel-default">
<div class="panel-heading panel-title">

View File

@ -3,11 +3,10 @@
Create New Authentication Backend
</h4>
<?php if ($this->errorMessage): ?>
<div class="alert alert-danger">
<?= $this->escape($this->errorMessage); ?>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<p>
Create a new backend for authenticating your users. This backend will be added at the end of your authentication order.

View File

@ -3,11 +3,14 @@
Edit Backend "<?= $this->escape($this->name); ?>"
</h4>
<?php if ($this->errorMessage || $this->form->getErrorMessages()): ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?php if ($this->form->getErrorMessages()): ?>
<div class="alert alert-danger">
<?= $this->escape($this->errorMessage); ?>
<?php foreach ($this->form->getErrorMessages() as $error): ?>
<?= $this->escape($error); ?><br/>
<?= $this->escape($error); ?><br/>
<?php endforeach; ?>
</div>
<?php endif; ?>

View File

@ -2,4 +2,9 @@
<i class="icinga-icon-remove"></i>
Remove Backend "<?= $this->escape($this->name); ?>"
</h4>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -1,10 +1,7 @@
<?= $this->tabs->render($this); ?>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>
<strong><?= $this->escape($this->successMessage); ?></strong>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -2,6 +2,10 @@
<?php $errors = $this->form->getErrorMessages(); ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>

View File

@ -9,12 +9,9 @@ $modules = $this->modules->paginate();
<h3>Installed Modules</h3>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>
<strong><?= $this->escape($this->successMessage); ?></strong>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->paginationControl($modules, null, null, array(
'preserve' => $this->preserve

View File

@ -2,28 +2,11 @@
use Icinga\Web\Url;
$createResource = $this->href('/config/createresource');
?>
<?= $this->tabs->render($this); ?>
<?php if ($this->errorMessage): ?>
<div class="alert alert-danger">
<i class="icinga-icon-error"></i>
<strong><?= $this->escape($this->errorMessage); ?></strong>
</div>
<?php endif; ?>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>
<strong><?= $this->escape($this->successMessage); ?></strong>
</div>
<?php elseif ($this->flashMessages): ?>
<div class="alert alert-success">
<i class="icinga-icon-success"></i>
<strong><?= $this->escape($this->flashMessages); ?></strong>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<div class="panel panel-default">
<div class="panel-heading panel-title">

View File

@ -3,14 +3,12 @@
Create New Resource
</h4>
<?php if ($this->errorMessage): ?>
<div class="alert alert-danger">
<?= $this->escape($this->errorMessage); ?>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<p>
Create a new resource to describes a data sourc
Resources are entities that provide data to Icingaweb.
</p>
<?= $this->form ?>

View File

@ -3,13 +3,16 @@
Edit Resource "<?= $this->escape($this->name); ?>"
</h4>
<?php if ($this->errorMessage || $this->form->getErrorMessages()): ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?php if ($this->form->getErrorMessages()): ?>
<div class="alert alert-danger">
<?= $this->escape($this->errorMessage); ?>
<?php foreach ($this->form->getErrorMessages() as $error): ?>
<?= $this->escape($error); ?><br/>
<?= $this->escape($error); ?><br/>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -2,4 +2,9 @@
<i class="icinga-icon-remove"></i>
Remove Resource "<?= $this->escape($this->name); ?>"
</h4>
<?= $this->form ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -1,4 +1,6 @@
<?= $this->tabs->render($this); ?>
<br/>
<div class="alert alert-error">
<h4><i>WARNING ICON</i>Saving "<?= $this->escape($this->file); ?>.ini" Failed</h4>

View File

@ -1,26 +1,9 @@
<?= $this->tabs->render($this); ?>
<div class="alert alert-error">
<h1>An error occurred</h1>
<p>
<?php echo $this->message ?>
</p>
<?php if (isset($this->exception)): ?>
<div style="text-align:left;">
<h3>Exception information:</h3>
<p>
<b>Message:</b>
<?= $this->exception->getMessage(); ?>
</p>
<h3>Stack trace:</h3>
<pre>
<?= $this->exception->getTraceAsString(); ?>
</pre>
<h3>Request Parameters:</h3>
<pre><?= var_export(\Zend_Controller_Front::getInstance()->getParams(), true); ?>
</pre>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)) : ?>
<?= $this->messageBox->render() ?>
<? endif ?>
</div>

View File

@ -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();

View File

@ -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()
{

View File

@ -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();
}
/**

View File

@ -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;
}
/**

View File

@ -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;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Icinga\User;
use \Zend_Log;
use \DateTime;
/**
* Class Message
*
* A Message with an additional logging level to indicate the type.
*
* @package Icinga\User
*/
class Message {
/**
* The content of this message
*
* @var string
*/
private $message;
/**
* The logging-level of this message
*/
private $level;
/**
* Create a new Message
*
* @param string $message The message content
* @param $level The status of the message
* * Zend_Log::INFO
* * Zend_Log::ERR
*/
public function __construct($message, $level = Zend_Log::INFO) {
$this->message = $message;
$this->level = $level;
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @return The
*/
public function getLevel()
{
return $this->level;
}
}

View File

@ -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();
}
/**

View File

@ -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');
}
}

View File

@ -0,0 +1,128 @@
<?php
namespace Icinga\Web\Widget;
use \Zend_Log;
use \Zend_Form;
use \Icinga\User;
use \Icinga\User\Message;
use \Zend_View_Abstract;
use \Icinga\Authentication\Manager as AuthenticationManager;
/**
* Displays a set of alert messages to the user.
*
* The messages are fetched automatically from the current AuthenticationManager,
* but this is done lazily when render() is called, to ensure that messages will
* always be displayed before they are cleared.
*/
class AlertMessageBox implements \Icinga\Web\Widget\Widget {
/**
* Remove all messages from the current user, return them and commit
* changes to the underlying session.
*
* @return array The messages
*/
protected function getAndClearMessages()
{
$messages = $this->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 .= '<div class="alert ' . $alert['state']. '">' .
'<i class="' . $alert['icon'] . '"></i>' .
'<strong>' . htmlspecialchars($message->getMessage()) . '</strong>' .
'</div>';
}
return $html;
}
}

View File

@ -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');
}

View File

@ -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'

View File

@ -1,8 +1,8 @@
<?= $this->tabs->render($this); ?>
<?php if ($this->name): ?>
<h4><i>{{EDIT_ICON}} Edit Backend "<?= $this->escape($this->name) ?>"</h4>
<h4><i> <i class="icinga-icon-edit"></i> Edit Backend "<?= $this->escape($this->name) ?>"</h4>
<?php else: ?>
<h4>{{CREATE_ICON}} Create New Backend</h4>
<h4> <i class="icinga-icon-create"></i> Create New Backend</h4>
<?php endif; ?>
<?php if ($this->error): ?>

View File

@ -1,9 +1,8 @@
<?= $this->tabs->render($this); ?>
<?php if (isset($this->name)): ?>
<h4>{{EDIT_ICON}} Edit Instance Configuration for "<?= $this->escape($this->name) ?>"</h4>
<h4><i class="icinga-icon-edit"></i> } Edit Instance Configuration for "<?= $this->escape($this->name) ?>"</h4>
<?php else: ?>
<h4>{{CREATE_ICON}} Configure New Icinga Instance</h4>
<h4><i class="icinga-icon-create"></i> Configure New Icinga Instance</h4>
<?php endif; ?>
<?php if ($this->error): ?>

View File

@ -3,16 +3,13 @@
<h3>Monitoring Backends</h3>
<?php if ($this->successMessage): ?>
<div class="alert alert-success">
<i>{{OK_ICON}}</i>
<strong><?= $this->escape($this->successMessage); ?></strong>
</div>
<?php endif; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<div>
<a href="<?= Url::fromPath('/monitoring/config/createbackend')->getAbsoluteUrl();?>">
{{CREATE_ICON}} Create New Monitoring Backend
<i class="icinga-icon-create"></i> Create New Monitoring Backend
</a>
</div>
<br/>
@ -24,8 +21,8 @@
<b><?= $this->escape($backendName); ?></b>
<small>(Type: <?= $this->escape($config['type'] === 'ido' ? 'IDO' : ucfirst($config['type'])); ?>)</small>
<div>
<a href="<?= $removeUrl; ?>">{{REMOVE_ICON}} Remove This Backend</a><br/>
<a href="<?= $editUrl; ?>">{{EDIT_ICON}} Edit This Backend</a>
<a href="<?= $removeUrl; ?>"><i class="icinga-icon-remove"></i> Remove This Backend</a><br/>
<a href="<?= $editUrl; ?>"><i class="icinga-icon-edit"></i> Edit This Backend</a>
</div>
</div>
<br/>
@ -37,7 +34,7 @@
<div>
<a href="<?= Url::fromPath('/monitoring/config/createinstance')->getAbsoluteUrl();?>">
{{CREATE_ICON}} Create New Instance
<i class="icinga-icon-create"></i> Create New Instance
</a>
</div>
@ -50,8 +47,8 @@
<small>(Type: <?= isset($config['host']) ? 'Remote' : 'Local'; ?>)</small>
<div>
<a href="<?= $removeUrl; ?>">{{REMOVE_ICON}} Remove This Instance</a><br/>
<a href="<?= $editUrl; ?>">{{EDIT_ICON}} Edit This Instance</a>
<a href="<?= $removeUrl; ?>"><i class="icinga-icon-remove"></i> Remove This Instance</a><br/>
<a href="<?= $editUrl; ?>"><i class="icinga-icon-edit"></i> Edit This Instance</a>
</div>
</div>
<br/>

View File

@ -1,5 +1,5 @@
<?= $this->tabs->render($this); ?>
<h4>{{REMOVE_ICON}} Remove Backend "<?= $this->escape($this->name) ?>"</h4>
<h4><i class="icinga-icon-remove"></i> Remove Backend "<?= $this->escape($this->name) ?>"</h4>
<p>
Are you sure you want to remove the backend <?= $this->escape($this->name) ?>?

View File

@ -1,12 +1,12 @@
<?= $this->tabs->render($this); ?>
<h4>{{REMOVE_ICON}} Remove Instance "<?= $this->escape($this->name) ?>"</h4>
<h4><i class="icinga-icon-remove"></i> Remove Instance "<?= $this->escape($this->name) ?>"</h4>
<p>
Are you sure you want to remove the instance <?= $this->escape($this->name) ?>?
</p>
<p>
{{WARNING_ICON}} If you have still any environments or views refering to this instance, you won't be able to send commands anymore
<i class="icinga-icon-warning"></i> If you have still any environments or views refering to this instance, you won't be able to send commands anymore
after deletion.
</p>

View File

@ -1,7 +1,7 @@
<?= $this->tabs->render($this); ?>
<br/>
<div class="alert alert-error">
<h4><i>{{ERROR_ICON}}</i> Saving <?= $this->escape($this->file); ?>failed</h4>
<h4><i><i class="icinga-icon-error"></i> </i> Saving <?= $this->escape($this->file); ?>failed</h4>
<br/>
<p>
Your <?= $this->escape($this->file); ?> configuration couldn't be stored (error: "<?= $this->exceptionMessage; ?>").<br/>

View File

@ -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

View File

@ -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'));
}
}