Merge branch 'bugfix/rebuild-form-builder-5525' into bugfix/commands-6593

Conflicts:
	library/Icinga/Web/Form.php
	modules/monitoring/application/forms/Config/SecurityForm.php
This commit is contained in:
Eric Lippmann 2014-08-28 13:58:02 +02:00
commit 4ca1eaa7ce
51 changed files with 2433 additions and 3178 deletions

View File

@ -14,7 +14,6 @@ use Icinga\Exception\AuthenticationException;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\User; use Icinga\User;
use Icinga\Web\Session;
use Icinga\Web\Url; use Icinga\Web\Url;
/** /**
@ -36,7 +35,6 @@ class AuthenticationController extends ActionController
{ {
$auth = $this->Auth(); $auth = $this->Auth();
$this->view->form = $form = new LoginForm(); $this->view->form = $form = new LoginForm();
$form->setRequest($this->_request);
$this->view->title = $this->translate('Icingaweb Login'); $this->view->title = $this->translate('Icingaweb Login');
try { try {
@ -55,27 +53,17 @@ class AuthenticationController extends ActionController
$config = Config::app('authentication'); $config = Config::app('authentication');
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
throw new ConfigurationError( throw new ConfigurationError(
$this->translate( $this->translate('Could not read your authentiction.ini, no authentication methods are available.'),
'Could not read your authentiction.ini, no authentication methods are available.' 0,
) $e
); );
} }
$chain = new AuthChain($config); $chain = new AuthChain($config);
if ($this->getRequest()->isGet()) { $request = $this->getRequest();
$user = new User(''); if ($request->isPost() && $this->view->form->isValid($request->getPost())) {
foreach ($chain as $backend) { $user = new User($this->view->form->getValue('username'));
if ($backend instanceof AutoLoginBackend) { $password = $this->view->form->getValue('password');
$authenticated = $backend->authenticate($user);
if ($authenticated === true) {
$auth->setAuthenticated($user);
$this->rerenderLayout()->redirectNow($redirectUrl);
}
}
}
} elseif ($form->isSubmittedAndValid()) {
$user = new User($form->getValue('username'));
$password = $form->getValue('password');
$backendsTried = 0; $backendsTried = 0;
$backendsWithError = 0; $backendsWithError = 0;
@ -121,14 +109,25 @@ class AuthenticationController extends ActionController
); );
} }
if ($backendsWithError) { if ($backendsWithError) {
$form->addNote( $this->view->form->getElement('username')->addError(
$this->translate( $this->translate(
'Please note that not all authentication methods where available.' 'Please note that not all authentication methods where available.'
. ' Check the system log or Icinga Web 2 log for more information.' . ' Check the system log or Icinga Web 2 log for more information.'
) )
); );
} }
$form->getElement('password')->addError($this->translate('Incorrect username or password')); $this->view->form->getElement('password')->addError($this->translate('Incorrect username or password'));
} elseif ($request->isGet()) {
$user = new User('');
foreach ($chain as $backend) {
if ($backend instanceof AutoLoginBackend) {
$authenticated = $backend->authenticate($user);
if ($authenticated === true) {
$auth->setAuthenticated($user);
$this->rerenderLayout()->redirectNow($redirectUrl);
}
}
}
} }
} catch (Exception $e) { } catch (Exception $e) {
$this->view->errorInfo = $e->getMessage(); $this->view->errorInfo = $e->getMessage();

View File

@ -3,23 +3,22 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Controller\BaseConfigController; use Icinga\Web\Controller\BaseConfigController;
use Icinga\Web\Widget\Tab;
use Icinga\Web\Widget\AlertMessageBox; use Icinga\Web\Widget\AlertMessageBox;
use Icinga\Web\Notification; use Icinga\Web\Notification;
use Icinga\Application\Modules\Module; use Icinga\Application\Modules\Module;
use Icinga\Web\Url; use Icinga\Web\Form;
use Icinga\Web\Widget; use Icinga\Web\Widget;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Application\Config as IcingaConfig; use Icinga\Application\Config as IcingaConfig;
use Icinga\Data\ResourceFactory;
use Icinga\Form\Config\GeneralForm; use Icinga\Form\Config\GeneralForm;
use Icinga\Form\Config\Authentication\ReorderForm;
use Icinga\Form\Config\Authentication\LdapBackendForm; use Icinga\Form\Config\Authentication\LdapBackendForm;
use Icinga\Form\Config\Authentication\DbBackendForm; use Icinga\Form\Config\Authentication\DbBackendForm;
use Icinga\Form\Config\Authentication\AutologinBackendForm;
use Icinga\Form\Config\ResourceForm; use Icinga\Form\Config\ResourceForm;
use Icinga\Form\Config\LoggingForm; use Icinga\Form\Config\LoggingForm;
use Icinga\Form\Config\ConfirmRemovalForm; use Icinga\Form\Config\ConfirmRemovalForm;
use Icinga\Config\PreservingIniWriter; use Icinga\Config\PreservingIniWriter;
use Icinga\Exception\ConfigurationError;
/** /**
@ -27,13 +26,6 @@ use Icinga\Config\PreservingIniWriter;
*/ */
class ConfigController extends BaseConfigController class ConfigController extends BaseConfigController
{ {
/**
* The resource types that are available.
*
* @var array
*/
private $resourceTypes = array('livestatus', 'ido', 'statusdat', 'ldap');
public function init() public function init()
{ {
$this->view->tabs = Widget::create('tabs')->add('index', array( $this->view->tabs = Widget::create('tabs')->add('index', array(
@ -45,9 +37,6 @@ class ConfigController extends BaseConfigController
))->add('resources', array( ))->add('resources', array(
'title' => 'Resources', 'title' => 'Resources',
'url' => 'config/resource' 'url' => 'config/resource'
))->add('logging', array(
'title' => 'Logging',
'url' => 'config/logging'
)); ));
} }
@ -63,39 +52,20 @@ class ConfigController extends BaseConfigController
{ {
$this->view->messageBox = new AlertMessageBox(true); $this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('index'); $this->view->tabs->activate('index');
$form = new GeneralForm(); $form = new GeneralForm();
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
if ($this->writeConfigFile($form->getConfiguration(), 'config')) {
Notification::success($this->translate('New configuration has successfully been stored'));
$this->redirectNow('config');
}
}
} else {
$form->setConfiguration(IcingaConfig::app()); $form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) {
if (!$this->writeConfigFile($form->getConfig(), 'config')) {
return;
}
Notification::success('New configuration has successfully been stored');
$form->setConfiguration(IcingaConfig::app(), true);
$this->redirectNow('config/index');
}
$this->view->form = $form;
} }
/**
* Form for modifying the logging configuration
*/
public function loggingAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('logging');
$form = new LoggingForm();
$form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) {
if (!$this->writeConfigFile($form->getConfig(), 'config')) {
return;
}
Notification::success('New configuration has sucessfully been stored');
$form->setConfiguration(IcingaConfig::app(), true);
$this->redirectNow('config/logging');
}
$this->view->form = $form; $this->view->form = $form;
} }
@ -172,40 +142,47 @@ class ConfigController extends BaseConfigController
} }
/** /**
* Action for creating a new authentication backend * Action for reordering authentication backends
*/ */
public function authenticationAction() public function authenticationAction()
{ {
$config = IcingaConfig::app('authentication', true); $this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('authentication'); $this->view->tabs->activate('authentication');
$order = array_keys($config->toArray()); $config = IcingaConfig::app('authentication');
$this->view->messageBox = new AlertMessageBox(true); $backendOrder = array_keys($config->toArray());
$form = new Form();
$form->setName('form_reorder_authbackend');
$request = $this->getRequest();
if ($request->isPost()) {
$requestData = $request->getPost();
if ($form->isValid($requestData)) { // Validate the CSRF token
$reordered = false;
foreach ($backendOrder as $backendName) {
if (isset($requestData[$backendName])) {
array_splice($backendOrder, array_search($backendName, $backendOrder), 1);
array_splice($backendOrder, $requestData[$backendName], 0, $backendName);
$reordered = true;
break;
}
}
$backends = array(); if ($reordered) {
foreach ($order as $backend) { $reorderedConfig = array();
$form = new ReorderForm(); foreach ($backendOrder as $backendName) {
$form->setName('form_reorder_backend_' . $backend); $reorderedConfig[$backendName] = $config->{$backendName};
$form->setBackendName($backend); }
$form->setCurrentOrder($order);
$form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) { if ($this->writeAuthenticationFile($reorderedConfig)) {
if ($this->writeAuthenticationFile($form->getReorderedConfig($config))) { Notification::success($this->translate('Authentication order updated!'));
Notification::success('Authentication Order Updated');
$this->redirectNow('config/authentication'); $this->redirectNow('config/authentication');
} }
}
return; }
} }
$backends[] = (object) array( $this->view->form = $form->create(); // Necessary in case its a GET request
'name' => $backend, $this->view->backendNames = $backendOrder;
'reorderForm' => $form
);
}
$this->view->backends = $backends;
} }
/** /**
@ -214,38 +191,56 @@ class ConfigController extends BaseConfigController
public function createauthenticationbackendAction() public function createauthenticationbackendAction()
{ {
$this->view->messageBox = new AlertMessageBox(true); $this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('authentication');
if ($this->getRequest()->getParam('type') === 'ldap') { $backendType = $this->getRequest()->getParam('type');
$authenticationConfig = IcingaConfig::app('authentication')->toArray();
try {
switch ($backendType) {
case 'ldap':
$form = new LdapBackendForm(); $form = new LdapBackendForm();
} else { break;
case 'db':
$form = new DbBackendForm(); $form = new DbBackendForm();
break;
case 'autologin':
foreach ($authenticationConfig as $ac) {
if (array_key_exists('backend', $ac) && $ac['backend'] === 'autologin') {
throw new ConfigurationError(
$this->translate('An autologin backend already exists')
);
} }
if ($this->getParam('auth_backend')) {
$form->setBackendName($this->getParam('auth_backend'));
} }
$form->setRequest($this->getRequest()); $form = new AutologinBackendForm();
break;
default:
$this->addErrorMessage(sprintf(
$this->translate('There is no backend type `%s\''),
$backendType
));
$this->redirectNow('config/configurationerror');
}
} catch (ConfigurationError $e) {
$this->addErrorMessage($e->getMessage());
$this->redirectNow('config/configurationerror');
}
if ($form->isSubmittedAndValid()) { $request = $this->getRequest();
$backendCfg = IcingaConfig::app('authentication')->toArray(); if ($request->isPost() && $form->isValid($request->getPost())) {
foreach ($backendCfg as $backendName => $settings) { list($backendName, $backendConfig) = $form->getBackendConfig();
unset($backendCfg[$backendName]['name']); if (isset($authenticationConfig[$backendName])) {
$this->addErrorMessage(
$this->translate('Backend name already exists')
);
} else {
$authenticationConfig[$backendName] = $backendConfig;
if ($this->writeConfigFile($authenticationConfig, 'authentication')) {
$this->addSuccessMessage(
$this->translate('Backend Modification Written.')
);
$this->redirectNow('config/authentication');
} }
foreach ($form->getConfig() as $backendName => $settings) {
unset($settings->{'name'});
if (isset($backendCfg[$backendName])) {
$this->addErrorMessage('Backend name already exists');
$this->view->form = $form;
$this->render('authentication/create');
return;
} }
$backendCfg[$backendName] = $settings;
}
if ($this->writeAuthenticationFile($backendCfg)) {
// redirect to overview with success message
Notification::success('Backend Modification Written.');
$this->redirectNow("config/authentication");
}
return;
} }
$this->view->messageBox->addForm($form); $this->view->messageBox->addForm($form);
@ -266,18 +261,21 @@ class ConfigController extends BaseConfigController
$configArray = IcingaConfig::app('authentication', true)->toArray(); $configArray = IcingaConfig::app('authentication', true)->toArray();
$authBackend = $this->getParam('auth_backend'); $authBackend = $this->getParam('auth_backend');
if (!isset($configArray[$authBackend])) { if (false === isset($configArray[$authBackend])) {
$this->addErrorMessage('Can\'t edit: Unknown Authentication Backend Provided'); $this->addErrorMessage(
$this->configurationerrorAction(); $this->translate('Can\'t edit: Unknown Authentication Backend Provided')
return; );
} $this->redirectNow('config/configurationerror');
if (!array_key_exists('resource', $configArray[$authBackend])) {
$this->addErrorMessage('Configuration error: Backend "' . $authBackend . '" has no Resource');
$this->configurationerrorAction();
return;
} }
$type = ResourceFactory::getResourceConfig($configArray[$authBackend]['resource'])->type; if (false === array_key_exists('backend', $configArray[$authBackend])) {
$this->addErrorMessage(sprintf(
$this->translate('Backend "%s" has no `backend\' setting'),
$authBackend
));
$this->redirectNow('config/configurationerror');
}
$type = $configArray[$authBackend]['backend'];
switch ($type) { switch ($type) {
case 'ldap': case 'ldap':
$form = new LdapBackendForm(); $form = new LdapBackendForm();
@ -285,33 +283,38 @@ class ConfigController extends BaseConfigController
case 'db': case 'db':
$form = new DbBackendForm(); $form = new DbBackendForm();
break; break;
case 'autologin':
$form = new AutologinBackendForm();
break;
default: default:
$this->addErrorMessage('Can\'t edit: backend type "' . $type . '" of given resource not supported.'); $this->addErrorMessage(sprintf(
$this->configurationerrorAction(); $this->translate('Can\'t edit: backend type "%s" of given resource not supported.'),
return; $type
));
$this->redirectNow('config/configurationerror');
} }
$form->setBackendName($this->getParam('auth_backend')); $request = $this->getRequest();
$form->setBackend(IcingaConfig::app('authentication', true)->$authBackend); if ($request->isPost()) {
$form->setRequest($this->getRequest()); if ($form->isValid($request->getPost())) {
list($backendName, $backendConfig) = $form->getBackendConfig();
if ($form->isSubmittedAndValid()) { $configArray[$backendName] = $backendConfig;
$backendCfg = IcingaConfig::app('authentication')->toArray();
foreach ($form->getConfig() as $backendName => $settings) {
$backendCfg[$backendName] = $settings;
// Remove the old section if the backend is renamed
if ($backendName != $authBackend) { if ($backendName != $authBackend) {
unset($backendCfg[$authBackend]); unset($configArray[$authBackend]);
} }
unset($settings['name']); if ($this->writeAuthenticationFile($configArray)) {
}
if ($this->writeAuthenticationFile($backendCfg)) {
// redirect to overview with success message // redirect to overview with success message
Notification::success('Backend "' . $authBackend . '" created'); Notification::success(sprintf(
$this->redirectNow("config/authentication"); $this->translate('Backend "%s" saved'),
$backendName
));
$this->redirectNow('config/authentication');
} }
return; return;
} }
} else {
$form->setBackendConfig($authBackend, $configArray[$authBackend]);
}
$this->view->messageBox->addForm($form); $this->view->messageBox->addForm($form);
$this->view->name = $authBackend; $this->view->name = $authBackend;
@ -330,23 +333,25 @@ class ConfigController extends BaseConfigController
$configArray = IcingaConfig::app('authentication', true)->toArray(); $configArray = IcingaConfig::app('authentication', true)->toArray();
$authBackend = $this->getParam('auth_backend'); $authBackend = $this->getParam('auth_backend');
if (!isset($configArray[$authBackend])) { if (false === array_key_exists($authBackend, $configArray)) {
Notification::error('Can\'t perform removal: Unknown Authentication Backend Provided'); $this->addErrorMessage(
$this->render('authentication/remove'); $this->translate('Can\'t perform removal: Unknown authentication backend provided')
return; );
$this->redirectNow('config/configurationerror');
} }
$form = new ConfirmRemovalForm(); $form = new ConfirmRemovalForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
$form->setRemoveTarget('auth_backend', $authBackend);
if ($form->isSubmittedAndValid()) { if ($request->isPost() && $form->isValid($request->getPost())) {
unset($configArray[$authBackend]); unset($configArray[$authBackend]);
if ($this->writeAuthenticationFile($configArray)) { if ($this->writeAuthenticationFile($configArray)) {
Notification::success('Authentication Backend "' . $authBackend . '" Removed'); Notification::success(sprintf(
$this->redirectNow("config/authentication"); $this->translate('Authentication Backend "%s" Removed'),
$authBackend
));
$this->redirectNow('config/authentication');
} }
return;
} }
$this->view->form = $form; $this->view->form = $form;
@ -354,116 +359,130 @@ class ConfigController extends BaseConfigController
$this->render('authentication/remove'); $this->render('authentication/remove');
} }
public function resourceAction($showOnly = false) /**
* Display all available resources and a link to create a new one
*/
public function resourceAction()
{ {
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('resources'); $this->view->tabs->activate('resources');
$this->view->messageBox = new AlertMessageBox(true);
$this->view->resources = IcingaConfig::app('resources', true)->toArray(); $this->view->resources = IcingaConfig::app('resources', true)->toArray();
$this->render('resource');
} }
/**
* Display a form to create a new resource
*/
public function createresourceAction() public function createresourceAction()
{ {
$this->view->resourceTypes = $this->resourceTypes; $this->view->messageBox = new AlertMessageBox(true);
$resources = IcingaConfig::app('resources', true);
$form = new ResourceForm(); $form = new ResourceForm();
$form->setRequest($this->_request); $request = $this->getRequest();
if ($form->isSubmittedAndValid()) { if ($request->isPost() && $form->isValid($request->getPost())) {
$name = $form->getName(); list($name, $config) = $form->getResourceConfig();
if (isset($resources->{$name})) { $resources = IcingaConfig::app('resources')->toArray();
$this->addErrorMessage('Resource name "' . $name .'" already in use.'); if (array_key_exists($name, $resources)) {
$this->addErrorMessage(sprintf($this->translate('Resource name "%s" already in use.'), $name));
} else { } else {
$resources->{$name} = $form->getConfig(); $resources[$name] = $config;
if ($this->writeConfigFile($resources, 'resources')) { if ($this->writeConfigFile($resources, 'resources')) {
$this->addSuccessMessage('Resource "' . $name . '" created.'); $this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully created.'), $name));
$this->redirectNow("config/resource"); $this->redirectNow('config/resource');
} }
} }
} }
$this->view->messageBox = new AlertMessageBox(true);
$this->view->messageBox->addForm($form);
$this->view->form = $form; $this->view->form = $form;
$this->view->messageBox->addForm($form);
$this->render('resource/create'); $this->render('resource/create');
} }
/**
* Display a form to edit a existing resource
*/
public function editresourceAction() public function editresourceAction()
{ {
$this->view->messageBox = new AlertMessageBox(true); $this->view->messageBox = new AlertMessageBox(true);
$resources = ResourceFactory::getResourceConfigs(); // Fetch the resource to be edited
$resources = IcingaConfig::app('resources')->toArray();
$name = $this->getParam('resource'); $name = $this->getParam('resource');
if ($resources->get($name) === null) { if (false === array_key_exists($name, $resources)) {
$this->addErrorMessage('Can\'t edit: Unknown Resource Provided'); $this->addErrorMessage(sprintf($this->translate('Cannot edit "%s". Resource not found.'), $name));
$this->render('resource/modify'); $this->redirectNow('config/configurationerror');
return;
} }
$form = new ResourceForm(); $form = new ResourceForm();
if ($this->_request->isPost() === false) { $request = $this->getRequest();
$form->setOldName($name); if ($request->isPost()) {
$form->setName($name); if ($form->isValid($request->getPost())) {
} list($newName, $config) = $form->getResourceConfig();
$form->setRequest($this->_request);
$form->setResource($resources->get($name)); if ($newName !== $name) {
if ($form->isSubmittedAndValid()) { // Resource name has changed
$oldName = $form->getOldName(); unset($resources[$name]); // We can safely use unset as all values are part of the form
$name = $form->getName(); }
if ($oldName !== $name) {
unset($resources->{$oldName}); $resources[$newName] = $config;
} if ($this->writeConfigFile($resources, 'resources')) {
$resources->{$name} = $form->getConfig(); $this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully edited.'), $name));
if ($this->writeConfigFile($resources, 'resources')) { $this->redirectNow('config/resource');
$this->addSuccessMessage('Resource "' . $name . '" edited.'); }
$this->redirectNow("config/resource"); }
} } else {
return; $form->setResourceConfig($name, $resources[$name]);
} }
$this->view->messageBox->addForm($form);
$this->view->form = $form; $this->view->form = $form;
$this->view->name = $name; $this->view->messageBox->addForm($form);
$this->render('resource/modify'); $this->render('resource/modify');
} }
/**
* Display a confirmation form to remove a resource
*/
public function removeresourceAction() public function removeresourceAction()
{ {
$this->view->messageBox = new AlertMessageBox(true); $this->view->messageBox = new AlertMessageBox(true);
$resources = ResourceFactory::getResourceConfigs()->toArray(); // Fetch the resource to be removed
$resources = IcingaConfig::app('resources')->toArray();
$name = $this->getParam('resource'); $name = $this->getParam('resource');
if (!isset($resources[$name])) { if (false === array_key_exists($name, $resources)) {
$this->addSuccessMessage('Can\'t remove: Unknown resource provided'); $this->addErrorMessage(sprintf($this->translate('Cannot remove "%s". Resource not found.'), $name));
$this->render('resource/remove'); $this->redirectNow('config/configurationerror');
return;
} }
$form = new ConfirmRemovalForm();
$form->setRequest($this->getRequest());
$form->setRemoveTarget('resource', $name);
// Check if selected resource is currently used for authentication // Check if selected resource is currently used for authentication
$authConfig = IcingaConfig::app('authentication', true)->toArray(); $authConfig = IcingaConfig::app('authentication')->toArray();
foreach ($authConfig as $backendName => $config) { foreach ($authConfig as $backendName => $config) {
if (array_key_exists('resource', $config) && $config['resource'] === $name) { if (array_key_exists('resource', $config) && $config['resource'] === $name) {
$this->addErrorMessage( $this->addWarningMessage(
'Warning: The resource "' . $name . '" is currently used for user authentication by "' . $backendName . '". ' . sprintf(
' Deleting it could eventally make login impossible.' $this->translate(
'The resource "%s" is currently in use by the authentication backend "%s". ' .
'Removing the resource can result in noone being able to log in any longer.'
),
$name,
$backendName
)
); );
} }
} }
if ($form->isSubmittedAndValid()) { $form = new ConfirmRemovalForm();
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
unset($resources[$name]); unset($resources[$name]);
if ($this->writeConfigFile($resources, 'resources')) { if ($this->writeConfigFile($resources, 'resources')) {
$this->addSuccessMessage('Resource "' . $name . '" removed.'); $this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully removed.'), $name));
$this->redirectNow('config/resource'); $this->redirectNow('config/resource');
} }
return;
} }
$this->view->name = $name;
$this->view->form = $form; $this->view->form = $form;
$this->view->messageBox->addForm($form);
$this->render('resource/remove'); $this->render('resource/remove');
} }

