Configuration interfaces for logging, authentication and general configuration

- Added HelpText decorator
- Added Time and DateFormatValidator
- Added tests

refs #3777
This commit is contained in:
Jannis Moßhammer 2013-08-19 18:25:20 +02:00 committed by Eric Lippmann
parent 4810a0d47e
commit 972bc9853e
20 changed files with 1276 additions and 221 deletions

View File

@ -31,6 +31,7 @@ use \Icinga\Web\Widget\Tab;
use \Icinga\Web\Url; use \Icinga\Web\Url;
use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder; use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
use \Icinga\Application\Icinga; use \Icinga\Application\Icinga;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Form\Config\GeneralForm; use \Icinga\Form\Config\GeneralForm;
use \Icinga\Form\Config\AuthenticationForm; use \Icinga\Form\Config\AuthenticationForm;
use \Icinga\Form\Config\Authentication\LdapBackendForm; use \Icinga\Form\Config\Authentication\LdapBackendForm;
@ -55,32 +56,32 @@ class ConfigController extends BaseConfigController
return array( return array(
'index' => new Tab( 'index' => new Tab(
array( array(
"name" => "index", 'name' => 'index',
"title" => "Application", 'title' => 'Application',
"url" => Url::fromPath("/config") 'url' => Url::fromPath('/config')
) )
), ),
"authentication" => new Tab( 'authentication' => new Tab(
array( array(
"name" => "auth", 'name' => 'auth',
"title" => "Authentication", 'title' => 'Authentication',
"url" => Url::fromPath('/config/authentication') 'url' => Url::fromPath('/config/authentication')
) )
), ),
"logging" => new Tab( 'logging' => new Tab(
array( array(
"name" => "logging", 'name' => 'logging',
"title" => "Logging", 'title' => 'Logging',
"url" => Url::fromPath("/config/logging") 'url' => Url::fromPath('/config/logging')
) )
), ),
"modules" => new Tab( 'modules' => new Tab(
array( array(
"name" => "modules", 'name' => 'modules',
"title" => "Modules", 'title' => 'Modules',
"url" => Url::fromPath("/config/moduleoverview") 'url' => Url::fromPath('/config/moduleoverview')
) )
) )
); );
@ -88,7 +89,6 @@ class ConfigController extends BaseConfigController
/** /**
* Index action, entry point for configuration * Index action, entry point for configuration
* @TODO: Implement configuration interface (#3777)
*/ */
public function indexAction() public function indexAction()
{ {
@ -96,26 +96,30 @@ class ConfigController extends BaseConfigController
$form->setConfiguration(IcingaConfig::app()); $form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request); $form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) { if ($form->isSubmittedAndValid()) {
$cfg = IcingaConfig::app()->getConfigFile(); if (!$this->writeConfigFile($form->getConfig(), 'config')) {
$writer = new PreservingIniWriter( return false;
array( }
'config' => $form->getConfig(), $this->redirectNow('/config');
'filename' => $cfg
)
);
$writer->write();
} }
$this->view->form = $form; $this->view->form = $form;
} }
/**
* Form for modifying the logging configuration
*/
public function loggingAction() public function loggingAction()
{ {
$form = new LoggingForm(); $form = new LoggingForm();
$form->setConfiguration(IcingaConfig::app()); $form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request); $form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) {
$config = $form->getConfig();
if (!$this->writeConfigFile($form->getConfig(), 'config')) {
return false;
}
$this->redirectNow('/config/logging');
}
$this->view->form = $form; $this->view->form = $form;
} }
@ -151,24 +155,6 @@ class ConfigController extends BaseConfigController
$this->redirectNow('config/moduleoverview?_render=body'); $this->redirectNow('config/moduleoverview?_render=body');
} }
private function writeAuthenticationFile(array $config)
{
$cfg = new Zend_Config($config);
$writer = new Zend_Config_Writer_Ini(
array(
'config' => $cfg,
'filename' => IcingaConfig::app('authentication')->getConfigFile()
)
);
try {
$writer->write();
} catch (Exception $exc) {
$this->view->exceptionMessage = $exc->getMessage();
$this->view->iniConfigurationString = $writer->render();
$this->render('authentication/show-configuration');
}
}
/** /**
* Action for creating a new authentication backend * Action for creating a new authentication backend
* *
@ -181,10 +167,16 @@ class ConfigController extends BaseConfigController
$form->setRequest($this->_request); $form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) { if ($form->isSubmittedAndValid()) {
$this->writeAuthenticationFile($form->getConfig()); $modifiedConfig = $form->getConfig();
if (empty($modifiedConfig)) {
$form->addError('You need at least one authentication backend.');
} else if (!$this->writeAuthenticationFile($modifiedConfig)) {
return;
} else {
$this->redirectNow('/config/authentication');
}
} }
$this->view->form = $form; $this->view->form = $form;
} }
/** /**
@ -201,16 +193,72 @@ class ConfigController extends BaseConfigController
$form->setRequest($this->getRequest()); $form->setRequest($this->getRequest());
if ($form->isSubmittedAndValid()) { if ($form->isSubmittedAndValid()) {
$backendCfg = IcingaConfig::app('authentication')->toArray(); $backendCfg = IcingaConfig::app('authentication')->toArray();
foreach ($form->getConfig() as $backendName => $settings) { foreach ($form->getConfig() as $backendName => $settings) {
$backendCfg[$backendName] = $settings; $backendCfg[$backendName] = $settings;
} }
if (!$this->writeAuthenticationFile($backendCfg)) {
return;
}
$this->redirectNow('/config/authentication');
$this->writeAuthenticationFile($backendCfg);
} }
$this->view->form = $form; $this->view->form = $form;
$this->render('authentication/modify'); $this->render('authentication/modify');
} }
/**
* Write changes to an authentication file.
*
* This uses the Zend_Config_Writer_Ini implementation for now, as the Preserving ini writer can't
* handle ordering
*
* @param array $config The configuration changes
*
* @return bool True when persisting succeeded, otherwise false
* @see writeConfigFile()
*/
private function writeAuthenticationFile($config) {
$writer = new Zend_Config_Writer_Ini(
array(
'config' => new Zend_Config($config),
'filename' => IcingaConfig::app('authentication')->getConfigFile()
)
);
return $this->writeConfigFile($config, 'authentication', $writer);
}
/**
* Write changes to a configuration file $file, using the supllied writer or PreservingIniWriter if none is set
*
* @param array|Zend_Config $config The configuration to write
* @param string $file The filename to write to (without .ini)
* @param Zend_Config_Writer $writer An optional writer to use for persisting changes
*
* @return bool True when persisting succeeded, otherwise false
*/
private function writeConfigFile($config, $file, $writer = null)
{
if (is_array($config)) {
$config = new Zend_Config($config);
}
if ($writer === null) {
$writer = new PreservingIniWriter(
array(
'config' => $config,
'filename' => IcingaConfig::app($file)->getConfigFile()
)
);
}
try {
$writer->write();
return true;
} catch (Exception $exc) {
$this->view->exceptionMessage = $exc->getMessage();
$this->view->iniConfigurationString = $writer->render();
$this->view->file = $file;
$this->render('show-configuration');
return false;
}
}
} }
// @codingStandardsIgnoreEnd // @codingStandardsIgnoreEnd

View File

