diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index 4f7adf963..5e6269ce8 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -31,6 +31,13 @@ use \Icinga\Web\Widget\Tab;
use \Icinga\Web\Url;
use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
use \Icinga\Application\Icinga;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Form\Config\GeneralForm;
+use \Icinga\Form\Config\AuthenticationForm;
+use \Icinga\Form\Config\Authentication\LdapBackendForm;
+use \Icinga\Form\Config\Authentication\DbBackendForm;
+use \Icinga\Form\Config\LoggingForm;
+use \Icinga\Config\PreservingIniWriter;
/**
* Application wide controller for application preferences
@@ -50,16 +57,30 @@ class ConfigController extends BaseConfigController
'index' => new Tab(
array(
'name' => 'index',
- 'title' => 'Configuration',
- 'iconCls' => 'wrench',
+ 'title' => 'Application',
'url' => Url::fromPath('/config')
)
),
+
+ 'authentication' => new Tab(
+ array(
+ 'name' => 'auth',
+ 'title' => 'Authentication',
+ 'url' => Url::fromPath('/config/authentication')
+ )
+ ),
+
+ 'logging' => new Tab(
+ array(
+ 'name' => 'logging',
+ 'title' => 'Logging',
+ 'url' => Url::fromPath('/config/logging')
+ )
+ ),
'modules' => new Tab(
array(
'name' => 'modules',
'title' => 'Modules',
- 'iconCls' => 'puzzle-piece',
'url' => Url::fromPath('/config/moduleoverview')
)
)
@@ -68,11 +89,39 @@ class ConfigController extends BaseConfigController
/**
* Index action, entry point for configuration
- * @TODO: Implement configuration interface (#3777)
*/
public function indexAction()
{
+ $form = new GeneralForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->_request);
+ if ($form->isSubmittedAndValid()) {
+ if (!$this->writeConfigFile($form->getConfig(), 'config')) {
+ return false;
+ }
+ $this->redirectNow('/config');
+ }
+ $this->view->form = $form;
+ }
+
+
+ /**
+ * Form for modifying the logging configuration
+ */
+ public function loggingAction()
+ {
+ $form = new LoggingForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->_request);
+ if ($form->isSubmittedAndValid()) {
+ $config = $form->getConfig();
+ if (!$this->writeConfigFile($form->getConfig(), 'config')) {
+ return;
+ }
+ $this->redirectNow('/config/logging');
+ }
+ $this->view->form = $form;
}
/**
@@ -106,5 +155,110 @@ class ConfigController extends BaseConfigController
$manager->disableModule($this->_getParam('name'));
$this->redirectNow('config/moduleoverview?_render=body');
}
+
+ /**
+ * Action for creating a new authentication backend
+ */
+ public function authenticationAction()
+ {
+ $form = new AuthenticationForm();
+ $config = IcingaConfig::app('authentication');
+ $form->setConfiguration($config);
+ $form->setRequest($this->_request);
+
+ if ($form->isSubmittedAndValid()) {
+ $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;
+ }
+
+ /**
+ * Action for creating a new authentication backend
+ */
+ public function createauthenticationbackendAction()
+ {
+ if ($this->getRequest()->getParam('type') === 'ldap') {
+ $form = new LdapBackendForm();
+ } else {
+ $form = new DbBackendForm();
+ }
+ $form->setRequest($this->getRequest());
+ if ($form->isSubmittedAndValid()) {
+ $backendCfg = IcingaConfig::app('authentication')->toArray();
+ foreach ($form->getConfig() as $backendName => $settings) {
+ $backendCfg[$backendName] = $settings;
+ }
+ if (!$this->writeAuthenticationFile($backendCfg)) {
+ return;
+ }
+ $this->redirectNow('/config/authentication');
+
+ }
+ $this->view->form = $form;
+ $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 supplied 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
diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php
index d8bacbf1b..22dc8767f 100644
--- a/application/controllers/PreferenceController.php
+++ b/application/controllers/PreferenceController.php
@@ -29,13 +29,25 @@
use \Icinga\Web\Controller\BasePreferenceController;
use \Icinga\Web\Widget\Tab;
+use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Web\Url;
+use \Icinga\Form\Preference\GeneralForm;
/**
* Application wide preference controller for user preferences
*/
class PreferenceController extends BasePreferenceController
{
+
+ /**
+ * This controller modifies the session
+ *
+ * @var bool
+ *
+ * @see \Icinga\Web\Controller\ActionController::$modifiesSession
+ */
+ protected $modifiesSession = true;
+
/**
* Create tabs for this preference controller
*
@@ -48,9 +60,8 @@ class PreferenceController extends BasePreferenceController
return array(
'preference' => new Tab(
array(
- 'name' => 'preferences',
- 'iconCls' => 'user',
- 'title' => 'Preferences',
+ 'name' => 'general',
+ 'title' => 'General settings',
'url' => Url::fromPath('/preference')
)
)
@@ -58,11 +69,39 @@ class PreferenceController extends BasePreferenceController
}
/**
- * @TODO: Implement User preferences (feature #5425)
+ * General settings for date and time
*/
public function indexAction()
{
+ $form = new GeneralForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->getRequest());
+ if ($form->isSubmittedAndValid()) {
+ $preferences = $form->getPreferences();
+ $userPreferences = $this->getRequest()->getUser()->getPreferences();
+ $userPreferences->startTransaction();
+ foreach ($preferences as $key => $value) {
+ if (!$value) {
+ $userPreferences->remove($key);
+ } else {
+ $userPreferences->set($key, $value);
+ }
+ }
+ try {
+ $userPreferences->commit();
+ $this->view->success = true;
+
+ // recreate form to show new values
+ $form = new GeneralForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->getRequest());
+
+ } catch (Exception $e) {
+ $this->view->exceptionMessage = $e->getMessage();
+ }
+ }
+ $this->view->form = $form;
}
}
// @codingStandardsIgnoreEnd
diff --git a/application/forms/Config/Authentication/BaseBackendForm.php b/application/forms/Config/Authentication/BaseBackendForm.php
new file mode 100644
index 000000000..01b0acb43
--- /dev/null
+++ b/application/forms/Config/Authentication/BaseBackendForm.php
@@ -0,0 +1,139 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace Icinga\Form\Config\Authentication;
+
+use \Zend_Config;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Web\Form;
+
+/**
+ * Base form for authentication backend forms
+ */
+abstract class BaseBackendForm extends Form
+{
+ /**
+ * The name of the backend currently displayed in this form
+ *
+ * Will be the section in the authentication.ini file
+ *
+ * @var string
+ */
+ private $backendName = '';
+
+ /**
+ * The backend configuration as a Zend_Config object
+ *
+ * @var Zend_Config
+ */
+ private $backend;
+
+ /**
+ * The resources to use instead of the factory provided ones (use for testing)
+ *
+ * @var Zend_Config
+ */
+ private $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
+ * (used for testing)
+ *
+ * @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 for displaying in the database selection field
+ *
+ * @return array
+ */
+ public function getResources()
+ {
+ if ($this->resources === null) {
+ return DbAdapterFactory::getResources();
+ } else {
+ return $this->resources;
+ }
+ }
+
+ /**
+ * 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();
+}
diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php
new file mode 100644
index 000000000..df9d241a6
--- /dev/null
+++ b/application/forms/Config/Authentication/DbBackendForm.php
@@ -0,0 +1,121 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace Icinga\Form\Config\Authentication;
+
+use \Zend_Config;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Web\Form;
+
+/**
+ * Form class for adding/modifying database authentication backends
+ */
+class DbBackendForm extends BaseBackendForm
+{
+ /**
+ * Return a list of all database resource ready to be used as the multiOptions
+ * attribute in a Zend_Form_Element_Select object
+ *
+ * @return array
+ */
+ private function getDatabaseResources()
+ {
+ $backends = array();
+ foreach ($this->getResources() as $resname => $resource) {
+ if ($resource['type'] !== 'db') {
+ continue;
+ }
+ $backends[$resname] = $resname;
+ }
+ return $backends;
+ }
+
+ /**
+ * Create this form and add all required elements
+ *
+ * @see Form::create()
+ */
+ public function create()
+ {
+ $name = $this->filterName($this->getBackendName());
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_name',
+ array(
+ 'required' => true,
+ 'allowEmpty' => false,
+ 'label' => 'Backend Name',
+ 'helptext' => 'The name of this authentication provider',
+ 'value' => $this->getBackendName()
+ )
+ );
+
+ $this->addElement(
+ 'select',
+ 'backend_' . $name . '_resource',
+ array(
+ 'label' => 'Database Connection',
+ 'required' => true,
+ 'allowEmpty' => false,
+ 'helptext' => 'The database connection to use for authenticating with this provider',
+ 'value' => $this->getBackend()->get('resource'),
+ 'multiOptions' => $this->getDatabaseResources()
+ )
+ );
+
+ $this->setSubmitLabel('Save backend');
+ }
+
+ /**
+ * Return the datatbase authentication backend configuration for this form
+ *
+ * @return array
+ *
+ * @see BaseBackendForm::getConfig()
+ */
+ public function getConfig()
+ {
+ $name = $this->getBackendName();
+ $prefix = 'backend_' . $this->filterName($name) . '_';
+
+ $section = $this->getValue($prefix . 'name');
+ $cfg = array(
+ 'backend' => 'db',
+ 'target' => 'user',
+ 'resource' => $this->getValue($prefix . 'resource'),
+ );
+ return array(
+ $section => $cfg
+ );
+ }
+}
diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php
new file mode 100644
index 000000000..d186712f0
--- /dev/null
+++ b/application/forms/Config/Authentication/LdapBackendForm.php
@@ -0,0 +1,163 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Config\Authentication;
+
+use \Zend_Config;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Web\Form;
+
+/**
+ * Form for adding or modifying LDAP authentication backends
+ */
+class LdapBackendForm extends BaseBackendForm
+{
+ /**
+ * Create this form and add all required elements
+ *
+ * @see Form::create()
+ */
+ public function create()
+ {
+ $name = $this->filterName($this->getBackendName());
+ $backend = $this->getBackend();
+
+ $this->addElement(
+ 'text',
+ 'backend_'.$name.'_name',
+ array(
+ 'required' => true,
+ 'allowEmpty' => false,
+ 'label' => 'Backend Name',
+ 'helptext' => 'The name of this authentication backend',
+ 'value' => $this->getBackendName()
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_hostname',
+ array(
+ 'label' => 'LDAP Server Host',
+ 'allowEmpty' => false,
+ 'value' => $backend->get('hostname', 'localhost'),
+ 'helptext' => 'The hostname or address of the LDAP server to use for authentication',
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_root_dn',
+ array(
+ 'label' => 'LDAP Root DN',
+ '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
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_dn',
+ array(
+ 'label' => 'LDAP Bind DN',
+ 'value' => $backend->get('bind_dn', 'cn=admin,cn=config'),
+ 'helptext' => 'The user dn to use for querying the ldap server',
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'password',
+ 'backend_' . $name . '_bind_pw',
+ array(
+ 'label' => 'LDAP Bind Password',
+ 'renderPassword' => true,
+ 'value' => $backend->get('bind_pw', 'admin'),
+ 'helptext' => 'The password to use for querying the ldap server',
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_user_class',
+ array(
+ 'label' => 'LDAP User Object Class',
+ 'value' => $backend->get('user_class', 'inetOrgPerson'),
+ 'helptext' => 'The object class used for storing users on the ldap server',
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_user_name_attribute',
+ array(
+ 'label' => 'LDAP User Name Attribute',
+ 'value' => $backend->get('user_name_attribute', 'uid'),
+ 'helptext' => 'The attribute name used for storing the user name on the ldap server',
+ 'required' => true
+ )
+ );
+
+ $this->setSubmitLabel('Save Backend');
+ }
+
+ /**
+ * Return the ldap authentication backend configuration for this form
+ *
+ * @return array
+ *
+ * @see BaseBackendForm::getConfig()
+ */
+ public function getConfig()
+ {
+ $name = $this->getBackendName();
+ $prefix = 'backend_' . $this->filterName($name) . '_';
+
+ $section = $this->getValue($prefix . 'name');
+ $cfg = array(
+ 'backend' => 'ldap',
+ 'target' => 'user',
+ 'hostname' => $this->getValue($prefix . 'hostname'),
+ 'root_dn' => $this->getValue($prefix . 'root_dn'),
+ 'bind_dn' => $this->getValue($prefix . 'bind_dn'),
+ 'bind_pw' => $this->getValue($prefix . 'bind_pw'),
+ 'user_class' => $this->getValue($prefix . 'user_class'),
+ 'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute')
+ );
+ return array(
+ $section => $cfg
+ );
+ }
+}
diff --git a/application/forms/Config/AuthenticationForm.php b/application/forms/Config/AuthenticationForm.php
new file mode 100644
index 000000000..1ec5068a8
--- /dev/null
+++ b/application/forms/Config/AuthenticationForm.php
@@ -0,0 +1,396 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Config;
+
+use \Zend_Config;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Element\Note;
+use \Icinga\Web\Form\Decorator\ConditionalHidden;
+
+/**
+ * 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
+{
+ /**
+ * The configuration to use for populating this form
+ *
+ * @var IcingaConfig
+ */
+ private $config = null;
+
+ /**
+ * The resources to use instead of the factory provided ones (use for testing)
+ *
+ * @var null
+ */
+ private $resources = null;
+
+ /**
+ * An array containing all provider subforms currently displayed
+ *
+ * @var array
+ */
+ private $backendForms = array();
+
+
+ /**
+ * Set an alternative array of resources that should be used instead of the DBFactory resource set
+ * (used for testing)
+ *
+ * @param array $resources The resources to use for populating the db selection field
+ */
+ public function setResources(array $resources)
+ {
+ $this->resources = $resources;
+ }
+
+ /**
+ * Set the configuration to be used for this form
+ *
+ * @param IcingaConfig $cfg
+ */
+ public function setConfiguration($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)
+ {
+ $this->addElement(
+ 'checkbox',
+ 'backend_' . $name . '_remove',
+ array(
+ 'name' => 'backend_' . $name . '_remove',
+ 'label' => 'Remove this authentication provider',
+ 'value' => $name,
+ 'checked' => $this->isMarkedForDeletion($name)
+ )
+ );
+ $this->enableAutoSubmit(array('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)
+ {
+ $type = ucfirst(strtolower($backend->get('backend')));
+ $formClass = '\Icinga\Form\Config\Authentication\\' . $type . 'BackendForm';
+ if (!class_exists($formClass)) {
+ Logger::error('Unsupported backend found in authentication configuration: ' . $backend->get('backend'));
+ return;
+ }
+
+ $form = new $formClass();
+ $form->setBackendName($name);
+ $form->setBackend($backend);
+
+ if ($this->resources) {
+ $form->setResources($this->resources);
+ }
+
+ // It would be nice to directly set the form via
+ // this->setForm, but Zend doesn't handle form validation
+ // properly if doing so.
+ $form->create();
+ foreach ($form->getElements() as $elName => $element) {
+ if ($elName === 'backend_' . $this->filterName($name) . '_name') {
+ continue;
+ }
+ $this->addElement($element, $elName);
+ }
+ $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())
+ {
+ $formEls = array();
+ $priorities = array(
+ 'up' => join(',', self::moveElementUp($name, $order)),
+ 'down' => join(',', self::moveElementDown($name, $order))
+ );
+ if ($priorities['up'] != join(',', $order)) {
+ $this->addElement(
+ 'button',
+ 'priority' . $name . '_up',
+ array(
+ 'name' => 'priority',
+ 'label' => 'Move up in authentication order',
+ 'value' => $priorities['up'],
+ 'type' => 'submit'
+ )
+ );
+ $formEls[] = 'priority' . $name . '_up';
+ }
+ if ($priorities['down'] != join(',', $order)) {
+ $this->addElement(
+ 'button',
+ 'priority' . $name . '_down',
+ array(
+ 'name' => 'priority',
+ 'label' => 'Move down in authentication order',
+ 'value' => $priorities['down'],
+ 'type' => 'submit'
+ )
+ );
+ $formEls[] = 'priority' . $name . '_down';
+ }
+
+ 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 self
+ *
+ * @see Zend_Form::populate()
+ */
+ public function populate(array $values)
+ {
+ $last_priority = $this->getValue('current_priority');
+ parent::populate($values);
+ $this->getElement('current_priority')->setValue($last_priority);
+ return $this;
+ }
+
+ /**
+ * 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();
+ $order = $request->getParam(
+ 'priority',
+ $request->getParam('current_priority', null)
+ );
+
+ if ($order === null) {
+ $order = array_keys($this->config->toArray());
+ } else {
+ $order = explode(',', $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)
+ {
+ 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()
+ {
+ $this->addElement(
+ 'hidden',
+ 'current_priority',
+ array(
+ 'name' => 'current_priority',
+ 'value' => join(',', $this->getAuthenticationOrder())
+ )
+ );
+ }
+
+ /**
+ * Create the authentication provider configuration form
+ *
+ * @see IcingaForm::create()
+ */
+ public function create()
+ {
+ $order = $this->getAuthenticationOrder();
+
+ foreach ($order as $name) {
+ $this->addElement(
+ new Note(
+ array(
+ 'escape' => false,
+ 'name' => 'title_backend_' . $name,
+ 'value' => 'Backend ' . $name . ' '
+ )
+ )
+ );
+ $this->addRemoveHint($this->filterName($name));
+ $backend = $this->config->get($name, null);
+ if ($backend === null) {
+ continue;
+ }
+ if (!$this->isMarkedForDeletion($this->filterName($name))) {
+ $this->addProviderForm($name, $backend);
+ $this->addPriorityButtons($name, $order);
+ }
+ }
+
+ $this->addPersistentState();
+ $this->enableConditionalDecorator();
+ $this->setSubmitLabel('Save Changes');
+ }
+
+ /**
+ * Return the configuration state defined by this form
+ *
+ * @return array
+ */
+ public function getConfig()
+ {
+ $result = array();
+ foreach ($this->backendForms as $name) {
+
+ $name->populate($this->getRequest()->getParams());
+ $result += $name->getConfig();
+
+ }
+ return $result;
+ }
+
+ /**
+ * Enable the "ConditionalHidden" Decorator for all elements in this form
+ *
+ * @see ConditionalHidden
+ */
+ private function enableConditionalDecorator()
+ {
+ foreach ($this->getElements() as $element) {
+ $element->addDecorator(new ConditionalHidden());
+ }
+ }
+
+ /**
+ * Static helper for moving an element in an array one slot up, if possible
+ *
+ * Example:
+ *
+ *
+ * $array = array('first', 'second', 'third');
+ * moveElementUp('third', $array); // returns ['first', 'third', 'second']
+ *
+ *
+ * @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)
+ {
+ $swap = null;
+ for ($i=0; $i
+ * $array = array('first', 'second', 'third');
+ * moveElementDown('first', $array); // returns ['second', 'first', 'third']
+ *
+ *
+ * @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)
+ {
+ $swap = null;
+ for ($i=0; $i
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Config;
+
+use \DateTimeZone;
+use \Zend_Config;
+use \Zend_Form_Element_Text;
+use \Zend_Form_Element_Select;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\DbAdapterFactory;
+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;
+
+/**
+ * Configuration form for general, application-wide settings
+ *
+ */
+class GeneralForm extends Form
+{
+ /**
+ * The configuration to use for populating this form
+ *
+ * @var IcingaConfig
+ */
+ private $config = null;
+
+ /**
+ * The base directory of the icingaweb configuration
+ *
+ * @var string
+ */
+ private $configDir = null;
+
+
+ /**
+ * The resources to use instead of the factory provided ones (use for testing)
+ *
+ * @var null
+ */
+ private $resources = null;
+
+ /**
+ * Set the configuration to be used for this form
+ *
+ * @param IcingaConfig $cfg
+ */
+ public function setConfiguration($cfg)
+ {
+ $this->config = $cfg;
+ }
+
+ /**
+ * Set a specific configuration directory to use for configuration specific default paths
+ *
+ * @param string $dir
+ */
+ public function setConfigDir($dir)
+ {
+ $this->configDir = $dir;
+ }
+
+ /**
+ * Return the config path set for this form or the application wide config path if none is set
+ *
+ * @return string
+ *
+ * @see IcingaConfig::configDir
+ */
+ public function getConfigDir()
+ {
+ return $this->configDir === null ? IcingaConfig::$configDir : $this->configDir;
+ }
+
+ /**
+ * Set an alternative array of resources that should be used instead of the DBFactory resource set
+ * (used for testing)
+ *
+ * @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 for displaying in the database selection field
+ *
+ * @return array
+ */
+ public function getResources()
+ {
+ if ($this->resources === null) {
+ return DbAdapterFactory::getResources();
+ } else {
+ return $this->resources;
+ }
+ }
+
+ /**
+ * Add the checkbox for using the development environment to this form
+ *
+ * @param Zend_Config $cfg The "global" section of the config.ini
+ */
+ private function addDevelopmentCheckbox(Zend_Config $cfg)
+ {
+ $env = $cfg->get('environment', 'development');
+ $this->addElement(
+ 'checkbox',
+ 'environment',
+ array(
+ 'label' => 'Development Mode',
+ 'required' => true,
+ 'helptext' => 'Set true to show more detailed errors and disable certain optimizations in order to '
+ . 'make debugging easier.',
+ 'tooltip' => 'More verbose output',
+ 'value' => $env === 'development'
+ )
+ );
+
+ }
+
+ /**
+ * Add a select field for setting the default timezone.
+ *
+ * Possible values are determined by DateTimeZone::listIdentifiers
+ *
+ * @param Zend_Config $cfg The "global" section of the config.ini
+ */
+ private function addTimezoneSelection(Zend_Config $cfg)
+ {
+ $tzList = array();
+ foreach (DateTimeZone::listIdentifiers() as $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(
+ 'select',
+ 'timezone',
+ array(
+ 'label' => 'Default Application Timezone',
+ 'required' => true,
+ 'multiOptions' => $tzList,
+ 'helptext' => $helptext,
+ 'value' => $cfg->get('timezone', date_default_timezone_get())
+ )
+ );
+ }
+
+ /**
+ * Add configuration settings for module paths
+ *
+ * @param Zend_Config $cfg The "global" section of the config.ini
+ */
+ private function addModuleSettings(Zend_Config $cfg)
+ {
+ $this->addElement(
+ 'text',
+ 'module_folder',
+ array(
+ 'label' => 'Module Folder',
+ 'required' => true,
+ 'helptext' => 'The moduleFolder directive is currently not used anywhere but '
+ . 'configureable via the frontend and ini. With feature #4607 moduleFolder '
+ . 'will be replaced with a configuration directive for locations of '
+ . 'installed modules',
+ 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
+ )
+ );
+ }
+
+ /**
+ * Add text fields for the date and time format used in the application
+ *
+ * @param Zend_Config $cfg The "global" section of the config.ini
+ */
+ private function addDateFormatSettings(Zend_Config $cfg)
+ {
+ $phpUrl = ''
+ . 'the official PHP documentation ';
+
+ $txtDefaultDateFormat = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'date_format',
+ 'label' => 'Date Format',
+ 'helptext' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values',
+ 'required' => true,
+ 'value' => $cfg->get('dateFormat', 'd/m/Y')
+ )
+ );
+ $this->addElement($txtDefaultDateFormat);
+ $txtDefaultDateFormat->addValidator(new DateFormatValidator());
+
+ $txtDefaultTimeFormat = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'time_format',
+ 'label' => 'Time Format',
+ 'required' => true,
+ 'helptext' => 'Display times according to this format. See ' . $phpUrl . ' for possible values',
+ 'value' => $cfg->get('timeFormat', 'g:i A')
+ )
+ );
+ $txtDefaultTimeFormat->addValidator(new TimeFormatValidator());
+ $this->addElement($txtDefaultTimeFormat);
+ }
+
+ /**
+ * Add form elements for setting the user preference storage backend
+ *
+ * @param Zend_Config $cfg The Zend_config object of preference section
+ */
+ public function addUserPreferencesDialog(Zend_Config $cfg)
+ {
+ $backend = $cfg->get('type', 'ini');
+ if ($this->getRequest()->get('preferences_type', null) !== null) {
+ $backend = $this->getRequest()->get('preferences_type');
+ }
+ $this->addElement(
+ 'select',
+ 'preferences_type',
+ array(
+ 'label' => 'User Preference Storage Type',
+ 'required' => true,
+ 'value' => $backend,
+ 'multiOptions' => array(
+ 'ini' => 'File System (ini files)',
+ 'db' => 'Database'
+ )
+ )
+ );
+
+ $txtPreferencesIniPath = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'preferences_ini_path',
+ 'label' => 'User Preference Filepath',
+ 'required' => $backend === 'ini',
+ 'condition' => $backend === 'ini',
+ 'value' => $cfg->get('configPath')
+ )
+ );
+
+ $backends = array();
+ foreach ($this->getResources() as $name => $resource) {
+ if ($resource['type'] !== 'db') {
+ continue;
+ }
+ $backends[$name] = $name;
+ }
+
+ $txtPreferencesDbResource = new Zend_Form_Element_Select(
+ array(
+ 'name' => 'preferences_db_resource',
+ 'label' => 'Database Connection',
+ 'required' => $backend === 'db',
+ 'condition' => $backend === 'db',
+ 'value' => $cfg->get('resource'),
+ 'multiOptions' => $backends
+ )
+ );
+ $validator = new WritablePathValidator();
+ $validator->setRequireExistence();
+ $txtPreferencesIniPath->addValidator($validator);
+ $this->addElement($txtPreferencesIniPath);
+ $this->addElement($txtPreferencesDbResource);
+
+ $txtPreferencesIniPath->addDecorator(new ConditionalHidden());
+ $txtPreferencesDbResource->addDecorator(new ConditionalHidden());
+ $this->enableAutoSubmit(
+ array(
+ 'preferences_type'
+ )
+ );
+ }
+
+ /**
+ * Create the general form, using the provided configuration
+ *
+ * @see Form::create()
+ */
+ public function create()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+ $global = $this->config->global;
+ if ($global === null) {
+ $global = new Zend_Config(array());
+ }
+ $preferences = $this->config->preferences;
+
+ if ($preferences === null) {
+ $preferences = new Zend_Config(array());
+ }
+
+ $this->addDevelopmentCheckbox($global);
+ $this->addTimezoneSelection($global);
+ $this->addModuleSettings($global);
+ $this->addDateFormatSettings($global);
+ $this->addUserPreferencesDialog($preferences);
+
+ $this->setSubmitLabel('Save Changes');
+ }
+
+ /**
+ * Return an Zend_Config object containing the configuration set in this form
+ *
+ * @return Zend_Config
+ */
+ public function getConfig()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+ if ($this->config->global === null) {
+ $this->config->global = new Zend_Config(array());
+ }
+ if ($this->config->preferences === null) {
+ $this->config->preferences = new Zend_Config(array());
+ }
+
+ $values = $this->getValues();
+ $cfg = clone $this->config;
+ $cfg->global->environment = ($values['environment'] == 1) ? 'development' : 'production';
+ $cfg->global->timezone = $values['timezone'];
+ $cfg->global->moduleFolder = $values['module_folder'];
+ $cfg->global->dateFormat = $values['date_format'];
+ $cfg->global->timeFormat = $values['time_format'];
+
+ $cfg->preferences->type = $values['preferences_type'];
+ if ($cfg->preferences->type === 'ini') {
+ $cfg->preferences->configPath = $values['preferences_ini_path'];
+ } elseif ($cfg->preferences->type === 'db') {
+ $cfg->preferences->resource = $values['preferences_db_resource'];
+ }
+
+ return $cfg;
+ }
+}
diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php
new file mode 100644
index 000000000..bf426f342
--- /dev/null
+++ b/application/forms/Config/LoggingForm.php
@@ -0,0 +1,227 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Config;
+
+use \Zend_Config;
+use \Zend_Form_Element_Text;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Validator\WritablePathValidator;
+use \Icinga\Web\Form\Decorator\ConditionalHidden;
+
+/**
+ * Form class for setting the application wide logging configuration
+ */
+class LoggingForm extends Form
+{
+ /**
+ * The configuration to use for this form
+ *
+ * @var Zend_Config
+ */
+ 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
+ *
+ * If not called, default values are used instead
+ *
+ * @param Zend_Config $cfg The config.ini to set with this form
+ */
+ public function setConfiguration(Zend_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
+ *
+ * This is the case if the "logging_use_debug" field is autosubmitted
+ * and true or if it is not submitted, but the configuration for debug
+ * logging is set to true
+ *
+ * @param Zend_Config $config The debug section of the config.ini
+ *
+ * @return bool Whether to display the debug path field or not
+ */
+ private function shouldDisplayDebugLog(Zend_Config $config)
+ {
+ $debugParam = $this->getRequest()->getParam('logging_debug_enable', null);
+ if ($debugParam !== null) {
+ return intval($debugParam) === 1;
+ } else {
+ return intval($config->get('enable', 0)) === 1;
+ }
+
+ }
+
+ /**
+ * Create this logging configuration form
+ *
+ * @see Form::create()
+ */
+ public function create()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+
+ $logging = $this->config->logging;
+ if ($logging === null) {
+ $logging = new IcingaConfig(array());
+ }
+
+ $debug = $logging->debug;
+ if ($debug === null) {
+ $debug = new IcingaConfig(array());
+ }
+
+ $txtLogPath = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'logging_app_target',
+ '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,
+ 'value' => $logging->get('target', '/var/log/icingaweb.log')
+ )
+ );
+ $txtLogPath->addValidator(new WritablePathValidator());
+ $this->addElement($txtLogPath);
+
+ $this->addElement(
+ 'checkbox',
+ 'logging_app_verbose',
+ array(
+ 'label' => 'Verbose Logging',
+ 'required' => true,
+ 'helptext' => 'Check to write more verbose output to the icinga log file',
+ 'value' => intval($logging->get('verbose', 0)) === 1
+ )
+ );
+
+ $this->addElement(
+ 'checkbox',
+ 'logging_debug_enable',
+ array(
+ 'label' => 'Use Debug Log',
+ 'required' => true,
+ 'helptext' => 'Check to write a seperate debug log (Warning: This file can grow very big)',
+ 'value' => $this->shouldDisplayDebugLog($debug)
+ )
+ );
+
+ $textLoggingDebugPath = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'logging_debug_target',
+ 'label' => 'Debug Log Path',
+ 'required' => $this->shouldDisplayDebugLog($debug),
+ 'condition' => $this->shouldDisplayDebugLog($debug),
+ 'value' => $debug->get('target', $this->getBaseDir() . '/var/log/icinga2.debug.log'),
+ 'helptext' => 'Set the path to the debug log'
+ )
+ );
+ $textLoggingDebugPath->addValidator(new WritablePathValidator());
+
+ $decorator = new ConditionalHidden();
+ $this->addElement($textLoggingDebugPath);
+ $textLoggingDebugPath->addDecorator($decorator);
+
+
+ $this->enableAutoSubmit(array('logging_debug_enable'));
+
+ $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'] = 1;
+ $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);
+ }
+}
diff --git a/application/forms/Preference/GeneralForm.php b/application/forms/Preference/GeneralForm.php
new file mode 100644
index 000000000..306439a17
--- /dev/null
+++ b/application/forms/Preference/GeneralForm.php
@@ -0,0 +1,243 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Preference;
+
+use \DateTimeZone;
+use \Zend_Config;
+use \Zend_Form_Element_Text;
+use \Zend_Form_Element_Select;
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\User\Preferences;
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Validator\TimeFormatValidator;
+use \Icinga\Web\Form\Validator\DateFormatValidator;
+
+/**
+ * General user preferences
+ */
+class GeneralForm extends Form
+{
+ /**
+ * The configuration to use for populating this form
+ *
+ * @var IcingaConfig
+ */
+ private $config;
+
+ /**
+ * The preference object to use instead of the one from the user (used for testing)
+ *
+ * @var Zend_Config
+ */
+ private $preferences;
+
+ /**
+ * Set the configuration to be used for this form when no preferences are set yet
+ *
+ * @param IcingaConfig $cfg
+ */
+ public function setConfiguration($cfg)
+ {
+ $this->config = $cfg;
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Add a select field for setting the user's timezone.
+ *
+ * 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
+ *
+ * @param Zend_Config $cfg The "global" section of the config.ini to be used as default valuse
+ */
+ private function addTimezoneSelection(Zend_Config $cfg)
+ {
+ $tzList = array();
+ foreach (DateTimeZone::listIdentifiers() as $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(
+ array(
+ 'name' => 'timezone',
+ 'label' => 'Your Current Timezone',
+ 'required' => !$useGlobalTimezone,
+ 'multiOptions' => $tzList,
+ 'helptext' => $helptext,
+ 'value' => $prefs->get('app.timezone', $cfg->get('timezone', date_default_timezone_get()))
+ )
+ );
+ $this->addElement(
+ 'checkbox',
+ 'default_timezone',
+ array(
+ 'label' => 'Use Default Timezone',
+ 'value' => !$prefs->has('app.timezone'),
+ 'required' => true
+ )
+ );
+ if ($useGlobalTimezone) {
+ $selectTimezone->setAttrib('disabled', 1);
+ }
+ $this->addElement($selectTimezone);
+ $this->enableAutoSubmit(array('default_timezone'));
+ }
+
+ /**
+ * Add text fields for the date and time format used for this user
+ *
+ * Also, a 'use default format' 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 values
+ */
+ private function addDateFormatSettings(Zend_Config $cfg)
+ {
+ $prefs = $this->getUserPreferences();
+ $useGlobalDateFormat = $this->getRequest()->getParam('default_date_format', !$prefs->has('app.dateFormat'));
+ $useGlobalTimeFormat = $this->getRequest()->getParam('default_time_format', !$prefs->has('app.timeFormat'));
+
+ $phpUrl = ''
+ . 'the official PHP documentation ';
+
+
+ $this->addElement(
+ 'checkbox',
+ 'default_date_format',
+ array(
+ 'label' => 'Use Default Date Format',
+ 'value' => !$prefs->has('app.dateFormat'),
+ 'required' => true
+ )
+ );
+ $txtDefaultDateFormat = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'date_format',
+ 'label' => 'Preferred Date Format',
+ 'helptext' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values',
+ 'required' => !$useGlobalDateFormat,
+ 'value' => $prefs->get('app.dateFormat', $cfg->get('dateFormat', 'd/m/Y'))
+ )
+ );
+
+ $this->addElement($txtDefaultDateFormat);
+ $txtDefaultDateFormat->addValidator(new DateFormatValidator());
+ if ($useGlobalDateFormat) {
+ $txtDefaultDateFormat->setAttrib('disabled', '1');
+ }
+
+ $this->addElement(
+ 'checkbox',
+ 'default_time_format',
+ array(
+ 'label' => 'Use Default Time Format',
+ 'value' => !$prefs->has('app.timeFormat'),
+ 'required' => !$useGlobalTimeFormat
+ )
+ );
+ $txtDefaultTimeFormat = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'time_format',
+ 'label' => 'Preferred Time Format',
+ 'required' => !$useGlobalTimeFormat,
+ 'helptext' => 'Display times according to this format. See ' . $phpUrl . ' for possible values',
+ 'value' => $prefs->get('app.timeFormat', $cfg->get('timeFormat', 'g:i A'))
+ )
+ );
+ $txtDefaultTimeFormat->addValidator(new TimeFormatValidator());
+ $this->addElement($txtDefaultTimeFormat);
+ if ($useGlobalTimeFormat) {
+ $txtDefaultTimeFormat->setAttrib('disabled', '1');
+ }
+
+ $this->enableAutoSubmit(array('default_time_format', 'default_date_format'));
+ }
+
+ /**
+ * Create the general form, using the global configuration as fallback values for preferences
+ *
+ * @see Form::create()
+ */
+ public function create()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+ $global = $this->config->global;
+ if ($global === null) {
+ $global = new Zend_Config(array());
+ }
+
+ $this->addTimezoneSelection($global);
+ $this->addDateFormatSettings($global);
+
+ $this->setSubmitLabel('Save Changes');
+ }
+
+ /**
+ * Return an array containing the preferences set in this form
+ *
+ * @return array
+ */
+ public function getPreferences()
+ {
+ $values = $this->getValues();
+ return array(
+ 'app.timezone' => $values['timezone'],
+ 'app.dateFormat' => $values['date_format'],
+ 'app.timeFormat' => $values['time_format']
+ );
+ }
+}
diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml
new file mode 100644
index 000000000..8e4f8e864
--- /dev/null
+++ b/application/views/scripts/config/authentication.phtml
@@ -0,0 +1,35 @@
+ 'ldap')
+)->getAbsoluteUrl();
+
+$createDbBackend = Url::fromPath(
+ '/config/createAuthenticationBackend',
+ array('type' => 'db')
+)->getAbsoluteUrl();
+
+?>
+= $this->tabs->render($this); ?>
+
+form->getErrorMessages();
+ if (!empty($errors)):
+?>
+
+
There are errors in your configuration
+
+
+
+
+
+
+= $this->form ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/authentication/modify.phtml b/application/views/scripts/config/authentication/modify.phtml
new file mode 100644
index 000000000..23d46b9c5
--- /dev/null
+++ b/application/views/scripts/config/authentication/modify.phtml
@@ -0,0 +1,4 @@
+= $this->tabs->render($this); ?>
+
+Create new backend
+= $this->form ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml
index ef3c458db..f0b046499 100644
--- a/application/views/scripts/config/index.phtml
+++ b/application/views/scripts/config/index.phtml
@@ -1,12 +1,2 @@
= $this->tabs->render($this); ?>
-
-Configuration
-
-
-
Dear developer
-
-
- Add shortcuts for often used configuration options so users can quickly change settings without having to
- search in the tab overview
-
-
\ No newline at end of file
+= $this->form ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/logging.phtml b/application/views/scripts/config/logging.phtml
new file mode 100644
index 000000000..f1b7ef3d1
--- /dev/null
+++ b/application/views/scripts/config/logging.phtml
@@ -0,0 +1,19 @@
+= $this->tabs->render($this); ?>
+
+form->getErrorMessages(); ?>
+
+
+
+
Errors occured when trying to save the project
+
+ The following errors occured when trying to save the configuration:
+
+
+
+ = $this->escape($error) ?>
+
+
+
+
+
+= $this->form ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/show-configuration.phtml b/application/views/scripts/config/show-configuration.phtml
new file mode 100644
index 000000000..87a86b51f
--- /dev/null
+++ b/application/views/scripts/config/show-configuration.phtml
@@ -0,0 +1,30 @@
+= $this->tabs->render($this); ?>
+
+
+
Saving = $this->escape($this->file); ?>.ini failed
+
+
+ Your = $this->escape($this->file); ?> configuration couldn't be stored (error: "= $this->exceptionMessage; ?>").
+ This could have one or more of the following reasons:
+
+
+ You don't have file-system permissions to write to the = $this->escape($this->file); ?>.ini file
+ Something went wrong while writing the file
+ There's an application error preventing you from persisting the configuration
+
+
+
+
+ Details can be seen in your application log (if you don't have access to this file, call your administrator in this case).
+
+ 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:
+
+
+
+
+
+= $this->escape($this->iniConfigurationString); ?>
+
+
+
\ No newline at end of file
diff --git a/application/views/scripts/preference/index.phtml b/application/views/scripts/preference/index.phtml
index 81dc0fb8c..a718a201c 100644
--- a/application/views/scripts/preference/index.phtml
+++ b/application/views/scripts/preference/index.phtml
@@ -1,3 +1,15 @@
= $this->tabs->render($this); ?>
-Preferences
\ No newline at end of file
+success)) : ?>
+
+
Preferences updated sucessfully
+
+
+
+exceptionMessage)): ?>
+
+
Could not update preferences due to an internal exception (= $this->exceptionMessage ?>)
+
+
+
+= $this->form ?>
\ No newline at end of file
diff --git a/config/config.ini b/config/config.ini
index 1f57302d0..e10e68a6f 100755
--- a/config/config.ini
+++ b/config/config.ini
@@ -1,30 +1,36 @@
[global]
-environment = development
-timezone = "Europe/Berlin"
-indexModule = monitoring
-indexController = dashboard
-moduleFolder = "/etc/icinga2-web/enabledModules"
-dateFormat = "d/m/Y"
-timeFormat = "g:i A"
+environment = "development"
+timezone = "Europe/Berlin"
+indexModule = "monitoring"
+indexController = "dashboard"
+; The moduleFolder directive is currently not used anywhere but configureable
+; via the frontend and this file. With feature #4607 moduleFolder will
+; be replaced with a configuration directive for locations of
+; installed modules
+moduleFolder = "/etc/icinga2-web/enabledModules"
+dateFormat = "d/m/Y"
+timeFormat = "g:i A"
[logging]
; General log
-enable = 1
-type = stream
-verbose = 1
-target = /tmp/icinga2.log
+enable = "1"
+type = "stream"
+verbose = "1"
+target = "/tmp/icinga2.log"
; For development and debug purposes: Logs additional (non critical) events to a
; seperate log
-debug.enable = 1
-debug.type = stream
-debug.target = /tmp/icinga2.debug.log
+debug.enable = "1"
+debug.type = "stream"
+debug.target = "/tmp/icinga2.debug.log"
; Use ini store to store preferences on local disk
[preferences]
-type=ini
+type = "ini"
; Use database to store preference into mysql or postgres
;[preferences]
;type=db
;resource=icingaweb-mysql
+
+configPath = "/vagrant/config/preferences"
diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php
index 4bba5fb6b..4ff92ede9 100644
--- a/library/Icinga/Application/Web.php
+++ b/library/Icinga/Application/Web.php
@@ -35,6 +35,7 @@ use Icinga\User;
use Icinga\Web\Request;
use Zend_Controller_Front;
use Zend_Layout;
+use Zend_Config;
use Zend_Paginator;
use Zend_View_Helper_PaginationControl;
use Zend_Controller_Action_HelperBroker;
@@ -206,8 +207,9 @@ class Web extends ApplicationBootstrap
/**
* Create user object and inject preference interface
*
- * @throws ConfigurationError
* @return User
+ *
+ * @throws ConfigurationError
*/
private function setupUser()
{
@@ -225,7 +227,9 @@ class Web extends ApplicationBootstrap
$user = $authenticationManager->getUser();
- $this->getConfig()->preferences->configPath = $this->getConfigDir('preferences');
+ $this->getConfig()->preferences->configPath = Config::app()
+ ->get('preferences', new Zend_Config(array()))
+ ->get('configPath', $this->getConfigDir('preferences'));
$preferenceStore = StoreFactory::create(
$this->getConfig()->preferences,
@@ -325,7 +329,7 @@ class Web extends ApplicationBootstrap
/**
* Configure pagination settings
-
+ *
* @return self
*/
private function setupPagination()
diff --git a/library/Icinga/Config/IniEditor.php b/library/Icinga/Config/IniEditor.php
index afb89d44a..c24186ca0 100644
--- a/library/Icinga/Config/IniEditor.php
+++ b/library/Icinga/Config/IniEditor.php
@@ -28,8 +28,6 @@
namespace Icinga\Config;
-use \Zend_Config_Exception;
-
/**
* Edit the sections and keys of an ini in-place
*/
@@ -52,7 +50,7 @@ class IniEditor
/**
* Create a new IniEditor
*
- * @param string $content The content of the ini as string
+ * @param string $content The content of the ini as string
*/
public function __construct($content)
{
@@ -62,9 +60,9 @@ class IniEditor
/**
* Set the value of the given key.
*
- * @param array $key The key to set
- * @param mixed $value The value to set
- * @param string $section The section to insert to.
+ * @param array $key The key to set
+ * @param string $value The value to set
+ * @param array $section The section to insert to.
*/
public function set(array $key, $value, $section = null)
{
@@ -80,8 +78,8 @@ class IniEditor
/**
* Reset the value of the given array element
*
- * @param array $key The key of the array value
- * @param string $section The section of the array.
+ * @param array $key The key of the array value
+ * @param array $section The section of the array.
*/
public function resetArrayElement(array $key, $section = null)
{
@@ -94,9 +92,9 @@ class IniEditor
/**
* Set the value for an array element
*
- * @param array $key The key of the property
- * @param mixed $value The value of the property
- * @param string $section The section to use
+ * @param array $key The key of the property
+ * @param string $value The value of the property
+ * @param array $section The section to use
*/
public function setArrayElement(array $key, $value, $section = null)
{
@@ -119,14 +117,14 @@ class IniEditor
/**
* Get the line of an array element
*
- * @param array $key The key of the property.
- * @param string $section The section to use
+ * @param array $key The key of the property.
+ * @param mixed $section The section to use
*
- * @return int The line of the array element.
+ * @return int The line of the array element.
*/
private function getArrayElement(array $key, $section = null)
{
- $line = isset($section) ? $this->getSectionLine($section) +1 : 0;
+ $line = isset($section) ? $this->getSectionLine($section) + 1 : 0;
$index = array_pop($key);
$formatted = $this->formatKey($key);
for (; $line < count($this->text); $line++) {
@@ -134,7 +132,7 @@ class IniEditor
if ($this->isSectionDeclaration($l)) {
return -1;
}
- if (preg_match('/^\s*' . $formatted.'\[\]\s*=/', $l) === 1) {
+ if (preg_match('/^\s*' . $formatted . '\[\]\s*=/', $l) === 1) {
return $line;
}
if ($this->isPropertyDeclaration($l, array_merge($key, array($index)))) {
@@ -147,8 +145,8 @@ class IniEditor
/**
* When it exists, set the key back to null
*
- * @param array $key The key to reset
- * @param string $section The section of the key
+ * @param array $key The key to reset
+ * @param array $section The section of the key
*/
public function reset(array $key, $section = null)
{
@@ -162,15 +160,15 @@ class IniEditor
/**
* Create the section if it does not exist and set the properties
*
- * @param string $section The section name
- * @param string $extend The section that should be extended by this section
+ * @param string $section The section name
+ * @param array $extend The section that should be extended by this section
*/
public function setSection($section, $extend = null)
{
if (isset($extend)) {
$decl = '[' . $section . ' : ' . $extend.']';
} else {
- $decl = '[' . $section.']';
+ $decl = '[' . $section . ']';
}
$line = $this->getSectionLine($section);
if ($line !== -1) {
@@ -185,7 +183,7 @@ class IniEditor
/**
* Remove a section declaration
*
- * @param string $section The section name
+ * @param string $section The section name
*/
public function removeSection($section)
{
@@ -198,9 +196,9 @@ class IniEditor
/**
* Insert the key at the end of the corresponding section
*
- * @param array $key The key to insert
- * @param mixed $value The value to insert
- * @param string $section
+ * @param array $key The key to insert
+ * @param mixed $value The value to insert
+ * @param array $key The key to insert
*/
private function insert(array $key, $value, $section = null)
{
@@ -225,10 +223,11 @@ class IniEditor
*/
private function cleanUpWhitespaces()
{
+
$i = count($this->text) - 1;
for (; $i > 0; $i--) {
$line = $this->text[$i];
- if ($this->isSectionDeclaration($line)) {
+ if ($this->isSectionDeclaration($line) && $i > 0) {
$i--;
$line = $this->text[$i];
/*
@@ -259,8 +258,8 @@ class IniEditor
/**
* Insert the text at line $lineNr
*
- * @param int $lineNr The line nr the inserted line should have
- * @param string $toInsert The text that will be inserted
+ * @param $lineNr The line nr the inserted line should have
+ * @param $toInsert The text that will be inserted
*/
private function insertAtLine($lineNr, $toInsert)
{
@@ -270,8 +269,8 @@ class IniEditor
/**
* Update the line $lineNr
*
- * @param int $lineNr The line number of the target line
- * @param string $content The content to replace
+ * @param int $lineNr The line number of the target line
+ * @param string $toInsert The new line content
*/
private function updateLine($lineNr, $content)
{
@@ -285,9 +284,9 @@ class IniEditor
/**
* Get the comment from the given line
*
- * @param string $lineContent The content of the line
+ * @param $lineContent The content of the line
*
- * @return string The extracted comment
+ * @return string The extracted comment
*/
private function getComment($lineContent)
{
@@ -297,14 +296,14 @@ class IniEditor
*/
$cleaned = preg_replace('/^[^;"]*"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"/s', '', $lineContent);
- $matches = mb_split(';', $cleaned, 2);
+ $matches = explode(';', $cleaned, 2);
return array_key_exists(1, $matches) ? $matches[1] : '';
}
/**
* Delete the line $lineNr
*
- * @param int $lineNr The lineNr starting at 0
+ * @param $lineNr The lineNr starting at 0
*/
private function deleteLine($lineNr)
{
@@ -314,10 +313,10 @@ class IniEditor
/**
* Format a key-value pair to an INI file-entry
*
- * @param array $key The key
- * @param mixed $value The value
+ * @param array $key The key to format
+ * @param string $value The value to format
*
- * @return string The formatted key-value pair
+ * @return string The formatted key-value pair
*/
private function formatKeyValuePair(array $key, $value)
{
@@ -327,8 +326,9 @@ class IniEditor
/**
* Format a key to an INI key
*
- * @param array $key
- * @return string
+ * @param array $key the key array to format
+ *
+ * @return string
*/
private function formatKey(array $key)
{
@@ -338,14 +338,14 @@ class IniEditor
/**
* Get the first line after the given $section
*
- * @param string $section The name of the section
+ * @param $section The name of the section
*
- * @return int The line number of the section
+ * @return int The line number of the section
*/
private function getSectionEnd($section = null)
{
$i = 0;
- $started = isset($section) ? false: true;
+ $started = isset($section) ? false : true;
foreach ($this->text as $line) {
if ($started && $this->isSectionDeclaration($line)) {
if ($i === 0) {
@@ -373,15 +373,15 @@ class IniEditor
/**
* Check if the line contains the property declaration for a key
*
- * @param string $lineContent The content of the line
- * @param array $key The key this declaration is supposed to have
+ * @param string $lineContent The content of the line
+ * @param array $key The key this declaration is supposed to have
*
- * @return bool True, when the lineContent is a property declaration
+ * @return boolean True, when the lineContent is a property declaration
*/
private function isPropertyDeclaration($lineContent, array $key)
{
return preg_match(
- '/^\s*' . $this->formatKey($key) .'\s*=\s*/',
+ '/^\s*' . $this->formatKey($key) . '\s*=\s*/',
$lineContent
) === 1;
}
@@ -389,15 +389,15 @@ class IniEditor
/**
* Check if the given line contains a section declaration
*
- * @param string $lineContent The content of the line
- * @param string $section The optional section name that will be assumed
+ * @param $lineContent The content of the line
+ * @param string $section The optional section name that will be assumed
*
- * @return bool True, when the lineContent is a section declaration
+ * @return bool True, when the lineContent is a section declaration
*/
private function isSectionDeclaration($lineContent, $section = null)
{
if (isset($section)) {
- return preg_match('/^\s*\[\s*'.$section.'\s*[\]:]/', $lineContent) === 1;
+ return preg_match('/^\s*\[\s*' . $section . '\s*[\]:]/', $lineContent) === 1;
} else {
return preg_match('/^\s*\[/', $lineContent) === 1;
}
@@ -406,9 +406,9 @@ class IniEditor
/**
* Get the line where the section begins
*
- * @param string $section The section
+ * @param $section The section
*
- * @return int The line number
+ * @return int The line number
*/
private function getSectionLine($section)
{
@@ -425,13 +425,14 @@ class IniEditor
/**
* Get the line number where the given key occurs
*
- * @param array $keys The key and its parents
- * @param string $section The section of the key
+ * @param array $keys The key and its parents
+ * @param $section The section of the key
*
* @return int The line number
*/
private function getKeyLine(array $keys, $section = null)
{
+ $key = implode($this->nestSeparator, $keys);
$inSection = isset($section) ? false : true;
$i = 0;
foreach ($this->text as $line) {
@@ -452,7 +453,7 @@ class IniEditor
/**
* Get the last line number occurring in the text
*
- * @return int The line number of the last line
+ * @return The line number of the last line
*/
private function getLastLine()
{
@@ -462,9 +463,9 @@ class IniEditor
/**
* Insert a new element into a specific position of an array
*
- * @param array $array The array to use
- * @param int $pos The target position
- * @param mixed $element The element to insert
+ * @param $array The array to use
+ * @param $pos The target position
+ * @param $element The element to insert
*
* @return array The changed array
*/
@@ -477,12 +478,10 @@ class IniEditor
/**
* Remove an element from an array
*
- * @param array $array The array to use
- * @param mixed $pos The position to remove
- *
- * @return array
+ * @param $array The array to use
+ * @param $pos The position to remove
*/
- private function removeFromArray(array $array, $pos)
+ private function removeFromArray($array, $pos)
{
unset($array[$pos]);
return array_values($array);
@@ -491,9 +490,10 @@ class IniEditor
/**
* Prepare a value for INe
*
- * @param mixed $value The value of the string
+ * @param $value The value of the string
+ *
+ * @return string The formatted value
*
- * @return string The formatted value
* @throws Zend_Config_Exception
*/
private function formatValue($value)
diff --git a/library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php b/library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php
index 272b4b34d..e90c89000 100644
--- a/library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php
+++ b/library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php
@@ -28,12 +28,14 @@
namespace Icinga\Protocol\Commandpipe\Transport;
-use Icinga\Application\Logger;
+use \RuntimeException;
+use \Zend_Config;
+use \Icinga\Application\Logger;
/**
- * Command pipe transport class that uses ssh for connecting to a remote filesystem with the icinga.cmd pipe
- * The remote host must have KeyAuth enabled for this user
+ * Command pipe transport class that uses ssh for connecting to a remote filesystem with the icinga.cmd pipe
*
+ * The remote host must have KeyAuth enabled for this user
*/
class SecureShell implements Transport
{
@@ -66,21 +68,27 @@ class SecureShell implements Transport
private $user = null;
/**
- * @see Transport::setEndpoint()
+ * Overwrite the target file of this Transport class using the given config from instances.ini
*
+ * @param Zend_Config $config
+ *
+ * @see Transport::setEndpoint()
*/
- public function setEndpoint(\Zend_Config $config)
+ public function setEndpoint(Zend_Config $config)
{
- $this->host = isset($config->host) ? $config->host : "localhost";
+ $this->host = isset($config->host) ? $config->host : 'localhost';
$this->port = isset($config->port) ? $config->port : 22;
$this->user = isset($config->user) ? $config->user : null;
- $this->password = isset($config->password) ? $config->password : null;
- $this->path = isset($config->path) ? $config->path : "/usr/local/icinga/var/rw/icinga.cmd";
+ $this->path = isset($config->path) ? $config->path : '/usr/local/icinga/var/rw/icinga.cmd';
}
/**
- * @see Transport::send()
+ * Write the given external command to the command pipe
*
+ * @param string $command
+ *
+ * @throws RuntimeException When the command could not be sent to the remote Icinga host
+ * @see Transport::send()
*/
public function send($command)
{
@@ -114,11 +122,11 @@ class SecureShell implements Transport
Logger::debug("Return code %s: %s ", $retCode, $output);
if ($retCode != 0) {
- $msg = 'Could not send command to remote icinga host: '
+ $msg = 'Could not send command to remote Icinga host: '
. implode(PHP_EOL, $output)
. " (returncode $retCode)";
Logger::error($msg);
- throw new \RuntimeException($msg);
+ throw new RuntimeException($msg);
}
}
}
diff --git a/library/Icinga/Protocol/Commandpipe/Transport/Transport.php b/library/Icinga/Protocol/Commandpipe/Transport/Transport.php
index d249c86e0..c33190092 100644
--- a/library/Icinga/Protocol/Commandpipe/Transport/Transport.php
+++ b/library/Icinga/Protocol/Commandpipe/Transport/Transport.php
@@ -28,23 +28,24 @@
namespace Icinga\Protocol\Commandpipe\Transport;
+use \Zend_Config;
+
/**
* Interface for Transport classes handling the concrete access to the command pipe
- *
*/
interface Transport
{
/**
* Overwrite the target file of this Transport class using the given config from instances.ini
*
- * @param \Zend_Config $config A configuration file containing a 'path' setting
+ * @param Zend_Config $config A configuration file containing a 'path' setting
*/
- public function setEndpoint(\Zend_Config $config);
+ public function setEndpoint(Zend_Config $config);
/**
* Write the given external command to the command pipe
*
- * @param string $message The command to send, without the timestamp (this will be added here)
+ * @param string $message The command to send, without the timestamp (this will be added here)
*/
public function send($message);
}
diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php
index 5698de2d0..d5b06b61d 100755
--- a/library/Icinga/Web/Controller/ActionController.php
+++ b/library/Icinga/Web/Controller/ActionController.php
@@ -28,26 +28,23 @@
namespace Icinga\Web\Controller;
+use \Zend_Controller_Action as ZfController;
+use \Zend_Controller_Request_Abstract as ZfRequest;
+use \Zend_Controller_Response_Abstract as ZfResponse;
+use \Zend_Controller_Action_HelperBroker as ZfActionHelper;
+use \Zend_Layout as ZfLayout;
use \Icinga\Authentication\Manager as AuthManager;
use \Icinga\Application\Benchmark;
use \Icinga\Exception;
use \Icinga\Application\Config;
use \Icinga\Web\Notification;
use \Icinga\Web\Widget\Tabs;
-use \Zend_Layout as ZfLayout;
-use \Zend_Controller_Action as ZfController;
-use \Zend_Controller_Request_Abstract as ZfRequest;
-use \Zend_Controller_Response_Abstract as ZfResponse;
-use \Zend_Controller_Action_HelperBroker as ZfActionHelper;
+use \Icinga\Web\Url;
/**
* Base class for all core action controllers
*
* All Icinga Web core controllers should extend this class
- *
- * @copyright Copyright (c) 2013 Icinga-Web Team
- * @author Icinga-Web Team
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class ActionController extends ZfController
{
@@ -78,7 +75,7 @@ class ActionController extends ZfController
protected $modifiesSession = false;
/**
- * True if authentication suceeded, otherwise false
+ * True if authentication succeeded, otherwise false
*
* @var bool
*/
@@ -148,7 +145,7 @@ class ActionController extends ZfController
/**
* Return the tabs
*
- * @return \Icinga\Widget\Web\Tabs
+ * @return Tabs
*/
public function getTabs()
{
@@ -159,39 +156,15 @@ class ActionController extends ZfController
/**
* Translate the given string with the global translation catalog
*
- * @param string $string The string that should be translated
+ * @param string $string The string that should be translated
*
- * @return string
+ * @return string
*/
public function translate($string)
{
return t($string);
}
- /**
- * Whether the current user has the given permission
- *
- * TODO: This has not been implemented yet (Feature #4111)
- *
- * @return bool
- */
- final protected function hasPermission($uri)
- {
- return true;
- }
-
- /**
- * Assert the current user has the given permission
- *
- * TODO: This has not been implemented yet (Feature #4111)
- *
- * @return self
- */
- final protected function assertPermission()
- {
- return $this;
- }
-
private function redirectToLogin()
{
$this->_request->setModuleName('default')
@@ -202,8 +175,6 @@ class ActionController extends ZfController
/**
* Prepare action execution by testing for correct permissions and setting shortcuts
- *
- * @return void
*/
public function preDispatch()
{
@@ -229,7 +200,7 @@ class ActionController extends ZfController
/**
* Redirect to a specific url, updating the browsers URL field
*
- * @param Url|string $url The target to redirect to
+ * @param Url|string $url The target to redirect to
**/
public function redirectNow($url)
{
diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php
index 93873e4fd..2b7bf738f 100644
--- a/library/Icinga/Web/Form.php
+++ b/library/Icinga/Web/Form.php
@@ -26,12 +26,13 @@
namespace Icinga\Web;
use \Zend_Controller_Request_Abstract;
+use \Zend_Form;
use \Zend_Form_Element_Submit;
use \Zend_Form_Element_Reset;
use \Zend_View_Interface;
-use \Zend_Form;
-use Icinga\Exception\ProgrammingError;
-use Icinga\Web\Form\InvalidCSRFTokenException;
+use \Icinga\Exception\ProgrammingError;
+use \Icinga\Web\Form\Decorator\HelpText;
+use \Icinga\Web\Form\InvalidCSRFTokenException;
/**
* Base class for forms providing CSRF protection, confirmation logic and auto submission
@@ -40,6 +41,7 @@ abstract class Form extends Zend_Form
{
/**
* The form's request object
+ *
* @var Zend_Controller_Request_Abstract
*/
private $request;
@@ -48,24 +50,28 @@ abstract class Form extends Zend_Form
* Whether this form should NOT add random generated "challenge" tokens that are associated with the user's current
* session in order to prevent Cross-Site Request Forgery (CSRF). It is the form's responsibility to verify the
* existence and correctness of this token
+ *
* @var bool
*/
protected $tokenDisabled = false;
/**
* Name of the CSRF token element (used to create non-colliding hashes)
+ *
* @var string
*/
private $tokenElementName = 'CSRFToken';
/**
* Flag to indicate that form is already build
+ *
* @var bool
*/
private $created = false;
/**
* Session id used for CSRF token generation
+ *
* @var string
*/
private $sessionId;
@@ -94,6 +100,7 @@ abstract class Form extends Zend_Form
* If the ID has never been set, the ID from session_id() is returned
*
* @return string
+ *
* @see session_id()
* @see setSessionId()
*/
@@ -110,7 +117,7 @@ abstract class Form extends Zend_Form
*
* This method should be used for testing purposes only
*
- * @param string $sessionId
+ * @param string $sessionId
*/
public function setSessionId($sessionId)
{
@@ -120,7 +127,7 @@ abstract class Form extends Zend_Form
/**
* Return the HTML element name of the CSRF token field
*
- * @return string
+ * @return string
*/
public function getTokenElementName()
{
@@ -131,6 +138,7 @@ abstract class Form extends Zend_Form
* Render the form to HTML
*
* @param Zend_View_Interface $view
+ *
* @return string
*/
public function render(Zend_View_Interface $view = null)
@@ -155,7 +163,7 @@ abstract class Form extends Zend_Form
/**
* Setter for the request
*
- * @param Zend_Controller_Request_Abstract $request
+ * @param Zend_Controller_Request_Abstract $request
*/
public function setRequest(Zend_Controller_Request_Abstract $request)
{
@@ -165,7 +173,7 @@ abstract class Form extends Zend_Form
/**
* Getter for the request
*
- * @return Zend_Controller_Request_Abstract
+ * @return Zend_Controller_Request_Abstract
*/
public function getRequest()
{
@@ -179,6 +187,7 @@ abstract class Form extends Zend_Form
*/
public function buildForm()
{
+
if ($this->created === false) {
$this->initCsrfToken();
$this->create();
@@ -195,7 +204,7 @@ abstract class Form extends Zend_Form
if (!$this->getAction() && $this->getRequest()) {
$this->setAction($this->getRequest()->getRequestUri());
}
-
+ $this->addElementDecorators();
$this->created = true;
}
}
@@ -203,7 +212,7 @@ abstract class Form extends Zend_Form
/**
* Setter for the cancel label
*
- * @param string $cancelLabel
+ * @param string $cancelLabel
*/
public function setCancelLabel($cancelLabel)
{
@@ -228,7 +237,7 @@ abstract class Form extends Zend_Form
/**
* Setter for the submit label
*
- * @param string $submitLabel
+ * @param string $submitLabel
*/
public function setSubmitLabel($submitLabel)
{
@@ -255,8 +264,9 @@ abstract class Form extends Zend_Form
*
* 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
+ * @param array $triggerElements The element names which should auto-submit the form
+ *
+ * @throws ProgrammingError When an element is found which does not yet exist
*/
final public function enableAutoSubmit($triggerElements)
{
@@ -279,7 +289,7 @@ abstract class Form extends Zend_Form
* 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
+ * @return bool
*/
public function isSubmittedAndValid()
{
@@ -312,7 +322,8 @@ abstract class Form extends Zend_Form
*
* This method should be used for testing purposes only
*
- * @param bool $disabled
+ * @param bool $disabled
+ *
* @see tokenDisabled
*/
final public function setTokenDisabled($disabled = true)
@@ -344,8 +355,9 @@ abstract class Form extends Zend_Form
/**
* 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
+ * @param array $checkData The POST data send by the user
+ *
+ * @throws InvalidCSRFTokenException When CSRF Validation fails
*/
final public function assertValidCsrfToken(array $checkData)
{
@@ -363,7 +375,8 @@ abstract class Form extends Zend_Form
/**
* Check whether the form's CSRF token-field has a valid value
*
- * @param string $elementValue Value from the form element
+ * @param string $elementValue Value from the form element
+ *
* @return bool
*/
private function hasValidCsrfToken($elementValue)
@@ -384,10 +397,24 @@ abstract class Form extends Zend_Form
return $token === hash('sha256', $this->getSessionId() . $seed);
}
+ /**
+ * Add element decorators which apply to all elements
+ *
+ * Adds `HelpText` decorator
+ *
+ * @see HelpText
+ */
+ private function addElementDecorators()
+ {
+ foreach ($this->getElements() as $element) {
+ $element->addDecorator(new HelpText());
+ }
+ }
+
/**
* Generate a new (seed, token) pair
*
- * @return array
+ * @return array
*/
final public function generateCsrfToken()
{
@@ -400,7 +427,7 @@ abstract class Form extends Zend_Form
/**
* Return the string representation of the CSRF seed/token pair
*
- * @return string
+ * @return string
*/
final public function generateCsrfTokenAsString()
{
diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
new file mode 100644
index 000000000..40dac4a75
--- /dev/null
+++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
@@ -0,0 +1,60 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Web\Form\Decorator;
+
+use \Zend_Form_Decorator_Abstract;
+
+/**
+ * Decorator to hide elements using a >noscript< tag instead of
+ * type='hidden' or css styles.
+ *
+ * This allows to hide depending elements for browsers with javascript
+ * (who can then automatically refresh their pages) but show them in
+ * case JavaScript is disabled
+ */
+class ConditionalHidden extends Zend_Form_Decorator_Abstract
+{
+ /**
+ * Generate a field that will be wrapped in tag if the
+ * "condition" attribute is set and false or 0
+ *
+ * @param string $content The tag's content
+ *
+ * @return string The generated tag
+ */
+ public function render($content = '')
+ {
+ $attributes = $this->getElement()->getAttribs();
+ $condition = isset($attributes['condition']) ? $attributes['condition'] : 1;
+ if ($condition != 1) {
+ $content = '' . $content . ' ';
+ }
+ return $content;
+ }
+}
diff --git a/library/Icinga/Web/Form/Decorator/HelpText.php b/library/Icinga/Web/Form/Decorator/HelpText.php
new file mode 100644
index 000000000..a9a82c800
--- /dev/null
+++ b/library/Icinga/Web/Form/Decorator/HelpText.php
@@ -0,0 +1,59 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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
+ *
+ * @param string $content The help text
+ *
+ * @return string The generated tag
+ */
+ public function render($content = '')
+ {
+ $attributes = $this->getElement()->getAttribs();
+
+ if (isset($attributes['helptext'])) {
+ $content = ''
+ . $content
+ . ''
+ . $attributes['helptext']
+ . '
';
+ }
+ return $content;
+ }
+}
diff --git a/library/Icinga/Web/Form/Element/Note.php b/library/Icinga/Web/Form/Element/Note.php
index 77ec2a785..2c01a24c4 100644
--- a/library/Icinga/Web/Form/Element/Note.php
+++ b/library/Icinga/Web/Form/Element/Note.php
@@ -37,7 +37,19 @@ class Note extends Zend_Form_Element_Xhtml
{
/**
* Name of the view helper
+ *
* @var string
*/
public $helper = 'formNote';
+
+ /**
+ * Return true to ensure redrawing
+ *
+ * @param mixed $value The value of to validate (ignored)
+ * @return bool Always true
+ */
+ public function isValid($value)
+ {
+ return true;
+ }
}
diff --git a/library/Icinga/Web/Form/Validator/DateFormatValidator.php b/library/Icinga/Web/Form/Validator/DateFormatValidator.php
new file mode 100644
index 000000000..038eba79b
--- /dev/null
+++ b/library/Icinga/Web/Form/Validator/DateFormatValidator.php
@@ -0,0 +1,88 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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;
+ }
+}
diff --git a/library/Icinga/Web/Form/Validator/TimeFormatValidator.php b/library/Icinga/Web/Form/Validator/TimeFormatValidator.php
new file mode 100644
index 000000000..434db3ecb
--- /dev/null
+++ b/library/Icinga/Web/Form/Validator/TimeFormatValidator.php
@@ -0,0 +1,85 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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;
+ }
+}
diff --git a/library/Icinga/Web/Form/Validator/WritablePathValidator.php b/library/Icinga/Web/Form/Validator/WritablePathValidator.php
new file mode 100644
index 000000000..0447a4f42
--- /dev/null
+++ b/library/Icinga/Web/Form/Validator/WritablePathValidator.php
@@ -0,0 +1,95 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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',
+ 'DOES_NOT_EXIST' => 'Path does not exist'
+ );
+ // @codingStandardsIgnoreEnd
+
+ /**
+ * When true, the file or directory must exist
+ *
+ * @var bool
+ */
+ private $requireExistence = false;
+
+ /**
+ * Set this validator to require the target file to exist
+ */
+ public function setRequireExistence()
+ {
+ $this->requireExistence = true;
+ }
+
+ /**
+ * Check whether the given value is writable path
+ *
+ * @param string $value The value submitted in the form
+ * @param mixed $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 ($this->requireExistence && !file_exists($value)) {
+ $this->_error('DOES_NOT_EXIST');
+ return false;
+ }
+
+ if ((file_exists($value) && is_writable($value)) ||
+ (is_dir(dirname($value)) && is_writable(dirname($value)))
+ ) {
+ return true;
+ }
+ $this->_error('NOT_WRITABLE');
+ return false;
+ }
+}
diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php
index fbc0a52f5..a0777ee46 100644
--- a/modules/monitoring/application/controllers/ConfigController.php
+++ b/modules/monitoring/application/controllers/ConfigController.php
@@ -3,52 +3,280 @@
// {{{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
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team
*/
// {{{ICINGA_LICENSE_HEADER}}}
+use \Exception;
+
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Config\PreservingIniWriter;
use \Icinga\Web\Controller\BaseConfigController;
use \Icinga\Web\Widget\Tab;
use \Icinga\Web\Url;
+use \Monitoring\Form\Config\ConfirmRemovalForm;
+use \Monitoring\Form\Config\Backend\EditBackendForm;
+use \Monitoring\Form\Config\Backend\CreateBackendForm;
+
+use \Monitoring\Form\Config\Instance\EditInstanceForm;
+use \Monitoring\Form\Config\Instance\CreateInstanceForm;
+
+/**
+ * Configuration controller for editing monitoring resources
+ */
class Monitoring_ConfigController extends BaseConfigController {
+ /**
+ * Create the tabs for being available via the applications 'Config' view
+ *
+ * @return array
+ */
static public function createProvidedTabs()
{
return array(
- "backends" => new Tab(array(
- "name" => "backends",
- "iconCls" => "hdd",
- "title" => "Monitoring Backends",
- "url" => Url::fromPath("/monitoring/config/backend")
+ 'backends' => new Tab(array(
+ 'name' => 'backends',
+ 'title' => 'Monitoring Backends',
+ 'url' => Url::fromPath('/monitoring/config')
))
);
}
- public function backendAction()
+ /**
+ * Display a list of available backends and instances
+ */
+ public function indexAction()
{
- $this->redirectNow("/config");
+ $this->view->backends = IcingaConfig::module('monitoring', 'backends')->toArray();
+ $this->view->instances = IcingaConfig::module('monitoring', 'instances')->toArray();
}
+ /**
+ * Display a form to modify the backend identified by the 'backend' parameter of the request
+ */
+ public function editbackendAction()
+ {
+ $backend = $this->getParam('backend');
+ if (!$this->isExistingBackend($backend)) {
+ $this->view->error = 'Unknown backend ' . $backend;
+ return;
+ }
+ $backendForm = new EditBackendForm();
+ $backendForm->setRequest($this->getRequest());
+ $backendForm->setBackendConfiguration(IcingaConfig::module('monitoring', 'backends')->get($backend));
+
+ if ($backendForm->isSubmittedAndValid()) {
+
+ $newConfig = $backendForm->getConfig();
+ $config = IcingaConfig::module('monitoring', 'backends');
+ $config->$backend = $newConfig;
+ if ($this->writeConfiguration($config, 'backends')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+ $this->view->name = $backend;
+ $this->view->form = $backendForm;
+ }
+
+ /**
+ * Display a form to create a new backends
+ */
+ public function createbackendAction()
+ {
+ $form = new CreateBackendForm();
+ $form->setRequest($this->getRequest());
+ if ($form->isSubmittedAndValid()) {
+ $configArray = IcingaConfig::module('monitoring', 'backends')->toArray();
+ $configArray[$form->getBackendName()] = $form->getConfig();
+
+ if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+ $this->view->form = $form;
+ $this->render('editbackend');
+ }
+
+ /**
+ * Display a confirmation form to remove the backend identified by the 'backend' parameter
+ */
+ public function removebackendAction()
+ {
+ $backend = $this->getParam('backend');
+ if (!$this->isExistingBackend($backend)) {
+ $this->view->error = 'Unknown backend ' . $backend;
+ return;
+ }
+ $form = new ConfirmRemovalForm();
+ $form->setRequest($this->getRequest());
+ $form->setRemoveTarget('backend', $backend);
+
+ if ($form->isSubmittedAndValid()) {
+ $configArray = IcingaConfig::module('monitoring', 'backends')->toArray();
+ unset($configArray[$backend]);
+
+ if ($this->writeConfiguration(new Zend_Config($configArray), 'backends')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+
+ $this->view->form = $form;
+ $this->view->name = $backend;
+ }
+
+ /**
+ * Display a form to remove the instance identified by the 'instance' parameter
+ */
+ public function removeinstanceAction()
+ {
+ $instance = $this->getParam('instance');
+ if (!$this->isExistingInstance($instance)) {
+ $this->view->error = 'Unknown instance ' . $instance;
+ return;
+ }
+
+ $form = new ConfirmRemovalForm();
+ $form->setRequest($this->getRequest());
+ $form->setRemoveTarget('instance', $instance);
+
+ if ($form->isSubmittedAndValid()) {
+ $configArray = IcingaConfig::module('monitoring', 'instances')->toArray();
+ unset($configArray[$instance]);
+
+ if ($this->writeConfiguration(new Zend_Config($configArray), 'instances')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+
+ $this->view->form = $form;
+ $this->view->name = $instance;
+ }
+
+ /**
+ * Display a form to edit the instance identified by the 'instance' parameter of the request
+ */
+ public function editinstanceAction()
+ {
+ $instance = $this->getParam('instance');
+ if (!$this->isExistingInstance($instance)) {
+ $this->view->error = 'Unknown instance ' . htmlentities($instance);
+ return;
+ }
+ $form = new EditInstanceForm();
+ $form->setInstanceConfiguration(IcingaConfig::module('monitoring', 'instances')->get($instance));
+ $form->setRequest($this->getRequest());
+ if ($form->isSubmittedAndValid()) {
+ $instanceConfig = IcingaConfig::module('monitoring', 'instances')->toArray();
+ $instanceConfig[$instance] = $form->getConfig();
+ if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+ $this->view->form = $form;
+ }
+
+ /**
+ * Display a form to create a new instance
+ */
+ public function createinstanceAction()
+ {
+ $form = new CreateInstanceForm();
+ $form->setRequest($this->getRequest());
+ if ($form->isSubmittedAndValid()) {
+ $instanceConfig = IcingaConfig::module('monitoring', 'instances')->toArray();
+ $instanceConfig[$form->getInstanceName()] = $form->getConfig()->toArray();
+ if ($this->writeConfiguration(new Zend_Config($instanceConfig), 'instances')) {
+ $this->redirectNow('monitoring/config');
+ } else {
+ $this->render('show-configuration');
+ return;
+ }
+ }
+ $this->view->form = $form;
+ $this->render('editinstance');
+ }
+
+ /**
+ * Display a form to remove the instance identified by the 'instance' parameter
+ */
+ private function writeConfiguration($config, $file)
+ {
+ $writer = new PreservingIniWriter(array(
+ 'filename' => IcingaConfig::module('monitoring', $file)->getConfigFile(),
+ 'config' => $config
+ ));
+
+ try {
+ $writer->write();
+ return true;
+ } catch (Exception $exc) {
+ $this->view->exceptionMessage = $exc->getMessage();
+ $this->view->iniConfigurationString = $writer->render();
+ $this->view->file = IcingaConfig::module('monitoring', $file)->getConfigFile();
+ return false;
+ }
+ }
+
+ /**
+ * Return true if the backend exists in the current configuration
+ *
+ * @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 = IcingaConfig::module('monitoring', '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 = IcingaConfig::module('monitoring', 'instances');
+ return $instanceCfg && $instanceCfg->get($instance);
+ }
}
// @codingStandardsIgnoreEnd
diff --git a/modules/monitoring/application/forms/Config/Backend/CreateBackendForm.php b/modules/monitoring/application/forms/Config/Backend/CreateBackendForm.php
new file mode 100644
index 000000000..3f0055451
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/Backend/CreateBackendForm.php
@@ -0,0 +1,70 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace 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');
+ }
+}
diff --git a/modules/monitoring/application/forms/Config/Backend/EditBackendForm.php b/modules/monitoring/application/forms/Config/Backend/EditBackendForm.php
new file mode 100644
index 000000000..91ecc9d70
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/Backend/EditBackendForm.php
@@ -0,0 +1,286 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Monitoring\Form\Config\Backend;
+
+use \Zend_Config;
+
+use \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Element\Note;
+
+/**
+ * Form for modifying a monitoring backend
+ */
+class EditBackendForm extends Form
+{
+ /**
+ * Database resources to use instead of the one's from DBAdapterFactory (used for testing)
+ *
+ * @var array
+ */
+ private $resources;
+
+ /**
+ * The Backend configuration to use for populating the form
+ *
+ * @var Zend_Config
+ */
+ private $backend;
+
+ /**
+ * Mapping from form fields to configuration fields
+ *
+ * @var array
+ */
+ private $propertyMapping = array(
+ 'livestatus' => array(
+ 'backend_livestatus_socket' => 'socket'
+ ),
+ 'ido' => array(
+ 'backend_ido_resource' => 'resource'
+ ),
+ 'statusdat' => array(
+ 'backend_statusdat_statusfile' => 'status_file',
+ 'backend_statusdat_objectfile' => 'object_file'
+ )
+ );
+
+ /**
+ * 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 DbAdapterFactory
+ * (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 DbAdapterFactory::getResources();
+ } else {
+ return $this->resources;
+ }
+ }
+
+ /**
+ * Return a list of all database resource ready to be used as the multiOptions
+ * attribute in a Zend_Form_Element_Select object
+ *
+ * @return array
+ */
+ private function getDatabaseResources()
+ {
+ $backends = array();
+ foreach ($this->getResources() as $resname => $resource) {
+ if ($resource['type'] !== 'db') {
+ continue;
+ }
+ $backends[$resname] = $resname;
+ }
+ return $backends;
+ }
+
+
+ /**
+ * Add form elements used for setting IDO backend parameters
+ */
+ private function addIdoBackendForm()
+ {
+ $this->addElement(
+ 'select',
+ 'backend_ido_resource',
+ array(
+ 'label' => 'IDO Connection',
+ 'value' => $this->backend->resource,
+ 'required' => true,
+ 'multiOptions' => $this->getDatabaseResources(),
+ 'helptext' => 'The database to use for querying monitoring data',
+ )
+ );
+ }
+
+ /**
+ * Add form elements used for setting status.dat backend parameters
+ */
+ private function addStatusDatForm()
+ {
+ $this->addElement(
+ 'text',
+ 'backend_statusdat_statusfile',
+ array (
+ 'label' => 'Status.dat File',
+ 'value' => $this->backend->status_file,
+ 'required' => true,
+ 'helptext' => 'Location of your icinga status.dat file'
+ )
+ );
+ $this->addElement(
+ 'text',
+ 'backend_statusdat_objectfile',
+ array (
+ 'label' => 'Objects.cache File',
+ 'value' => $this->backend->status_file,
+ 'required' => true,
+ 'helptext' => 'Location of your icinga objects.cache file'
+ )
+ );
+ }
+
+ /**
+ * Add form elements used for setting Livestatus parameters
+ */
+ private function addLivestatusForm()
+ {
+ $this->addElement(
+ 'text',
+ 'backend_livestatus_socket',
+ array(
+ 'label' => 'Livestatus Socket Location',
+ 'required' => true,
+ 'helptext' => 'The path to your livestatus socket used for querying monitoring data',
+ 'value' => $this->backend->socket,
+ )
+ );
+ }
+
+ /**
+ * Add a checkbox to disable this backends
+ */
+ private function addDisableButton()
+ {
+ $this->addElement(
+ 'checkbox',
+ 'backend_disable',
+ array(
+ 'label' => 'Disable this Backend',
+ 'required' => true,
+ 'value' => $this->backend->disabled
+ )
+ );
+ }
+
+ /**
+ * Add a select box for choosing the type to use for this backend
+ */
+ private function addTypeSelectionBox()
+ {
+ $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->enableAutoSubmit(array('backend_type'));
+ }
+
+ /**
+ * Create this form
+ *
+ * @see Icinga\Web\Form::create()
+ */
+ public function create()
+ {
+ $this->addTypeSelectionBox();
+ switch ($this->getRequest()->getParam('backend_type', $this->backend->type)) {
+ case 'ido':
+ $this->addIdoBackendForm();
+ break;
+ case 'statusdat':
+ $this->addStatusDatForm();
+ break;
+ case 'livestatus':
+ $this->addLivestatusForm();
+ break;
+ default:
+ $this->removeElement('backend_type');
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'error_note',
+ 'value' => 'Unknown Backend Type "' . $this->backend->type. '"'
+ )
+ )
+ );
+ return;
+ }
+ $this->addDisableButton();
+ $this->setSubmitLabel('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();
+ $type = $values['backend_type'];
+
+ $map = $this->propertyMapping[$type];
+ $result = array(
+ 'type' => $type,
+ 'disabled' => $values['backend_disable']
+ );
+ foreach ($map as $formKey => $mappedKey) {
+ $result[$mappedKey] = $values[$formKey];
+ }
+ return new Zend_Config($result);
+ }
+}
diff --git a/modules/monitoring/application/forms/Config/ConfirmRemovalForm.php b/modules/monitoring/application/forms/Config/ConfirmRemovalForm.php
new file mode 100644
index 000000000..b3fcec8a9
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/ConfirmRemovalForm.php
@@ -0,0 +1,82 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace 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->setSubmitLabel('Confirm Removal');
+ }
+}
diff --git a/modules/monitoring/application/forms/Config/Instance/CreateInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/CreateInstanceForm.php
new file mode 100644
index 000000000..b46021eed
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/Instance/CreateInstanceForm.php
@@ -0,0 +1,71 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace 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');
+ }
+}
diff --git a/modules/monitoring/application/forms/Config/Instance/EditInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/EditInstanceForm.php
new file mode 100644
index 000000000..3ba39127f
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/Instance/EditInstanceForm.php
@@ -0,0 +1,180 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+namespace Monitoring\Form\Config\Instance;
+
+use \Zend_Config;
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Element\Note;
+
+/**
+ * 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->addElement(
+ new Note(
+ array(
+ 'name' => 'note_ssh_info',
+ 'value' => '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');
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/modules/monitoring/application/views/scripts/config/editbackend.phtml b/modules/monitoring/application/views/scripts/config/editbackend.phtml
new file mode 100644
index 000000000..0760a73a6
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/editbackend.phtml
@@ -0,0 +1,14 @@
+= $this->tabs->render($this); ?>
+name): ?>
+ Edit Backend "= $this->escape($this->name) ?>"
+
+ Create New Backend
+
+
+error): ?>
+
+ = $this->escape($this->error); ?>
+
+
+
+= $this->form; ?>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/config/editinstance.phtml b/modules/monitoring/application/views/scripts/config/editinstance.phtml
new file mode 100644
index 000000000..deb0b36fd
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/editinstance.phtml
@@ -0,0 +1,15 @@
+= $this->tabs->render($this); ?>
+
+name)): ?>
+ Edit Instance Configuration for "= $this->escape($this->name) ?>"
+
+ Configure New Icinga Instance
+
+
+error): ?>
+
+ = $this->escape($this->error); ?>
+
+
+
+= $this->form; ?>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml
new file mode 100644
index 000000000..91be1a100
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/index.phtml
@@ -0,0 +1,55 @@
+
+= $this->tabs->render($this); ?>
+
+Backends
+
+
+
+
+backends as $backendName => $config): ?>
+
+ $backendName)); ?>
+ $backendName)); ?>
+
= $this->escape($backendName); ?>
+
(Type: = $this->escape($config['type'] === 'ido' ? 'IDO' : ucfirst($config['type'])); ?>)
+
+ -
Disabled
+
+
+
+
+
+
+
+
+Monitoring Instances
+
+
+
+
+instances as $instanceName => $config): ?>
+ $instanceName)); ?>
+ $instanceName)); ?>
+
+
= $this->escape($instanceName); ?>
+
(Type: = isset($config['host']) ? 'Remote' : 'Local'; ?>)
+
+
+
+
+
+
diff --git a/modules/monitoring/application/views/scripts/config/removebackend.phtml b/modules/monitoring/application/views/scripts/config/removebackend.phtml
new file mode 100644
index 000000000..6087b120b
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/removebackend.phtml
@@ -0,0 +1,8 @@
+= $this->tabs->render($this); ?>
+Remove Backend "= $this->escape($this->name) ?>"
+
+
+ Are you sure you want to remove the backend = $this->escape($this->name) ?>?
+
+
+= $this->form; ?>
diff --git a/modules/monitoring/application/views/scripts/config/removeinstance.phtml b/modules/monitoring/application/views/scripts/config/removeinstance.phtml
new file mode 100644
index 000000000..f4516151b
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/removeinstance.phtml
@@ -0,0 +1,13 @@
+= $this->tabs->render($this); ?>
+Remove Instance "= $this->escape($this->name) ?>"
+
+
+ Are you sure you want to remove the instance = $this->escape($this->name) ?>?
+
+
+
+ If you have still any environments or views refering to this instance, you won't be able to send commands anymore
+ after deletion.
+
+
+= $this->form; ?>
diff --git a/modules/monitoring/application/views/scripts/config/show-configuration.phtml b/modules/monitoring/application/views/scripts/config/show-configuration.phtml
new file mode 100644
index 000000000..b3c822655
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/config/show-configuration.phtml
@@ -0,0 +1,30 @@
+= $this->tabs->render($this); ?>
+
+
+
Saving = $this->escape($this->file); ?>failed
+
+
+ Your = $this->escape($this->file); ?> configuration couldn't be stored (error: "= $this->exceptionMessage; ?>").
+ This could have one or more of the following reasons:
+
+
+ You don't have file-system permissions to write to the = $this->escape($this->file); ?> file
+ Something went wrong while writing the file
+ There's an application error preventing you from persisting the configuration
+
+
+
+
+ Details can be seen in your application log (if you don't have access to this file, call your administrator in this case).
+
+ In case you can access the configuration file (config/= $this->escape($this->file); ?>) by yourself, you can open it and
+ insert the config manually:
+
+
+
+
+
+= $this->escape($this->iniConfigurationString); ?>
+
+
+
\ No newline at end of file
diff --git a/modules/monitoring/library/Monitoring/Backend.php b/modules/monitoring/library/Monitoring/Backend.php
index e62342f62..922837a08 100644
--- a/modules/monitoring/library/Monitoring/Backend.php
+++ b/modules/monitoring/library/Monitoring/Backend.php
@@ -28,9 +28,9 @@
namespace Monitoring;
+use \Exception;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Authentication\Manager as AuthManager;
-use \Exception;
use \Monitoring\Backend\AbstractBackend;
/**
@@ -62,9 +62,9 @@ class Backend
/**
* Test if configuration key exist
*
- * @param string $name
+ * @param string $name
*
- * @return bool
+ * @return bool
*/
public static function exists($name)
{
@@ -75,9 +75,9 @@ class Backend
/**
* Get the first configuration name of all backends
*
- * @throws Exception
+ * @return string
*
- * @return string
+ * @throws Exception
*/
public static function getDefaultName()
{
@@ -99,9 +99,12 @@ class Backend
public static function getBackendConfigs()
{
if (self::$backendConfigs === null) {
+ $resources = IcingaConfig::app('resources');
+ foreach ($resources as $resource) {
+
+ }
$backends = IcingaConfig::module('monitoring', 'backends');
foreach ($backends as $name => $config) {
- // TODO: Check if access to this backend is allowed
self::$backendConfigs[$name] = $config;
}
}
@@ -112,10 +115,11 @@ class Backend
/**
* Get a backend by name or a default one
*
- * @throws \Exception
- * @param string $name
+ * @param string $name
*
- * @return AbstractBackend
+ * @return AbstractBackend
+ *
+ * @throws Exception
*/
public static function getBackend($name = null)
{
@@ -145,9 +149,9 @@ class Backend
/**
* Get backend by name or by user configuration
*
- * @param string $name
+ * @param string $name
*
- * @return AbstractBackend
+ * @return AbstractBackend
*/
public static function getInstance($name = null)
{
diff --git a/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php
index ece3c02c0..cc1be7363 100644
--- a/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php
@@ -1,6 +1,6 @@
'host_accept_passive_checks',
'host_last_state_change',
- 'host_problems' => 'is_flapping',
- 'service_in_downtime' => 'is_flapping',
- 'service_handled' => 'is_flapping',
-
// Service config
'service_description' => 'description',
'service_display_name' => 'display_name',
@@ -41,34 +37,12 @@ class StatusQuery extends AbstractQuery
'service_last_state_change' => 'last_state_change',
// Service comments
- //'comments_with_info',
- //'downtimes_with_info',
+ 'comments_with_info',
+ 'downtimes_with_info',
);
- public function init()
- {
- $this->query = $this->createQuery();
- //print_r($this->ds->getConnection()->fetchAll($this->query));
- //die('asdf');
- }
-
- public function count()
- {
- return $this->ds->getConnection()->count($this->query);
- }
-
- public function fetchAll()
- {
- return $this->ds->getConnection()->fetchAll($this->query);
- }
-
- public function fetchRow()
- {
- return array_shift($this->ds->getConnection()->fetchAll($this->query));
- }
-
protected function createQuery()
{
- return $this->ds->getConnection()->select()->from('services', $this->available_columns);
+ return $this->connection->getConnection()->select()->from('services', $this->available_columns);
}
}
diff --git a/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php b/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php
index 1e0e08f44..e6a625ab8 100644
--- a/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php
+++ b/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php
@@ -5,7 +5,8 @@
namespace Test\Monitoring\Forms\Command;
-require_once realpath(__DIR__ . '/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__ . '/../../../../../../../library/Icinga/Util/ConfigAwareFactory.php');
require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/DateTimeFactory.php');
@@ -13,6 +14,7 @@ require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/DateT
use \DateTimeZone;
use \Monitoring\Form\Command\AcknowledgeForm; // Used by constant FORMCLASS
use \Icinga\Util\DateTimeFactory;
+use \Test\Icinga\Web\Form\BaseFormTest;
class AcknowledgeFormTest extends BaseFormTest
{
diff --git a/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php b/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php
index 354aad114..e740b7101 100644
--- a/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php
+++ b/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php
@@ -5,10 +5,11 @@
namespace Test\Monitoring\Forms\Command;
-require_once realpath(__DIR__ . '/BaseFormTest.php');
+require_once realpath('library/Icinga/Web/Form/BaseFormTest.php');
require_once realpath(__DIR__ . '/../../../../../../../modules/monitoring/application/forms/Command/CommentForm.php');
use \Monitoring\Form\Command\CommentForm; // Used by constant FORMCLASS
+use \Test\Icinga\Web\Form\BaseFormTest;
class CommentFormTest extends BaseFormTest
{
diff --git a/modules/monitoring/test/php/application/forms/Command/ConfirmationFormTest.php b/modules/monitoring/test/php/application/forms/Command/ConfirmationFormTest.php
index 70e8b64c6..53434bb0a 100644
--- a/modules/monitoring/test/php/application/forms/Command/ConfirmationFormTest.php
+++ b/modules/monitoring/test/php/application/forms/Command/ConfirmationFormTest.php
@@ -1,7 +1,7 @@
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+
+ $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' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+
+ $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' => array(
+ 'type' => 'db'
+ ),
+ 'db_resource_2' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+
+ $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' => array(
+ 'type' => 'db'
+ ),
+ 'db_resource_2' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+
+ $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'
+ );
+
+ }
+}
\ No newline at end of file
diff --git a/test/php/application/forms/Config/GeneralFormTest.php b/test/php/application/forms/Config/GeneralFormTest.php
new file mode 100644
index 000000000..2bf646238
--- /dev/null
+++ b/test/php/application/forms/Config/GeneralFormTest.php
@@ -0,0 +1,182 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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/GeneralForm.php'));
+
+use Test\Icinga\Web\Form\BaseFormTest;
+use \Icinga\Web\Form;
+use \DOMDocument;
+use \Zend_Config;
+use \Zend_View;
+
+class GeneralFormTest extends \Test\Icinga\Web\Form\BaseFormTest
+{
+
+ private function isHiddenElement($value, $htmlString)
+ {
+ $html = new DOMDocument();
+ $html->loadHTML($htmlString);
+ $hidden = $html->getElementsByTagName('noscript');
+
+ foreach($hidden as $node) {
+ foreach($node->childNodes as $child) {
+ if ($child->hasAttributes() === false) {
+ continue;
+ }
+ if (strpos($child->attributes->item(0)->value, $value) !== false) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ /**
+ *
+ */
+ public function testCorrectFieldPopulation()
+ {
+ date_default_timezone_set('UTC');
+ $form = $this->getRequestForm(array(), 'Icinga\Form\Config\GeneralForm');
+ $form->setConfiguration(
+ new Zend_Config(
+ array(
+ 'global' => array(
+ 'environment' => 'development',
+ 'timezone' => 'Europe/Berlin',
+ 'indexModule' => 'monitoring',
+ 'indexController' => 'dashboard',
+ 'moduleFolder' => '/my/module/path',
+ 'dateFormat' => 'd-m/Y',
+ 'timeFormat' => 'A:i'
+ ),
+ 'preferences' => array(
+ 'type' => 'ini',
+ 'configPath' => './my/path'
+ )
+ )
+ )
+ );
+ $form->setResources(
+ array(
+ 'db' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+ $form->setConfigDir('/tmp');
+ $view = new Zend_View();
+
+ $form->create();
+ $this->assertEquals(1, $form->getValue('environment'), 'Asserting the checkbox for devlopment being set to true');
+ $this->assertEquals('Europe/Berlin', $form->getValue('timezone'), 'Asserting the correct timezone to be displayed');
+ $this->assertEquals('/my/module/path', $form->getValue('module_folder'), 'Asserting the correct module folder to be set');
+ $this->assertEquals('d-m/Y', $form->getValue('date_format'), 'Asserting the correct data format to be set');
+ $this->assertEquals('A:i', $form->getValue('time_format'), 'Asserting the correct time to be set');
+ $this->assertEquals('ini', $form->getValue('preferences_type'), 'Asserting the correct preference type to be set');
+ $this->assertEquals('./my/path', $form->getValue('preferences_ini_path'), 'Asserting the correct ini path to be set');
+ $this->assertEquals('', $form->getValue('preferences_db_resource'), 'Asserting the database resource not to be set');
+ }
+
+ public function testCorrectConditionalIniFieldRendering()
+ {
+ date_default_timezone_set('UTC');
+ $form = $this->getRequestForm(array(), 'Icinga\Form\Config\GeneralForm');
+ $form->setConfiguration(
+ new Zend_Config(
+ array(
+ 'preferences' => array(
+ 'type' => 'ini',
+ 'configPath' => './my/path'
+ )
+ )
+ )
+ );
+ $form->setConfigDir('/tmp');
+ $form->setResources(
+ array(
+ 'db' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+ $form->create();
+
+ $view = new Zend_View();
+
+ $this->assertFalse(
+ $this->isHiddenElement('preferences_ini_path', $form->render($view)),
+ "Asserting the ini path field to be displayed when an ini preference is set"
+ );
+ $this->assertTrue(
+ $this->isHiddenElement('preferences_db_resource', $form->render($view)),
+ "Asserting the db resource to be hidden when an ini preference is set"
+ );
+ }
+
+ public function testCorrectConditionalDbFieldRendering()
+ {
+ date_default_timezone_set('UTC');
+ $form = $this->getRequestForm(array(), 'Icinga\Form\Config\GeneralForm');
+ $form->setConfiguration(
+ new Zend_Config(
+ array(
+ 'preferences' => array(
+ 'type' => 'db',
+ 'configPath' => './my/path',
+ 'resource' => 'my_resource'
+ )
+ )
+ )
+ );
+ $form->setConfigDir('/tmp');
+ $form->setResources(
+ array(
+ 'db' => array(
+ 'type' => 'db'
+ )
+ )
+ );
+ $form->create();
+ $view = new Zend_View();
+
+ $this->assertTrue(
+ $this->isHiddenElement('preferences_ini_path', $form->render($view)),
+ "Asserting the ini path field to be hidden when db preference is set"
+ );
+ $this->assertFalse(
+ $this->isHiddenElement('preferences_ini_resource', $form->render($view)),
+ "Asserting the db resource to be displayed when db preference is set"
+ );
+ }
+}
\ No newline at end of file
diff --git a/test/php/application/forms/Config/LoggingFormTest.php b/test/php/application/forms/Config/LoggingFormTest.php
new file mode 100644
index 000000000..8b1f92500
--- /dev/null
+++ b/test/php/application/forms/Config/LoggingFormTest.php
@@ -0,0 +1,170 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{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(
+ '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'
+ );
+ }
+}
diff --git a/test/php/application/forms/Preference/GeneralFormTest.php b/test/php/application/forms/Preference/GeneralFormTest.php
new file mode 100644
index 000000000..51cf862ac
--- /dev/null
+++ b/test/php/application/forms/Preference/GeneralFormTest.php
@@ -0,0 +1,113 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Test\Icinga\Form\Preference;
+
+
+require_once('Zend/Config.php');
+require_once('Zend/Config/Ini.php');
+require_once('Zend/Form/Element/Select.php');
+require_once(realpath('library/Icinga/Web/Form/BaseFormTest.php'));
+require_once(realpath('../../application/forms/Preference/GeneralForm.php'));
+require_once(realpath('../../library/Icinga/User/Preferences/ChangeSet.php'));
+require_once(realpath('../../library/Icinga/User/Preferences.php'));
+
+use Test\Icinga\Web\Form\BaseFormTest;
+use \Icinga\Web\Form;
+use \DOMDocument;
+use \Zend_Config;
+use \Zend_View;
+use Icinga\User\Preferences;
+
+/**
+ * Test for general form, mainly testing enable/disable behaviour
+ */
+class GeneralFormTest extends \Test\Icinga\Web\Form\BaseFormTest
+{
+
+ /**
+ * Test whether fields using the default values have input disabled
+ *
+ */
+ public function testDisableFormIfUsingDefault()
+ {
+ date_default_timezone_set('UTC');
+ $form = $this->getRequestForm(array(), 'Icinga\Form\Preference\GeneralForm');
+ $form->setRequest($this->getRequest());
+ $form->setConfiguration(
+ new Zend_Config(
+ array(
+ 'timezone' => 'UTC'
+ )
+ )
+ );
+ $form->setUserPreferences(
+ new Preferences(
+ array()
+ )
+ );
+ $form->create();
+ $this->assertSame(
+ 1,
+ $form->getElement('timezone')->getAttrib('disabled'),
+ 'Asserting form elements to be disabled when not set in a preference'
+ );
+ }
+
+ /**
+ * Test whether fields with preferences are enabled
+ *
+ */
+ public function testEnsableFormIfUsingPreference()
+ {
+ date_default_timezone_set('UTC');
+ $form = $this->getRequestForm(array(), 'Icinga\Form\Preference\GeneralForm');
+ $form->setRequest($this->getRequest());
+ $form->setConfiguration(
+ new Zend_Config(
+ array(
+ 'timezone' => 'UTC'
+ )
+ )
+ );
+ $form->setUserPreferences(
+ new Preferences(
+ array(
+ 'app.timezone' => 'Europe/Berlin'
+ )
+ )
+ );
+ $form->create();
+ $this->assertSame(
+ null,
+ $form->getElement('timezone')->getAttrib('disabled'),
+ 'Asserting form elements to be disabled when not set in a preference'
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/modules/monitoring/test/php/application/forms/Command/BaseFormTest.php b/test/php/library/Icinga/Web/Form/BaseFormTest.php
similarity index 50%
rename from modules/monitoring/test/php/application/forms/Command/BaseFormTest.php
rename to test/php/library/Icinga/Web/Form/BaseFormTest.php
index aaba6575c..facdaafa1 100644
--- a/modules/monitoring/test/php/application/forms/Command/BaseFormTest.php
+++ b/test/php/library/Icinga/Web/Form/BaseFormTest.php
@@ -1,4 +1,8 @@
setSessionId("test");
+ $form->setSessionId('test');
$form->initCsrfToken();
$request = $this->getRequest();
$data[$form->getTokenElementName()] = $form->getValue($form->getTokenElementName());
- $request->setMethod("POST")->setPost($data);
+ $request->setMethod('POST')->setPost($data);
$form->setRequest($request);
return $form;
}
+
+ /**
+ * This is just a test to avoid warnings being submitted from the testrunner
+ *
+ */
+ public function testForRemovingWarnings()
+ {
+ $this->assertTrue(true);
+ }
}
}
diff --git a/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php
new file mode 100644
index 000000000..75c50ef2c
--- /dev/null
+++ b/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php
@@ -0,0 +1,61 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Test\Icinga\Web\Form\Validator;
+
+require_once('Zend/Validate/Abstract.php');
+require_once(realpath('../../library/Icinga/Web/Form/Validator/DateFormatValidator.php'));
+
+use \PHPUnit_Framework_TestCase;
+use \Icinga\Web\Form\Validator\DateFormatValidator;
+
+class DateFormatValidatorTest extends PHPUnit_Framework_TestCase
+{
+
+ public function testValidateCorrectInput()
+ {
+ $validator = new DateFormatValidator();
+ $this->assertTrue(
+ $validator->isValid(
+ 'Y-m-d',
+ 'Asserting a valid date format to result in correct validation'
+ )
+ );
+ }
+
+ public function testValidateInorrectInput()
+ {
+ $validator = new DateFormatValidator();
+ $this->assertFalse(
+ $validator->isValid(
+ 'Y-m-d h:m:s',
+ 'Asserting a date format combined with time to result in a validation error'
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php
new file mode 100644
index 000000000..b8c5b6e34
--- /dev/null
+++ b/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php
@@ -0,0 +1,61 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Test\Icinga\Web\Form\Validator;
+
+require_once('Zend/Validate/Abstract.php');
+require_once(realpath('../../library/Icinga/Web/Form/Validator/TimeFormatValidator.php'));
+
+use \PHPUnit_Framework_TestCase;
+use \Icinga\Web\Form\Validator\TimeFormatValidator;
+
+class TimeFormatValidatorTest extends PHPUnit_Framework_TestCase
+{
+
+ public function testValidateCorrectInput()
+ {
+ $validator = new TimeFormatValidator();
+ $this->assertTrue(
+ $validator->isValid(
+ 'h-i-s',
+ 'Asserting a valid time format to result in correct validation'
+ )
+ );
+ }
+
+ public function testValidateInorrectInput()
+ {
+ $validator = new TimeFormatValidator();
+ $this->assertFalse(
+ $validator->isValid(
+ 'Y-m-d h:m:s',
+ 'Asserting a date format combined with time to result in a validation error'
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php
new file mode 100644
index 000000000..b9b579b29
--- /dev/null
+++ b/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php
@@ -0,0 +1,64 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Test\Icinga\Web\Form\Validator;
+
+require_once('Zend/Validate/Abstract.php');
+require_once(realpath('../../library/Icinga/Web/Form/Validator/WritablePathValidator.php'));
+
+use \PHPUnit_Framework_TestCase;
+use \Icinga\Web\Form\Validator\WritablePathValidator;
+
+class WritablePathValidatorTest extends PHPUnit_Framework_TestCase
+{
+
+ public function testValidateInputWithWritablePath()
+ {
+ $validator = new WritablePathValidator();
+ if (!is_writeable('/tmp')) {
+ $this->markTestSkipped('Need /tmp to be writable for testing WritablePathValidator');
+ }
+ $this->assertTrue(
+ $validator->isValid(
+ '/tmp/test',
+ 'Asserting a writable path to result in correct validation'
+ )
+ );
+ }
+
+ public function testValidateInputWithNonWritablePath()
+ {
+ $validator = new WritablePathValidator();
+ $this->assertFalse(
+ $validator->isValid(
+ '/etc/shadow',
+ 'Asserting a non writable path to result in a validation error'
+ )
+ );
+ }
+}
\ No newline at end of file