View File

@ -82,11 +82,9 @@ class DashboardController extends ActionController
)->activate('addurl'); )->activate('addurl');
$form = new AddUrlForm(); $form = new AddUrlForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
$form->setAction(Url::fromRequest()->setParams(array())->getAbsoluteUrl()); if ($request->isPost()) {
$this->view->form = $form; if ($form->isValid($request->getPost()) && $form->isSubmitted()) {
if ($form->isSubmittedAndValid()) {
$dashboard = $this->getDashboard(); $dashboard = $this->getDashboard();
$dashboard->setComponentUrl( $dashboard->setComponentUrl(
$form->getValue('pane'), $form->getValue('pane'),
@ -99,8 +97,14 @@ class DashboardController extends ActionController
$this->redirectNow(Url::fromPath('dashboard', array('pane' => $form->getValue('pane')))); $this->redirectNow(Url::fromPath('dashboard', array('pane' => $form->getValue('pane'))));
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
return;
} }
} }
} else {
$form->create()->setDefault('url', htmlspecialchars_decode($request->getParam('url', '')));
}
$this->view->form = $form;
} }
/** /**

View File

@ -4,7 +4,6 @@
use Icinga\Web\Controller\BasePreferenceController; use Icinga\Web\Controller\BasePreferenceController;
use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tab;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Web\Url; use Icinga\Web\Url;
use Icinga\Form\Preference\GeneralForm; use Icinga\Form\Preference\GeneralForm;
use Icinga\Web\Notification; use Icinga\Web\Notification;
@ -38,23 +37,29 @@ class PreferenceController extends BasePreferenceController
*/ */
public function indexAction() public function indexAction()
{ {
$form = new GeneralForm();
$this->getTabs()->activate('general'); $this->getTabs()->activate('general');
$form->setConfiguration(IcingaConfig::app())
->setRequest($this->getRequest());
if ($form->isSubmittedAndValid()) {
try {
$this->savePreferences($form->getPreferences());
Notification::success(t('Preferences updated successfully'));
// Recreate form to show new values
// TODO(el): It must sufficient to call $form->populate(...)
$form = new GeneralForm(); $form = new GeneralForm();
$form->setConfiguration(IcingaConfig::app()); $request = $this->getRequest();
$form->setRequest($this->getRequest()); if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
try {
$this->savePreferences($form->getPreferences()->toArray());
Notification::success($this->translate('Preferences updated successfully'));
$this->redirectNow('preference');
} catch (Exception $e) { } catch (Exception $e) {
Notification::error(sprintf(t('Failed to persist preferences. (%s)'), $e->getMessage())); Notification::error(
sprintf(
$this->translate('Failed to persist preferences. (%s)'),
$e->getMessage()
)
);
} }
} }
} else {
$form->setPreferences($request->getUser()->getPreferences());
}
$this->view->form = $form; $this->view->form = $form;
} }
} }

View File

@ -13,36 +13,47 @@ use Icinga\Web\Url;
class LoginForm extends Form class LoginForm extends Form
{ {
/** /**
* Interface how the form should be created * Initialize this login form
*/ */
protected function create() public function init()
{ {
$url = Url::fromRequest()->without('renderLayout');
$this->setName('form_login'); $this->setName('form_login');
$this->addElement('text', 'username', array( $this->setSubmitLabel(t('Login'));
}
/**
* @see Form::createElements()
*/
public function createElements($formData)
{
return array(
$this->createElement(
'text',
'username',
array(
'required' => true,
'label' => t('Username'), 'label' => t('Username'),
'placeholder' => t('Please enter your username...'), 'placeholder' => t('Please enter your username...'),
'class' => false === isset($formData['username']) ? 'autofocus' : ''
)
),
$this->createElement(
'password',
'password',
array(
'required' => true, 'required' => true,
));
$redir = $this->addElement('hidden', 'redirect');
$redirectUrl = $url->shift('redirect');
if ($redirectUrl) {
$this->setDefault('redirect', $redirectUrl);
}
$this->addElement('password', 'password', array(
'label' => t('Password'), 'label' => t('Password'),
'placeholder' => t('...and your password'), 'placeholder' => t('...and your password'),
'required' => true 'class' => isset($formData['username']) ? 'autofocus' : ''
)); )
// TODO: We need a place to intercept filled forms before rendering ),
if ($this->getRequest()->getPost('username') !== null) { $this->createElement(
$this->getElement('password')->setAttrib('class', 'autofocus'); 'hidden',
} else { 'redirect',
$this->getElement('username')->setAttrib('class', 'autofocus'); array(
} 'value' => Url::fromRequest()->getParam('redirect')
$this->setAction((string) $url); )
$this->setSubmitLabel('Login'); )
);
} }
} }

View File

@ -0,0 +1,89 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Authentication;
use Zend_Validate_Callback;
/**
* Form class for adding/modifying autologin authentication backends
*/
class AutologinBackendForm extends BaseBackendForm
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_authentication_autologin');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'name',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend'),
'validators' => array(
array(
'Regex',
false,
array(
'pattern' => '/^[^\\[\\]:]+$/',
'messages' => array(
'regexNotMatch' => 'The backend name cannot contain \'[\', \']\' or \':\'.'
)
)
)
)
)
),
$this->createElement(
'text',
'strip_username_regexp',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Backend Domain Pattern'),
'helptext' => t('The domain pattern of this authentication backend'),
'value' => '/\@[^$]+$/',
'validators' => array(
new Zend_Validate_Callback(function ($value) {
return @preg_match($value, '') !== false;
})
)
)
),
$this->createElement(
'hidden',
'backend',
array(
'required' => true,
'value' => 'autologin'
)
)
);
}
/**
* Validate the configuration state of this backend
*
* Returns just true as autologins are being handled externally by the webserver.
*
* @return true
*/
public function isValidAuthenticationBackend()
{
return true;
}
}

View File

@ -4,11 +4,7 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Zend_Config;
use \Zend_Form_Element_Checkbox;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Decorator\HelpText;
/** /**
* Base form for authentication backend forms * Base form for authentication backend forms
@ -16,149 +12,83 @@ use Icinga\Web\Form\Decorator\HelpText;
abstract class BaseBackendForm extends Form abstract class BaseBackendForm extends Form
{ {
/** /**
* The name of the backend currently displayed in this form * Return whether the given values are complete/valid and check whether it is possible to connect to the backend
* *
* Will be the section in the authentication.ini file * If connection validation fails, a checkbox is prepended to the form to allow users to skip it.
* *
* @var string * @param array $data The data to validate
*/
protected $backendName = '';
/**
* The backend configuration as a Zend_Config object
* *
* @var Zend_Config * @return bool Whether the validation succeeded or not
*/
protected $backend;
/**
* The resources to use instead of the factory provided ones (use for testing)
*
* @var Zend_Config
*/
protected $resources;
/**
* Set the name of the currently displayed backend
*
* @param string $name The name to be stored as the section when persisting
*/
public function setBackendName($name)
{
$this->backendName = $name;
}
/**
* Return the backend name of this form
*
* @return string
*/
public function getBackendName()
{
return $this->backendName;
}
/**
* Return the backend configuration or a empty Zend_Config object if none is given
*
* @return Zend_Config
*/
public function getBackend()
{
return ($this->backend !== null) ? $this->backend : new Zend_Config(array());
}
/**
* Set the backend configuration for initial population
*
* @param Zend_Config $backend The backend to display in this form
*/
public function setBackend(Zend_Config $backend)
{
$this->backend = $backend;
}
/**
* Set an alternative array of resources that should be used instead of the DBFactory resource set
*
* @param array $resources The resources to use for populating the db selection field
*/
public function setResources(array $resources)
{
$this->resources = $resources;
}
/**
* Return content of the resources.ini or previously set resources
*
* @return array
*/
public function getResources()
{
if ($this->resources === null) {
return ResourceFactory::getResourceConfigs()->toArray();
} else {
return $this->resources;
}
}
/**
* Add checkbox at the beginning of the form which allows to skip logic connection validation
*/
protected function addForceCreationCheckbox()
{
$checkbox = new Zend_Form_Element_Checkbox(
array(
'name' => 'backend_force_creation',
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation'),
'order' => 0
)
);
$checkbox->addDecorator(new HelpText());
$this->addElement($checkbox);
}
/**
* Validate this form with the Zend validation mechanism and perform a logic validation of the connection.
*
* If logic validation fails, the 'backend_force_creation' checkbox is prepended to the form to allow users to
* skip the logic connection validation.
*
* @param array $data The form input to validate
*
* @return bool Whether validation succeeded or not
*/ */
public function isValid($data) public function isValid($data)
{ {
if (!parent::isValid($data)) { if (false === parent::isValid($data)) {
return false; return false;
} }
if (isset($data['backend_force_creation']) && $data['backend_force_creation']) {
return true; if (
} (false === isset($data['force_creation']) || false === $data['force_creation'])
if (!$this->isValidAuthenticationBackend()) { && false === $this->isValidAuthenticationBackend()
) {
$this->addForceCreationCheckbox(); $this->addForceCreationCheckbox();
return false; return false;
} }
return true; return true;
} }
/**
* Return an array containing all sections defined by this form as the key and all settings
* as an key-value sub-array
*
* @return array
*/
abstract public function getConfig();
/** /**
* Validate the configuration state of this backend with the concrete authentication backend. * Validate the configuration state of this backend with the concrete authentication backend.
* *
* An implementation should not throw any exception, but use the add/setErrorMessages method of * An implementation should not throw any exception, but use the add/setErrorMessages method
* Zend_Form. If the 'backend_force_creation' checkbox is set, this method won't be called. * of Zend_Form. If the 'force_creation' checkbox is set, this method won't be called.
* *
* @return bool Whether validation succeeded or not * @return bool Whether validation succeeded or not
*/ */
abstract public function isValidAuthenticationBackend(); abstract public function isValidAuthenticationBackend();
/**
* Return the backend's configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getBackendConfig()
{
$values = $this->getValues();
$name = $values['name'];
unset($values['name']);
return array($name, $values);
}
/**
* Populate the form with the given configuration values
*
* @param string $name The name of the backend
* @param array $config The configuration values
*/
public function setBackendConfig($name, array $config)
{
$config['name'] = $name;
$this->populate($config);
}
/**
* Add a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*/
protected function addForceCreationCheckbox()
{
$this->addElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
} }

View File

@ -4,10 +4,9 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Exception; use Exception;
use \Zend_Config;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Authentication\DbConnection; use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\DbUserBackend; use Icinga\Authentication\Backend\DbUserBackend;
/** /**
@ -16,113 +15,97 @@ use Icinga\Authentication\Backend\DbUserBackend;
class DbBackendForm extends BaseBackendForm class DbBackendForm extends BaseBackendForm
{ {
/** /**
* Return content of the resources.ini or previously set resources * The available database resources prepared to be used as select input data
* *
* @return array * @var array
*/ */
public function getResources() protected $resources;
/**
* Initialize this form
*
* Populates $this->resources.
*
* @throws ConfigurationError In case no database resources can be found
*/
public function init()
{ {
if ($this->resources === null) { $this->setName('form_config_authentication_db');
$res = ResourceFactory::getResourceConfigs('db')->toArray(); $this->setSubmitLabel(t('Save Changes'));
foreach (array_keys($res) as $key) { $dbResources = array_keys(
$res[$key] = $key; ResourceFactory::getResourceConfigs('db')->toArray()
);
if (empty($dbResources)) {
throw new ConfigurationError(
t('There are no database resources')
);
} }
return $res; // array_combine() is necessary in order to use the array as select input data
} else { $this->resources = array_combine($dbResources, $dbResources);
return $this->resources;
}
} }
/** /**
* Create this form and add all required elements * @see Form::createElements()
*
* @see Form::create()
*/ */
public function create() public function createElements(array $formData)
{ {
$this->setName('form_modify_backend'); return array(
$name = $this->filterName($this->getBackendName()); $this->createElement(
$this->addElement(
'text', 'text',
'backend_' . $name . '_name', 'name',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false,
'label' => t('Backend Name'), 'label' => t('Backend Name'),
'helptext' => t('The name of this authentication provider'), 'helptext' => t('The name of this authentication provider'),
'value' => $this->getBackendName()
) )
); ),
$this->createElement(
$this->addElement(
'select', 'select',
'backend_' . $name . '_resource', 'resource',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false,
'label' => t('Database Connection'), 'label' => t('Database Connection'),
'helptext' => t('The database connection to use for authenticating with this provider'), 'helptext' => t('The database connection to use for authenticating with this provider'),
'value' => $this->getBackend()->get('resource'), 'multiOptions' => $this->resources
'multiOptions' => $this->getResources()
) )
); ),
$this->createElement(
$this->addElement( 'hidden',
'button', 'backend',
'btn_submit',
array( array(
'type' => 'submit', 'required' => true,
'value' => '1', 'value' => 'db'
'escape' => false, )
'class' => 'btn btn-cta btn-wide',
'label' => '<i class="icinga-icon-save"></i> Save Backend'
) )
); );
} }
/**
* Return the datatbase authentication backend configuration for this form
*
* @return array
*
* @see BaseBackendForm::getConfig()
*/
public function getConfig()
{
$prefix = 'backend_' . $this->filterName($this->getBackendName()) . '_';
$section = $this->getValue($prefix . 'name');
$cfg = array(
'backend' => 'db',
'resource' => $this->getValue($prefix . 'resource'),
);
return array($section => $cfg);
}
/** /**
* Validate the current configuration by creating a backend and requesting the user count * Validate the current configuration by creating a backend and requesting the user count
* *
* @return bool Whether validation succeeded or not * @return bool Whether validation succeeded or not
* *
* @see BaseBackendForm::isValidAuthenticationBackend * @see BaseBackendForm::isValidAuthenticationBackend()
*/ */
public function isValidAuthenticationBackend() public function isValidAuthenticationBackend()
{ {
try { try {
$testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig( $testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig(
$this->getValue('backend_' . $this->filterName($this->getBackendName()) . '_resource') $this->getValue('resource')
)); ));
$dbUserBackend = new DbUserBackend($testConnection); $dbUserBackend = new DbUserBackend($testConnection);
if ($dbUserBackend->count() < 1) { if ($dbUserBackend->count() < 1) {
$this->addErrorMessage(t("No users found under the specified database backend")); $this->addErrorMessage(t('No users found under the specified database backend'));
return false; return false;
} }
} catch (Exception $e) { } catch (Exception $e) {
$this->addErrorMessage(sprintf(t('Using the specified backend failed: %s'), $e->getMessage())); $this->addErrorMessage(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
return false; return false;
} }
return true; return true;
} }
} }

View File