@ -76,10 +76,11 @@ class DbBackendForm extends BaseBackendForm
'text', 'text',
'backend_' . $name . '_name', 'backend_' . $name . '_name',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false, 'allowEmpty'=> false,
'label' => 'Backend name', 'label' => 'Backend name',
'value' => $this->getBackendName() 'helptext' => 'The name of this authentication provider',
'value' => $this->getBackendName()
) )
); );
@ -90,6 +91,7 @@ class DbBackendForm extends BaseBackendForm
'label' => 'Database connection', 'label' => 'Database connection',
'required' => true, 'required' => true,
'allowEmpty' => false, 'allowEmpty' => false,
'helptext' => 'The database connection to use for authenticating with this provider',
'value' => $this->getBackend()->get('resource'), 'value' => $this->getBackend()->get('resource'),
'multiOptions' => $this->getDatabaseResources() 'multiOptions' => $this->getDatabaseResources()
) )

View File

@ -56,10 +56,11 @@ class LdapBackendForm extends BaseBackendForm
'text', 'text',
'backend_'.$name.'_name', 'backend_'.$name.'_name',
array( array(
'required' => true, 'required' => true,
'allowEmpty' => false, 'allowEmpty'=> false,
'label' => 'Backend name', 'label' => 'Backend name',
'value' => $this->getBackendName() 'helptext' => 'The name of this authentication backend',
'value' => $this->getBackendName()
) )
); );
@ -67,10 +68,11 @@ class LdapBackendForm extends BaseBackendForm
'text', 'text',
'backend_' . $name . '_hostname', 'backend_' . $name . '_hostname',
array( array(
'label' => 'LDAP server host', 'label' => 'LDAP server host',
'allowEmpty' => false, 'allowEmpty' => false,
'value' => $backend->get('hostname', 'localhost'), 'value' => $backend->get('hostname', 'localhost'),
'required' => true 'helptext' => 'The hostname or address of the LDAP server to use for authentication',
'required' => true
) )
); );
@ -79,7 +81,8 @@ class LdapBackendForm extends BaseBackendForm
'backend_' . $name . '_root_dn', 'backend_' . $name . '_root_dn',
array( array(
'label' => 'LDAP root dn', 'label' => 'LDAP root dn',
'value' => $backend->get('hostname', 'ou=people,dc=icinga,dc=org'), 'value' => $backend->get('root_dn', 'ou=people,dc=icinga,dc=org'),
'helptext' => 'The path where users can be found on the ldap server',
'required' => true 'required' => true
) )
); );
@ -90,6 +93,7 @@ class LdapBackendForm extends BaseBackendForm
array( array(
'label' => 'LDAP bind dn', 'label' => 'LDAP bind dn',
'value' => $backend->get('bind_dn', 'cn=admin,cn=config'), 'value' => $backend->get('bind_dn', 'cn=admin,cn=config'),
'helptext' => 'The user dn to use for querying the ldap server',
'required' => true 'required' => true
) )
); );
@ -101,26 +105,29 @@ class LdapBackendForm extends BaseBackendForm
'label' => 'LDAP bind password', 'label' => 'LDAP bind password',
'renderPassword' => true, 'renderPassword' => true,
'value' => $backend->get('bind_pw', 'admin'), 'value' => $backend->get('bind_pw', 'admin'),
'helptext' => 'The password to use for querying the ldap server',
'required' => true 'required' => true
) )
); );
$this->addElement( $this->addElement(
'text', 'text',
'backend_' . $name . '_bind_user_class', 'backend_' . $name . '_user_class',
array( array(
'label' => 'LDAP user object class', 'label' => 'LDAP user object class',
'value' => $backend->get('user_class', 'inetOrgPerson'), 'value' => $backend->get('user_class', 'inetOrgPerson'),
'helptext' => 'The object class used for storing users on the ldap server',
'required' => true 'required' => true
) )
); );
$this->addElement( $this->addElement(
'text', 'text',
'backend_' . $name . '_bind_user_name_attribute', 'backend_' . $name . '_user_name_attribute',
array( array(
'label' => 'LDAP user name attribute', 'label' => 'LDAP user name attribute',
'value' => $backend->get('user_name_attribute', 'uid'), 'value' => $backend->get('user_name_attribute', 'uid'),
'helptext' => 'The attribute name used for storing the user name on the ldap server',
'required' => true 'required' => true
) )
); );
@ -147,8 +154,8 @@ class LdapBackendForm extends BaseBackendForm
'root_dn' => $this->getValue($prefix . 'root_dn'), 'root_dn' => $this->getValue($prefix . 'root_dn'),
'bind_dn' => $this->getValue($prefix . 'bind_dn'), 'bind_dn' => $this->getValue($prefix . 'bind_dn'),
'bind_pw' => $this->getValue($prefix . 'bind_pw'), 'bind_pw' => $this->getValue($prefix . 'bind_pw'),
'bind_user_class' => $this->getValue($prefix . 'bind_user_class'), 'user_class' => $this->getValue($prefix . 'user_class'),
'bind_user_name_attribute' => $this->getValue($prefix . 'bind_user_name_attribute') 'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute')
); );
return array( return array(
$section => $cfg $section => $cfg

View File

@ -32,17 +32,17 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga; use \Icinga\Application\Icinga;
use \Icinga\Application\Logger; use \Icinga\Application\Logger;
use \Icinga\Application\DbAdapterFactory; use \Icinga\Application\DbAdapterFactory;
use \Icinga\Form\Config\Authentication\DbBackendForm;
use \Icinga\Form\Config\Authentication\LdapBackendForm;
use \Icinga\Web\Form; use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note; use \Icinga\Web\Form\Element\Note;
use \Icinga\Web\Form\Decorator\ConditionalHidden; use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Config; use \Zend_Config;
use \Zend_Form_Element_Text;
use \Zend_Form_Element_Select;
use \Zend_Form_Element_Button;
/**
* Form for modifying the authentication provider and order.
*
* This is a composite form from one or more forms under the Authentication folder
*/
class AuthenticationForm extends Form class AuthenticationForm extends Form
{ {
/** /**
@ -59,7 +59,11 @@ class AuthenticationForm extends Form
*/ */
private $resources = null; private $resources = null;
/**
* An array containing all provider subforms currently displayed
*
* @var array
*/
private $backendForms = array(); private $backendForms = array();
@ -84,7 +88,15 @@ class AuthenticationForm extends Form
$this->config = $cfg; $this->config = $cfg;
} }
/**
* Add a hint to remove the backend identified by $name
*
* The button will have the name "backend_$name_remove"
*
* @param string $name The backend to add this button for
*
* @return string The id of the added button
*/
private function addRemoveHint($name) private function addRemoveHint($name)
{ {
$this->addElement( $this->addElement(
@ -101,6 +113,19 @@ class AuthenticationForm extends Form
return 'backend_' . $name . '_remove'; return 'backend_' . $name . '_remove';
} }
/**
* Add the form for the provider identified by $name, with the configuration $backend
*
* Supported backends are backends with a form found under \Icinga\Form\Config\Authentication.
* The backend name ist the (uppercase first) prefix with 'BackendForm' as the suffix.
*
* Originally it was intended to add the provider as a subform. As this didn't really work with
* the Zend validation logic (maybe our own validation logic breaks it), we now create the form, but add
* all elements to this form explicitly.
*
* @param string $name The name of the backend to add
* @param Zend_Config $backend The configuration of the backend
*/
private function addProviderForm($name, $backend) private function addProviderForm($name, $backend)
{ {
$type = ucfirst(strtolower($backend->get('backend'))); $type = ucfirst(strtolower($backend->get('backend')));
@ -117,49 +142,56 @@ class AuthenticationForm extends Form
if ($this->resources) { if ($this->resources) {
$form->setResources($this->resources); $form->setResources($this->resources);
} }
// It would be nice to directly set the form via // It would be nice to directly set the form via
// this->setForm, but Zend doesn't handle form validation // this->setForm, but Zend doesn't handle form validation
// properly if doing so. // properly if doing so.
$form->create(); $form->create();
foreach ($form->getElements() as $name => $element) { foreach ($form->getElements() as $elName => $element) {
$this->addElement($element, $name); if ($elName === 'backend_' . $this->filterName($name) . '_name') {
continue;
}
$this->addElement($element, $elName);
} }
$this->backendForms[] = $form; $this->backendForms[] = $form;
} }
/**
* Add the buttons for modifying authentication priorities
*
* @param string $name The name of the backend to add the buttons for
* @param array $order The current order which will be used to determine the changed order
*
* @return array An array containing the newly added form element ids as strings
*/
public function addPriorityButtons($name, $order = array()) public function addPriorityButtons($name, $order = array())
{ {
$formEls = array(); $formEls = array();
$priorities = array( $priorities = array(
"up" => join(',', self::moveElementUp($name, $order)), 'up' => join(',', self::moveElementUp($name, $order)),
"down" => join(',', self::moveElementDown($name, $order)) 'down' => join(',', self::moveElementDown($name, $order))
); );
if ($priorities["up"] != join(',', $order)) { if ($priorities['up'] != join(',', $order)) {
$this->addElement( $this->addElement(
'button', 'button',
'priority' . $name . '_up', 'priority' . $name . '_up',
array( array(
'name' => 'priority', 'name' => 'priority',
'label' => 'Move up in authentication order', 'label' => 'Move up in authentication order',
'value' => $priorities["up"], 'value' => $priorities['up'],
'type' => 'submit' 'type' => 'submit'
) )
); );
$formEls[] = 'priority' . $name . '_up'; $formEls[] = 'priority' . $name . '_up';
} }
if ($priorities["down"] != join(',', $order)) { if ($priorities['down'] != join(',', $order)) {
$this->addElement( $this->addElement(
'button', 'button',
'priority' . $name . '_down', 'priority' . $name . '_down',
array( array(
'name' => 'priority', 'name' => 'priority',
'label' => 'Move down in authentication order', 'label' => 'Move down in authentication order',
'value' => $priorities["down"], 'value' => $priorities['down'],
'type' => 'submit' 'type' => 'submit'
) )
); );
@ -169,7 +201,14 @@ class AuthenticationForm extends Form
return $formEls; return $formEls;
} }
/**
* Overwrite for Zend_Form::populate in order to preserve the modified priority of the backends
*
* @param array $values The values to populate the form with
*
* @return void|\Zend_Form
* @see Zend_Form::populate
*/
public function populate(array $values) public function populate(array $values)
{ {
$last_priority = $this->getValue('current_priority'); $last_priority = $this->getValue('current_priority');
@ -178,7 +217,13 @@ class AuthenticationForm extends Form
} }
private function getAuthenticationOrder () /**
* Return an array containing all authentication providers in the order they should be used
*
* @return array An array containing the identifiers (section names) of the authentication backend in
* the order they should be persisted
*/
private function getAuthenticationOrder()
{ {
$request = $this->getRequest(); $request = $this->getRequest();
$order = $request->getParam( $order = $request->getParam(
@ -195,15 +240,26 @@ class AuthenticationForm extends Form
return $order; return $order;
} }
/**
* Return true if the backend should be deleted when the changes are persisted
*
* @param string $backendName The name of the backend to check for being in a 'delete' state
*
* @return bool Whether this backend will be deleted on save
*/
private function isMarkedForDeletion($backendName) private function isMarkedForDeletion($backendName)
{ {
return intval($this->getRequest()->getParam('backend_' . $backendName . '_remove', 0)) === 1; return intval($this->getRequest()->getParam('backend_' . $backendName . '_remove', 0)) === 1;
} }
/**
* Add persistent values to the form in hidden fields
*
* Currently this adds the 'current_priority' field to persist priority modifications. This prevents changes in the
* authentication order to be lost as soon as other changes are submitted (like marking a backend for deletion)
*/
private function addPersistentState() private function addPersistentState()
{ {
$this->addElement( $this->addElement(
'hidden', 'hidden',
'current_priority', 'current_priority',
@ -214,8 +270,11 @@ class AuthenticationForm extends Form
); );
} }
/**
* Create the authentication provider configuration form
*
* @see IcingaForm::create()
*/
public function create() public function create()
{ {
$order = $this->getAuthenticationOrder(); $order = $this->getAuthenticationOrder();
@ -246,6 +305,11 @@ class AuthenticationForm extends Form
$this->setSubmitLabel('Save changes'); $this->setSubmitLabel('Save changes');
} }
/**
* Return the configuration state defined by this form
*
* @return array
*/
public function getConfig() public function getConfig()
{ {
$result = array(); $result = array();
@ -258,6 +322,11 @@ class AuthenticationForm extends Form
return $result; return $result;
} }
/**
* Enable the "ConditionalHidden" Decorator for all elements in this form
*
* @see ConditionalHidden
*/
private function enableConditionalDecorator() private function enableConditionalDecorator()
{ {
foreach ($this->getElements() as $element) { foreach ($this->getElements() as $element) {
@ -265,6 +334,21 @@ class AuthenticationForm extends Form
} }
} }
/**
* 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
*/
private static function moveElementUp($key, array $array) private static function moveElementUp($key, array $array)
{ {
$swap = null; $swap = null;
@ -280,6 +364,21 @@ class AuthenticationForm extends Form
return $array; return $array;
} }
/**
* Static helper for moving an element in an array one slot up, 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
*/
private static function moveElementDown($key, array $array) private static function moveElementDown($key, array $array)
{ {
$swap = null; $swap = null;

View File

@ -32,8 +32,10 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga; use \Icinga\Application\Icinga;
use \Icinga\Application\DbAdapterFactory; use \Icinga\Application\DbAdapterFactory;
use \Icinga\Web\Form; use \Icinga\Web\Form;
use \Icinga\Web\Form\Validator\WritablePathValidator;
use \Icinga\Web\Form\Validator\TimeFormatValidator;
use \Icinga\Web\Form\Validator\DateFormatValidator;
use \Icinga\Web\Form\Decorator\ConditionalHidden; use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Icinga\Web\Form\Element\Note;
use \DateTimeZone; use \DateTimeZone;
use \Zend_Config; use \Zend_Config;
@ -138,20 +140,14 @@ class GeneralForm extends Form
array( array(
'label' => 'Development mode', 'label' => 'Development mode',
'required' => true, 'required' => true,
'helptesxt' => 'Set true to show more detailed errors '
. 'and disable certain optimizations '
. 'in order to make debugging easier.',
'tooltip' => 'More verbose output', 'tooltip' => 'More verbose output',
'value' => $env === 'development' 'value' => $env === 'development'
) )
); );
$this->addElement(
new Note(
array(
'name' => 'note_env',
'value' => 'Set true to show more detailed errors '
. 'and disable certain optimizations '
. 'in order to make debugging easier.'
)
)
);
} }
/** /**
@ -167,6 +163,8 @@ class GeneralForm extends Form
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',
@ -175,18 +173,10 @@ class GeneralForm extends Form
'label' => 'Default application timezone', 'label' => 'Default application timezone',
'required' => true, 'required' => true,
'multiOptions' => $tzList, 'multiOptions' => $tzList,
'helptext' => $helptext,
'value' => $cfg->get('timezone', date_default_timezone_get()) 'value' => $cfg->get('timezone', date_default_timezone_get())
) )
); );
$this->addElement(
new Note(
array(
'name' => 'noteTimezone',
'value' => '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 .'
)
)
);
} }
/** /**
@ -202,17 +192,10 @@ class GeneralForm extends Form
array( array(
'label' => 'Module folder', 'label' => 'Module folder',
'required' => true, 'required' => true,
'helptext' => 'Use this folder to activate modules (must be writable by your webserver)',
'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules') 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
) )
); );
$this->addElement(
new Note(
array(
'name' => 'noteModuleFolder',
'value' => 'Use this folder to activate modules (must be writable by your webserver)'
)
)
);
} }
/** /**
@ -225,43 +208,29 @@ class GeneralForm extends Form
$phpUrl = '<a href="http://php.net/manual/en/function.date.php" target="_new">' $phpUrl = '<a href="http://php.net/manual/en/function.date.php" target="_new">'
. 'the official PHP documentation</a>'; . 'the official PHP documentation</a>';
$this->addElement( $txtDefaultDateFormat = new Zend_Form_Element_Text(
'text',
'date_format',
array( array(
'name' => 'date_format',
'label' => 'Date format', 'label' => 'Date format',
'helptext' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values',
'required' => true, 'required' => true,
'value' => $cfg->get('dateFormat', 'd/m/Y') 'value' => $cfg->get('dateFormat', 'd/m/Y')
)
);
$this->addElement(
new Note(
array(
'name' => 'noteDateFormat',
'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values'
)
) )
); );
$this->addElement($txtDefaultDateFormat);
$txtDefaultDateFormat->addValidator(new DateFormatValidator());
$txtDefaultTimeFormat = new Zend_Form_Element_Text(
$this->addElement(
'text',
'time_format',
array( array(
'name' => 'time_format',
'label' => 'Time format', 'label' => 'Time format',
'required' => true, 'required' => true,
'value' => $cfg->get('timeFormat', 'g:i A') 'helptext' => 'Display times according to this format. See ' . $phpUrl . ' for possible values',
) 'value' => $cfg->get('timeFormat', 'g:i A')
);
$this->addElement(
new Note(
array(
'name' => 'noteTimeFormat',
'value' => 'Display times according to this format. See '
. $phpUrl . ' for possible values'
)
) )
); );
$txtDefaultTimeFormat->addValidator(new TimeFormatValidator());
$this->addElement($txtDefaultTimeFormat);
} }
/** /**
@ -316,7 +285,7 @@ class GeneralForm extends Form
'multiOptions' => $backends 'multiOptions' => $backends
) )
); );
$txtPreferencesIniPath->addValidator(new WritablePathValidator());
$this->addElement($txtPreferencesIniPath); $this->addElement($txtPreferencesIniPath);
$this->addElement($txtPreferencesDbResource); $this->addElement($txtPreferencesDbResource);

View File

@ -32,6 +32,7 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga; use \Icinga\Application\Icinga;
use \Icinga\Web\Form; use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note; use \Icinga\Web\Form\Element\Note;
use \Icinga\Web\Form\Validator\WritablePathValidator;
use \Icinga\Web\Form\Decorator\ConditionalHidden; use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Config; use \Zend_Config;
use \Zend_Form_Element_Text; use \Zend_Form_Element_Text;
@ -49,6 +50,13 @@ class LoggingForm extends Form
*/ */
private $config = null; private $config = null;
/**
* Base directory to use instead of the one provided by Icinga::app (used for testing)
*
* @var null
*/
private $baseDir = null;
/** /**
* Set the configuration of this form * Set the configuration of this form
* *
@ -61,6 +69,32 @@ class LoggingForm extends Form
$this->config = $cfg; $this->config = $cfg;
} }
/**
* Set a different base directory to use for default paths instead of the one provided by Icinga::app()
*
* @param string $dir The new directory to use
*/
public function setBaseDir($dir)
{
$this->baseDir = $dir;
}
/**
* Return the applications base directory or the value from a previous setBaseDir call
*
* This is used to determine the default logging paths in a manner that allows to set a different path
* during testing
*
* @return string
*/
public function getBaseDir()
{
if ($this->baseDir) {
return $this->baseDir;
}
return realpath(Icinga::app()->getApplicationDir().'/../');
}
/** /**
* Return true if the debug log path textfield should be displayed * Return true if the debug log path textfield should be displayed
* *
@ -74,7 +108,7 @@ class LoggingForm extends Form
*/ */
private function shouldDisplayDebugLog(Zend_Config $config) private function shouldDisplayDebugLog(Zend_Config $config)
{ {
$debugParam = $this->getRequest()->getParam('logging_use_debug', null); $debugParam = $this->getRequest()->getParam('logging_debug_enable', null);
if ($debugParam !== null) { if ($debugParam !== null) {
return intval($debugParam) === 1; return intval($debugParam) === 1;
} else { } else {
@ -101,6 +135,8 @@ class LoggingForm extends Form
} }
/** /**
* Create this logging configuration form
*
* @see Form::create() * @see Form::create()
*/ */
public function create() public function create()
@ -127,7 +163,7 @@ class LoggingForm extends Form
'value' => $this->loggingIsEnabled($logging) 'value' => $this->loggingIsEnabled($logging)
) )
); );
if (!$this->loggingIsEnabled($debug)) { if (!$this->loggingIsEnabled($logging)) {
$this->addElement( $this->addElement(
new Note( new Note(
array( array(
@ -142,25 +178,19 @@ class LoggingForm extends Form
return; return;
} }
$this->addElement(
'text', $txtLogPath = new Zend_Form_Element_Text(
'logging_app_path',
array( array(
'name' => 'logging_app_target',
'label' => 'Application log path', 'label' => 'Application log path',
'helptext' => 'The logfile to write the icingaweb debug logs to.'
. 'The webserver must be able to write at this location',
'required' => true, 'required' => true,
'value' => $logging->get('target', '/var/log/icingaweb.log') 'value' => $logging->get('target', '/var/log/icingaweb.log')
) )
); );
$txtLogPath->addValidator(new WritablePathValidator());
$this->addElement( $this->addElement($txtLogPath);
new Note(
array(
'name' => 'note_logging_app_path',
'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write'
. 'at this location'
)
)
);
$this->addElement( $this->addElement(
'checkbox', 'checkbox',
@ -168,63 +198,73 @@ class LoggingForm extends Form
array( array(
'label' => 'Verbose logging', 'label' => 'Verbose logging',
'required' => true, 'required' => true,
'helptext' => 'Check to write more verbose output to the icinga log file',
'value' => intval($logging->get('verbose', 0)) === 1 'value' => intval($logging->get('verbose', 0)) === 1
) )
); );
$this->addElement(
new Note(
array(
'name' => 'note_logging_app_verbose',
'value'=> 'Check to write more verbose output to the icinga log file'
)
)
);
$this->addElement( $this->addElement(
'checkbox', 'checkbox',
'logging_use_debug', 'logging_debug_enable',
array( array(
'label' => 'Use debug log', 'label' => 'Use debug log',
'required' => true, 'required' => true,
'helptext' => 'Check to write a seperate debug log (Warning: This file can grow very big)',
'value' => $this->shouldDisplayDebugLog($debug) 'value' => $this->shouldDisplayDebugLog($debug)
) )
); );
$this->addElement(
new Note(
array(
'name' => 'note_logging_use_debug',
'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)'
)
)
);
$textLoggingDebugPath = new Zend_Form_Element_Text( $textLoggingDebugPath = new Zend_Form_Element_Text(
array( array(
'name' => 'logging_debug_path', 'name' => 'logging_debug_target',
'label' => 'Debug log path', 'label' => 'Debug log path',
'required' => true, 'required' => $this->shouldDisplayDebugLog($debug),
'condition' => $this->shouldDisplayDebugLog($debug), 'condition' => $this->shouldDisplayDebugLog($debug),
'value' => $debug->get('target') 'value' => $debug->get('target', $this->getBaseDir() . '/var/log/icinga2.debug.log'),
) 'helptext' => 'Set the path to the debug log'
);
$loggingPathNote = new Note(
array(
'name' => 'note_logging_debug_path',
'value' => 'Set the path to the debug log',
'condition' => $this->shouldDisplayDebugLog($debug)
) )
); );
$textLoggingDebugPath->addValidator(new WritablePathValidator());
$decorator = new ConditionalHidden(); $decorator = new ConditionalHidden();
$this->addElement($textLoggingDebugPath); $this->addElement($textLoggingDebugPath);
$this->addElement($loggingPathNote);
$textLoggingDebugPath->addDecorator($decorator); $textLoggingDebugPath->addDecorator($decorator);
$loggingPathNote->addDecorator($decorator);
$this->enableAutoSubmit(array('logging_use_debug', 'logging_enable'));
$this->enableAutoSubmit(array('logging_debug_enable', 'logging_enable'));
$this->setSubmitLabel('Save changes'); $this->setSubmitLabel('Save changes');
} }
/**
* Return a Zend_Config object containing the state defined in this form
*
* @return Zend_Config The config defined in this form
*/
public function getConfig()
{
if ($this->config === null) {
$this->config = new Zend_Config(array());
}
if ($this->config->logging === null) {
$this->config->logging = new Zend_Config(array());
}
if ($this->config->logging->debug === null) {
$this->config->logging->debug = new Zend_Config(array());
}
$values = $this->getValues();
$cfg = $this->config->toArray();
$cfg['logging']['enable'] = intval($values['logging_enable']);
$cfg['logging']['type'] = 'stream';
$cfg['logging']['verbose'] = $values['logging_app_verbose'];
$cfg['logging']['target'] = $values['logging_app_target'];
$cfg['logging']['debug']['enable'] = intval($values['logging_debug_enable']);
$cfg['logging']['debug']['type'] = 'stream';
$cfg['logging']['debug']['target'] = $values['logging_debug_target'];
return new Zend_Config($cfg);
}
} }

View File

@ -13,6 +13,21 @@ $createDbBackend = Url::fromPath(
?> ?>
<?= $this->tabs->render($this); ?> <?= $this->tabs->render($this); ?>
<?php
$errors = $this->form->getErrorMessages();
if (!empty($errors)):
?>
<div class="alert alert-danger">
<h4>There are errors in your configuration</h4>
<br/>
<ul>
<?php foreach($errors as $error): ?>
<li><?= $error ?></li>
<?php endforeach;?>
</ul>
</div>
<?php endif; ?>
<div> <div>
<a href="<?= $createLdapBackend ?>">Create a new LDAP authentication backend</a><br/> <a href="<?= $createLdapBackend ?>">Create a new LDAP authentication backend</a><br/>
<a href="<?= $createDbBackend ?>">Create a new DB authentication backend</a> <a href="<?= $createDbBackend ?>">Create a new DB authentication backend</a>

View File

@ -0,0 +1,4 @@
<?= $this->tabs->render($this); ?>
<h4>Create new backend</h4>
<?= $this->form ?>

View File

@ -1,3 +1,17 @@
<?= $this->tabs->render($this); ?> <?= $this->tabs->render($this); ?>
<?php $errors = $this->form->getErrorMessages(); ?>
<?php if (!empty($errors)) : ?>
<div class="alert alert-danger">
<h4>Errors occured when trying to save the project</h4>
<p>
The following errors occured when trying to save the configuration:
</p>
<ul>
<?php foreach($errors as $error): ?>
<li><?= $this->escape($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?= $this->form ?> <?= $this->form ?>

View File

@ -1,14 +1,14 @@
<?= $this->tabs->render($this); ?> <?= $this->tabs->render($this); ?>
<br/> <br/>
<div class="alert alert-error"> <div class="alert alert-error">
<h4><i class="icon-warning-sign"> </i>Saving authentication.ini failed</h4> <h4><i class="icon-warning-sign"> </i>Saving <?= $this->escape($this->file); ?>.ini failed</h4>
<br/> <br/>
<p> <p>
Your authentication configuration couldn't be stored (error: "<?= $this->exceptionMessage; ?>"). This could have one or more Your <?= $this->escape($this->file); ?> configuration couldn't be stored (error: "<?= $this->exceptionMessage; ?>").<br/>
of the following reasons: This could have one or more of the following reasons:
</p> </p>
<ul> <ul>
<li>You don't have file-system permissions to write to the authentication.ini file</li> <li>You don't have file-system permissions to write to the <?= $this->escape($this->file); ?>.ini file</li>
<li>Something went wrong while writing the file</li> <li>Something went wrong while writing the file</li>
<li>There's an application error preventing you from persisting the configuration</li> <li>There's an application error preventing you from persisting the configuration</li>
</ul> </ul>
@ -17,7 +17,7 @@
<p> <p>
Details can be seen in your application log (if you don't have access to this file, call your administrator in this case). Details can be seen in your application log (if you don't have access to this file, call your administrator in this case).
<br/> <br/>
In case you can access the configuration file (config/authentication.ini) by yourself, you can open it and In case you can access the configuration file (config/<?= $this->escape($this->file); ?>.ini) by yourself, you can open it and
insert the config manually: insert the config manually:
</p> </p>

View File

@ -25,7 +25,7 @@
namespace Icinga\Web; namespace Icinga\Web;
use \Icinga\Web\Form\Decorator\ConditionalHidden; use \Icinga\Web\Form\Decorator\HelpText;
use \Zend_Controller_Request_Abstract; use \Zend_Controller_Request_Abstract;
use \Zend_Form_Element_Submit; use \Zend_Form_Element_Submit;
use \Zend_Form_Element_Reset; use \Zend_Form_Element_Reset;
@ -197,7 +197,7 @@ abstract class Form extends Zend_Form
if (!$this->getAction() && $this->getRequest()) { if (!$this->getAction() && $this->getRequest()) {
$this->setAction($this->getRequest()->getRequestUri()); $this->setAction($this->getRequest()->getRequestUri());
} }
$this->enableAdditionalDecorators();
$this->created = true; $this->created = true;
} }
} }
@ -387,6 +387,13 @@ abstract class Form extends Zend_Form
return $token === hash('sha256', $this->getSessionId() . $seed); return $token === hash('sha256', $this->getSessionId() . $seed);
} }
public function enableAdditionalDecorators()
{
foreach ($this->getElements() as $element) {
$element->addDecorator(new HelpText());
}
}
/** /**
* Generate a new (seed, token) pair * Generate a new (seed, token) pair
* *

View File

@ -26,6 +26,9 @@
*/ */
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Decorator;
use \Zend_Form_Decorator_Abstract;
/** /**
* Decorator to hide elements using a &gt;noscript&lt; tag instead of * Decorator to hide elements using a &gt;noscript&lt; tag instead of
@ -35,15 +38,11 @@
* (who can then automatically refresh their pages) but show them in * (who can then automatically refresh their pages) but show them in
* case JavaScript is disabled * case JavaScript is disabled
*/ */
namespace Icinga\Web\Form\Decorator;
use \Zend_Form_Decorator_Abstract;
class ConditionalHidden extends Zend_Form_Decorator_Abstract class ConditionalHidden extends Zend_Form_Decorator_Abstract
{ {
/** /**
* Generates a html number input * Generate a field that will be wrapped in <noscript> tag if the
* "condition" attribute is set and false or 0
* *
* @access public * @access public
* *

View File

@ -0,0 +1,63 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Decorator;
use \Zend_Form_Decorator_Abstract;
/**
* Decorator that automatically adds a helptext to an input element
* when the 'helptext' attribute is set
*/
class HelpText extends Zend_Form_Decorator_Abstract
{
/**
* Add a helptext to an input field
*
* @access public
*
* @param string $name The element name.
* @param string $value The default value.
* @param array $attribs Attributes which should be added to the input tag.
*
* @return string The input tag and options XHTML.
*/
public function render($content = '')
{
$attributes = $this->getElement()->getAttribs();
if (isset($attributes['helptext'])) {
$content = '<div>'
. $content
. '<span class="helptext">'
. $attributes['helptext']
. '</span></div><br/>';
}
return $content;
}
}

View File

@ -0,0 +1,86 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
/**
* Validator that checks if a textfield contains a correct date format
*
*/
class DateFormatValidator extends Zend_Validate_Abstract
{
/**
* Valid date characters according to @see http://www.php.net/manual/en/function.date.php
*
* @var array
* @see http://www.php.net/manual/en/function.date.php
*/
private $validChars =
array('d', 'D', 'j', 'l', 'N', 'S', 'w', 'z', 'W', 'F', 'm', 'M', 'n', 't', 'L', 'o', 'Y', 'y');
/**
* List of sensible time separators
*
* @var array
*/
private $validSeparators = array(' ', ':', '-', '/', ';', ',', '.');
/**
* Error templates
*
* @var array
* @see Zend_Validate_Abstract::$_messageTemplates
*/
// @codingStandardsIgnoreStart
protected $_messageTemplates = array(
'INVALID_CHARACTERS' => 'Invalid date format'
);
// @codingStandardsIgnoreEnd
/**
* Validate the input value
*
* @param string $value The format string to validate
* @param null $context The form context (ignored)
*
* @return bool True when the input is valid, otherwise false
* @see Zend_Validate_Abstract::isValid
*/
public function isValid($value, $context = null)
{
$rest = trim($value, join(' ', array_merge($this->validChars, $this->validSeparators)));
if (strlen($rest) > 0) {
$this->_error('INVALID_CHARACTERS');
return false;
}
return true;
}
}

View File

@ -0,0 +1,85 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
/**
* Validator that checks if a textfield contains a correct time format
*
*/
class TimeFormatValidator extends Zend_Validate_Abstract
{
/**
* Valid time characters according to @see http://www.php.net/manual/en/function.date.php
*
* @var array
* @see http://www.php.net/manual/en/function.date.php
*/
private $validChars = array('a', 'A', 'B', 'g', 'G', 'h', 'H', 'i', 's', 'u');
/**
* List of sensible time separators
*
* @var array
*/
private $validSeparators = array(' ', ':', '-', '/', ';', ',', '.');
/**
* Error templates
*
* @var array
* @see Zend_Validate_Abstract::$_messageTemplates
*/
// @codingStandardsIgnoreStart
protected $_messageTemplates = array(
'INVALID_CHARACTERS' => 'Invalid time format'
);
// @codingStandardsIgnoreEnd
/**
* Validate the input value
*
* @param string $value The format string to validate
* @param null $context The form context (ignored)
*
* @return bool True when the input is valid, otherwise false
* @see Zend_Validate_Abstract::isValid
*/
public function isValid($value, $context = null)
{
$rest = trim($value, join(' ', array_merge($this->validChars, $this->validSeparators)));
if (strlen($rest) > 0) {
$this->_error('INVALID_CHARACTERS');
return false;
}
return true;
}
}

View File

@ -0,0 +1,72 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
/**
* Validator that interprets the value as a path and checks if it's writable
*
*/
class WritablePathValidator extends Zend_Validate_Abstract
{
/**
* The messages to write on differen error states
*
* @var array
* @see Zend_Validate_Abstract::$_messageTemplates
*/
// @codingStandardsIgnoreStart
protected $_messageTemplates = array(
'NOT_WRITABLE' => 'Path is not writable'
);
// @codingStandardsIgnoreEnd
/**
* Check whether the given value is writable path
*
* @param string $value The value submitted in the form
* @param null $context The context of the form
*
* @return bool True when validation worked, otherwise false
* @see Zend_Validate_Abstract::isValid()
*/
public function isValid($value, $context = null)
{
$value = (string) $value;
$this->_setValue($value);
if ((file_exists($value) && is_writable($value)) ||
(is_dir(dirname($value)) != '' && is_writable(dirname($value)))) {
return true;
}
$this->_error('NOT_WRITABLE');
return false;
}
}

View File

@ -6,6 +6,7 @@
namespace Test\Monitoring\Forms\Command; namespace Test\Monitoring\Forms\Command;
require_once realpath('library/Icinga/Web/Form/BaseFormTest.php'); require_once realpath('library/Icinga/Web/Form/BaseFormTest.php');
require_once realpath(__DIR__ . '/../../../../../../../modules/monitoring/application/forms/Command/CommandForm.php');
require_once realpath(__DIR__ . '/../../../../../../../modules/monitoring/application/forms/Command/AcknowledgeForm.php'); require_once realpath(__DIR__ . '/../../../../../../../modules/monitoring/application/forms/Command/AcknowledgeForm.php');
require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/ConfigAwareFactory.php'); require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/ConfigAwareFactory.php');
require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/DateTimeFactory.php'); require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/DateTimeFactory.php');

View File

@ -0,0 +1,315 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Test\Icinga\Form\Config;
require_once('Zend/Config.php');
require_once('Zend/Config/Ini.php');
require_once(realpath('library/Icinga/Web/Form/BaseFormTest.php'));
require_once(realpath('../../application/forms/Config/AuthenticationForm.php'));
require_once(realpath('../../application/forms/Config/Authentication/BaseBackendForm.php'));
require_once(realpath('../../application/forms/Config/Authentication/DbBackendForm.php'));
require_once(realpath('../../application/forms/Config/Authentication/LdapBackendForm.php'));
use \Test\Icinga\Web\Form\BaseFormTest;
use \Icinga\Web\Form;
use \DOMDocument;
use \Zend_Config;
use \Zend_View;
/**
* Test for the authentication provider form
*
*/
class AuthenticationFormTest extends \Test\Icinga\Web\Form\BaseFormTest
{
/**
* Return a test configuration containing a database and a ldap backend
*
* @return Zend_Config
*/
private function getTestConfig()
{
return new Zend_Config(
array(
'test-db' => array(
'backend' => 'db',
'target' => 'user',
'resource' => 'db_resource'
),
'test-ldap' => array(
'backend' => 'ldap',
'target' => 'user',
'hostname' => 'test host',
'root_dn' => 'ou=test,dc=icinga,dc=org',
'bind_dn' => 'cn=testuser,cn=config',
'bind_pw' => 'password',
'user_class' => 'testClass',
'user_name_attribute' => 'testAttribute'
)
)
);
}
/**
* Test the ldap provider form population from config
*
*/
public function testLdapProvider()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(array(), 'Icinga\Form\Config\AuthenticationForm');
$config = new Zend_Config(
array(
'test-ldap' => array(
'backend' => 'ldap',
'target' => 'user',
'hostname' => 'test host',
'root_dn' => 'ou=test,dc=icinga,dc=org',
'bind_dn' => 'cn=testuser,cn=config',
'bind_pw' => 'password',
'user_class' => 'testClass',
'user_name_attribute' => 'testAttribute'
)
)
);
$form->setConfiguration($config);
$form->create();
// parameters to be hidden
$notShown = array('backend', 'target');
foreach ($config->get('test-ldap')->toArray() as $name => $value) {
if (in_array($name, $notShown)) {
continue;
}
$this->assertEquals(
$value,
$form->getValue('backend_testldap_' . $name),
'Asserting the ' . $name . ' parameter to be correctly populated for a ldap authentication form'
);
}
}
/**
* Test the database provider form population from config
*
*/
public function testDbProvider() {
date_default_timezone_set('UTC');
$form = $this->getRequestForm(array(), 'Icinga\Form\Config\AuthenticationForm');
$config = new Zend_Config(
array(
'test-db' => array(
'backend' => 'db',
'target' => 'user',
'resource' => 'db_resource'
)
)
);
$form->setResources(
array('db_resource' => 'db_resource')
);
$form->setConfiguration($config);
$form->create();
// parameters to be hidden
$notShown = array('backend', 'target');
foreach ($config->get('test-db')->toArray() as $name => $value) {
if (in_array($name, $notShown)) {
continue;
}
$this->assertEquals(
$value,
$form->getValue('backend_testdb_' . $name),
'Asserting the ' . $name . ' parameter to be correctly populated for a db authentication form'
);
}
}
/**
* Test whether order modifications via 'priority' are considered
*
*/
public function testShowModifiedOrder()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(
array('priority' => 'test-ldap,test-db'),
'Icinga\Form\Config\AuthenticationForm'
);
$config = $this->getTestConfig();
$form->setResources(
array('db_resource' => 'db_resource')
);
$form->setConfiguration($config);
$form->create();
$prio = array_keys($form->getConfig());
$this->assertEquals('test-ldap', $prio[0], "Asserting priority changes to be persisted");
$this->assertEquals('test-db', $prio[1], "Asserting priority changes to be persisted");
}
/**
* Test whether configuration changes are correctly returned when calling getConfig
*
*/
public function testConfigurationCreation()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(
array(
'priority' => 'test-ldap,test-db',
'backend_testdb_resource' => 'db_resource_2',
'backend_testldap_hostname' => 'modified_host',
'backend_testldap_root_dn' => 'modified_root_dn',
'backend_testldap_bind_dn' => 'modified_bind_dn',
'backend_testldap_bind_pw' => 'modified_bind_pw',
'backend_testldap_user_class' => 'modified_user_class',
'backend_testldap_user_name_attribute' => 'modified_user_name_attribute',
'backend_testdb_resource' => 'db_resource_2'
),
'Icinga\Form\Config\AuthenticationForm'
);
$form->setResources(
array(
'db_resource' => 'db_resource',
'db_resource_2' => 'db_resource_2'
)
);
$form->setConfiguration($this->getTestConfig());
$form->create();
$modified = new Zend_Config($form->getConfig());
$this->assertEquals(
'db_resource_2',
$modified->get('test-db')->resource,
'Asserting database resource modifications to be applied'
);
$this->assertEquals(
'user',
$modified->get('test-db')->target,
'Asserting database target still being user when modifying'
);
$this->assertEquals(
'db',
$modified->get('test-db')->backend,
'Asserting database backend still being db when modifying'
);
$ldap = $modified->get('test-ldap');
$this->assertEquals(
'modified_host',
$ldap->hostname,
'Asserting hostname modifications to be applied when modifying ldap authentication backends'
);
$this->assertEquals(
'modified_root_dn',
$ldap->root_dn,
'Asserting root dn modifications to be applied when modifying ldap authentication backends'
);
$this->assertEquals(
'modified_bind_dn',
$ldap->bind_dn,
'Asserting bind dn modifications to be applied when modifying ldap authentication backends'
);
$this->assertEquals(
'modified_bind_pw',
$ldap->bind_pw,
'Asserting bind pw modifications to be applied when modifying ldap authentication backends'
);
$this->assertEquals(
'modified_user_class',
$ldap->user_class,
'Asserting user class modifications to be applied when modifying ldap authentication backends'
);
$this->assertEquals(
'modified_user_name_attribute',
$ldap->user_name_attribute,
'Asserting user name attribute modifications to be applied when modifying ldap authentication backends'
);
}
/**
* Test correct behaviour when ticking the 'remove backend' option
*/
public function testBackendRemoval()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(
array(
'priority' => 'test-ldap,test-db',
'backend_testdb_resource' => 'db_resource_2',
'backend_testldap_remove' => 1,
'backend_testldap_hostname' => 'modified_host',
'backend_testldap_root_dn' => 'modified_root_dn',
'backend_testldap_bind_dn' => 'modified_bind_dn',
'backend_testldap_bind_pw' => 'modified_bind_pw',
'backend_testldap_user_class' => 'modified_user_class',
'backend_testldap_user_name_attribute' => 'modified_user_name_attribute',
'backend_testdb_resource' => 'db_resource_2'
),
'Icinga\Form\Config\AuthenticationForm'
);
$form->setResources(
array(
'db_resource' => 'db_resource',
'db_resource_2' => 'db_resource_2'
)
);
$form->setConfiguration($this->getTestConfig());
$form->create();
$view = new Zend_View();
$html = new DOMDocument();
$html->loadHTML($form->render($view));
$this->assertEquals(
null,
$html->getElementById('backend_testldap_hostname-element'),
'Asserting configuration to be hidden when an authentication is marked as to be removed'
);
$config = $form->getConfig();
$this->assertFalse(
isset($config['test-ldap']),
'Asserting deleted backends not being persisted in the configuration'
);
}
}