@ -4,10 +4,9 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Exception; use Exception;
use \Zend_Config;
use Icinga\Web\Form;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\LdapUserBackend; use Icinga\Authentication\Backend\LdapUserBackend;
/** /**
@ -16,154 +15,122 @@ use Icinga\Authentication\Backend\LdapUserBackend;
class LdapBackendForm extends BaseBackendForm class LdapBackendForm extends BaseBackendForm
{ {
/** /**
* Return content of the resources.ini or previously set resources * The available ldap resources prepared to be used as select input data
* *
* @return array * @var array
*/ */
public function getResources() protected $resources;
/**
* Initialize this form
*
* Populates $this->resources.
*
* @throws ConfigurationError In case no database resources can be found
*/
public function init()
{ {
if ($this->resources === null) { $this->setName('form_config_authentication_ldap');
$res = ResourceFactory::getResourceConfigs('ldap')->toArray(); $this->setSubmitLabel(t('Save Changes'));
foreach (array_keys($res) as $key) { $ldapResources = array_keys(
$res[$key] = $key; ResourceFactory::getResourceConfigs('ldap')->toArray()
);
if (empty($ldapResources)) {
throw new ConfigurationError(
t('There are no LDAP resources')
);
} }
return $res; // array_combine() is necessary in order to use the array as select input data
} else { $this->resources = array_combine($ldapResources, $ldapResources);
return $this->resources;
}
} }
/** /**
* Create this form and add all required elements * @see Form::createElements()
*
* @see Form::create()
*/ */
public function create() public function createElements(array $formData)
{ {
$this->setName('form_modify_backend'); return array(
$name = $this->filterName($this->getBackendName()); $this->createElement(
$backend = $this->getBackend();
$this->addElement(
'text', 'text',
'backend_' . $name . '_name', 'name',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false,
'label' => t('Backend Name'), 'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend'), 'helptext' => t('The name of this authentication backend')
'value' => $this->getBackendName()
) )
); ),
$this->createElement(
$this->addElement(
'select', 'select',
'backend_' . $name . '_resource', 'resource',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false,
'label' => t('LDAP Resource'), 'label' => t('LDAP Resource'),
'helptext' => t('The resource to use for authenticating with this provider'), 'helptext' => t('The resource to use for authenticating with this provider'),
'value' => $this->getBackend()->get('resource'), 'multiOptions' => $this->resources
'multiOptions' => $this->getResources()
) )
); ),
$this->createElement(
$this->addElement(
'text', 'text',
'backend_' . $name . '_user_class', 'user_class',
array( array(
'required' => true, 'required' => true,
'label' => t('LDAP User Object Class'), 'label' => t('LDAP User Object Class'),
'helptext' => t('The object class used for storing users on the ldap server'), 'helptext' => t('The object class used for storing users on the ldap server'),
'value' => $backend->get('user_class', 'inetOrgPerson') 'value' => 'inetOrgPerson'
) )
); ),
$this->createElement(
$this->addElement(
'text', 'text',
'backend_' . $name . '_user_name_attribute', 'user_name_attribute',
array( array(
'required' => true, 'required' => true,
'label' => t('LDAP User Name Attribute'), 'label' => t('LDAP User Name Attribute'),
'helptext' => t('The attribute name used for storing the user name on the ldap server'), 'helptext' => t('The attribute name used for storing the user name on the ldap server'),
'value' => $backend->get('user_name_attribute', 'uid') 'value' => 'uid'
) )
); ),
$this->createElement(
$this->addElement( 'hidden',
'button', 'backend',
'btn_submit',
array( array(
'type' => 'submit', 'required' => true,
'value' => '1', 'value' => 'ldap'
'escape' => false, )
'class' => 'btn btn-cta btn-wide',
'label' => '<i class="icinga-icon-save"></i> Save Backend'
) )
); );
} }
/** /**
* Return the ldap authentication backend configuration for this form * Validate the current configuration by connecting to a backend and requesting the user count
*
* @return array
*
* @see BaseBackendForm::getConfig()
*/
public function getConfig()
{
$prefix = 'backend_' . $this->filterName($this->getBackendName()) . '_';
$section = $this->getValue($prefix . 'name');
$cfg = array(
'backend' => 'ldap',
'resource' => $this->getValue($prefix . 'resource'),
'user_class' => $this->getValue($prefix . 'user_class'),
'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute')
);
return array($section => $cfg);
}
/**
* Validate the current configuration by creating a backend and requesting the user count
* *
* @return bool Whether validation succeeded or not * @return bool Whether validation succeeded or not
* *
* @see BaseBackendForm::isValidAuthenticationBacken * @see BaseBackendForm::isValidAuthenticationBacken()
*/ */
public function isValidAuthenticationBackend() public function isValidAuthenticationBackend()
{ {
if (! ResourceFactory::ldapAvailable()) { if (false === ResourceFactory::ldapAvailable()) {
/* // It should be possible to run icingaweb without the php ldap extension. When the user
* It should be possible to run icingaweb without the php ldap extension, when // tries to create an ldap backend without ldap being installed we display an error.
* no ldap backends are needed. When the user tries to create an ldap backend
* without ldap installed we need to show him an error.
*/
$this->addErrorMessage(t('Using ldap is not possible, the php extension "ldap" is not installed.')); $this->addErrorMessage(t('Using ldap is not possible, the php extension "ldap" is not installed.'));
return false; return false;
} }
try { try {
$cfg = $this->getConfig(); $backend = ResourceFactory::createResource(
$backendName = 'backend_' . $this->filterName($this->getBackendName()) . '_name'; ResourceFactory::getResourceConfig($this->getValue('resource'))
$backendConfig = new Zend_Config($cfg[$this->getValue($backendName)]); );
$backend = ResourceFactory::createResource(ResourceFactory::getResourceConfig($backendConfig->resource));
$testConn = new LdapUserBackend( $testConn = new LdapUserBackend(
$backend, $backend,
$backendConfig->user_class, $this->getValue('user_class'),
$backendConfig->user_name_attribute $this->getValue('user_name_attribute')
); );
$testConn->assertAuthenticationPossible(); $testConn->assertAuthenticationPossible();
/*
if ($testConn->count() === 0) {
throw new Exception('No Users Found On Directory Server');
}
*/
} catch (Exception $exc) { } catch (Exception $exc) {
$this->addErrorMessage( $this->addErrorMessage(sprintf(t('Connection validation failed: %s'), $exc->getMessage()));
t('Connection Validation Failed: ' . $exc->getMessage())
);
return false; return false;
} }

View File

@ -1,233 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Authentication;
use \Zend_Config;
use Icinga\Web\Form;
/**
* Form for modifying the authentication provider order
*/
class ReorderForm extends Form
{
/**
* The name of the current backend which will get action buttons for up and down movement
*
* @var string
*/
protected $backend;
/**
* The current ordering of all backends, required to determine possible changes
*
* @var array
*/
protected $currentOrder = array();
/**
* Set an array with the current order of all backends
*
* @param array $order An array containing backend names in the order
* they are defined in the authentication.ini
*/
public function setCurrentOrder(array $order)
{
$this->currentOrder = $order;
}
/**
* Set the name of the authentication backend for which to create the form
*
* @param string $backend The name of the authentication backend
*/
public function setBackendName($backend)
{
$this->backend = $backend;
}
/**
* Return the name of the currently set backend as it will appear in the form
*
* @return string The name of the backend
*/
public function getBackendName()
{
return $this->filterName($this->backend);
}
/**
* Create this form
*
* @see Form::create
*/
public function create()
{
if ($this->moveElementUp($this->backend, $this->currentOrder) !== $this->currentOrder) {
$upForm = new Form();
$upForm->addElement(
'hidden',
'form_backend_order',
array(
'required' => true,
'value' => join(',', $this->moveElementUp($this->backend, $this->currentOrder))
)
);
$upForm->addElement(
'button',
'btn_' . $this->getBackendName() . '_reorder_up',
array(
'type' => 'submit',
'escape' => false,
'value' => 'btn_' . $this->getBackendName() . '_reorder_up',
'name' => 'btn_' . $this->getBackendName() . '_reorder_up',
'label' => $this->getView()->icon('up.png', t('Move up in authentication order'))
)
);
$this->addSubForm($upForm, 'btn_reorder_up');
}
if ($this->moveElementDown($this->backend, $this->currentOrder) !== $this->currentOrder) {
$downForm = new Form();
$downForm->addElement(
'hidden',
'form_backend_order',
array(
'required' => true,
'value' => join(',', $this->moveElementDown($this->backend, $this->currentOrder))
)
);
$downForm->addElement(
'button',
'btn_' . $this->getBackendName() . '_reorder_down',
array(
'type' => 'submit',
'escape' => false,
'value' => 'btn_' . $this->getBackendName() . '_reorder_down',
'name' => 'btn_' . $this->getBackendName() . '_reorder_down',
'label' => $this->getView()->icon('down.png', t('Move down in authentication order'))
)
);
$this->addSubForm($downForm, 'btn_reorder_down');
}
}
/**
* Return the flattened result of $this->getValues
*
* @return array The currently set values
*
* @see Form::getValues()
*/
protected function getFlattenedValues()
{
$result = array();
foreach (parent::getValues() as $key => $value) {
if (is_array($value)) {
$result += $value;
} else {
$result[$key] = $value;
}
}
return $result;
}
/**
* Determine whether this form is submitted by testing the submit buttons of both subforms
*
* @return bool Whether the form has been submitted or not
*/
public function isSubmitted()
{
$checkData = $this->getRequest()->getParams();
return isset($checkData['btn_' . $this->getBackendName() . '_reorder_up']) ||
isset($checkData['btn_' . $this->getBackendName() . '_reorder_down']);
}
/**
* Return the reordered configuration after a reorder button has been submitted
*
* @param Zend_Config $config The configuration to reorder
*
* @return array An array containing the reordered configuration
*/
public function getReorderedConfig(Zend_Config $config)
{
$originalConfig = $config->toArray();
$newOrder = $this->getFlattenedValues();
$order = explode(',', $newOrder['form_backend_order']);
$reordered = array();
foreach ($order as $key) {
if (isset($originalConfig[$key])) {
$reordered[$key] = $originalConfig[$key];
}
}
return $reordered;
}
/**
* Static helper for moving an element in an array one slot up, if possible
*
* Example:
*
* <pre>
* $array = array('first', 'second', 'third');
* moveElementUp('third', $array); // returns ['first', 'third', 'second']
* </pre>
*
* @param string $key The key to bubble up one slot
* @param array $array The array to work with
*
* @return array The modified array
*/
protected static function moveElementUp($key, array $array)
{
for ($i = 0; $i < count($array) - 1; $i++) {
if ($array[$i + 1] === $key) {
$swap = $array[$i];
$array[$i] = $array[$i + 1];
$array[$i + 1] = $swap;
return $array;
}
}
return $array;
}
/**
* Static helper for moving an element in an array one slot down, if possible
*
* Example:
*
* <pre>
* $array = array('first', 'second', 'third');
* moveElementDown('first', $array); // returns ['second', 'first', 'third']
* </pre>
*
* @param string $key The key to bubble up one slot
* @param array $array The array to work with
*
* @return array The modified array
*/
protected static function moveElementDown($key, array $array)
{
for ($i = 0; $i < count($array) - 1; $i++) {
if ($array[$i] === $key) {
$swap = $array[$i + 1];
$array[$i + 1] = $array[$i];
$array[$i] = $swap;
return $array;
}
}
return $array;
}
}

View File

@ -12,58 +12,11 @@ use Icinga\Web\Form;
class ConfirmRemovalForm extends Form class ConfirmRemovalForm extends Form
{ {
/** /**
* The value of the target to remove * Initalize this form
*
* @var string
*/ */
private $removeTarget; public function init()
/**
* The name of the target parameter to remove
*
* @var string
*/
private $targetName;
/**
* Set the remove target in this field to be a hidden field with $name and value $target
*
* @param string $name The name to be set in the hidden field
* @param string $target The value to be set in the hidden field
*/
public function setRemoveTarget($name, $target)
{
$this->targetName = $name;
$this->removeTarget = $target;
}
/**
* Create the confirmation form
*
* @see Form::create()
*/
public function create()
{ {
$this->setName('form_confirm_removal'); $this->setName('form_confirm_removal');
$this->addElement( $this->setSubmitLabel(t('Confirm Removal'));
'hidden',
$this->targetName,
array(
'value' => $this->removeTarget,
'required' => true
)
);
$this->addElement(
'button',
'btn_submit',
array(
'type' => 'submit',
'escape' => false,
'value' => '1',
'class' => 'btn btn-cta btn-common',
'label' => '<i class="icinga-icon-remove"></i> Confirm Removal'
)
);
} }
} }

View File

@ -4,15 +4,13 @@
namespace Icinga\Form\Config; namespace Icinga\Form\Config;
use Icinga\Application\Config as IcingaConfig; use DateTimeZone;
use Icinga\Data\ResourceFactory; use Zend_Config;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Util\Translator; use Icinga\Util\Translator;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Validator\WritablePathValidator; use Icinga\Web\Form\Validator\WritablePathValidator;
use Icinga\Web\Form\Decorator\ConditionalHidden;
use DateTimeZone;
use Zend_Form_Element_Select;
use Zend_Config;
/** /**
* Configuration form for general, application-wide settings * Configuration form for general, application-wide settings
@ -20,251 +18,295 @@ use Zend_Config;
class GeneralForm extends Form class GeneralForm extends Form
{ {
/** /**
* The base directory of the icingaweb configuration * Initialize this configuration form
*
* @var string
*/ */
private $configDir = null; public function init()
/**
* The resources to use instead of the factory provided ones (use for testing)
*
* @var null
*/
private $resources;
/**
* Set a specific configuration directory to use for configuration specific default paths
*
* @param string $dir
*/
public function setConfigDir($dir)
{ {
$this->configDir = $dir; $this->setName('form_config_general');
$this->setSubmitLabel(t('Save Changes'));
} }
/** /**
* Return the config path set for this form or the application wide config path if none is set * @see Form::createElements()
*
* @return string
*
* @see IcingaConfig::configDir
*/ */
public function getConfigDir() public function createElements(array $formData)
{ {
return $this->configDir === null ? IcingaConfig::$configDir : $this->configDir; $elements = array(
$this->getLanguageSelection(),
$this->getTimezoneSelection(),
$this->getModulePathInput()
);
return array_merge(
$elements,
$this->getPreferencesElements($formData),
$this->getLoggingElements($formData)
);
} }
/** /**
* Set an alternative array of resources that should be used instead of the DBFactory resource set * Populate this form with the given configuration
* (used for testing)
* *
* @param array $resources The resources to use for populating the db selection field * @param Zend_Config $config The configuration to populate this form with
*/
public function setResources(array $resources)
{
$this->resources = $resources;
}
/**
* Return content of the resources.ini or previously set resources for displaying in the database selection field
* *
* @return array * @return self
*/ */
public function getResources() public function setConfiguration(Zend_Config $config)
{ {
if ($this->resources === null) { $defaults = array();
return ResourceFactory::getResourceConfigs()->toArray(); foreach ($config as $section => $properties) {
} else { foreach ($properties as $name => $value) {
return $this->resources; $defaults[$section . '_' . $name] = $value;
} }
} }
$this->populate($defaults);
return $this;
}
/** /**
* Add a select field for setting the default language * Return the configured configuration values
*
* @return Zend_Config
*/
public function getConfiguration()
{
$config = array();
$values = $this->getValues();
foreach ($values as $sectionAndPropertyName => $value) {
list($section, $property) = explode('_', $sectionAndPropertyName);
$config[$section][$property] = $value;
}
return new Zend_Config($config);
}
/**
* Return a select field for setting the default language
* *
* Possible values are determined by Translator::getAvailableLocaleCodes. * Possible values are determined by Translator::getAvailableLocaleCodes.
* *
* @param Zend_Config $cfg The "global" section of the config.ini * @return Zend_Form_Element
*/ */
private function addLanguageSelection(Zend_Config $cfg) protected function getLanguageSelection()
{ {
$languages = array(); $languages = array();
foreach (Translator::getAvailableLocaleCodes() as $language) { foreach (Translator::getAvailableLocaleCodes() as $language) {
$languages[$language] = $language; $languages[$language] = $language;
} }
$this->addElement( return $this->createElement(
'select', 'select',
'language', 'global_language',
array( array(
'label' => t('Default Language'), 'label' => t('Default Language'),
'required' => true, 'required' => true,
'multiOptions' => $languages, 'multiOptions' => $languages,
'helptext' => t( 'helptext' => t(
'Select the language to use by default. Can be overwritten by a user in his preferences.' 'Select the language to use by default. Can be overwritten by a user in his preferences.'
), )
'value' => $cfg->get('language', Translator::DEFAULT_LOCALE)
) )
); );
} }
/** /**
* Add a select field for setting the default timezone. * Return a select field for setting the default timezone
* *
* Possible values are determined by DateTimeZone::listIdentifiers * Possible values are determined by DateTimeZone::listIdentifiers.
* *
* @param Zend_Config $cfg The "global" section of the config.ini * @return Zend_Form_Element
*/ */
private function addTimezoneSelection(Zend_Config $cfg) protected function getTimezoneSelection()
{ {
$tzList = array(); $tzList = array();
foreach (DateTimeZone::listIdentifiers() as $tz) { foreach (DateTimeZone::listIdentifiers() as $tz) {
$tzList[$tz] = $tz; $tzList[$tz] = $tz;
} }
$helptext = 'Select the timezone to be used as the default. User\'s can set their own timezone if'
. ' they like to, but this is the timezone to be used as the default setting .';
$this->addElement( $this->addElement(
'select', 'select',
'timezone', 'global_timezone',
array( array(
'label' => 'Default Application Timezone', 'label' => t('Default Application Timezone'),
'required' => true, 'required' => true,
'multiOptions' => $tzList, 'multiOptions' => $tzList,
'helptext' => $helptext, 'helptext' => t(
'value' => $cfg->get('timezone', date_default_timezone_get()) 'Select the timezone to be used as the default. User\'s can set their own timezone if'
. ' they like to, but this is the timezone to be used as the default setting .'
),
'value' => date_default_timezone_get()
) )
); );
} }
/** /**
* Add configuration settings for module paths * Return a input field for setting the module path
*
* @param Zend_Config $cfg The "global" section of the config.ini
*/ */
private function addModuleSettings(Zend_Config $cfg) protected function getModulePathInput()
{ {
$this->addElement( $this->addElement(
'text', 'text',
'module_path', 'global_modulePath',
array( array(
'label' => 'Module Path', 'label' => t('Module Path'),
'required' => true, 'required' => true,
'helptext' => 'Contains the directories that will be searched for available modules, separated by ' . 'helptext' => t(
' colons. Modules that don\'t exist in these directories can still be symlinked in the module ' . 'Contains the directories that will be searched for available modules, separated by '
' folder, but won\'t show up in the list of disabled modules.', . 'colons. Modules that don\'t exist in these directories can still be symlinked in '
'value' => $cfg->get('modulePath', realpath(ICINGAWEB_APPDIR . '/../modules')) . 'the module folder, but won\'t show up in the list of disabled modules.'
),
'value' => realpath(ICINGAWEB_APPDIR . '/../modules')
) )
); );
} }
/** /**
* Add form elements for setting the user preference storage backend * Return form elements for setting the user preference storage backend
* *
* @param Zend_Config $cfg The Zend_config object of preference section * @param array $formData The data sent by the user
*/ */
public function addUserPreferencesDialog(Zend_Config $cfg) protected function getPreferencesElements(array $formData)
{ {
$backend = $cfg->get('type', 'ini'); $elements = array(
if ($this->getRequest()->get('preferences_type', null) !== null) { $this->createElement(
$backend = $this->getRequest()->get('preferences_type');
}
$this->addElement(
'select', 'select',
'preferences_type', 'preferences_type',
array( array(
'label' => 'User Preference Storage Type',
'required' => true, 'required' => true,
'value' => $backend, 'class' => 'autosubmit',
'label' => t('User Preference Storage Type'),
'multiOptions' => array( 'multiOptions' => array(
'ini' => 'File System (INI Files)', 'ini' => t('File System (INI Files)'),
'db' => 'Database', 'db' => t('Database'),
'null' => 'Don\'t Store Preferences' 'null' => t('Don\'t Store Preferences')
)
) )
) )
); );
if (isset($formData['preferences_type']) && $formData['preferences_type'] === 'db') {
$backends = array(); $backends = array();
foreach ($this->getResources() as $name => $resource) { foreach (ResourceFactory::getResourceConfigs()->toArray() as $name => $resource) {
if ($resource['type'] !== 'db') { if ($resource['type'] === 'db') {
continue;
}
$backends[$name] = $name; $backends[$name] = $name;
} }
}
$txtPreferencesDbResource = new Zend_Form_Element_Select( $elements[] = $this->createElement(
'select',
'preferences_resource',
array( array(
'name' => 'preferences_db_resource', 'required' => true,
'label' => 'Database Connection', 'multiOptions' => $backends,
'required' => $backend === 'db', 'label' => t('Database Connection')
'condition' => $backend === 'db',
'value' => $cfg->get('resource'),
'multiOptions' => $backends
)
);
$validator = new WritablePathValidator();
$validator->setRequireExistence();
$this->addElement($txtPreferencesDbResource);
$txtPreferencesDbResource->addDecorator(new ConditionalHidden());
$this->enableAutoSubmit(
array(
'preferences_type'
) )
); );
} }
/** return $elements;
* Create the general form, using the provided configuration
*
* @see Form::create()
*/
public function create()
{
$config = $this->getConfiguration();
$global = $config->global;
if ($global === null) {
$global = new Zend_Config(array());
}
$preferences = $config->preferences;
if ($preferences === null) {
$preferences = new Zend_Config(array());
}
$this->setName('form_config_general');
$this->addLanguageSelection($global);
$this->addTimezoneSelection($global);
$this->addModuleSettings($global);
$this->addUserPreferencesDialog($preferences);
$this->setSubmitLabel('Save Changes');
} }
/** /**
* Return an Zend_Config object containing the configuration set in this form * Return form elements to setup the application's logging
* *
* @return Zend_Config * @param array $formData The data sent by the user
*
* @return array
*/ */
public function getConfig() protected function getLoggingElements(array $formData)
{ {
$config = $this->getConfiguration(); $elements = array();
if ($config->global === null) {
$config->global = new Zend_Config(array(), true); $elements[] = $this->createElement(
} 'select',
if ($config->preferences === null) { 'logging_level',
$config->preferences = new Zend_Config(array(), true); array(
'required' => true,
'label' => t('Logging Level'),
'helptext' => t('The maximum loglevel to emit.'),
'multiOptions' => array(
0 => t('None'),
1 => t('Error'),
2 => t('Warning'),
3 => t('Information'),
4 => t('Debug')
)
)
);
$elements[] = $this->createElement(
'select',
'logging_type',
array(
'required' => true,
'class' => 'autosubmit',
'label' => t('Logging Type'),
'helptext' => t('The type of logging to utilize.'),
'multiOptions' => array(
'syslog' => 'Syslog',
'file' => t('File')
)
)
);
if (false === isset($formData['logging_type']) || $formData['logging_type'] === 'syslog') {
$elements[] = $this->createElement(
'text',
'logging_application',
array(
'required' => true,
'label' => t('Application Prefix'),
'helptext' => t('The name of the application by which to prefix syslog messages.'),
'value' => 'icingaweb',
'validators' => array(
array(
'Regex',
false,
array(
'pattern' => '/^[^\W]+$/',
'messages' => array(
'regexNotMatch' => 'The application prefix cannot contain any whitespaces.'
)
)
)
)
)
);
$elements[] = $this->createElement(
'select',
'logging_facility',
array(
'required' => true,
'label' => t('Facility'),
'helptext' => t('The Syslog facility to utilize.'),
'multiOptions' => array(
'LOG_USER' => 'LOG_USER'
)
)
);
} elseif ($formData['logging_type'] === 'file') {
$elements[] = $this->createElement(
'text',
'logging_target',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The logfile to write messages to.'),
'value' => $this->getDefaultLogDir(),
'validators' => array(new WritablePathValidator())
)
);
} }
$values = $this->getValues(); return $elements;
$cfg = clone $config;
$cfg->global->language = $values['language'];
$cfg->global->timezone = $values['timezone'];
$cfg->global->modulePath = $values['module_path'];
$cfg->preferences->type = $values['preferences_type'];
if ($cfg->preferences->type === 'db') {
$cfg->preferences->resource = $values['preferences_db_resource'];
} }
return $cfg; /**
* Return the default logging directory for type "file"
*
* @return string
*/
protected function getDefaultLogDir()
{
return realpath(Icinga::app()->getApplicationDir('../var/log/icingaweb.log'));
} }
} }

View File

@ -1,178 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
use \Zend_Config;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Web\Form\Validator\WritablePathValidator;
/**
* Form class for setting the application wide logging configuration
*/
class LoggingForm extends Form
{
/**
* Return the default logging directory for type "file"
*
* @return string
*/
protected function getDefaultLogDir()
{
return realpath(Icinga::app()->getApplicationDir() . '/../var/log/icingaweb.log');
}
/**
* Create this logging configuration form
*
* @see Form::create()
*/
public function create()
{
$this->setName('form_config_logging');
$config = $this->getConfiguration();
if (($loggingConfig = $config->logging) === null) {
$loggingConfig = new Zend_Config(array());
}
$this->addElement(
'checkbox',
'logging_enable',
array(
'required' => true,
'label' => t('Logging Enabled'),
'helptext' => t('Check this to enable logging.'),
'value' => $loggingConfig->enable ? 1 : 0
)
);
$this->addElement(
'select',
'logging_level',
array(
'required' => true,
'label' => t('Logging Level'),
'helptext' => t('The maximum loglevel to emit.'),
'value' => intval($loggingConfig->get('level', 0)),
'multiOptions' => array(
0 => t('Error'),
1 => t('Warning'),
2 => t('Information'),
3 => t('Debug')
)
)
);
$this->addElement(
'select',
'logging_type',
array(
'required' => true,
'label' => t('Logging Type'),
'helptext' => t('The type of logging to utilize.'),
'value' => $loggingConfig->get('type', 'file'),
'multiOptions' => array(
'file' => t('File'),
'syslog' => 'Syslog'
)
)
);
$this->enableAutoSubmit(array('logging_type'));
switch ($this->getRequest()->getParam('logging_type', $loggingConfig->get('type', 'file')))
{
case 'syslog':
$this->addElement(
'text',
'logging_application',
array(
'required' => true,
'label' => t('Application Prefix'),
'helptext' => t('The name of the application by which to prefix syslog messages.'),
'value' => $loggingConfig->get('application', 'icingaweb'),
'validators' => array(
array(
'Regex',
false,
array(
'pattern' => '/^[^\W]+$/',
'messages' => array(
'regexNotMatch' => 'The application prefix cannot contain any whitespaces.'
)
)
)
)
)
);
$this->addElement(
'select',
'logging_facility',
array(
'required' => true,
'label' => t('Facility'),
'helptext' => t('The Syslog facility to utilize.'),
'value' => $loggingConfig->get('facility', 'LOG_USER'),
'multiOptions' => array(
'LOG_USER' => 'LOG_USER'
)
)
);
break;
case 'file':
default:
$this->addElement(
'text',
'logging_target',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The logfile to write messages to.'),
'value' => $loggingConfig->target ? $loggingConfig->target : $this->getDefaultLogDir(),
'validators' => array(new WritablePathValidator())
)
);
}
$this->setSubmitLabel('{{SAVE_ICON}} Save Changes');
}
public function isValid($data) {
foreach ($this->getElements() as $key => $element) {
// Initialize all empty elements with their default values.
if (!isset($data[$key])) {
$data[$key] = $element->getValue();
}
}
return parent::isValid($data);
}
/**
* Return a Zend_Config object containing the state defined in this form
*
* @return Zend_Config The config defined in this form
*/
public function getConfig()
{
$values = $this->getValues();
$cfg = $this->getConfiguration()->toArray();
$cfg['logging']['enable'] = $values['logging_enable'] == 1;
$cfg['logging']['level'] = $values['logging_level'];
switch ($values['logging_type'])
{
case 'file':
$cfg['logging']['type'] = 'file';
$cfg['logging']['target'] = $values['logging_target'];
break;
case 'syslog':
$cfg['logging']['type'] = 'syslog';
$cfg['logging']['application'] = $values['logging_application'];
$cfg['logging']['facility'] = $values['logging_facility'];
break;
}
return new Zend_Config($cfg);
}
}

View File

@ -6,350 +6,47 @@ namespace Icinga\Form\Config;
use Exception; use Exception;
use Zend_Config; use Zend_Config;
use Zend_Form_Element_Checkbox;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Element\Number; use Icinga\Web\Form\Element\Number;
use Icinga\Web\Form\Decorator\HelpText; use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\ElementWrapper;
class ResourceForm extends Form class ResourceForm extends Form
{ {
/** /**
* The resource * Initialize this form
*
* @var Zend_Config
*/ */
protected $resource; public function init()
/**
* The (new) name of the resource
*
* @var string
*/
protected $name;
/**
* The old name of the resource
*
* @var string
*/
protected $oldName;
/**
* Set the current resource name
*
* @param string $name The name to set
*/
public function setName($name)
{ {
$this->name = $name; $this->setName('form_config_resource');
$this->setSubmitLabel(t('Save Changes'));
} }
/** /**
* Get the current resource name * @see Form::createElemeents()
*
* @return null|string
*/ */
public function getName() public function createElements(array $formData)
{ {
$name = $this->getValue('resource_all_name'); $elements = array();
if (!$name) { $elements[] = $this->createElement(
return $this->name;
}
return $name;
}
/**
* Set the original name of the resource
*
* @param string $name The name to set
*/
public function setOldName($name)
{
$this->oldName = $name;
}
/**
* Get the resource name that was initially set
*
* @return null|string
*/
public function getOldName()
{
$oldName = $this->getValue('resource_all_name_old');
if (!$oldName) {
return $this->oldName;
}
return $oldName;
}
/**
* Set the resource configuration to edit.
*
* @param Zend_Config $resource The config to set
*/
public function setResource(Zend_Config $resource)
{
$this->resource = $resource;
}
/**
* Get the current resource configuration.
*
* @return Zend_Config
*/
public function getResource()
{
if (!isset($this->resource)) {
$this->resource = new Zend_Config(array('type' => 'db'));
}
return $this->resource;
}
protected function addDbForm()
{
$this->addElement(
'select',
'resource_db_db',
array(
'required' => true,
'label' => t('Database Type'),
'helptext' => t('The type of SQL database you want to create.'),
'value' => $this->getResource()->get('db', 'mysql'),
'multiOptions' => array(
'mysql' => 'MySQL',
'pgsql' => 'PostgreSQL'
//'oracle' => 'Oracle'
)
)
);
$this->addElement(
'text', 'text',
'resource_db_host', 'name',
array (
'required' => true,
'label' => t('Host'),
'helptext' => t('The hostname of the database.'),
'value' => $this->getResource()->get('host', 'localhost')
)
);
$this->addElement(
new Number(
array(
'name' => 'resource_db_port',
'required' => true,
'label' => t('Port'),
'helptext' => t('The port to use.'),
'value' => $this->getResource()->get('port', 3306)
)
)
);
$this->addElement(
'text',
'resource_db_dbname',
array(
'required' => true,
'label' => t('Database Name'),
'helptext' => t('The name of the database to use'),
'value' => $this->getResource()->get('dbname', '')
)
);
$this->addElement(
'text',
'resource_db_username',
array (
'required' => true,
'label' => t('Username'),
'helptext' => t('The user name to use for authentication.'),
'value' => $this->getResource()->get('username', '')
)
);
$this->addElement(
'password',
'resource_db_password',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Password'),
'helptext' => t('The password to use for authentication'),
'value' => $this->getResource()->get('password', '')
)
);
}
protected function addStatusdatForm()
{
$this->addElement(
'text',
'resource_statusdat_status_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga status.dat file'),
'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/status.dat')
)
);
$this->addElement(
'text',
'resource_statusdat_object_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga objects.cache file'),
'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/objects.cache')
)
);
}
protected function addLivestatusForm()
{
$this->addElement(
'text',
'resource_livestatus_socket',
array(
'required' => true,
'label' => t('Socket'),
'helptext' => t('The path to your livestatus socket used for querying monitoring data'),
'value' => $this->getResource()->get('socket', '/usr/local/icinga/var/rw/livestatus')
)
);
}
protected function addLdapForm()
{
$this->addElement(
'text',
'resource_ldap_hostname',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Host'),
'helptext' => t('The hostname or address of the LDAP server to use for authentication'),
'value' => $this->getResource()->get('hostname', 'localhost')
)
);
$this->addElement(
'text',
'resource_ldap_root_dn',
array(
'required' => true,
'label' => t('Root DN'),
'helptext' => t('The path where users can be found on the ldap server'),
'value' => $this->getResource()->get('root_dn', 'ou=people,dc=icinga,dc=org')
)
);
$this->addElement(
'text',
'resource_ldap_bind_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'helptext' => t('The user dn to use for querying the ldap server'),
'value' => $this->getResource()->get('bind_dn', 'cn=admin,cn=config')
)
);
$this->addElement(
'password',
'resource_ldap_bind_pw',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Bind Password'),
'helptext' => t('The password to use for querying the ldap server'),
'value' => $this->getResource()->get('bind_pw', '')
)
);
}
protected function addFileForm()
{
$this->addElement(
'text',
'resource_file_filename',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The filename to fetch information from'),
'value' => $this->getResource()->get('filename', '')
)
);
$this->addElement(
'text',
'resource_file_fields',
array(
'required' => true,
'label' => t('Pattern'),
'helptext' => t('The regular expression by which to identify columns'),
'value' => $this->getResource()->get('fields', '')
)
);
}
protected function addNameFields()
{
$this->addElement(
'text',
'resource_all_name',
array( array(
'required' => true, 'required' => true,
'label' => t('Resource Name'), 'label' => t('Resource Name'),
'helptext' => t('The unique name of this resource'), 'helptext' => t('The unique name of this resource')
'value' => $this->getName()
) )
); );
$elements[] = $this->createElement(
$this->addElement(
'hidden',
'resource_all_name_old',
array(
'value' => $this->getOldName()
)
);
}
/**
* Add checkbox at the beginning of the form which allows to skip connection validation
*/
protected function addForceCreationCheckbox()
{
$checkbox = new Zend_Form_Element_Checkbox(
array(
'order' => 0,
'name' => 'resource_force_creation',
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
$checkbox->addDecorator(new HelpText());
$this->addElement($checkbox);
}
/**
* Add a select box for choosing the type to use for this backend
*/
protected function addTypeSelectionBox()
{
$this->addElement(
'select', 'select',
'resource_type', 'type',
array( array(
'required' => true, 'required' => true,
'class' => 'autosubmit',
'label' => t('Resource Type'), 'label' => t('Resource Type'),
'helptext' => t('The type of resource'), 'helptext' => t('The type of resource'),
'value' => $this->getResource()->type,
'multiOptions' => array( 'multiOptions' => array(
'db' => t('SQL Database'), 'db' => t('SQL Database'),
'ldap' => 'LDAP', 'ldap' => 'LDAP',
@ -359,60 +56,76 @@ class ResourceForm extends Form
) )
) )
); );
$this->enableAutoSubmit(array('resource_type'));
if (isset($formData['force_creation']) && $formData['force_creation']) {
// In case the resource name already exists and the checkbox was displayed before
$elements[] = $this->getForceCreationCheckbox();
}
if (false === isset($formData['type']) || $formData['type'] === 'db') {
return array_merge($elements, $this->getDbElements());
} elseif ($formData['type'] === 'statusdat') {
return array_merge($elements, $this->getStatusdatElements());
} elseif ($formData['type'] === 'livestatus') {
return array_merge($elements, $this->getLivestatusElements());
} elseif ($formData['type'] === 'ldap') {
return array_merge($elements, $this->getLdapElements());
} elseif ($formData['type'] === 'file') {
return array_merge($elements, $this->getFileElements());
}
} }
/** /**
* Validate this form with the Zend validation mechanism and perform a validation of the connection * Return whether the given values are complete/valid and check whether it is possible to connect to the resource
* *
* If validation fails, the 'resource_force_creation' checkbox is prepended to the form to allow users to * If connection validation fails, a checkbox is prepended to the form to allow users to skip it.
* skip the connection validation
* *
* @param array $data The form input to validate * @param array $data The data to validate
* *
* @return bool True when validation succeeded, false if not * @return bool Whether the validation succeeded or not
*/ */
public function isValid($data) public function isValid($data)
{ {
if (!parent::isValid($data)) { if (false === parent::isValid($data)) {
return false; return false;
} }
if (isset($data['resource_force_creation']) && $data['resource_force_creation']) {
return true; if (
} (false === isset($data['force_creation']) || false == $data['force_creation'])
if (!$this->isValidResource()) { && false === $this->isValidResource()
$this->addForceCreationCheckbox(); ) {
$this->addElement($this->getForceCreationCheckbox());
return false; return false;
} }
return true; return true;
} }
/** /**
* Test if the changed resource is a valid resource, by instantiating it and * Return whether a connection can be established with the current resource configuration values
* checking if a connection is possible
* *
* @return bool True when a connection to the resource is possible * @return bool Whether the connection validation was successful or not
*/ */
public function isValidResource() public function isValidResource()
{ {
$config = $this->getConfig(); list($name, $config) = $this->getResourceConfig();
try { try {
switch ($config->type) { switch ($config['type']) {
case 'db': case 'db':
/* /*
* It should be possible to run icingaweb without the pgsql or mysql extension or Zend-Pdo-Classes, * It should be possible to run icingaweb without the pgsql or mysql extension or Zend-Pdo-Classes,
* in case they aren't actually used. When the user tries to create a resource that depends on an * in case they aren't actually used. When the user tries to create a resource that depends on an
* uninstalled extension, an error should be displayed. * uninstalled extension, an error should be displayed.
*/ */
if ($config->db === 'mysql' && !ResourceFactory::mysqlAvailable()) { if ($config['db'] === 'mysql' && false === ResourceFactory::mysqlAvailable()) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "mysql" and the ' . t('You need to install the php extension "mysql" and the ' .
'Zend_Pdo_Mysql classes to use MySQL database resources.') 'Zend_Pdo_Mysql classes to use MySQL database resources.')
); );
return false; return false;
} }
if ($config->db === 'pgsql' && !ResourceFactory::pgsqlAvailable()) { if ($config['db'] === 'pgsql' && false === ResourceFactory::pgsqlAvailable()) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "pgsql" and the ' . t('You need to install the php extension "pgsql" and the ' .
'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.') 'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.')
@ -420,30 +133,31 @@ class ResourceForm extends Form
return false; return false;
} }
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->getConnection()->getConnection(); $resource->getConnection()->getConnection();
break; break;
case 'statusdat': case 'statusdat':
if (!file_exists($config->object_file) || !file_exists($config->status_file)) { if (
false === file_exists($config['object_file'])
|| false === file_exists($config['status_file'])
) {
$this->addErrorMessage( $this->addErrorMessage(
t('Connectivity validation failed, the provided file does not exist.') t('Connectivity validation failed. At least one of the provided files does not exist.')
); );
return false; return false;
} }
break; break;
case 'livestatus': case 'livestatus':
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect()->disconnect(); $resource->connect()->disconnect();
break; break;
case 'ldap': case 'ldap':
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect(); $resource->connect();
break; break;
case 'file': case 'file':
if (!file_exists($config->filename)) { if (false === file_exists($config['filename'])) {
$this->addErrorMessage( $this->addErrorMessage(t('Connectivity validation failed. The provided file does not exist.'));
t('Connectivity validation failed, the provided file does not exist.')
);
return false; return false;
} }
break; break;
@ -456,51 +170,274 @@ class ResourceForm extends Form
return true; return true;
} }
public function create() /**
* Return the resource configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getResourceConfig()
{ {
$this->addNameFields(); $values = $this->getValues();
$this->addTypeSelectionBox(); $name = $values['name'];
unset($values['name']);
switch ($this->getRequest()->getParam('resource_type', $this->getResource()->type)) { return array($name, $values);
case 'db':
$this->addDbForm();
break;
case 'statusdat':
$this->addStatusdatForm();
break;
case 'livestatus':
$this->addLivestatusForm();
break;
case 'ldap':
$this->addLdapForm();
break;
case 'file':
$this->addFileForm();
break;
}
$this->setSubmitLabel('{{SAVE_ICON}} Save Changes');
} }
/** /**
* Return a configuration containing the backend settings entered in this form * Populate the form with the given configuration values
* *
* @return Zend_Config The updated configuration for this backend * @param string $name The name of the resource
* @param array $config The configuration values
*/ */
public function getConfig() public function setResourceConfig($name, array $config)
{ {
$values = $this->getValues(); $config['name'] = $name;
$this->populate($config);
$result = array('type' => $values['resource_type']);
foreach ($values as $key => $value) {
if ($key !== 'resource_type' && $key !== 'resource_all_name' && $key !== 'resource_all_name_old') {
$configKey = explode('_', $key, 3);
if (count($configKey) === 3) {
$result[$configKey[2]] = $value;
}
}
} }
return new Zend_Config($result); /**
* Return a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*
* @return Zend_Form_Element
*/
protected function getForceCreationCheckbox()
{
return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
/**
* Return all required elements to define a resource of type "db"
*
* @return array
*/
protected function getDbElements()
{
return array(
$this->createElement(
'select',
'db',
array(
'required' => true,
'label' => t('Database Type'),
'helptext' => t('The type of SQL database'),
'multiOptions' => array(
'mysql' => 'MySQL',
'pgsql' => 'PostgreSQL'
//'oracle' => 'Oracle'
)
)
),
$this->createElement(
'text',
'host',
array (
'required' => true,
'label' => t('Host'),
'helptext' => t('The hostname of the database'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'helptext' => t('The port to use'),
'value' => 3306,
'decorators' => array( // The order is important!
'ViewHelper',
'Errors',
new ElementWrapper(),
new HelpText()
)
)
),
$this->createElement(
'text',
'dbname',
array(
'required' => true,
'label' => t('Database Name'),
'helptext' => t('The name of the database to use')
)
),
$this->createElement(
'text',
'username',
array (
'required' => true,
'label' => t('Username'),
'helptext' => t('The user name to use for authentication')
)
),
$this->createElement(
'password',
'password',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Password'),
'helptext' => t('The password to use for authentication')
)
)
);
}
/**
* Return all required elements to define a resource of type "statusdat"
*
* @return array
*/
protected function getStatusdatElements()
{
return array(
$this->createElement(
'text',
'status_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga status.dat file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/status.dat')
)
),
$this->createElement(
'text',
'object_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga objects.cache file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/objects.cache')
)
)
);
}
/**
* Return all required elements to define a resource of type "livestatus"
*
* @return array
*/
protected function getLivestatusElements()
{
return array(
$this->createElement(
'text',
'socket',
array(
'required' => true,
'label' => t('Socket'),
'helptext' => t('The path to your livestatus socket used for querying monitoring data'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus')
)
)
);
}
/**
* Return all required elements to define a resource of type "ldap"
*
* @return array
*/
protected function getLdapElements()
{
return array(
$this->createElement(
'text',
'hostname',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Host'),
'helptext' => t('The hostname or address of the LDAP server to use for authentication'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'helptext' => t('The port of the LDAP server to use for authentication'),
'value' => 389,
'decorators' => array( // The order is important!
'ViewHelper',
'Errors',
new ElementWrapper(),
new HelpText()
)
)
),
$this->createElement(
'text',
'root_dn',
array(
'required' => true,
'label' => t('Root DN'),
'helptext' => t('The path where users can be found on the ldap server')
)
),
$this->createElement(
'text',
'bind_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'helptext' => t('The user dn to use for querying the ldap server')
)
),
$this->createElement(
'password',
'bind_pw',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Bind Password'),
'helptext' => t('The password to use for querying the ldap server')
)
)
);
}
/**
* Return all required elements to define a resource of type "file"
*
* @return array
*/
protected function getFileElements()
{
return array(
$this->createElement(
'text',
'filename',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The filename to fetch information from')
)
),
$this->createElement(
'text',
'fields',
array(
'required' => true,
'label' => t('Pattern'),
'helptext' => t('The regular expression by which to identify columns')
)
)
);
} }
} }

View File