View File

@ -0,0 +1,214 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Test\Icinga\Form\Config;
require_once('Zend/Config.php');
require_once('Zend/Config/Ini.php');
require_once(realpath('library/Icinga/Web/Form/BaseFormTest.php'));
require_once(realpath('../../application/forms/Config/LoggingForm.php'));
require_once(realpath('../../library/Icinga/Application/Icinga.php'));
use \Test\Icinga\Web\Form\BaseFormTest;
use \Icinga\Web\Form;
use \Zend_Config;
/**
* Test for the authentication provider form
*
*/
class LoggingFormTest extends BaseFormTest
{
/**
* Test the logging form to be correctly populated from configuration
*
*/
public function testLoggingFormPopulation()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(array(), 'Icinga\Form\Config\LoggingForm');
$config = new Zend_Config(
array(
'logging' => array(
'enable' => 1,
'target' => '/some/path',
'verbose' => 0,
'type' => 'stream',
'debug' => array(
'enable' => 1,
'target' => '/some/debug/path',
'type' => 'stream'
)
)
)
);
$form->setConfiguration($config);
$form->setBaseDir('basedir');
$form->create();
$this->assertEquals(
'1',
$form->getValue('logging_enable'),
'Asserting the logging enable tick to be set'
);
$this->assertEquals(
'0',
$form->getValue('logging_app_verbose'),
'Asserting the logging verbose tick not to be set'
);
$this->assertEquals('/some/path', $form->getValue('logging_app_target'), 'Asserting the logging path to be set');
$this->assertEquals(
1,
$form->getValue('logging_debug_enable'),
'Asserting the debug log enable tick to be set'
);
$this->assertEquals(
'/some/debug/path',
$form->getValue('logging_debug_target'),
'Asserting the debug log path to be set'
);
}
/**
* Test the logging form to create correct modified configurations when submit
*
*/
public function testCorrectConfigCreation()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(
array(
'logging_enable' => 1,
'logging_app_target' => 'some/new/target',
'logging_app_verbose' => 1,
'logging_debug_enable' => 0,
'logging_debug_target' => 'a/new/target'
),
'Icinga\Form\Config\LoggingForm'
);
$baseConfig = new Zend_Config(
array(
'global' => array(
'option' => 'value'
),
'logging' => array(
'enable' => 1,
'target' => '/some/path',
'verbose' => 0,
'type' => 'stream',
'debug' => array(
'enable' => 1,
'target' => '/some/debug/path',
'type' => 'stream'
)
)
)
);
$form->setConfiguration($baseConfig);
$form->setBaseDir('basedir');
$form->create();
$form->populate($this->getRequest()->getParams());
$config = $form->getConfig();
$this->assertEquals(
'value',
$config->global->option,
'Asserting global options not to be altered when changing log'
);
$this->assertEquals(
1,
$config->logging->enable,
'Asserting logging to stay enabled when enable is ticked'
);
$this->assertEquals(
'some/new/target',
$config->logging->target,
'Asserting target modifications to be applied'
);
$this->assertEquals(
1,
$config->logging->verbose,
'Asserting ticking the verbose checkbox to be applied'
);
$this->assertEquals(
'stream',
$config->logging->type,
'Asserting the type to stay "stream"'
);
$this->assertEquals(
0,
$config->logging->debug->enable,
'Asserting debug log to be disabled'
);
$this->assertEquals(
'a/new/target',
$config->logging->debug->target,
'Asserting the debug log target modifications to be applied'
);
}
/**
* Test form elements to be hidden when logging is disabled
*
*/
public function testLoggingDisabled()
{
date_default_timezone_set('UTC');
$form = $this->getRequestForm(
array(),
'Icinga\Form\Config\LoggingForm'
);
$baseConfig = new Zend_Config(
array(
'global' => array(
'option' => 'value'
),
'logging' => array(
'enable' => 0,
'target' => '/some/path',
'verbose' => 0,
'type' => 'stream',
'debug' => array(
'enable' => 1,
'target' => '/some/debug/path',
'type' => 'stream'
)
)
)
);
$form->setConfiguration($baseConfig);
$form->create();
$this->assertEquals(
null,
$form->getElement('logging_app_target'),
'Asserting no fields being rendered when logging is off'
);
}
}