@ -5,12 +5,8 @@
namespace Icinga\Form\Dashboard; namespace Icinga\Form\Dashboard;
use Icinga\Application\Config as IcingaConfig; use Icinga\Application\Config as IcingaConfig;
use Icinga\Web\Form;
use Icinga\Web\Widget\Dashboard; use Icinga\Web\Widget\Dashboard;
use Zend_Form_Element_Text; use Icinga\Web\Form;
use Zend_Form_Element_Submit;
use Zend_Form_Element_Hidden;
use Zend_Form_Element_Select;
/** /**
* Form to add an url a dashboard pane * Form to add an url a dashboard pane
@ -18,124 +14,106 @@ use Zend_Form_Element_Select;
class AddUrlForm extends Form class AddUrlForm extends Form
{ {
/** /**
* Add a selection box for different panes to the form * Initialize this form
*
* @param Dashboard $dashboard The dashboard to retrieve the panes from
*/ */
private function addPaneSelectionBox(Dashboard $dashboard) public function init()
{ {
$selectPane = new Zend_Form_Element_Select( $this->setName('form_dashboard_addurl');
'pane', $this->setSubmitLabel(t('Add To Dashboard'));
array(
'label' => 'Dashboard',
'required' => true,
'style' => 'display:inline-block;',
'multiOptions' => $dashboard->getPaneKeyTitleArray()
)
);
$newDashboardBtn = new Zend_Form_Element_Submit(
'create_new_pane',
array(
'label' => 'Create A New Pane',
'required' => false,
'class' => 'btn btn-default',
'style' => 'display:inline-block'
)
);
$newDashboardBtn->removeDecorator('DtDdWrapper');
$selectPane->removeDecorator('DtDdWrapper');
$selectPane->removeDecorator('htmlTag');
$this->addElement($selectPane);
$this->addElement($newDashboardBtn);
$this->enableAutoSubmit(array('create_new_pane'));
} }
/** /**
* Add a textfield for creating a new pane to this form * @see Form::createElements()
*/ */
private function addNewPaneTextField($showExistingButton = true) public function createElements(array $formData)
{ {
$txtCreatePane = new Zend_Form_Element_Text( $elements = array(
'pane', $this->createElement(
array(
'label' => 'New Dashboard Title',
'required' => true,
'style' => 'display:inline-block'
)
);
// Marks this field as a new pane (and prevents the checkbox being displayed when validation errors occur)
$markAsNewPane = new Zend_Form_Element_Hidden(
'create_new_pane',
array(
'required' => true,
'value' => 1
)
);
$cancelDashboardBtn = new Zend_Form_Element_Submit(
'use_existing_dashboard',
array(
'class' => 'btn',
'escape' => false,
'label' => 'Use An Existing Dashboard',
'required' => false
)
);
$cancelDashboardBtn->removeDecorator('DtDdWrapper');
$txtCreatePane->removeDecorator('DtDdWrapper');
$txtCreatePane->removeDecorator('htmlTag');
$this->addElement($txtCreatePane);
if ($showExistingButton) {
$this->addElement($cancelDashboardBtn);
}
$this->addElement($markAsNewPane);
}
/**
* Add elements to this form (used by extending classes)
*/
protected function create()
{
$dashboard = new Dashboard();
$this->setName('form_dashboard_add');
$dashboard->readConfig(IcingaConfig::app('dashboard/dashboard'));
$this->addElement(
'text', 'text',
'url', 'url',
array( array(
'label' => 'Url',
'required' => true, 'required' => true,
'value' => htmlspecialchars_decode($this->getRequest()->getParam('url', '')) 'label' => t('Url'),
'helptext' => t('The url being loaded in the dashlet')
)
) )
); );
$elems = $dashboard->getPaneKeyTitleArray();
if (empty($elems) || // show textfield instead of combobox when no pane is available $paneSelectionValues = $this->getDashboardPaneSelectionValues();
($this->getRequest()->getPost('create_new_pane', '0') && // or when a new pane should be created (+ button) if (empty($paneSelectionValues) ||
!$this->getRequest()->getPost('use_existing_dashboard', '0')) // and the user didn't click the 'use ((isset($formData['create_new_pane']) && $formData['create_new_pane'] != false) &&
// existing' button (false === isset($formData['use_existing_dashboard']) || $formData['use_existing_dashboard'] != true))
) { ) {
$this->addNewPaneTextField(!empty($elems)); $elements[] = $this->createElement(
'text',
'pane',
array(
'required' => true,
'label' => t("The New Pane's Title"),
'style' => 'display: inline-block'
)
);
$elements[] = $this->createElement( // Prevent the button from being displayed again on validation errors
'hidden',
'create_new_pane',
array(
'value' => 1
)
);
if (false === empty($paneSelectionValues)) {
$elements[] = $this->createElement(
'submit',
'use_existing_dashboard',
array(
'ignore' => true,
'label' => t('Use An Existing Pane'),
'style' => 'display: inline-block'
)
);
}
} else { } else {
$this->addPaneSelectionBox($dashboard); $elements[] = $this->createElement(
'select',
'pane',
array(
'required' => true,
'label' => t('Pane'),
'style' => 'display: inline-block;',
'multiOptions' => $paneSelectionValues
)
);
$elements[] = $this->createElement(
'submit',
'create_new_pane',
array(
'ignore' => true,
'label' => t('Create A New Pane'),
'style' => 'display: inline-block'
)
);
} }
$this->addElement( $elements[] = $this->createElement(
'text', 'text',
'component', 'component',
array( array(
'label' => 'Title',
'required' => true, 'required' => true,
'label' => t('Title'),
'helptext' => t('The title for the dashlet')
) )
); );
$this->setSubmitLabel("Add To Dashboard"); return $elements;
}
/**
* Return the names and titles of the available dashboard panes as key-value array
*
* @return array
*/
protected function getDashboardPaneSelectionValues()
{
$dashboard = new Dashboard();
$dashboard->readConfig(IcingaConfig::app('dashboard/dashboard'));
return $dashboard->getPaneKeyTitleArray();
} }
} }

View File

@ -1,65 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Install;
use Zend_Config;
use Icinga\Web\Wizard\Page;
use Icinga\Form\Config\LoggingForm;
class LoggingPage extends Page
{
/**
* The logging form
*
* @var LoggingForm
*/
protected $loggingForm;
/**
* Initialize this LoggingPage
*/
public function init()
{
$this->setName('logging');
}
/**
* Create and return the logging form
*
* @return LoggingForm
*/
protected function createForm()
{
if ($this->loggingForm === null) {
$this->loggingForm = new LoggingForm();
$this->loggingForm->hideButtons();
$this->loggingForm->setTokenDisabled();
$this->loggingForm->setRequest($this->getRequest());
$this->loggingForm->setConfiguration($this->getConfiguration());
}
return $this->loggingForm;
}
/**
* Create this wizard page
*/
protected function create()
{
$loggingForm = $this->createForm();
$loggingForm->buildForm(); // Needs to get called manually as it's nothing that Zend knows about
$this->addSubForm($loggingForm, $loggingForm->getName());
}
/**
* Return a config containing all values provided by the user
*
* @return Zend_Config
*/
public function getConfig()
{
return $this->createForm()->getConfig();
}
}

View File

@ -4,147 +4,168 @@
namespace Icinga\Form\Preference; namespace Icinga\Form\Preference;
use \DateTimeZone; use DateTimeZone;
use \Zend_Config; use Icinga\Web\Form;
use \Zend_Form_Element_Text; use Icinga\Util\Translator;
use \Zend_Form_Element_Select; use Icinga\User\Preferences;
use \Zend_View_Helper_DateFormat;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Validator\TimeFormatValidator;
use \Icinga\Web\Form\Validator\DateFormatValidator;
use \Icinga\Util\Translator;
/** /**
* General user preferences * General user preferences
*/ */
class GeneralForm extends Form class GeneralForm extends Form
{ {
/**
* Initialize this preferences config form
*/
public function init()
{
$this->setName('form_config_preferences');
$this->setSubmitLabel(t('Save Changes'));
}
/** /**
* Add a select field for setting the user's language * Add a select field for setting the user's language
* *
* Possible values are determined by Translator::getAvailableLocaleCodes. * Possible values are determined by Translator::getAvailableLocaleCodes.
* Also, a 'use default format' checkbox is added in order to allow a user to discard his overwritten setting * Also, a 'use browser language' checkbox is added in order to allow a user to discard his setting
* *
* @param Zend_Config $cfg The "global" section of the config.ini to be used as default value * @param array $formData The data sent by the user
*/ */
private function addLanguageSelection(Zend_Config $cfg) protected function getLanguageElements(array $formData)
{ {
$languages = array(); $languages = array();
foreach (Translator::getAvailableLocaleCodes() as $language) { foreach (Translator::getAvailableLocaleCodes() as $language) {
$languages[$language] = $language; $languages[$language] = $language;
} }
$prefs = $this->getUserPreferences();
$useDefaultLanguage = $this->getRequest()->getParam('default_language', !$prefs->has('app.language'));
$this->addElement( $useBrowserLanguage = isset($formData['browser_language']) ? $formData['browser_language'] == 1 : true;
'checkbox',
'default_language',
array(
'label' => t('Use Default Language'),
'value' => $useDefaultLanguage,
'required' => true
)
);
$selectOptions = array( $selectOptions = array(
'label' => t('Your Current Language'), 'label' => t('Your Current Language'),
'required' => !$useDefaultLanguage, 'required' => false === $useBrowserLanguage,
'multiOptions' => $languages, 'multiOptions' => $languages,
'helptext' => t('Use the following language to display texts and messages'), 'helptext' => t('Use the following language to display texts and messages'),
'value' => $prefs->get('app.language', $cfg->get('language', Translator::DEFAULT_LOCALE)) 'value' => substr(setlocale(LC_ALL, 0), 0, 5)
); );
if ($useDefaultLanguage) { if ($useBrowserLanguage) {
$selectOptions['disabled'] = 'disabled'; $selectOptions['disabled'] = 'disabled';
} }
$this->addElement('select', 'language', $selectOptions);
$this->enableAutoSubmit(array('default_language')); return array(
$this->createElement(
'checkbox',
'browser_language',
array(
'required' => true,
'class' => 'autosubmit',
'label' => t('Use your browser\'s language suggestions'),
'value' => $useBrowserLanguage
)
),
$this->createElement('select', 'language', $selectOptions)
);
} }
/** /**
* Add a select field for setting the user's timezone. * Add a select field for setting the user's timezone
* *
* Possible values are determined by DateTimeZone::listIdentifiers * Possible values are determined by DateTimeZone::listIdentifiers.
* Also, a 'use default format' checkbox is added in order to allow a user to discard his overwritten setting * Also, a 'use local timezone' checkbox is added in order to allow a user to discard his overwritten setting
* *
* @param Zend_Config $cfg The "global" section of the config.ini to be used as default value * @param array $formData The data sent by the user
*/ */
private function addTimezoneSelection(Zend_Config $cfg) protected function getTimezoneElements(array $formData)
{ {
$tzList = array(); $tzList = array();
foreach (DateTimeZone::listIdentifiers() as $tz) { foreach (DateTimeZone::listIdentifiers() as $tz) {
$tzList[$tz] = $tz; $tzList[$tz] = $tz;
} }
$helptext = 'Use the following timezone for dates and times';
$prefs = $this->getUserPreferences();
$useGlobalTimezone = $this->getRequest()->getParam('default_timezone', !$prefs->has('app.timezone'));
$selectTimezone = new Zend_Form_Element_Select( $useLocalTimezone = isset($formData['local_timezone']) ? $formData['local_timezone'] == 1 : true;
array( $selectOptions = array(
'name' => 'timezone',
'label' => 'Your Current Timezone', 'label' => 'Your Current Timezone',
'required' => !$useGlobalTimezone, 'required' => false === $useLocalTimezone,
'multiOptions' => $tzList, 'multiOptions' => $tzList,
'helptext' => $helptext, 'helptext' => t('Use the following timezone for dates and times'),
'value' => $prefs->get('app.timezone', $cfg->get('timezone', date_default_timezone_get())) 'value' => date_default_timezone_get()
)
); );
$this->addElement( if ($useLocalTimezone) {
'checkbox', $selectOptions['disabled'] = 'disabled';
'default_timezone',
array(
'label' => 'Use Default Timezone',
'value' => $useGlobalTimezone,
'required' => true
)
);
if ($useGlobalTimezone) {
$selectTimezone->setAttrib('disabled', 1);
} }
$this->addElement($selectTimezone);
$this->enableAutoSubmit(array('default_timezone')); return array(
$this->createElement(
'checkbox',
'local_timezone',
array(
'required' => true,
'class' => 'autosubmit',
'label' => t('Use your local timezone'),
'value' => $useLocalTimezone,
)
),
$this->createElement('select', 'timezone', $selectOptions)
);
} }
/** /**
* Create the general form, using the global configuration as fallback values for preferences * @see Form::createElements()
*
* @see Form::create()
*/ */
public function create() public function createElements(array $formData)
{ {
$this->setName('form_preference_set'); $elements = array_merge($this->getLanguageElements($formData), $this->getTimezoneElements($formData));
$elements[] = $this->createElement(
$config = $this->getConfiguration();
$global = $config->global;
if ($global === null) {
$global = new Zend_Config(array());
}
$this->addLanguageSelection($global);
$this->addTimezoneSelection($global);
$this->setSubmitLabel('Save Changes');
$this->addElement(
'checkbox', 'checkbox',
'show_benchmark', 'show_benchmark',
array( array(
'label' => 'Use benchmark', 'label' => t('Use benchmark')
'value' => $this->getUserPreferences()->get('app.show_benchmark')
) )
); );
return $elements;
} }
/** /**
* Return an array containing the preferences set in this form * Populate the form with the given preferences
* *
* @return array * @param Preferences $preferences The preferences to populate the form with
*
* @return self
*/
public function setPreferences(Preferences $preferences)
{
$defaults = array(
'browser_language' => $preferences->get('app.language') === null,
'local_timezone' => $preferences->get('app.timezone') === null
);
if ($preferences->get('app.language') !== null) {
$defaults['language'] = $preferences->get('app.language');
}
if ($preferences->get('app.timezone') !== null) {
$defaults['timezone'] = $preferences->get('app.timezone');
}
if ($preferences->get('app.show_benchmark')) {
$defaults['show_benchmark'] = $preferences->get('app.show_benchmark');
}
$this->setDefaults($defaults);
return $this;
}
/**
* Return the configured preferences
*
* @return Preferences
*/ */
public function getPreferences() public function getPreferences()
{ {
$values = $this->getValues(); $values = $this->getValues();
return array( return new Preferences(
'app.language' => $values['default_language'] ? null : $values['language'], array(
'app.timezone' => $values['default_timezone'] ? null : $values['timezone'], 'app.language' => $values['browser_language'] ? null : $values['language'],
'app.show_benchmark' => $values['show_benchmark'] === '1' ? true : false 'app.timezone' => $values['local_timezone'] ? null : $values['timezone'],
'app.show_benchmark' => $values['show_benchmark'] ? $values['show_benchmark'] : null
)
); );
} }
} }

View File

@ -1,45 +1,57 @@
<div class="controls"> <div class="controls">
<?= $this->tabs ?> <?= $tabs; ?>
</div> </div>
<div class="content" data-base-target="_next"> <div class="content" data-base-target="_next">
<?php <?= $messageBox; ?>
if (isset($this->messageBox)) {
// TODO: Get rid of such boxes -> notifications?
echo $this->messageBox->render();
}
?>
<p> <p>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'ldap')) ?>"><?= $this->icon('create.png'); ?> Create A New LDAP Authentication Backend</a> <a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'ldap')); ?>">
<br /> <?= $this->icon('create.png'); ?><?= $this->translate('Create A New LDAP Authentication Backend'); ?>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'db')) ?>"><?= $this->icon('create.png'); ?> Create A New DB Authentication Backend</a> </a>
<br>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'db')); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New DB Authentication Backend'); ?>
</a>
<br>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'autologin')); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New Autologin Authentication Backend'); ?>
</a>
</p> </p>
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>">
<?= $form->getElement($form->getTokenElementName()); ?>
<table class="action"> <table class="action">
<thead> <thead>
<th>Resource</th> <th>Backend</th>
<th style="width: 5em">Remove</th> <th style="width: 5em"><?= $this->translate('Remove'); ?></th>
<th style="width: 5em">Order</th> <th style="width: 5em"><?= $this->translate('Order'); ?></th>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($this->backends as $backend): ?> <?php for ($i = 0; $i < count($backendNames); $i++): ?>
<tr> <tr>
<td class="action"> <td class="action">
<a href="<?= $this->href('config/editAuthenticationBackend', array('auth_backend' => $backend->name)) ?>"> <a href="<?= $this->href('config/editAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('edit.png') ?> <?= $this->escape($backend->name); ?> <?= $this->icon('edit.png'); ?> <?= $this->escape($backendNames[$i]); ?>
</a> </a>
</td> </td>
<td> <td>
<a href="<?= $this->href('config/removeAuthenticationBackend', array('auth_backend' => $backend->name)) ?>"> <a href="<?= $this->href('config/removeAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('remove.png', 'Remove') ?> <?= $this->icon('remove.png', $this->translate('Remove')); ?>
</a> </a>
</td> </td>
<td> <td>
<?= $backend->reorderForm; ?> <?php if ($i > 0): ?>
<button type="submit" name="<?= $backendNames[$i]; ?>" value="<?= $i - 1; ?>">
<?= $this->icon('up.png', $this->translate('Move up in authentication order')); ?>
</button>
<?php endif; ?>
<?php if ($i + 1 < count($backendNames)): ?>
<button type="submit" name="<?= $backendNames[$i]; ?>" value="<?= $i + 1; ?>">
<?= $this->icon('down.png', $this->translate('Move down in authentication order')); ?>
</button>
<?php endif; ?>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endfor; ?>
</tbody>
</table> </table>
</form>
</div> </div>

View File

@ -1,18 +1,8 @@
<h4> <h4>
<i class="icinga-icon-edit"></i> <?php printf(
Edit Backend "<?= $this->escape($this->name); ?>" $this->translate('Edit Backend "%s"'),
$this->escape($this->name)
); ?>
</h4> </h4>
<?= $messageBox; ?>
<?php if (isset($this->messageBox)): ?> <?= $this->form; ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?php if ($this->form->getErrorMessages()): ?>
<div>
<?php foreach ($this->form->getErrorMessages() as $error): ?>
<?= $this->escape($error); ?><br/>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?= $this->form ?>

View File

@ -1,10 +1,8 @@
<h4> <h4>
<i class="icinga-icon-remove"></i> <?php printf(
Remove Backend "<?= $this->escape($this->name); ?>" $this->translate('Remove Backend "%s"'),
$this->escape($name)
); ?>
</h4> </h4>
<?= $messageBox ?>
<?php if (isset($this->messageBox)): ?> <?= $form ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -1,30 +1,33 @@
<div class="controls"> <div class="controls">
<?= $this->tabs ?> <?= $tabs; ?>
</div> </div>
<div class="content" data-base-target="_next"> <div class="content" data-base-target="_next">
<?php <?= $messageBox; ?>
<p>
if (isset($this->messageBox)) { <a href="<?= $this->href('/config/createresource') ?>">
// TODO: Get rid of messageBoxes in favour of notifications <?= $this->icon('create.png'); ?> <?= $this->translate('Create a new resource'); ?>
echo $this->messageBox->render(); </a>
} </p>
?>
<p><a href="<?= $this->href('/config/createresource') ?>"><?= $this->icon('create.png'); ?> Create A New Resource</a></p>
<table class="action"> <table class="action">
<thead> <thead>
<th>Resource</th> <th><?= $this->translate('Resource'); ?></th>
<th style="width: 5em">Remove</th> <th style="width: 5em"><?= $this->translate('Remove'); ?></th>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($this->resources as $name => $resource): ?> <?php foreach ($this->resources as $name => $resource): ?>
<tr> <tr>
<td><a href="<?= $this->href('config/editresource', array('resource' => $name)) ?>"><?= $this->icon('edit.png') ?> <?= $this->escape($name); ?></td> <td>
<td style="text-align: center"><a href="<?= $this->href('config/removeresource', array('resource' => $name)) ?>"><?= $this->icon('remove.png'); ?></a></td> <a href="<?= $this->href('config/editresource', array('resource' => $name)) ?>">
<?= $this->icon('edit.png') ?> <?= $this->escape($name); ?>
</a>
</td>
<td style="text-align: center">
<a href="<?= $this->href('config/removeresource', array('resource' => $name)) ?>">
<?= $this->icon('remove.png'); ?>
</a>
</td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody>
</table> </table>
</div> </div>

View File

@ -1,14 +1,4 @@
<h4> <?= $messageBox; ?>
<i class="icinga-icon-create"></i> <h4><?= $this->translate('Create a new resource'); ?></h4>
Create New Resource <p><?= $this->translate('Resources are entities that provide data to Icingaweb.'); ?></p>
</h4> <?= $form; ?>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<p>
Resources are entities that provide data to Icingaweb.
</p>
<?= $this->form ?>

View File

@ -1,18 +1,3 @@
<h4> <h4><?= $this->translate('Edit Existing Resource'); ?></h4>
<i class="icinga-icon-edit"></i> <?= $messageBox; ?>
Edit Resource "<?= $this->escape($this->name); ?>" <?= $form; ?>
</h4>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?php if ($this->form->getErrorMessages()): ?>
<div>
<?php foreach ($this->form->getErrorMessages() as $error): ?>
<?= $this->escape($error); ?><br/>
<?php endforeach; ?>
</div>
<?php endif ?>
<?= $this->form ?>

View File

@ -1,10 +1,3 @@
<h4> <h4><?= $this->translate('Remove Existing Resource'); ?></h4>
<i class="icinga-icon-remove"></i> <?= $messageBox; ?>
Remove Resource "<?= $this->escape($this->name); ?>" <?= $form; ?>
</h4>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>

View File

@ -6,6 +6,7 @@ namespace Icinga\Logger;
use Exception; use Exception;
use Zend_Config; use Zend_Config;
use LogicException;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
/** /**
@ -37,10 +38,11 @@ class Logger
/** /**
* The supported severities * The supported severities
*/ */
public static $ERROR = 0; public static $NONE = 0;
public static $WARNING = 1; public static $ERROR = 1;
public static $INFO = 2; public static $WARNING = 2;
public static $DEBUG = 3; public static $INFO = 3;
public static $DEBUG = 4;
/** /**
* Create a new logger object * Create a new logger object
@ -93,9 +95,15 @@ class Logger
* *
* @param string $message The message to write * @param string $message The message to write
* @param int $severity The severity to use * @param int $severity The severity to use
*
* @throws LogicException In case $severity equals self::$NONE
*/ */
public function log($message, $severity) public function log($message, $severity)
{ {
if ($severity === static::$NONE) {
throw new LogicException("`None' (0) is not a valid severity to log messages");
}
if ($this->writer !== null && $this->verbosity >= $severity) { if ($this->writer !== null && $this->verbosity >= $severity) {
$this->writer->log($severity, $message); $this->writer->log($severity, $message);
} }

View File

@ -315,14 +315,7 @@ namespace Icinga\Test {
public function createForm($formClass, array $requestData = array()) public function createForm($formClass, array $requestData = array())
{ {
$form = new $formClass; $form = new $formClass;
// If the form has CSRF protection enabled, add the token to the request data, else all calls to $form->setTokenDisabled(); // Disable CSRF protection else all calls to isSubmittedAndValid will fail
// isSubmittedAndValid will fail
$form->setSessionId('1234');
$form->initCsrfToken();
$token = $form->getValue($form->getTokenElementName());
if ($token !== null) {
$requestData[$form->getTokenElementName()] = $token;
}
$request = $this->getRequest(); $request = $this->getRequest();
$request->setMethod('POST'); $request->setMethod('POST');
$request->setPost($requestData); $request->setPost($requestData);

View File

@ -47,6 +47,20 @@ class BaseConfigController extends ActionController
Session::getSession()->write(); Session::getSession()->write();
} }
/**
* Send a message with the logging level Zend_Log::WARN to the current user and
* commit the changes to the underlying session.
*
* @param $msg The message content
*/
protected function addWarningMessage($msg)
{
AuthenticationManager::getInstance()->getUser()->addMessage(
new Message($msg, Zend_Log::WARN)
);
Session::getSession()->write();
}
/* /*
* Return an array of tabs provided by this configuration controller. * Return an array of tabs provided by this configuration controller.
* *

View File

@ -4,19 +4,12 @@
namespace Icinga\Web; namespace Icinga\Web;
use Zend_Controller_Request_Abstract;
use Zend_Form; use Zend_Form;
use Zend_Config;
use Zend_Form_Element_Submit;
use Zend_Form_Element_Reset;
use Zend_View_Interface; use Zend_View_Interface;
use Icinga\Web\Session; use Icinga\Application\Icinga;
use Icinga\Web\Form\Element\Note;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\Form\Decorator\HelpText; use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\BootstrapForm; use Icinga\Web\Form\Decorator\ElementWrapper;
use Icinga\Web\Form\InvalidCSRFTokenException; use Icinga\Web\Form\Element\CsrfCounterMeasure;
use Icinga\Application\Config as IcingaConfig;
/** /**
* Base class for forms providing CSRF protection, confirmation logic and auto submission * Base class for forms providing CSRF protection, confirmation logic and auto submission
@ -24,27 +17,32 @@ use Icinga\Application\Config as IcingaConfig;
class Form extends Zend_Form class Form extends Zend_Form
{ {
/** /**
* The form's request object * Whether this form has been created
* *
* @var Zend_Controller_Request_Abstract * @var bool
*/ */
protected $request; protected $created = false;
/** /**
* Main configuration * Label to use for the standard submit button
* *
* Used as fallback if user preferences are not available. * @var string
*
* @var IcingaConfig
*/ */
protected $config; protected $submitLabel;
/** /**
* The preference object to use instead of the one from the user (used for testing) * The url to redirect to upon success
* *
* @var Zend_Config * @var string|Url
*/ */
protected $preferences; protected $redirectUrl;
/**
* The view script to use when rendering this form
*
* @var string
*/
protected $viewScript;
/** /**
* Whether this form should NOT add random generated "challenge" tokens that are associated with the user's current * Whether this form should NOT add random generated "challenge" tokens that are associated with the user's current
@ -56,83 +54,129 @@ class Form extends Zend_Form
protected $tokenDisabled = false; protected $tokenDisabled = false;
/** /**
* Name of the CSRF token element (used to create non-colliding hashes) * Name of the CSRF token element
* *
* @var string * @var string
*/ */
protected $tokenElementName = 'CSRFToken'; protected $tokenElementName = 'CSRFToken';
/** /**
* Flag to indicate that form is already build * Set the label to use for the standard submit button
* *
* @var bool * @param string $label The label to use for the submit button
*
* @return self
*/ */
protected $created = false; public function setSubmitLabel($label)
{
$this->submitLabel = $label;
return $this;
}
/** /**
* Session id used for CSRF token generation * Return the label being used for the standard submit button
*
* @var string
*/
protected $sessionId;
/**
* Label for submit button
*
* If omitted, no button will be shown
*
* @var string
*/
protected $submitLabel;
/**
* Label for cancel button
*
* If omitted, no button will be shown
*
* @var string
*/
protected $cancelLabel;
/**
* Last used note-id
*
* Helper to generate unique names for note elements
*
* @var int
*/
protected $last_note_id = 0;
/**
* Getter for the session ID
*
* If the ID has never been set, the ID from session_id() is returned
* *
* @return string * @return string
*/ */
public function getSessionId() public function getSubmitLabel()
{ {
if (!$this->sessionId) { return $this->submitLabel;
$this->sessionId = Session::getSession()->getId();
}
return $this->sessionId;
} }
/** /**
* Setter for the session ID * Set the url to redirect to upon success
* *
* This method should be used for testing purposes only * @param string|Url $url The url to redirect to
* *
* @param string $sessionId * @return self
*/ */
public function setSessionId($sessionId) public function setRedirectUrl($url)
{ {
$this->sessionId = $sessionId; $this->redirectUrl = $url;
return $this;
} }
/** /**
* Return the HTML element name of the CSRF token field * Return the url to redirect to upon success
*
* @return string|Url
*/
public function getRedirectUrl()
{
if ($this->redirectUrl === null) {
// Be sure to remove all form dependent params because we do not want to submit it again
$this->redirectUrl = Url::fromRequest()->without(array_keys($this->getElements()));
}
return $this->redirectUrl;
}
/**
* Set the view script to use when rendering this form
*
* @param string $viewScript The view script to use
*
* @return self
*/
public function setViewScript($viewScript)
{
$this->viewScript = $viewScript;
return $this;
}
/**
* Return the view script being used when rendering this form
*
* @return string
*/
public function getViewScript()
{
return $this->viewScript;
}
/**
* Disable CSRF counter measure and remove its field if already added
*
* @param bool $disabled Set true in order to disable CSRF protection for this form, otherwise false
*
* @return self
*/
public function setTokenDisabled($disabled = true)
{
$this->tokenDisabled = (bool) $disabled;
if ($disabled && $this->getElement($this->tokenElementName) !== null) {
$this->removeElement($this->tokenElementName);
}
return $this;
}
/**
* Return whether CSRF counter measures are disabled for this form
*
* @return bool
*/
public function getTokenDisabled()
{
return $this->tokenDisabled;
}
/**
* Set the name to use for the CSRF element
*
* @param string $name The name to set
*
* @return self
*/
public function setTokenElementName($name)
{
$this->tokenElementName = $name;
return $this;
}
/**
* Return the name of the CSRF element
* *
* @return string * @return string
*/ */
@ -142,427 +186,284 @@ class Form extends Zend_Form
} }
/** /**
* Render the form to HTML * Create this form
* *
* @param Zend_View_Interface $view * @param array $formData The data sent by the user
*
* @return string
*/
public function render(Zend_View_Interface $view = null)
{
// Elements must be there to render the form
$this->buildForm();
return parent::render($view);
}
/**
* Add elements to this form (used by extending classes)
*/
protected function create()
{
}
/**
* Method called before validation
*/
protected function preValidation(array $data)
{
}
/**
* Setter for the request
*
* @param Zend_Controller_Request_Abstract $request
*/
public function setRequest(Zend_Controller_Request_Abstract $request)
{
$this->request = $request;
}
/**
* Getter for the request
*
* @return Zend_Controller_Request_Abstract
*/
public function getRequest()
{
return $this->request;
}
/**
* Set the configuration to be used for this form when no preferences are set yet
*
* @param IcingaConfig $cfg
* *
* @return self * @return self
*/ */
public function setConfiguration($cfg) public function create(array $formData = array())
{ {
$this->config = $cfg; if (false === $this->created) {
return $this; $this->addElements($this->createElements($formData));
} $this->addFormIdentification()
->addCsrfCounterMeasure()
->addSubmitButton();
/** if ($this->getAction() === '') {
* Get the main configuration // We MUST set an action as JS gets confused otherwise, if
* // this form is being displayed in an additional column
* Returns the set configuration or an empty default one. $this->setAction(Url::fromRequest()->getUrlWithout(array_keys($this->getElements())));
*
* @return Zend_Config
*/
public function getConfiguration()
{
if ($this->config === null) {
$this->config = new Zend_Config(array(), true);
}
return $this->config;
}
/**
* Set preferences to be used instead of the one from the user object (used for testing)
*
* @param Zend_Config $prefs
*/
public function setUserPreferences($prefs)
{
$this->preferences = $prefs;
}
/**
* Return the preferences of the user or the overwritten ones
*
* @return Zend_Config
*/
public function getUserPreferences()
{
if ($this->preferences) {
return $this->preferences;
}
return $this->getRequest()->getUser()->getPreferences();
}
/**
* Create the form if not done already
*
* Adds all elements to the form
*/
public function buildForm()
{
if ($this->created === false) {
$this->initCsrfToken();
$this->create();
if ($this->submitLabel) {
$this->addSubmitButton();
}
if ($this->cancelLabel) {
$this->addCancelButton();
}
// Empty action if not safe
if (!$this->getAction() && $this->getRequest()) {
$this->setAction($this->getRequest()->getRequestUri());
} }
$this->created = true; $this->created = true;
} }
return $this;
} }
/** /**
* Setter for the cancel label * Create and return the elements to add to this form
* *
* @param string $cancelLabel * Intended to be implemented by concrete form classes.
*/
public function setCancelLabel($cancelLabel)
{
$this->cancelLabel = $cancelLabel;
}
/**
* Add cancel button to form
*/
protected function addCancelButton()
{
$this->addElement(
new Zend_Form_Element_Reset(
array(
'name' => 'btn_reset',
'label' => $this->cancelLabel,
'class' => 'btn pull-right'
)
)
);
}
/**
* Setter for the submit label
* *
* @param string $submitLabel * @param array $formData The data sent by the user
*/
public function setSubmitLabel($submitLabel)
{
$this->submitLabel = $submitLabel;
}
/**
* Add submit button to form
*/
protected function addSubmitButton()
{
$this->addElement(
new Zend_Form_Element_Submit(
array(
'name' => 'btn_submit',
'label' => $this->submitLabel
)
)
);
}
/**
* Add message to form
*
* @param string $message The message to be displayed
* @param int $headingType Whether it should be displayed as heading (1-6) or not (null)
*/
public function addNote($message, $headingType = null)
{
$this->addElement(
new Note(
array(
'escape' => $headingType === null ? false : true,
'name' => sprintf('note_%s', $this->last_note_id++),
'value' => $headingType === null ? $message : sprintf(
'<h%1$s>%2$s</h%1$s>',
$headingType,
$message
)
)
)
);
}
/**
* Enable automatic form submission on the given elements
*
* Enables automatic submission of this form once the user edits specific elements
*
* @param array $triggerElements The element names which should auto-submit the form
*
* @throws ProgrammingError When an element is found which does not yet exist
*/
public function enableAutoSubmit($triggerElements)
{
foreach ($triggerElements as $elementName) {
$element = $this->getElement($elementName);
if ($element !== null) {
$class = $element->getAttrib('class');
if ($class === null) {
$class = 'autosubmit';
} else {
$class .= ' autosubmit';
}
$element->setAttrib('class', $class);
} else {
throw new ProgrammingError(
'You need to add the element "%s" to the form before automatic submission can be enabled!',
$elementName
);
}
}
}
/**
* Check whether the form was submitted with a valid request
*
* Ensures that the current request method is POST, that the form was manually submitted and that the data provided
* in the request is valid and gets repopulated in case its invalid.
*
* @return bool True when the form is submitted and valid, otherwise false
*/
public function isSubmittedAndValid()
{
if ($this->getRequest()->isPost() === false) {
return false;
}
$this->buildForm();
$checkData = $this->getRequest()->getParams();
$this->assertValidCsrfToken($checkData);
if ($this->isSubmitted()) {
// perform full validation if submitted
$this->preValidation($checkData);
return $this->isValid($checkData);
} else {
// only populate if not submitted
$this->populate($checkData);
$this->setAttrib('data-icinga-form-modified', 'true');
return false;
}
}
/**
* Check whether this form has been submitted
*
* Per default, this checks whether the button set with the 'setSubmitLabel' method
* is being submitted. For custom submission logic, this method must be overwritten
*
* @return bool True when the form is marked as submitted, otherwise false
*/
public function isSubmitted()
{
// TODO: There are some missunderstandings and missconceptions to be
// found in this class. If populate() etc would have been used as
// designed this function would read as simple as:
// return $this->getElement('btn_submit')->isChecked();
if ($this->submitLabel) {
$checkData = $this->getRequest()->getParams();
return isset($checkData['btn_submit']) && $checkData['btn_submit'];
}
return true;
}
/**
* Disable CSRF counter measure and remove its field if already added
*
* This method should be used for testing purposes only
*
* @param bool $disabled Set true in order to disable CSRF tokens in
* this form (default: true), otherwise false
*/
public function setTokenDisabled($disabled = true)
{
$this->tokenDisabled = (boolean) $disabled;
if ($disabled === true) {
$this->removeElement($this->tokenElementName);
}
}
/**
* Add CSRF counter measure field to form
*/
public function initCsrfToken()
{
if (!$this->tokenDisabled && $this->getElement($this->tokenElementName) === null) {
$this->addElement(
'hidden',
$this->tokenElementName,
array(
'value' => $this->generateCsrfTokenAsString()
)
);
}
}
/**
* Test the submitted data for a correct CSRF token
*
* @param array $checkData The POST data send by the user
*
* @throws InvalidCSRFTokenException When CSRF Validation fails
*/
public function assertValidCsrfToken(array $checkData)
{
if (!$this->tokenDisabled) {
if (!isset($checkData[$this->tokenElementName])
|| !$this->hasValidCsrfToken($checkData[$this->tokenElementName])
) {
throw new InvalidCSRFTokenException();
}
}
}
/**
* Check whether the form's CSRF token-field has a valid value
*
* @param string $elementValue Value from the form element
*
* @return bool
*/
protected function hasValidCsrfToken($elementValue)
{
if ($this->getElement($this->tokenElementName) === null || strpos($elementValue, '|') === false) {
return false;
}
list($seed, $token) = explode('|', $elementValue);
if (!is_numeric($seed)) {
return false;
}
return $token === hash('sha256', $this->getSessionId() . $seed);
}
/**
* Generate a new (seed, token) pair
* *
* @return array * @return array
*/ */
public function generateCsrfToken() public function createElements(array $formData)
{ {
$seed = mt_rand(); return array();
$hash = hash('sha256', $this->getSessionId() . $seed);
return array($seed, $hash);
} }
/** /**
* Return the string representation of the CSRF seed/token pair * Perform actions after this form was submitted using a valid request
* *
* @return string * Intended to be implemented by concrete form classes. The base implementation returns always FALSE.
*
* @param Request $request The valid request used to process this form
*
* @return bool Whether any redirection should take place
*/ */
public function generateCsrfTokenAsString() public function onSuccess(Request $request)
{ {
list ($seed, $token) = $this->generateCsrfToken($this->getSessionId()); return false;
return sprintf('%s|%s', $seed, $token);
} }
/** /**
* Add a new element * Perform actions when no form dependent data was sent
* *
* Additionally, all DtDd tags will be removed and the Bootstrap compatible * Intended to be implemented by concrete form classes.
* BootstrapForm decorator will be added to the elements
* *
* @param string|Zend_Form_Element $element String element type, or an object of type Zend_Form_Element * @param Request $request The current request
* @param string $name The name of the element to add if $element is a string */
* @param array $options The settings for the element if $element is a string public function onShow(Request $request)
{
}
/**
* Add a submit button to this form
*
* Uses the label previously set with Form::setSubmitLabel(). Overwrite this
* method in order to add multiple submit buttons or one with a custom name.
* *
* @return self * @return self
* @see Zend_Form::addElement()
*/ */
public function addElement($element, $name = null, $options = null) public function addSubmitButton()
{ {
parent::addElement($element, $name, $options); if ($this->submitLabel !== null) {
$el = $name !== null ? $this->getElement($name) : $element; $this->addElement(
'submit',
'btn_submit',
array(
'ignore' => true,
'label' => $this->submitLabel
)
);
}
return $this;
}
/**
* Create a new element
*
* Additionally, all structural form element decorators by Zend are replaced with our own ones.
*
* @param string $type String element type
* @param string $name The name of the element to add
* @param array $options The options for the element
*
* @return Zend_Form_Element
*
* @see Zend_Form::createElement()
*/
public function createElement($type, $name, $options = null)
{
$el = parent::createElement($type, $name, $options);
if ($el) { if ($el) {
if (strpos(strtolower(get_class($el)), 'hidden') !== false) { if (strpos(strtolower(get_class($el)), 'hidden') !== false) {
// Do not add structural elements to invisible elements which produces ugly views
$el->setDecorators(array('ViewHelper')); $el->setDecorators(array('ViewHelper'));
} else { } else {
$el->removeDecorator('HtmlTag'); $el->removeDecorator('HtmlTag');
$el->removeDecorator('Label'); $el->removeDecorator('Label');
$el->removeDecorator('DtDdWrapper'); $el->removeDecorator('DtDdWrapper');
$el->addDecorator(new BootstrapForm()); $el->addDecorator(new ElementWrapper());
$el->addDecorator(new HelpText()); $el->addDecorator(new HelpText());
} }
} }
return $el;
}
/**
* Add a field with a unique and form specific ID
*
* @return self
*/
public function addFormIdentification()
{
$this->addElement(
'hidden',
'form_uid',
array(
'ignore' => true,
'value' => $this->getName()
)
);
return $this;
}
/**
* Add CSRF counter measure field to this form
*
* @return self
*/
public function addCsrfCounterMeasure()
{
if (false === $this->tokenDisabled && $this->getElement($this->tokenElementName) === null) {
$element = new CsrfCounterMeasure($this->tokenElementName);
$element->setDecorators(array('ViewHelper'));
$this->addElement($element);
}
return $this; return $this;
} }
/**
* Populate the elements with the given values
*
* @param array $defaults The values to populate the elements with
*/
public function setDefaults(array $defaults)
{
$this->create($defaults);
return parent::setDefaults($defaults);
}
/**
* Process the given request using this form
*
* Redirects to the url set with setRedirectUrl() upon success. See onSuccess()
* and onShow() wherewith you can customize the processing logic.
*
* @param Request $request The request to be processed
*
* @return Request The request supposed to be processed
*/
public function handleRequest(Request $request = null)
{
if ($request === null) {
$request = $this->getRequest();
}
$formData = $this->getRequestData($request);
if ($this->wasSent($formData)) {
$this->populate($formData); // Necessary to get isSubmitted() to work
if ($this->isSubmitted() || ! $this->getSubmitLabel()) {
if ($this->isValid($formData) && $this->onSuccess($request)) {
$this->getResponse()->redirectAndExit($this->getRedirectUrl());
}
} else {
// The form can't be processed but we want to show validation errors though
$this->isValidPartial($formData);
}
} else {
$this->onShow($request);
}
return $request;
}
/**
* Return whether the submit button of this form was pressed
*
* When overwriting Form::addSubmitButton() be sure to overwrite this method as well.
*
* @return bool True in case it was pressed, False otherwise or no submit label was set
*/
public function isSubmitted()
{
if ($this->submitLabel !== null) {
return $this->getElement('btn_submit')->isChecked();
}
return false;
}
/**
* Return whether the data sent by the user refers to this form
*
* Ensures that the correct form gets processed in case there are multiple forms
* with equal submit button names being posted against the same route.
*
* @param array $formData The data sent by the user
*
* @return bool Whether the given data refers to this form
*/
public function wasSent(array $formData)
{
return isset($formData['form_uid']) && $formData['form_uid'] === $this->getName();
}
/**
* Return whether the given values (possibly incomplete) are valid
*
* Unlike Zend_Form::isValid() this will not set NULL as value for
* an element that is not present in the given data.
*
* @param array $formData The data to validate
*
* @return bool
*/
public function isValidPartial(array $formData)
{
$this->create($formData);
return parent::isValidPartial($formData);
}
/**
* Return whether the given values are valid
*
* @param array $formData The data to validate
*
* @return bool
*/
public function isValid($formData)
{
$this->create($formData);
return parent::isValid($formData);
}
/**
* Remove all elements of this form
*
* @return self
*/
public function clearElements()
{
$this->created = false;
return parent::clearElements();
}
/** /**
* Load the default decorators * Load the default decorators
* *
* Overwrites Zend_Form::loadDefaultDecorators to avoid having the HtmlTag-Decorator added * Overwrites Zend_Form::loadDefaultDecorators to avoid having
* the HtmlTag-Decorator added and to provide viewscript usage
* *
* @return self * @return self
*/ */
@ -574,11 +475,83 @@ class Form extends Zend_Form
$decorators = $this->getDecorators(); $decorators = $this->getDecorators();
if (empty($decorators)) { if (empty($decorators)) {
if ($this->viewScript) {
$this->addDecorator('ViewScript', array(
'viewScript' => $this->viewScript,
'form' => $this
));
} else {
$this->addDecorator('FormElements') $this->addDecorator('FormElements')
//->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')) //->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
->addDecorator('Form'); ->addDecorator('Form');
} }
}
return $this; return $this;
} }
/**
* Return the name of this form
*
* @return string
*/
public function getName()
{
$name = parent::getName();
if (! $name) {
$name = get_class($this);
$this->setName($name);
}
return $name;
}
/**
* Return the request data based on this form's request method
*
* @param Request $request The request to fetch the data from
*
* @return array
*/
public function getRequestData(Request $request)
{
if (strtolower($request->getMethod()) === $this->getMethod()) {
return $request->{'get' . ($request->isPost() ? 'Post' : 'Query')}();
}
return array();
}
/**
* Return the current request
*
* @return Request
*/
public function getRequest()
{
return Icinga::app()->getFrontController()->getRequest();
}
/**
* Return the current Response
*
* @return Response
*/
public function getResponse()
{
return Icinga::app()->getFrontController()->getResponse();
}
/**
* Render this form
*
* @param Zend_View_Interface $view The view context to use
*
* @return string
*/
public function render(Zend_View_Interface $view = null)
{
$this->create();
return parent::render($view);
}
} }