View File

@ -24,46 +24,61 @@ namespace Test\Icinga\Web\Form {
require_once 'Zend/Form.php'; require_once 'Zend/Form.php';
require_once 'Zend/View.php'; require_once 'Zend/View.php';
require_once 'Zend/Form/Element/Submit.php'; require_once 'Zend/Form/Element/Submit.php';
require_once 'Zend/Form/Element/Text.php';
require_once 'Zend/Form/Element/Password.php';
require_once 'Zend/Form/Element/Reset.php'; require_once 'Zend/Form/Element/Reset.php';
require_once 'Zend/Form/Element/Checkbox.php'; require_once 'Zend/Form/Element/Checkbox.php';
require_once 'Zend/Form/Element/Hidden.php'; require_once 'Zend/Form/Element/Hidden.php';
require_once 'Zend/Form/Decorator/Abstract.php'; require_once 'Zend/Form/Decorator/Abstract.php';
require_once 'Zend/Validate/Date.php'; require_once 'Zend/Validate/Date.php';
$base = '../../'; $base = '../../';
require_once realpath($base . 'library/Icinga/Exception/ProgrammingError.php');
require_once realpath($base . 'library/Icinga/Web/Form.php'); require_once realpath($base.'library/Icinga/Exception/ProgrammingError.php');
require_once realpath($base . 'library/Icinga/Web/Form/InvalidCSRFTokenException.php'); require_once realpath($base.'library/Icinga/Web/Form.php');
require_once realpath($base . 'library/Icinga/Web/Form/Element/Note.php'); require_once realpath($base.'library/Icinga/Web/Form/InvalidCSRFTokenException.php');
require_once realpath($base . 'library/Icinga/Web/Form/Element/DateTimePicker.php'); require_once realpath($base.'library/Icinga/Web/Form/Element/Note.php');
require_once realpath($base . 'modules/monitoring/application/forms/Command/CommandForm.php'); require_once realpath($base.'library/Icinga/Web/Form/Element/DateTimePicker.php');
require_once realpath($base . 'modules/monitoring/application/forms/Command/WithChildrenCommandForm.php');
require_once realpath('../../library/Icinga/Web/Form/Decorator/ConditionalHidden.php'); require_once realpath('../../library/Icinga/Web/Form/Decorator/ConditionalHidden.php');
use \Zend_View; require_once realpath('../../library/Icinga/Web/Form/Decorator/HelpText.php');
require_once realpath('../../library/Icinga/Web/Form/Validator/WritablePathValidator.php');
require_once realpath('../../library/Icinga/Web/Form/Validator/DateFormatValidator.php');
require_once realpath('../../library/Icinga/Web/Form/Validator/TimeFormatValidator.php');
use \Zend_Form; use \Zend_Form;
use \Zend_View_Interface;
use \Zend_Form_Element_Reset;
use \Zend_Form_Element_Submit;
use \Zend_Controller_Request_Abstract;
use \Zend_Test_PHPUnit_ControllerTestCase; use \Zend_Test_PHPUnit_ControllerTestCase;
/**
* Base test to be extended for testing forms
*/
class BaseFormTest extends Zend_Test_PHPUnit_ControllerTestCase class BaseFormTest extends Zend_Test_PHPUnit_ControllerTestCase
{ {
/**
* Returns a formclass with the given set of POST data applied
*
* @param array $data The POST parameters to ste
* @param string $formClass The class name (full namespace) to return
*
* @return Zend_Form $form A form of type $formClass
*/
public function getRequestForm(array $data, $formClass) public function getRequestForm(array $data, $formClass)
{ {
$form = new $formClass(); $form = new $formClass();
$form->setSessionId("test"); $form->setSessionId('test');
$form->initCsrfToken(); $form->initCsrfToken();
$request = $this->getRequest(); $request = $this->getRequest();
$data[$form->getTokenElementName()] = $form->getValue($form->getTokenElementName()); $data[$form->getTokenElementName()] = $form->getValue($form->getTokenElementName());
$request->setMethod("POST")->setPost($data); $request->setMethod('POST')->setPost($data);
$form->setRequest($request); $form->setRequest($request);
return $form; return $form;
} }
/**
* This is just a test to avoid warnings being submitted from the testrunner
*
*/
public function testForRemovingWarnings() public function testForRemovingWarnings()
{ {
$this->assertTrue(true); $this->assertTrue(true);