View File

@ -7,23 +7,21 @@ namespace Icinga\Web\Form\Decorator;
use Zend_Form_Decorator_Abstract; use Zend_Form_Decorator_Abstract;
/** /**
* Decorator that styles forms in the DOM Bootstrap wants for it's forms * Decorator that wraps form elements with their labels to allow easier styling
*
* This component replaces the dt/dd wrapping of elements with the approach used by bootstrap.
* *
* Labels are drawn for all elements, except hidden, button and submit elements. If you want a * Labels are drawn for all elements, except hidden, button and submit elements. If you want a
* placeholder for this elements, set the 'addLabelPlaceholder' property. This can be useful in * placeholder for these elements, set the 'addLabelPlaceholder' property. This can be useful in
* cases where you want to put inputs with and inputs without labels on the same line and don't * cases where you want to put inputs with and inputs without labels on the same line and don't
* want buttons to 'jump' * want buttons to 'jump'
*/ */
class BootstrapForm extends Zend_Form_Decorator_Abstract class ElementWrapper extends Zend_Form_Decorator_Abstract
{ {
/** /**
* An array of elements that won't get a <label> dom added per default * An array of elements that won't get a <label> dom added per default
* *
* @var array * @var array
*/ */
private static $noLabel = array( protected static $noLabel = array(
'Zend_Form_Element_Hidden', 'Zend_Form_Element_Hidden',
'Zend_Form_Element_Button', 'Zend_Form_Element_Button',
'Zend_Form_Element_Submit' 'Zend_Form_Element_Submit'
@ -42,8 +40,9 @@ class BootstrapForm extends Zend_Form_Decorator_Abstract
if (! $label) { if (! $label) {
$label = '&nbsp;'; $label = '&nbsp;';
} }
if (in_array($this->getElement()->getType(), self::$noLabel) if (in_array($this->getElement()->getType(), self::$noLabel)
&& !$this->getElement()->getAttrib('addLabelPlaceholder', false)) { && false === $this->getElement()->getAttrib('addLabelPlaceholder', false)) {
$label = ''; $label = '';
} else { } else {
if (in_array($this->getElement()->getType(), self::$noLabel)) { if (in_array($this->getElement()->getType(), self::$noLabel)) {
@ -51,30 +50,21 @@ class BootstrapForm extends Zend_Form_Decorator_Abstract
} }
$label = '<label for="' . $elementName . '">' . $label . '</label>'; $label = '<label for="' . $elementName . '">' . $label . '</label>';
} }
return $label; return $label;
} }
/** /**
* Render this element * Render this element
* *
* Renders as the following:
* <div class="form-group">
* $dtLabel
* $dtElement
* </div>
*
* @param String $content The content of the form element * @param String $content The content of the form element
* *
* @return String The decorated form element * @return String The decorated form element
*/ */
public function render($content) public function render($content)
{ {
$el = $this->getElement(); $elementName = $this->getElement()->getName();
$elementName = $el->getName();
$label = $this->getLabel($elementName); $label = $this->getLabel($elementName);
return '<div class="form-group" id="' . $elementName . '-element">' return '<div class="form-element" id="' . $elementName . '-element">' . $label . $content . '</div>';
. $label
. $content
. '</div>';
} }
} }

View File

@ -0,0 +1,87 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Element;
use Zend_Form_Element_Xhtml;
use Icinga\Web\Session;
use Icinga\Web\Form\InvalidCSRFTokenException;
/**
* CSRF counter measure element
*
* You must not set a value to successfully use this element, just give it a name and you're good to go.
*/
class CsrfCounterMeasure extends Zend_Form_Element_Xhtml
{
/**
* Default form view helper to use for rendering
*
* @var string
*/
public $helper = 'formHidden';
/**
* Initialize this form element
*/
public function init()
{
$this->setRequired(true); // Not requiring this element would not make any sense
$this->setIgnore(true); // We do not want this element's value being retrieved by Form::getValues()
$this->setValue($this->generateCsrfToken());
}
/**
* Check whether $value is a valid CSRF token
*
* @param string $value The value to check
* @param mixed $context Context to use
*
* @return bool True, in case the CSRF token is valid
*
* @throws InvalidCSRFTokenException In case the CSRF token is not valid
*/
public function isValid($value, $context = null)
{
if (parent::isValid($value, $context) && $this->isValidCsrfToken($value)) {
return true;
}
throw new InvalidCSRFTokenException();
}
/**
* Check whether the given value is a valid CSRF token for the current session
*
* @param string $token The CSRF token
*
* @return bool
*/
protected function isValidCsrfToken($token)
{
if (strpos($token, '|') === false) {
return false;
}
list($seed, $hash) = explode('|', $token);
if (false === is_numeric($seed)) {
return false;
}
return $hash === hash('sha256', Session::getSession()->getId() . $seed);
}
/**
* Generate a new (seed, token) pair
*
* @return string
*/
protected function generateCsrfToken()
{
$seed = mt_rand();
$hash = hash('sha256', Session::getSession()->getId() . $seed);
return sprintf('%s|%s', $seed, $hash);
}
}

View File

@ -6,6 +6,7 @@ namespace Icinga\Web\Widget;
use Zend_Log; use Zend_Log;
use Zend_Form; use Zend_Form;
use Zend_View_Abstract;
use Icinga\User; use Icinga\User;
use Icinga\User\Message; use Icinga\User\Message;
use Icinga\Web\Session; use Icinga\Web\Session;

View File

@ -132,7 +132,6 @@ class SortBox extends AbstractWidget
$sort = $form->getElement('sort')->setDecorators(array('ViewHelper')); $sort = $form->getElement('sort')->setDecorators(array('ViewHelper'));
$dir = $form->getElement('dir')->setDecorators(array('ViewHelper')); $dir = $form->getElement('dir')->setDecorators(array('ViewHelper'));
if ($this->request) { if ($this->request) {
$form->setAction($this->request->getRequestUri());
$form->populate($this->request->getParams()); $form->populate($this->request->getParams());
} }
return $form; return $form;

View File

@ -2,15 +2,8 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Application\Icinga;
use Icinga\Application\Config;
use Icinga\Logger\Logger;
use Icinga\Web\Form;
use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Controller;
use Icinga\Chart\SVGRenderer;
use Icinga\Chart\GridChart; use Icinga\Chart\GridChart;
use Icinga\Chart\Palette;
use Icinga\Chart\Axis;
use Icinga\Chart\PieChart; use Icinga\Chart\PieChart;
use Icinga\Chart\Unit\StaticAxis; use Icinga\Chart\Unit\StaticAxis;
@ -140,7 +133,7 @@ class Monitoring_ChartController extends Controller
} }
$this->view->chart = new GridChart(); $this->view->chart = new GridChart();
$this->view->chart->setAxisLabel('', t('Services')) $this->view->chart->setAxisLabel('', t('Services'))
->setXAxis(new \Icinga\Chart\Unit\StaticAxis()) ->setXAxis(new StaticAxis())
->setAxisMin(null, 0); ->setAxisMin(null, 0);
$this->view->chart->drawBars( $this->view->chart->drawBars(

View File

@ -3,19 +3,14 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use \Exception; use \Exception;
use \Zend_Config;
use Icinga\Config\PreservingIniWriter; use Icinga\Config\PreservingIniWriter;
use Icinga\Web\Controller\ModuleActionController; use Icinga\Web\Controller\ModuleActionController;
use Icinga\Web\Notification; use Icinga\Web\Notification;
use Icinga\Web\Url; use Icinga\Form\Config\ConfirmRemovalForm;
use Icinga\Module\Monitoring\Form\Config\BackendForm;
use Icinga\Module\Monitoring\Form\Config\ConfirmRemovalForm; use Icinga\Module\Monitoring\Form\Config\InstanceForm;
use Icinga\Module\Monitoring\Form\Config\Backend\EditBackendForm;
use Icinga\Module\Monitoring\Form\Config\Backend\CreateBackendForm;
use Icinga\Module\Monitoring\Form\Config\Instance\EditInstanceForm;
use Icinga\Module\Monitoring\Form\Config\Instance\CreateInstanceForm;
use Icinga\Module\Monitoring\Form\Config\SecurityForm; use Icinga\Module\Monitoring\Form\Config\SecurityForm;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
/** /**
@ -23,7 +18,6 @@ use Icinga\Exception\NotReadableError;
*/ */
class Monitoring_ConfigController extends ModuleActionController class Monitoring_ConfigController extends ModuleActionController
{ {
/** /**
* Display a list of available backends and instances * Display a list of available backends and instances
*/ */
@ -49,52 +43,63 @@ class Monitoring_ConfigController extends ModuleActionController
*/ */
public function editbackendAction() public function editbackendAction()
{ {
// Fetch the backend to be edited
$backend = $this->getParam('backend'); $backend = $this->getParam('backend');
if (!$this->isExistingBackend($backend)) { $backendsConfig = $this->Config('backends')->toArray();
$this->view->error = 'Unknown backend ' . $backend; if (false === array_key_exists($backend, $backendsConfig)) {
return; // TODO: Should behave as in the app's config controller (Specific redirect to an error action)
Notification::error(sprintf($this->translate('Cannot edit "%s". Backend not found.'), $backend));
$this->redirectNow('monitoring/config');
} }
$backendForm = new EditBackendForm();
$backendForm->setRequest($this->getRequest());
$backendForm->setBackendConfiguration($this->Config('backends')->get($backend));
if ($backendForm->isSubmittedAndValid()) { $form = new BackendForm();
$newConfig = $backendForm->getConfig(); $request = $this->getRequest();
$config = $this->Config('backends'); if ($request->isPost()) {
$config->$backend = $newConfig; if ($form->isValid($request->getPost())) {
if ($this->writeConfiguration($config, 'backends')) { list($newName, $config) = $form->getBackendConfig();
Notification::success('Backend ' . $backend . ' Modified.');
if ($newName !== $backend) {
// Backend name has changed
unset($backendsConfig[$backend]); // We can safely use unset as all values are part of the form
}
$backendsConfig[$newName] = $config;
if ($this->writeConfiguration($backendsConfig, 'backends')) {
Notification::success(sprintf($this->translate('Backend "%s" successfully modified.'), $backend));
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
return; return;
} }
} }
$this->view->name = $backend; } else {
$this->view->form = $backendForm; $form->setBackendConfig($backend, $backendsConfig[$backend]);
}
$this->view->form = $form;
} }
/** /**
* Display a form to create a new backends * Display a form to create a new backend
*/ */
public function createbackendAction() public function createbackendAction()
{ {
$form = new CreateBackendForm(); $form = new BackendForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
if ($form->isSubmittedAndValid()) { if ($request->isPost() && $form->isValid($request->getPost())) {
$configArray = $this->Config('backends')->toArray(); list($name, $config) = $form->getBackendConfig();
$configArray[$form->getBackendName()] = $form->getConfig(); $backendsConfig = $this->Config('backends')->toArray();
$backendsConfig[$name] = $config;
if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) { if ($this->writeConfiguration($backendsConfig, 'backends')) {
Notification::success('Backend Creation Succeeded'); Notification::success(sprintf($this->translate('Backend "%s" created successfully.'), $name));
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
}
return; return;
} }
}
$this->view->form = $form; $this->view->form = $form;
$this->render('editbackend');
} }
/** /**
@ -103,58 +108,54 @@ class Monitoring_ConfigController extends ModuleActionController
public function removebackendAction() public function removebackendAction()
{ {
$backend = $this->getParam('backend'); $backend = $this->getParam('backend');
if (!$this->isExistingBackend($backend)) { $backendsConfig = $this->Config('backends')->toArray();
$this->view->error = 'Unknown backend ' . $backend; if (false === array_key_exists($backend, $backendsConfig)) {
return; // TODO: Should behave as in the app's config controller (Specific redirect to an error action)
Notification::error(sprintf($this->translate('Cannot remove "%s". Backend not found.'), $backend));
$this->redirectNow('monitoring/config');
} }
$form = new ConfirmRemovalForm(); $form = new ConfirmRemovalForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
$form->setRemoveTarget('backend', $backend); if ($request->isPost() && $form->isValid($request->getPost())) {
unset($backendsConfig[$backend]);
if ($form->isSubmittedAndValid()) { if ($this->writeConfiguration($backendsConfig, 'backends')) {
$configArray = $this->Config('backends')->toArray(); Notification::success(sprintf($this->translate('Backend "%s" successfully removed.'), $backend));
unset($configArray[$backend]);
if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) {
Notification::success('Backend "' . $backend . '" Removed');
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
}
return; return;
} }
}
$this->view->form = $form; $this->view->form = $form;
$this->view->name = $backend;
} }
/** /**
* Display a form to remove the instance identified by the 'instance' parameter * Display a confirmation form to remove the instance identified by the 'instance' parameter
*/ */
public function removeinstanceAction() public function removeinstanceAction()
{ {
$instance = $this->getParam('instance'); $instance = $this->getParam('instance');
if (!$this->isExistingInstance($instance)) { $instancesConfig = $this->Config('instances')->toArray();
$this->view->error = 'Unknown instance ' . $instance; if (false === array_key_exists($instance, $instancesConfig)) {
return; // TODO: Should behave as in the app's config controller (Specific redirect to an error action)
Notification::error(sprintf($this->translate('Cannot remove "%s". Instance not found.'), $instance));
$this->redirectNow('monitoring/config');
} }
$form = new ConfirmRemovalForm(); $form = new ConfirmRemovalForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
$form->setRemoveTarget('instance', $instance); if ($request->isPost() && $form->isValid($request->getPost())) {
unset($instancesConfig[$instance]);
if ($form->isSubmittedAndValid()) { if ($this->writeConfiguration($instancesConfig, 'instances')) {
$configArray = $this->Config('instances')->toArray(); Notification::success(sprintf($this->translate('Instance "%s" successfully removed.'), $instance));
unset($configArray[$instance]);
if ($this->writeConfiguration(new Zend_Config($configArray), 'instances')) {
Notification::success('Instance "' . $instance . '" Removed');
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
}
return; return;
} }
}
$this->view->form = $form; $this->view->form = $form;
$this->view->name = $instance; $this->view->name = $instance;
@ -166,24 +167,36 @@ class Monitoring_ConfigController extends ModuleActionController
public function editinstanceAction() public function editinstanceAction()
{ {
$instance = $this->getParam('instance'); $instance = $this->getParam('instance');
if (!$this->isExistingInstance($instance)) { $instancesConfig = $this->Config('instances')->toArray();
$this->view->error = 'Unknown instance ' . htmlentities($instance); if (false === array_key_exists($instance, $instancesConfig)) {
return; // TODO: Should behave as in the app's config controller (Specific redirect to an error action)
Notification::error(sprintf($this->translate('Cannot edit "%s". Instance not found.'), $instance));
$this->redirectNow('monitoring/config');
} }
$form = new EditInstanceForm();
$form->setInstanceConfiguration($this->Config('instances')->get($instance)); $form = new InstanceForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
if ($form->isSubmittedAndValid()) { if ($request->isPost()) {
$instanceConfig = $this->Config('instances')->toArray(); if ($form->isValid($request->getPost())) {
$instanceConfig[$instance] = $form->getConfig(); list($newName, $config) = $form->getInstanceConfig();
if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) {
Notification::success('Instance Modified'); if ($newName !== $instance) {
unset($instancesConfig[$instance]); // We can safely use unset as all values are part of the form
}
$instancesConfig[$newName] = $config;
if ($this->writeConfiguration($instancesConfig, 'instances')) {
Notification::success(sprintf($this->translate('Instance "%s" successfully modified.'), $instance));
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
return; return;
} }
} }
} else {
$form->setInstanceConfig($instance, $instancesConfig[$instance]);
}
$this->view->form = $form; $this->view->form = $form;
} }
@ -192,33 +205,37 @@ class Monitoring_ConfigController extends ModuleActionController
*/ */
public function createinstanceAction() public function createinstanceAction()
{ {
$form = new CreateInstanceForm(); $form = new InstanceForm();
$form->setRequest($this->getRequest()); $request = $this->getRequest();
if ($form->isSubmittedAndValid()) { if ($request->isPost() && $form->isValid($request->getPost())) {
$instanceConfig = $this->Config('instances'); list($name, $config) = $form->getInstanceConfig();
if ($instanceConfig === null) { $instancesConfig = $this->Config('instances')->toArray();
$instanceConfig = array(); $instancesConfig[$name] = $config;
} else { if ($this->writeConfiguration($instancesConfig, 'instances')) {
$instanceConfig = $instanceConfig->toArray(); Notification::success(sprintf($this->translate('Instance "%s" created successfully.'), $name));
}
$instanceConfig[$form->getInstanceName()] = $form->getConfig()->toArray();
if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) {
Notification::success('Instance Creation Succeeded');
$this->redirectNow('monitoring/config'); $this->redirectNow('monitoring/config');
} else { } else {
$this->render('show-configuration'); $this->render('show-configuration');
}
return; return;
} }
}
$this->view->form = $form; $this->view->form = $form;
$this->render('editinstance');
} }
/** /**
* Display a form to remove the instance identified by the 'instance' parameter * Write configuration to an ini file
*
* @param Zend_Config $config The configuration to write
* @param string $file The config file to write to
*
* @return bool Whether the configuration was written or not
*/ */
private function writeConfiguration($config, $file = null) protected function writeConfiguration($config, $file = null)
{ {
if (is_array($config)) {
$config = new Zend_Config($config);
}
$target = $this->Config($file)->getConfigFile(); $target = $this->Config($file)->getConfigFile();
$writer = new PreservingIniWriter(array('filename' => $target, 'config' => $config)); $writer = new PreservingIniWriter(array('filename' => $target, 'config' => $config));
@ -235,41 +252,18 @@ class Monitoring_ConfigController extends ModuleActionController
} }
/** /**
* Return true if the backend exists in the current configuration * Display a form to adjust security relevant settings
*
* @param string $backend The name of the backend to check for existence
*
* @return bool True if the backend name exists, otherwise false
*/ */
private function isExistingBackend($backend)
{
$backendCfg = $this->Config('backends');
return $backend && $backendCfg->get($backend);
}
/**
* Return true if the instance exists in the current configuration
*
* @param string $instance The name of the instance to check for existence
*
* @return bool True if the instance name exists, otherwise false
*/
private function isExistingInstance($instance)
{
$instanceCfg = $this->Config('instances');
return $instanceCfg && $instanceCfg->get($instance);
}
public function securityAction() public function securityAction()
{ {
$this->view->tabs = $this->Module()->getConfigTabs()->activate('security'); $this->view->tabs = $this->Module()->getConfigTabs()->activate('security');
$form = new SecurityForm(); $form = new SecurityForm();
$form->setConfiguration($this->Config()->get('security')); $request = $this->getRequest();
$form->setRequest($this->getRequest());
if ($form->isSubmittedAndValid()) {
$config = $this->Config()->toArray(); $config = $this->Config()->toArray();
$config['security'] = $form->getConfig(); if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
$config['security'] = $form->getValues();
if ($this->writeConfiguration(new Zend_Config($config))) { if ($this->writeConfiguration(new Zend_Config($config))) {
Notification::success('Configuration modified successfully'); Notification::success('Configuration modified successfully');
$this->redirectNow('monitoring/config/security'); $this->redirectNow('monitoring/config/security');
@ -278,6 +272,10 @@ class Monitoring_ConfigController extends ModuleActionController
return; return;
} }
} }
} elseif (isset($config['security'])) {
$form->populate($config['security']);
}
$this->view->form = $form; $this->view->form = $form;
} }
} }

View File

@ -2,10 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Form;
use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Backend;
use Icinga\Data\SimpleQuery;
use Icinga\Web\Widget\Chart\InlinePie; use Icinga\Web\Widget\Chart\InlinePie;
use Icinga\Module\Monitoring\Form\Command\MultiCommandFlagForm; use Icinga\Module\Monitoring\Form\Command\MultiCommandFlagForm;
use Icinga\Web\Widget; use Icinga\Web\Widget;

View File

@ -1,45 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config\Backend;
use \Zend_Config;
/**
* Extended EditBackendForm for creating new Backends
*
* @see EditBackendForm
*/
class CreateBackendForm extends EditBackendForm
{
/**
* Create this form
*
* @see EditBackendForm::create()
*/
public function create()
{
$this->setBackendConfiguration(new Zend_Config(array('type' => 'ido')));
$this->addElement(
'text',
'backend_name',
array(
'label' => 'Backend Name',
'required' => true,
'helptext' => 'This will be the identifier of this backend'
)
);
parent::create();
}
/**
* Return the name of the backend that is to be created
*
* @return string The name of the backend as entered in the form
*/
public function getBackendName()
{
return $this->getValue('backend_name');
}
}

View File

@ -1,148 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config\Backend;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory;
/**
* Form for modifying a monitoring backend
*/
class EditBackendForm extends Form
{
/**
* Database resources to use instead of the one's from ResourceFactory (used for testing)
*
* @var array
*/
protected $resources;
/**
* The Backend configuration to use for populating the form
*
* @var Zend_Config
*/
protected $backend;
/**
* Set the configuration to be used for initial population of the form
*
* @param Zend_Form $config
*/
public function setBackendConfiguration($config)
{
$this->backend = $config;
}
/**
* Set a custom array of resources to be used in this form instead of the ones from ResourceFactory
* (used for testing)
*/
public function setResources($resources)
{
$this->resources = $resources;
}
/**
* Return content of the resources.ini or previously set resources for displaying in the database selection field
*
* @return array
*/
public function getResources()
{
if ($this->resources === null) {
return ResourceFactory::getResourceConfigs()->toArray();
} else {
return $this->resources;
}
}
/**
* Return a list of all resources of the given type ready to be used as content for a select input
*
* @param string $type The type of resources to return
*
* @return array
*/
protected function getResourcesByType($type)
{
$backends = array();
foreach ($this->getResources() as $name => $resource) {
if ($resource['type'] === $type) {
$backends[$name] = $name;
}
}
return $backends;
}
/**
* Create this form
*
* @see Icinga\Web\Form::create()
*/
public function create()
{
$backendType = $this->getRequest()->getParam('backend_type', $this->backend->type);
$this->addElement(
'select',
'backend_type',
array(
'label' => 'Backend Type',
'value' => $this->backend->type,
'required' => true,
'helptext' => 'The data source used for retrieving monitoring information',
'multiOptions' => array(
'ido' => 'IDO Backend',
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus'
)
)
);
$this->addElement(
'select',
'backend_resource',
array(
'label' => 'Resource',
'value' => $this->backend->resource,
'required' => true,
'multiOptions' => $this->getResourcesByType($backendType === 'ido' ? 'db' : $backendType),
'helptext' => 'The resource to use'
)
);
$this->addElement(
'checkbox',
'backend_disable',
array(
'label' => 'Disable This Backend',
'required' => true,
'value' => $this->backend->disabled
)
);
$this->enableAutoSubmit(array('backend_type'));
$this->setSubmitLabel('{{SAVE_ICON}} Save Changes');
}
/**
* Return a configuration containing the backend settings entered in this form
*
* @return Zend_Config The updated configuration for this backend
*/
public function getConfig()
{
$values = $this->getValues();
return new Zend_Config(
array(
'type' => $values['backend_type'],
'disabled' => $values['backend_disable'],
'resource' => $values['backend_resource']
)
);
}
}

View File

@ -0,0 +1,125 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config;
use Icinga\Web\Form;
use Icinga\Data\ResourceFactory;
/**
* Form for modifying a monitoring backend
*/
class BackendForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_monitoring_backends');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'name',
array(
'required' => true,
'label' => t('Backend Name'),
'helptext' => t('The identifier of this backend')
)
),
$this->createElement(
'select',
'type',
array(
'required' => true,
'class' => 'autosubmit',
'label' => t('Backend Type'),
'helptext' => t('The data source used for retrieving monitoring information'),
'multiOptions' => array(
'ido' => 'IDO Backend',
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus'
)
)
),
$this->createElement(
'select',
'resource',
array(
'required' => true,
'label' => t('Resource'),
'helptext' => t('The resource to use'),
'multiOptions' => $this->getResourcesByType(
false === isset($formData['type']) || $formData['type'] === 'ido' ? 'db' : $formData['type']
)
)
),
$this->createElement(
'checkbox',
'disabled',
array(
'required' => true,
'label' => t('Disable This Backend')
)
)
);
}
/**
* Return the backend configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getBackendConfig()
{
$values = $this->getValues();
$name = $values['name'];
if ($values['disabled'] == '0') {
unset($values['disabled']);
}
unset($values['name']);
return array($name, $values);
}
/**
* Populate the form with the given configuration values
*
* @param string $name The name of the backend
* @param array $config The configuration values
*/
public function setBackendConfig($name, array $config)
{
$config['name'] = $name;
$this->populate($config);
}
/**
* Return a list of all resources of the given type ready to be used as content for a select input
*
* @param string $type The type of resources to return
*
* @return array
*/
protected function getResourcesByType($type)
{
$backends = array();
foreach (array_keys(ResourceFactory::getResourceConfigs($type)->toArray()) as $name) {
$backends[$name] = $name;
}
return $backends;
}
}

View File

@ -1,68 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config;
use Icinga\Web\Form;
/**
* Form for confirming removal of an object
*/
class ConfirmRemovalForm extends Form
{
/**
* The value of the target to remove
*
* @var string
*/
private $removeTarget;
/**
* The name of the target parameter to remove
*
* @var string
*/
private $targetName;
/**
* Set the remove target in this field to be a hidden field with $name and value $target
*
* @param string $name The name to be set in the hidden field
* @param string $target The value to be set in the hidden field
*/
public function setRemoveTarget($name, $target)
{
$this->targetName = $name;
$this->removeTarget = $target;
}
/**
* Create the confirmation form
*
* @see Form::create()
*/
public function create()
{
$this->addElement(
'hidden',
$this->targetName,
array(
'value' => $this->removeTarget,
'required' => true
)
);
$this->addElement(
'button',
'btn_submit',
array(
'type' => 'submit',
'escape' => false,
'value' => '1',
'class' => 'btn btn-cta btn-common',
'label' => $this->getView()->icon('remove.png') . ' Confirm Removal'
)
);
}
}

View File

@ -1,46 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config\Instance;
use \Icinga\Web\Form;
use \Zend_Config;
/**
* Form for creating new instances
*
* @see EditInstanceForm
*/
class CreateInstanceForm extends EditInstanceForm
{
/**
* Create the form elements
*
* @see EditInstanceForm::create()
*/
public function create()
{
$this->setInstanceConfiguration(new Zend_Config(array()));
$this->addElement(
'text',
'instance_name',
array(
'label' => 'Instance Name',
'helptext' => 'Please enter the name for the instance to create'
)
);
parent::create();
}
/**
* Return the name of the instance to be created
*
* @return string The name of the instance as entered in the form
*/
public function getInstanceName()
{
return $this->getValue('instance_name');
}
}

View File

@ -1,148 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config\Instance;
use \Zend_Config;
use \Icinga\Web\Form;
/**
* Form for editing existing instances
*/
class EditInstanceForm extends Form
{
/**
* The instance to edit
*
* @var Zend_Config
*/
private $instance;
/**
* The type of the instance
*
* 'local' when no host is given, otherwise 'remote'
*
* @var string
*/
private $instanceType = 'local';
/**
* Set instance configuration to be used for initial form population
*
* @param Zend_Config $config
*/
public function setInstanceConfiguration($config)
{
$this->instance = $config;
if (isset($this->instance->host)) {
$this->instanceType = 'remote';
}
}
/**
* Add a form field for selecting the command pipe type (local or remote)
*/
private function addTypeSelection()
{
$this->addElement(
'select',
'instance_type',
array(
'value' => $this->instanceType,
'multiOptions' => array(
'local' => 'Local Command Pipe',
'remote' => 'Remote Command Pipe'
)
)
);
$this->enableAutoSubmit(array('instance_type'));
}
/**
* Add form elements for remote instance
*/
private function addRemoteInstanceForm()
{
$this->addNote('When configuring a remote host, you need to setup passwordless key authentication');
$this->addElement(
'text',
'instance_remote_host',
array(
'label' => 'Remote Host',
'required' => true,
'value' => $this->instance->host,
'helptext' => 'Enter the hostname or address of the machine on which the icinga instance is running'
)
);
$this->addElement(
'text',
'instance_remote_port',
array(
'label' => 'Remote SSH Port',
'required' => true,
'value' => $this->instance->get('port', 22),
'helptext' => 'Enter the ssh port to use for connecting to the remote icigna instance'
)
);
$this->addElement(
'text',
'instance_remote_user',
array(
'label' => 'Remote SSH User',
'value' => $this->instance->user,
'helptext' => 'Enter the username to use for connecting '
. 'to the remote machine or leave blank for default'
)
);
}
/**
* Create this form
*
* @see Icinga\Web\Form::create
*/
public function create()
{
$this->addTypeSelection();
if ($this->getRequest()->getParam('instance_type', $this->instanceType) === 'remote') {
$this->addRemoteInstanceForm();
}
$this->addElement(
'text',
'instance_path',
array(
'label' => 'Remote Pipe Filepath',
'required' => true,
'value' => $this->instance->get('path', '/usr/local/icinga/var/rw/icinga.cmd'),
'helptext' => 'The file path where the icinga commandpipe can be found'
)
);
$this->setSubmitLabel('{{SAVE_ICON}} Save');
}
/**
* Return the configuration set by this form
*
* @return Zend_Config The configuration set in this form
*/
public function getConfig()
{
$values = $this->getValues();
$config = array(
'path' => $values['instance_path']
);
if ($values['instance_type'] === 'remote') {
$config['host'] = $values['instance_remote_host'];
$config['port'] = $values['instance_remote_port'];
if (isset($values['instance_remote_user']) && $values['instance_remote_user'] != '') {
$config['user'] = $values['instance_remote_user'];
}
}
return new Zend_Config($config);
}
}

View File

@ -0,0 +1,156 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config;
use Icinga\Web\Form;
use Icinga\Web\Form\Element\Number;
use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\ElementWrapper;
/**
* Form for modifying/creating monitoring instances
*/
class InstanceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_monitoring_instances');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$elements = array(
$this->createElement(
'text',
'name',
array(
'required' => true,
'label' => t('Instance Name')
)
),
$this->createElement(
'select',
'type',
array(
'required' => true,
'ignore' => true,
'label' => t('Instance Type'),
'class' => 'autosubmit',
'helptext' => t(
'When configuring a remote host, you need to setup passwordless key authentication'
),
'multiOptions' => array(
'local' => t('Local Command Pipe'),
'remote' => t('Remote Command Pipe')
)
)
)
);
if (isset($formData['type']) && $formData['type'] === 'remote') {
$elements[] = $this->createElement(
'text',
'host',
array(
'required' => true,
'label' => t('Remote Host'),
'helptext' => t(
'Enter the hostname or address of the machine on which the icinga instance is running'
)
)
);
$elements[] = new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Remote SSH Port'),
'helptext' => t('Enter the ssh port to use for connecting to the remote icinga instance'),
'value' => 22,
'decorators' => array( // The order is important!
'ViewHelper',
'Errors',
new ElementWrapper(),
new HelpText()
)
)
);
$elements[] = $this->createElement(
'text',
'user',
array(
'required' => true,
'label' => t('Remote SSH User'),
'helptext' => t(
'Enter the username to use for connecting to the remote machine or leave blank for default'
)
)
);
} else {
// TODO(5967,5525): Without this element, switching the type to "local" causes
// the form to be processed as it's complete in that case.
$elements[] = $this->createElement(
'hidden',
'hitchhiker',
array(
'required' => true,
'ignore' => true,
'value' => 'Arthur'
)
);
}
$elements[] = $this->createElement(
'text',
'path',
array(
'required' => true,
'label' => t('Pipe Filepath'),
'value' => '/usr/local/icinga/var/rw/icinga.cmd',
'helptext' => t('The file path where the icinga commandpipe can be found')
)
);
return $elements;
}
/**
* Return the instance configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getInstanceConfig()
{
$values = $this->getValues();
$name = $values['name'];
unset($values['name']);
return array($name, $values);
}
/**
* Populate the form with the given configuration values
*
* @param string $name The name of the instance
* @param array $config The configuration values
*/
public function setInstanceConfig($name, array $config)
{
$config['name'] = $name;
if (isset($config['host'])) {
// Necessary as we have no config directive for setting the instance's type
$config['type'] = 'remote';
}
$this->populate($config);
}
}

View File

@ -4,57 +4,39 @@
namespace Icinga\Module\Monitoring\Form\Config; namespace Icinga\Module\Monitoring\Form\Config;
use Zend_Config;
use Icinga\Web\Form; use Icinga\Web\Form;
/**
* Form for modifying security relevant settings
*/
class SecurityForm extends Form class SecurityForm extends Form
{ {
/** /**
* The configuration to use for populating the form * Initialize this form
*/ */
protected $config; public function init()
{
$this->setName('form_config_monitoring_security');
$this->setSubmitLabel(t('Save Changes'));
}
/** /**
* Create this form * @see Form::createElements()
*
* @see Icinga\Web\Form::create
*/ */
public function create() public function createElements(array $formData)
{ {
$default = '*pw*,*pass*,community'; return array(
$this->addElement( $this->createElement(
'text', 'text',
'protected_customvars', 'protected_customvars',
array( array(
'label' => 'Protected Custom Variables', 'label' => 'Protected Custom Variables',
'required' => true, 'required' => true,
'value' => $this->config ? $this->config->get('protected_customvars', $default) : $default,
'helptext' => 'Comma separated case insensitive list of protected custom variables.' 'helptext' => 'Comma separated case insensitive list of protected custom variables.'
. ' Use * as a placeholder for zero or more wildcard characters.' . ' Use * as a placeholder for zero or more wildcard characters.'
. ' Existance of those custom variables will be shown, but their values will be masked.' . ' Existance of those custom variables will be shown, but their values will be masked.'
) )
)
); );
$this->setSubmitLabel('Save');
}
/**
* Set the configuration to be used for initial population of the form
*/
public function setConfiguration($config)
{
$this->config = $config;
}
/**
* Return the configuration set by this form
*
* @return Zend_Config The configuration set in this form
*/
public function getConfig()
{
$values = $this->getValues();
return new Zend_Config(array(
'protected_customvars' => $values['protected_customvars']
));
} }
} }

View File

@ -0,0 +1,2 @@
<h4><?= $this->translate('Add New Backend'); ?></h4>
<?= $form; ?>

View File

@ -0,0 +1,2 @@
<h4><?= $this->translate('Add New Instance'); ?></h4>
<?= $form; ?>

View File

@ -1,13 +1,2 @@
<?php if ($this->name): ?> <h4><?= $this->translate('Edit Existing Backend'); ?></h4>
<h4><i> <i class="icinga-icon-edit"></i> Edit Backend "<?= $this->escape($this->name) ?>"</h4> <?= $form; ?>
<?php else: ?>
<h4> <i class="icinga-icon-create"></i> Create New Backend</h4>
<?php endif; ?>
<?php if ($this->error): ?>
<div class="alert alert-danger">
<?= $this->escape($this->error); ?>
</div>
<?php endif; ?>
<?= $this->form; ?>

View File

@ -1,14 +1,2 @@
<h4><?= $this->translate('Edit Existing Instance'); ?></h4>
<?php if (isset($this->name)): ?> <?= $form; ?>
<h4><i class="icinga-icon-edit"></i> } Edit Instance Configuration for "<?= $this->escape($this->name) ?>"</h4>
<?php else: ?>
<h4><i class="icinga-icon-create"></i> Configure New Icinga Instance</h4>
<?php endif; ?>
<?php if ($this->error): ?>
<div class="alert alert-danger">
<?= $this->escape($this->error); ?>
</div>
<?php endif; ?>
<?= $this->form; ?>

View File

@ -1,8 +1,2 @@
<h4><?= $this->translate('Remove Existing Backend'); ?></h4>
<h4><i class="icinga-icon-remove"></i> Remove Backend "<?= $this->escape($this->name) ?>"</h4> <?= $form; ?>
<p>
Are you sure you want to remove the backend <?= $this->escape($this->name) ?>?
</p>
<?= $this->form; ?>

View File

@ -1,13 +1,4 @@
<h4><?= $this->translate('Remove Existing Instance'); ?></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($name); ?>?</p>
<p><i class="icinga-icon-warning"></i> If you have still any environments or views referring to this instance, you won't be able to send commands anymore after deletion.</p>
<p> <?= $form; ?>
Are you sure you want to remove the instance <?= $this->escape($this->name) ?>?
</p>
<p>
<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>
<?= $this->form; ?>

View File

@ -97,7 +97,6 @@ class TimelineIntervalBox extends AbstractWidget
); );
if ($this->request) { if ($this->request) {
$form->setAction($this->request->getRequestUri());
$form->populate($this->request->getParams()); $form->populate($this->request->getParams());
} }

View File

@ -17,11 +17,7 @@ td.configTable {
min-width: 300px; min-width: 300px;
} }
div.config-form-group { .form-element {
float: right;
}
.form-group {
margin-bottom: 1em; margin-bottom: 1em;
} }