From 26a5018d16fd8e4514120153e379a75851fad123 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Wed, 14 Aug 2013 10:53:25 +0200
Subject: [PATCH 01/20] Add Forms and conditional hidden
refs #3777
---
application/controllers/ConfigController.php | 47 ++-
application/forms/Config/GeneralForm.php | 278 ++++++++++++++++++
application/forms/Config/LoggingForm.php | 217 ++++++++++++++
application/views/scripts/config/index.phtml | 12 +-
.../views/scripts/config/logging.phtml | 3 +
library/Icinga/Config/IniEditor.php | 3 +-
.../Web/Form/Decorator/ConditionalHidden.php | 65 ++++
.../controllers/ConfigController.php | 1 -
8 files changed, 604 insertions(+), 22 deletions(-)
create mode 100644 application/forms/Config/GeneralForm.php
create mode 100644 application/forms/Config/LoggingForm.php
create mode 100644 application/views/scripts/config/logging.phtml
create mode 100644 library/Icinga/Web/Form/Decorator/ConditionalHidden.php
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index 4f7adf963..88ea60639 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -31,6 +31,9 @@ use \Icinga\Web\Widget\Tab;
use \Icinga\Web\Url;
use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
use \Icinga\Application\Icinga;
+use \Icinga\Form\Config\GeneralForm;
+use \Icinga\Form\Config\LoggingForm;
+use \Icinga\Config\PreservingIniWriter;
/**
* Application wide controller for application preferences
@@ -49,18 +52,23 @@ class ConfigController extends BaseConfigController
return array(
'index' => new Tab(
array(
- 'name' => 'index',
- 'title' => 'Configuration',
- 'iconCls' => 'wrench',
- 'url' => Url::fromPath('/config')
+ "name" => "index",
+ "title" => "Application",
+ "url" => Url::fromPath("/config")
)
),
- 'modules' => new Tab(
+ "logging" => new Tab(
array(
- 'name' => 'modules',
- 'title' => 'Modules',
- 'iconCls' => 'puzzle-piece',
- 'url' => Url::fromPath('/config/moduleoverview')
+ "name" => "logging",
+ "title" => "Logging",
+ "url" => Url::fromPath("/config/logging")
+ )
+ ),
+ "modules" => new Tab(
+ array(
+ "name" => "modules",
+ "title" => "Modules",
+ "url" => Url::fromPath("/config/moduleoverview")
)
)
);
@@ -72,7 +80,26 @@ class ConfigController extends BaseConfigController
*/
public function indexAction()
{
+ $form = new GeneralForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->_request);
+ if ($form->isSubmittedAndValid()) {
+ $cfg = IcingaConfig::app()->getConfigFile();
+ $writer = new PreservingIniWriter(
+ array('config' => $form->getConfig(),'filename' => $cfg)
+ );
+ print_r($writer->render());die();
+ }
+ $this->view->form = $form;
+ }
+ public function loggingAction()
+ {
+ $form = new LoggingForm();
+ $form->setConfiguration(IcingaConfig::app());
+ $form->setRequest($this->_request);
+
+ $this->view->form = $form;
}
/**
@@ -106,5 +133,7 @@ class ConfigController extends BaseConfigController
$manager->disableModule($this->_getParam('name'));
$this->redirectNow('config/moduleoverview?_render=body');
}
+
+
}
// @codingStandardsIgnoreEnd
diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php
new file mode 100644
index 000000000..4a416b48d
--- /dev/null
+++ b/application/forms/Config/GeneralForm.php
@@ -0,0 +1,278 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Form\Config;
+/**
+ * [global]
+environment = development
+timezone = "Europe/Berlin"
+indexModule = monitoring
+indexController = dashboard
+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
+
+; 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
+
+; Use ini store to store preferences on local disk
+[preferences]
+type=ini
+
+ */
+use \Icinga\Application\Config as IcingaConfig;
+use Icinga\Application\Icinga;
+use \Icinga\Web\Form;
+use \Zend_Form_Element_Radio;
+use \DateTimeZone;
+use \Zend_Config;
+use Icinga\Web\Form\Element\Note;
+
+/**
+ * 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;
+
+ /**
+ * Set the configuration to be used for this form
+ *
+ * @param IcingaConfig $cfg
+ */
+ public function setConfiguration(IcingaConfig $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;
+ }
+
+ /**
+ * 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,
+ 'tooltip' => 'More verbose output',
+ 'value' => $env === 'development'
+ )
+ );
+ $this->addElement(new Note(array(
+ 'name' => 'note_env',
+ 'value' => 'Set true to show more detailed errors and disable certain optimizations '
+ . 'in order to make debugging easier.'
+ )));
+ }
+
+ /**
+ * 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;
+ }
+
+ $this->addElement(
+ 'select',
+ 'timezone',
+ array(
+ 'label' => 'Default application timezone',
+ 'required' => true,
+ 'multiOptions' => $tzList,
+ 'value' => $cfg->get('timezone', date_default_timezone_get())
+ )
+ );
+ $this->addElement(new Note(array(
+ 'name' => 'noteTimezone',
+ 'value' => 'Select the timezone to be used as the default. User\'s can set their own timezone if'.
+ ' they like to, but this is the timezone to be used as the default setting .'
+ )));
+ }
+
+ /**
+ * 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,
+ 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
+ )
+ );
+ $this->addElement(new Note(array(
+ 'name' => 'noteModuleFolder',
+ 'value' => 'Use this folder to activate modules (must be writable by your webserver)'
+ )));
+ }
+
+ /**
+ * 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';
+
+ $this->addElement(
+ 'text',
+ 'date_format',
+ array(
+ 'label' => 'Date format',
+ 'required' => true,
+ 'value' => $cfg->get('dateFormat', 'd/m/Y')
+ )
+ );
+ $this->addElement(new Note(array(
+ 'name' => 'noteDateFormat',
+ 'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values'
+ )));
+
+
+ $this->addElement(
+ 'text',
+ 'time_format',
+ array(
+ 'label' => 'Time format',
+ 'required' => true,
+ 'value' => $cfg->get('timeFormat', 'g:i A')
+ )
+ );
+ $this->addElement(new Note(array(
+ 'name' => 'noteTimeFormat',
+ 'value' => 'Display times according to this format. See ' . $phpUrl . ' for possible values'
+ )));
+ }
+
+ /**
+ * 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());
+ }
+
+ $this->addDevelopmentCheckbox($global);
+ $this->addTimezoneSelection($global);
+ $this->addModuleSettings($global);
+ $this->addDateFormatSettings($global);
+
+ $this->setSubmitLabel('Save changes');
+ }
+
+ public function getConfig()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+ $global = $this->config->global;
+ if ($global === null) {
+ $this->config->global = 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'];
+
+ return $cfg;
+ }
+
+}
\ No newline at end of file
diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php
new file mode 100644
index 000000000..952ae1c61
--- /dev/null
+++ b/application/forms/Config/LoggingForm.php
@@ -0,0 +1,217 @@
+
+ * @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 \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Web\Form;
+use \Icinga\Web\Form\Element\Note;
+use \Icinga\Web\Form\Decorator\ConditionalHidden;
+use \Zend_Config;
+use \Zend_Form_Element_Text;
+
+/**
+ * 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;
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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_use_debug', null);
+ if ($debugParam !== null) {
+ return intval($debugParam) === 1;
+ } else {
+ return intval($config->get('enable', 0)) === 1;
+ }
+
+ }
+
+ private function loggingIsEnabled(Zend_Config $config)
+ {
+ $loggingRequestParam = $this->getRequest()->getParam('logging_enable', null);
+
+ if ($loggingRequestParam !== null) {
+ return intval($loggingRequestParam) === 1;
+ } else {
+ return intval($config->get('enable', 0)) === 1;
+ }
+ }
+
+ /**
+ * @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());
+ }
+ $this->addElement(
+ 'checkbox',
+ 'logging_enable',
+ array(
+ 'label' => 'Logging enabled',
+ 'required' => true,
+ 'value' => $this->loggingIsEnabled($logging)
+ )
+ );
+ if (!$this->loggingIsEnabled($debug)) {
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'note_logging_disabled',
+ 'value' => 'Logging is disabled.'
+ )
+ )
+ );
+ $this->setSubmitLabel('Save changes');
+ $this->enableAutoSubmit(array('logging_enable'));
+
+ return;
+ }
+ $this->addDecorator(new ConditionalHidden());
+
+ $this->addElement(
+ 'text',
+ 'logging_app_path',
+ array(
+ 'label' => 'Application log path',
+ 'required' => true,
+ 'value' => $logging->get('target', '/var/log/icingaweb.log')
+ )
+ );
+
+ $this->addElement(new Note(
+ array(
+ 'name' => 'note_logging_app_path',
+ 'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write'
+ . 'at this location'
+ )
+ ));
+
+ $this->addElement(
+ 'checkbox',
+ 'logging_app_verbose',
+ array(
+ 'label' => 'Verbose logging',
+ 'required' => true,
+ 'value' => intval($logging->get('verbose', 0)) === 1
+ )
+ );
+
+ $this->addElement(new Note(
+ array(
+ 'name' => 'note_logging_app_verbose',
+ 'value'=> 'Check to write more verbose output to the icinga log file'
+ )
+ ));
+
+ $this->addElement(
+ 'checkbox',
+ 'logging_use_debug',
+ array(
+ 'label' => 'Use debug log',
+ 'required' => true,
+ 'value' => $this->shouldDisplayDebugLog($debug)
+ )
+ );
+ $this->addElement(new Note(
+ array(
+ 'name' => 'note_logging_use_debug',
+ 'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)'
+ )
+ ));
+
+
+ $textLoggingDebugPath = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'logging_debug_path',
+ 'label' => 'Debug log path',
+ 'required' => true,
+ 'condition' => $this->shouldDisplayDebugLog($debug),
+ 'value' => $debug->get('target', '/var/log/icingaweb.debug.log')
+ )
+ );
+ $loggingPathNote = new Note(
+ array(
+ 'name' => 'note_logging_debug_path',
+ 'value' => 'Set the path to the debug log',
+ 'condition' => $this->shouldDisplayDebugLog($debug)
+ )
+ );
+
+ $this->addElement($textLoggingDebugPath);
+ $this->addElement($loggingPathNote);
+
+ $this->enableAutoSubmit(array('logging_use_debug', 'logging_enable'));
+
+ $this->setSubmitLabel('Save changes');
+ }
+
+}
\ 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..aa8ca9f49
--- /dev/null
+++ b/application/views/scripts/config/logging.phtml
@@ -0,0 +1,3 @@
+= $this->tabs->render($this); ?>
+
+= $this->form ?>
\ No newline at end of file
diff --git a/library/Icinga/Config/IniEditor.php b/library/Icinga/Config/IniEditor.php
index afb89d44a..42dd60380 100644
--- a/library/Icinga/Config/IniEditor.php
+++ b/library/Icinga/Config/IniEditor.php
@@ -225,10 +225,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];
/*
diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
new file mode 100644
index 000000000..7dc54a8fe
--- /dev/null
+++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
@@ -0,0 +1,65 @@
+
+ * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
+ * @author Icinga Development Team
+ */
+// {{{ICINGA_LICENSE_HEADER}}}
+
+
+/**
+ * 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
+ */
+
+namespace Icinga\Web\Form\Decorator;
+
+use \Zend_Form_Decorator_Abstract;
+
+class ConditionalHidden extends Zend_Form_Decorator_Abstract
+{
+ /**
+ * Generates a html number input
+ *
+ * @access public
+ *
+ * @param string $name The element name.
+ * @param string $value The default value.
+ * @param array $attribs Attributes which should be added to the input tag.
+ *
+ * @return string The input tag and options XHTML.
+ */
+ public function render($content ='')
+ {
+ $attributes = $this->getElement()->getAttribs();
+ $condition = isset($attributes['condition']) ? $attributes['condition'] : 1;
+ if ($condition != 1) {
+ $content = '';
+ }
+ return $content;
+ }
+}
diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php
index fbc0a52f5..e92e28f8f 100644
--- a/modules/monitoring/application/controllers/ConfigController.php
+++ b/modules/monitoring/application/controllers/ConfigController.php
@@ -38,7 +38,6 @@ class Monitoring_ConfigController extends BaseConfigController {
return array(
"backends" => new Tab(array(
"name" => "backends",
- "iconCls" => "hdd",
"title" => "Monitoring Backends",
"url" => Url::fromPath("/monitoring/config/backend")
))
From 9ddc03d571aeb17ca6ce01a07bbbd9161caa8571 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Wed, 14 Aug 2013 14:52:47 +0200
Subject: [PATCH 02/20] Implement General configuration form
Missing:
- Logical validation (check for writable paths)
- DB Resource selection (see #4503)
refs #3777
---
application/controllers/ConfigController.php | 7 +-
application/forms/Config/GeneralForm.php | 105 +++++++++++++------
application/forms/Config/LoggingForm.php | 8 +-
library/Icinga/Web/Form.php | 6 +-
library/Icinga/Web/Form/Element/Note.php | 5 +
5 files changed, 92 insertions(+), 39 deletions(-)
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index 88ea60639..b2d0a7b2e 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -86,9 +86,12 @@ class ConfigController extends BaseConfigController
if ($form->isSubmittedAndValid()) {
$cfg = IcingaConfig::app()->getConfigFile();
$writer = new PreservingIniWriter(
- array('config' => $form->getConfig(),'filename' => $cfg)
+ array(
+ 'config' => $form->getConfig(),
+ 'filename' => $cfg
+ )
);
- print_r($writer->render());die();
+ $writer->write();
}
$this->view->form = $form;
}
diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php
index 4a416b48d..bb9858b87 100644
--- a/application/forms/Config/GeneralForm.php
+++ b/application/forms/Config/GeneralForm.php
@@ -27,41 +27,17 @@
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
-/**
- * [global]
-environment = development
-timezone = "Europe/Berlin"
-indexModule = monitoring
-indexController = dashboard
-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
-
-; 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
-
-; Use ini store to store preferences on local disk
-[preferences]
-type=ini
-
- */
use \Icinga\Application\Config as IcingaConfig;
-use Icinga\Application\Icinga;
+use \Icinga\Application\Icinga;
use \Icinga\Web\Form;
-use \Zend_Form_Element_Radio;
+use \Icinga\Web\Form\Decorator\ConditionalHidden;
+use \Icinga\Web\Form\Element\Note;
+
use \DateTimeZone;
use \Zend_Config;
-use Icinga\Web\Form\Element\Note;
+use \Zend_Form_Element_Text;
+
/**
* Configuration form for general, application-wide settings
@@ -231,6 +207,56 @@ class GeneralForm extends Form
)));
}
+ 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' => 'Path to store user preference files',
+ 'required' => $backend === 'ini',
+ 'condition' => $backend === 'ini',
+ 'value' => $cfg->get('configPath')
+ )
+ );
+
+ $txtPreferencesDbResource = new Zend_Form_Element_Text(
+ array(
+ 'name' => 'preferences_db_resource',
+ 'label' => 'Database connection (TODO: Make select field)',
+ 'required' => $backend === 'db',
+ 'condition' => $backend === 'db',
+ 'value' => $cfg->get('resource')
+ )
+ );
+
+ $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
*
@@ -245,11 +271,17 @@ class GeneralForm extends Form
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');
}
@@ -259,10 +291,12 @@ class GeneralForm extends Form
if ($this->config === null) {
$this->config = new Zend_Config(array());
}
- $global = $this->config->global;
- if ($global === null) {
+ 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;
@@ -272,6 +306,13 @@ class GeneralForm extends Form
$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
index 952ae1c61..107e75ff2 100644
--- a/application/forms/Config/LoggingForm.php
+++ b/application/forms/Config/LoggingForm.php
@@ -135,7 +135,6 @@ class LoggingForm extends Form
return;
}
- $this->addDecorator(new ConditionalHidden());
$this->addElement(
'text',
@@ -195,7 +194,7 @@ class LoggingForm extends Form
'label' => 'Debug log path',
'required' => true,
'condition' => $this->shouldDisplayDebugLog($debug),
- 'value' => $debug->get('target', '/var/log/icingaweb.debug.log')
+ 'value' => $debug->get('target')
)
);
$loggingPathNote = new Note(
@@ -205,10 +204,13 @@ class LoggingForm extends Form
'condition' => $this->shouldDisplayDebugLog($debug)
)
);
-
+ $decorator = new ConditionalHidden();
$this->addElement($textLoggingDebugPath);
$this->addElement($loggingPathNote);
+ $textLoggingDebugPath->addDecorator($decorator);
+ $loggingPathNote->addDecorator($decorator);
+
$this->enableAutoSubmit(array('logging_use_debug', 'logging_enable'));
$this->setSubmitLabel('Save changes');
diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php
index 93873e4fd..593977d40 100644
--- a/library/Icinga/Web/Form.php
+++ b/library/Icinga/Web/Form.php
@@ -25,13 +25,14 @@
namespace Icinga\Web;
+use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Controller_Request_Abstract;
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\InvalidCSRFTokenException;
/**
* Base class for forms providing CSRF protection, confirmation logic and auto submission
@@ -179,6 +180,7 @@ abstract class Form extends Zend_Form
*/
public function buildForm()
{
+
if ($this->created === false) {
$this->initCsrfToken();
$this->create();
diff --git a/library/Icinga/Web/Form/Element/Note.php b/library/Icinga/Web/Form/Element/Note.php
index 77ec2a785..3d8af596b 100644
--- a/library/Icinga/Web/Form/Element/Note.php
+++ b/library/Icinga/Web/Form/Element/Note.php
@@ -40,4 +40,9 @@ class Note extends Zend_Form_Element_Xhtml
* @var string
*/
public $helper = 'formNote';
+
+ public function isValid($value)
+ {
+ return true;
+ }
}
From 17c1e5a4493747ec759def7d76a62c1f57498a5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Thu, 15 Aug 2013 10:56:17 +0200
Subject: [PATCH 03/20] Add tests, move BaseFormTest away from
modules/monitoring
refs #3777
---
application/forms/Config/GeneralForm.php | 2 +-
.../Backend/Livestatus/Query/StatusQuery.php | 34 +---
.../forms/Command/AcknowledgeFormTest.php | 3 +-
.../forms/Command/CommentFormTest.php | 3 +-
.../forms/Command/ConfirmationFormTest.php | 4 +-
.../ConfirmationWithIdentifierFormTest.php | 3 +-
.../Command/CustomNotificationFormTest.php | 3 +-
.../Command/DelayNotificationFormTest.php | 3 +-
.../Command/RescheduleNextCheckFormTest.php | 3 +-
.../Command/ScheduleDowntimeFormTest.php | 3 +-
.../Command/SubmitPassiveCheckResultTest.php | 3 +-
.../forms/Config/GeneralFormTest.php | 161 ++++++++++++++++++
.../library/Icinga/Web/Form}/BaseFormTest.php | 26 ++-
13 files changed, 203 insertions(+), 48 deletions(-)
create mode 100644 test/php/application/forms/Config/GeneralFormTest.php
rename {modules/monitoring/test/php/application/forms/Command => test/php/library/Icinga/Web/Form}/BaseFormTest.php (66%)
diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php
index bb9858b87..671d9694d 100644
--- a/application/forms/Config/GeneralForm.php
+++ b/application/forms/Config/GeneralForm.php
@@ -64,7 +64,7 @@ class GeneralForm extends Form
*
* @param IcingaConfig $cfg
*/
- public function setConfiguration(IcingaConfig $cfg)
+ public function setConfiguration($cfg)
{
$this->config = $cfg;
}
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..981d900cb 100644
--- a/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php
+++ b/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php
@@ -5,7 +5,7 @@
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/AcknowledgeForm.php');
require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/ConfigAwareFactory.php');
require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Util/DateTimeFactory.php');
@@ -13,6 +13,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/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->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->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->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/modules/monitoring/test/php/application/forms/Command/BaseFormTest.php b/test/php/library/Icinga/Web/Form/BaseFormTest.php
similarity index 66%
rename from modules/monitoring/test/php/application/forms/Command/BaseFormTest.php
rename to test/php/library/Icinga/Web/Form/BaseFormTest.php
index aaba6575c..1cde68e66 100644
--- a/modules/monitoring/test/php/application/forms/Command/BaseFormTest.php
+++ b/test/php/library/Icinga/Web/Form/BaseFormTest.php
@@ -1,4 +1,8 @@
assertTrue(true);
+ }
}
}
From 5a768ccaa9cafd0f40f4b76e2e7b8dc58f5e4e43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Thu, 15 Aug 2013 14:27:53 +0200
Subject: [PATCH 04/20] Start authentication form
refs #3777
---
application/controllers/ConfigController.php | 19 ++
.../forms/Config/AuthenticationForm.php | 279 ++++++++++++++++++
application/forms/Config/GeneralForm.php | 58 +++-
.../views/scripts/config/authentication.phtml | 2 +
4 files changed, 350 insertions(+), 8 deletions(-)
create mode 100644 application/forms/Config/AuthenticationForm.php
create mode 100644 application/views/scripts/config/authentication.phtml
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index b2d0a7b2e..5e69c219b 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -32,6 +32,7 @@ use \Icinga\Web\Url;
use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
use \Icinga\Application\Icinga;
use \Icinga\Form\Config\GeneralForm;
+use \Icinga\Form\Config\AuthenticationForm;
use \Icinga\Form\Config\LoggingForm;
use \Icinga\Config\PreservingIniWriter;
@@ -57,6 +58,15 @@ class ConfigController extends BaseConfigController
"url" => Url::fromPath("/config")
)
),
+
+ "authentication" => new Tab(
+ array(
+ "name" => "auth",
+ "title" => "Authentication",
+ "url" => Url::fromPath('/config/authentication')
+ )
+ ),
+
"logging" => new Tab(
array(
"name" => "logging",
@@ -96,6 +106,15 @@ class ConfigController extends BaseConfigController
$this->view->form = $form;
}
+ public function authenticationAction()
+ {
+ $form = new AuthenticationForm();
+ $form->setConfiguration(IcingaConfig::app('authentication'));
+ $form->setRequest($this->_request);
+ $form->isSubmittedAndValid();
+ $this->view->form = $form;
+ }
+
public function loggingAction()
{
$form = new LoggingForm();
diff --git a/application/forms/Config/AuthenticationForm.php b/application/forms/Config/AuthenticationForm.php
new file mode 100644
index 000000000..d835a956f
--- /dev/null
+++ b/application/forms/Config/AuthenticationForm.php
@@ -0,0 +1,279 @@
+
+ * @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 \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;
+use \Zend_Config;
+use \Zend_Form_Element_Text;
+use \Zend_Form_Element_Select;
+
+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;
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
+ * Set the configuration to be used for this form
+ *
+ * @param IcingaConfig $cfg
+ */
+ public function setConfiguration($cfg)
+ {
+ $this->config = $cfg;
+ }
+
+ private function addProviderFormForDb($name, $backend)
+ {
+
+ $backends = array();
+ foreach ($this->getResources() as $resname => $resource)
+ {
+ if ($resource['type'] !== 'db') {
+ continue;
+ }
+ $backends[$resname] = $resname;
+ }
+
+ $this->addElement(
+ 'select',
+ 'backend_' . $name . '_resource',
+ array(
+ 'label' => 'Database connection',
+ 'required' => true,
+ 'value' => $backend->get('resource'),
+ 'multiOptions' => $backends
+ )
+ );
+
+
+ $this->addElement(
+ 'submit',
+ 'backend_' . $name . '_remove',
+ array(
+ 'label' => 'Remove this backend',
+ 'required' => true
+ )
+ );
+
+ $this->addDisplayGroup(
+ array(
+ 'backend_' . $name . '_resource',
+ 'backend_' . $name . '_remove'
+ ),
+ 'auth_provider_' . $name,
+ array(
+ 'legend' => 'DB Authentication ' . $name
+ )
+ );
+ }
+
+ private function addProviderFormForLdap($name, $backend)
+ {
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_hostname',
+ array(
+ 'label' => 'LDAP server host',
+ 'value' => $backend->get('hostname', 'localhost'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_root_dn',
+ array(
+ 'label' => 'LDAP root dn',
+ 'value' => $backend->get('hostname', 'ou=people,dc=icinga,dc=org'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_dn',
+ array(
+ 'label' => 'LDAP bind dn',
+ 'value' => $backend->get('bind_dn', 'cn=admin,cn=config'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'password',
+ 'backend_' . $name . '_bind_pw',
+ array(
+ 'label' => 'LDAP bind password',
+ 'value' => $backend->get('bind_pw', 'admin'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_user_class',
+ array(
+ 'label' => 'LDAP user object class',
+ 'value' => $backend->get('user_class', 'inetOrgPerson'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_user_name_attribute',
+ array(
+ 'label' => 'LDAP user name attribute',
+ 'value' => $backend->get('user_name_attribute', 'uid'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'submit',
+ 'backend_' . $name . '_remove',
+ array(
+ 'label' => 'Remove this backend'
+ )
+ );
+
+ $this->addDisplayGroup(
+ array(
+ 'backend_' . $name . '_hostname',
+ 'backend_' . $name . '_root_dn',
+ 'backend_' . $name . '_bind_dn',
+ 'backend_' . $name . '_bind_pw',
+ 'backend_' . $name . '_bind_user_class',
+ 'backend_' . $name . '_bind_user_name_attribute',
+ 'backend_' . $name . '_remove'
+ ),
+ 'auth_provider_' . $name,
+ array(
+ 'legend' => 'LDAP Authentication ' . $name
+ )
+ );
+ }
+
+
+ public function addPriorityButtons($name, $pos)
+ {
+ if ($pos > 0) {
+ $this->addElement(
+ 'submit',
+ 'priority_change_'.$name.'_down',
+ array(
+ 'label' => 'Move up in authentication order',
+ 'value' => $pos-1
+ )
+ );
+ }
+ if ($pos+1 < count($this->config->keys())) {
+ $this->addElement(
+ 'submit',
+ 'priority_change_'.$name.'_up',
+ array(
+ 'label' => 'Move down in authentication order',
+ 'value' => $pos+1
+ )
+ );
+ }
+ }
+
+ public function create()
+ {
+ $this->addElement(
+ 'submit',
+ 'add_backend',
+ array(
+ 'label' => 'Add a new authentication provider',
+ 'class' => 'btn'
+ )
+ );
+ $pos = 0;
+ foreach ($this->config as $name => $backend) {
+
+ $type = strtolower($backend->get('backend'));
+ if ($type === 'db') {
+ $this->addProviderFormForDb($name, $backend);
+ } elseif ($type === 'ldap') {
+ $this->addProviderFormForLdap($name, $backend);
+ } else {
+ Logger::error('Unsupported backend found in authentication configuration: ' . $backend->get('backend'));
+ continue;
+ }
+ $this->addPriorityButtons($name, $pos);
+
+ $pos++;
+ }
+ $this->setSubmitLabel('Save changes');
+ }
+}
\ No newline at end of file
diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php
index 671d9694d..3d83272cd 100644
--- a/application/forms/Config/GeneralForm.php
+++ b/application/forms/Config/GeneralForm.php
@@ -30,6 +30,7 @@ namespace Icinga\Form\Config;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga;
+use \Icinga\Application\DbAdapterFactory;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Icinga\Web\Form\Element\Note;
@@ -37,7 +38,7 @@ use \Icinga\Web\Form\Element\Note;
use \DateTimeZone;
use \Zend_Config;
use \Zend_Form_Element_Text;
-
+use \Zend_Form_Element_Select;
/**
* Configuration form for general, application-wide settings
@@ -59,6 +60,14 @@ class GeneralForm extends Form
*/
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
*
@@ -90,6 +99,31 @@ class GeneralForm extends Form
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
*
@@ -236,14 +270,23 @@ class GeneralForm extends Form
'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_Text(
+ $txtPreferencesDbResource = new Zend_Form_Element_Select(
array(
- 'name' => 'preferences_db_resource',
- 'label' => 'Database connection (TODO: Make select field)',
- 'required' => $backend === 'db',
- 'condition' => $backend === 'db',
- 'value' => $cfg->get('resource')
+ 'name' => 'preferences_db_resource',
+ 'label' => 'Database connection',
+ 'required' => $backend === 'db',
+ 'condition' => $backend === 'db',
+ 'value' => $cfg->get('resource'),
+ 'multiOptions' => $backends
)
);
@@ -282,7 +325,6 @@ class GeneralForm extends Form
$this->addDateFormatSettings($global);
$this->addUserPreferencesDialog($preferences);
-
$this->setSubmitLabel('Save changes');
}
diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml
new file mode 100644
index 000000000..f0b046499
--- /dev/null
+++ b/application/views/scripts/config/authentication.phtml
@@ -0,0 +1,2 @@
+= $this->tabs->render($this); ?>
+= $this->form ?>
\ No newline at end of file
From c705f5d475dd0739ff886406d8f8ac655a219f93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Fri, 16 Aug 2013 16:24:12 +0200
Subject: [PATCH 05/20] Implement Authentication form
- Allow creation of authentication providers
- Allow modification of authentication providers
- Allow reordering of authentication providers
refs #3777
---
application/controllers/ConfigController.php | 71 +++-
.../Config/Authentication/BaseBackendForm.php | 140 +++++++
.../Config/Authentication/DbBackendForm.php | 122 ++++++
.../Config/Authentication/LdapBackendForm.php | 157 ++++++++
.../forms/Config/AuthenticationForm.php | 356 +++++++++---------
application/forms/Config/GeneralForm.php | 99 +++--
application/forms/Config/LoggingForm.php | 45 ++-
.../views/scripts/config/authentication.phtml | 18 +
.../authentication/show-configuration.phtml | 30 ++
library/Icinga/Web/Form.php | 1 +
.../Web/Form/Decorator/ConditionalHidden.php | 2 +-
11 files changed, 813 insertions(+), 228 deletions(-)
create mode 100644 application/forms/Config/Authentication/BaseBackendForm.php
create mode 100644 application/forms/Config/Authentication/DbBackendForm.php
create mode 100644 application/forms/Config/Authentication/LdapBackendForm.php
create mode 100644 application/views/scripts/config/authentication/show-configuration.phtml
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index 5e69c219b..fb8e63f34 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -33,6 +33,8 @@ use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
use \Icinga\Application\Icinga;
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;
@@ -106,14 +108,7 @@ class ConfigController extends BaseConfigController
$this->view->form = $form;
}
- public function authenticationAction()
- {
- $form = new AuthenticationForm();
- $form->setConfiguration(IcingaConfig::app('authentication'));
- $form->setRequest($this->_request);
- $form->isSubmittedAndValid();
- $this->view->form = $form;
- }
+
public function loggingAction()
{
@@ -156,6 +151,66 @@ class ConfigController extends BaseConfigController
$this->redirectNow('config/moduleoverview?_render=body');
}
+ private function writeAuthenticationFile(array $config)
+ {
+ $cfg = new Zend_Config($config);
+ $writer = new Zend_Config_Writer_Ini(
+ array(
+ 'config' => $cfg,
+ 'filename' => IcingaConfig::app('authentication')->getConfigFile()
+ )
+ );
+ try {
+ $writer->write();
+ } catch (Exception $exc) {
+ $this->view->exceptionMessage = $exc->getMessage();
+ $this->view->iniConfigurationString = $writer->render();
+ $this->render('authentication/show-configuration');
+ }
+ }
+
+ /**
+ * Action for creating a new authentication backend
+ *
+ */
+ public function authenticationAction()
+ {
+ $form = new AuthenticationForm();
+ $config = IcingaConfig::app('authentication');
+ $form->setConfiguration($config);
+ $form->setRequest($this->_request);
+
+ if ($form->isSubmittedAndValid()) {
+ $this->writeAuthenticationFile($form->getConfig());
+ }
+ $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;
+ }
+
+ $this->writeAuthenticationFile($backendCfg);
+ }
+ $this->view->form = $form;
+ $this->render('authentication/modify');
+ }
}
// @codingStandardsIgnoreEnd
diff --git a/application/forms/Config/Authentication/BaseBackendForm.php b/application/forms/Config/Authentication/BaseBackendForm.php
new file mode 100644
index 000000000..1844d4d47
--- /dev/null
+++ b/application/forms/Config/Authentication/BaseBackendForm.php
@@ -0,0 +1,140 @@
+
+ * @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 \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Web\Form;
+use \Zend_Config;
+
+/**
+ * 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 = null;
+
+ /**
+ * The resources to use instead of the factory provided ones (use for testing)
+ *
+ * @var Zend_Config
+ */
+ private $resources = null;
+
+ /**
+ * 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 keyvalue subarray
+ *
+ * @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..de2b0464f
--- /dev/null
+++ b/application/forms/Config/Authentication/DbBackendForm.php
@@ -0,0 +1,122 @@
+
+ * @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 \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+
+use \Icinga\Web\Form;
+use \Zend_Config;
+
+/**
+ * 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',
+ 'value' => $this->getBackendName()
+ )
+ );
+
+ $this->addElement(
+ 'select',
+ 'backend_' . $name . '_resource',
+ array(
+ 'label' => 'Database connection',
+ 'required' => true,
+ 'allowEmpty' => false,
+ '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..ea92c756b
--- /dev/null
+++ b/application/forms/Config/Authentication/LdapBackendForm.php
@@ -0,0 +1,157 @@
+
+ * @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 \Icinga\Application\Config as IcingaConfig;
+use \Icinga\Application\Icinga;
+use \Icinga\Application\Logger;
+use \Icinga\Application\DbAdapterFactory;
+
+use \Icinga\Web\Form;
+use \Zend_Config;
+
+/**
+ * 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',
+ 'value' => $this->getBackendName()
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_hostname',
+ array(
+ 'label' => 'LDAP server host',
+ 'allowEmpty' => false,
+ 'value' => $backend->get('hostname', 'localhost'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_root_dn',
+ array(
+ 'label' => 'LDAP root dn',
+ 'value' => $backend->get('hostname', 'ou=people,dc=icinga,dc=org'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_dn',
+ array(
+ 'label' => 'LDAP bind dn',
+ 'value' => $backend->get('bind_dn', 'cn=admin,cn=config'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'password',
+ 'backend_' . $name . '_bind_pw',
+ array(
+ 'label' => 'LDAP bind password',
+ 'renderPassword' => true,
+ 'value' => $backend->get('bind_pw', 'admin'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_user_class',
+ array(
+ 'label' => 'LDAP user object class',
+ 'value' => $backend->get('user_class', 'inetOrgPerson'),
+ 'required' => true
+ )
+ );
+
+ $this->addElement(
+ 'text',
+ 'backend_' . $name . '_bind_user_name_attribute',
+ array(
+ 'label' => 'LDAP user name attribute',
+ 'value' => $backend->get('user_name_attribute', 'uid'),
+ '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'),
+ 'bind_user_class' => $this->getValue($prefix . 'bind_user_class'),
+ 'bind_user_name_attribute' => $this->getValue($prefix . 'bind_user_name_attribute')
+ );
+ return array(
+ $section => $cfg
+ );
+ }
+}
diff --git a/application/forms/Config/AuthenticationForm.php b/application/forms/Config/AuthenticationForm.php
index d835a956f..135ddefdc 100644
--- a/application/forms/Config/AuthenticationForm.php
+++ b/application/forms/Config/AuthenticationForm.php
@@ -32,6 +32,8 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga;
use \Icinga\Application\Logger;
use \Icinga\Application\DbAdapterFactory;
+use \Icinga\Form\Config\Authentication\DbBackendForm;
+use \Icinga\Form\Config\Authentication\LdapBackendForm;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note;
@@ -39,6 +41,7 @@ use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Config;
use \Zend_Form_Element_Text;
use \Zend_Form_Element_Select;
+use \Zend_Form_Element_Button;
class AuthenticationForm extends Form
{
@@ -56,6 +59,10 @@ class AuthenticationForm extends Form
*/
private $resources = null;
+
+ private $backendForms = array();
+
+
/**
* Set an alternative array of resources that should be used instead of the DBFactory resource set
* (used for testing)
@@ -67,20 +74,6 @@ class AuthenticationForm extends Form
$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;
- }
- }
-
/**
* Set the configuration to be used for this form
*
@@ -91,189 +84,214 @@ class AuthenticationForm extends Form
$this->config = $cfg;
}
- private function addProviderFormForDb($name, $backend)
- {
- $backends = array();
- foreach ($this->getResources() as $resname => $resource)
- {
- if ($resource['type'] !== 'db') {
- continue;
- }
- $backends[$resname] = $resname;
+ 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';
+ }
+
+ 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;
}
- $this->addElement(
- 'select',
- 'backend_' . $name . '_resource',
- array(
- 'label' => 'Database connection',
- 'required' => true,
- 'value' => $backend->get('resource'),
- 'multiOptions' => $backends
- )
- );
+ $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 $name => $element) {
+ $this->addElement($element, $name);
+ }
- $this->addElement(
- 'submit',
- 'backend_' . $name . '_remove',
- array(
- 'label' => 'Remove this backend',
- 'required' => true
- )
- );
-
- $this->addDisplayGroup(
- array(
- 'backend_' . $name . '_resource',
- 'backend_' . $name . '_remove'
- ),
- 'auth_provider_' . $name,
- array(
- 'legend' => 'DB Authentication ' . $name
- )
- );
- }
-
- private function addProviderFormForLdap($name, $backend)
- {
- $this->addElement(
- 'text',
- 'backend_' . $name . '_hostname',
- array(
- 'label' => 'LDAP server host',
- 'value' => $backend->get('hostname', 'localhost'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'text',
- 'backend_' . $name . '_root_dn',
- array(
- 'label' => 'LDAP root dn',
- 'value' => $backend->get('hostname', 'ou=people,dc=icinga,dc=org'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'text',
- 'backend_' . $name . '_bind_dn',
- array(
- 'label' => 'LDAP bind dn',
- 'value' => $backend->get('bind_dn', 'cn=admin,cn=config'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'password',
- 'backend_' . $name . '_bind_pw',
- array(
- 'label' => 'LDAP bind password',
- 'value' => $backend->get('bind_pw', 'admin'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'text',
- 'backend_' . $name . '_bind_user_class',
- array(
- 'label' => 'LDAP user object class',
- 'value' => $backend->get('user_class', 'inetOrgPerson'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'text',
- 'backend_' . $name . '_bind_user_name_attribute',
- array(
- 'label' => 'LDAP user name attribute',
- 'value' => $backend->get('user_name_attribute', 'uid'),
- 'required' => true
- )
- );
-
- $this->addElement(
- 'submit',
- 'backend_' . $name . '_remove',
- array(
- 'label' => 'Remove this backend'
- )
- );
-
- $this->addDisplayGroup(
- array(
- 'backend_' . $name . '_hostname',
- 'backend_' . $name . '_root_dn',
- 'backend_' . $name . '_bind_dn',
- 'backend_' . $name . '_bind_pw',
- 'backend_' . $name . '_bind_user_class',
- 'backend_' . $name . '_bind_user_name_attribute',
- 'backend_' . $name . '_remove'
- ),
- 'auth_provider_' . $name,
- array(
- 'legend' => 'LDAP Authentication ' . $name
- )
- );
+ $this->backendForms[] = $form;
}
- public function addPriorityButtons($name, $pos)
+
+
+
+ public function addPriorityButtons($name, $order = array())
{
- if ($pos > 0) {
+ $formEls = array();
+ $priorities = array(
+ "up" => join(',', self::moveElementUp($name, $order)),
+ "down" => join(',', self::moveElementDown($name, $order))
+ );
+ if ($priorities["up"] != join(',', $order)) {
$this->addElement(
- 'submit',
- 'priority_change_'.$name.'_down',
+ 'button',
+ 'priority' . $name . '_up',
array(
+ 'name' => 'priority',
'label' => 'Move up in authentication order',
- 'value' => $pos-1
+ 'value' => $priorities["up"],
+ 'type' => 'submit'
)
);
+ $formEls[] = 'priority' . $name . '_up';
}
- if ($pos+1 < count($this->config->keys())) {
+ if ($priorities["down"] != join(',', $order)) {
$this->addElement(
- 'submit',
- 'priority_change_'.$name.'_up',
+ 'button',
+ 'priority' . $name . '_down',
array(
+ 'name' => 'priority',
'label' => 'Move down in authentication order',
- 'value' => $pos+1
+ 'value' => $priorities["down"],
+ 'type' => 'submit'
)
);
+ $formEls[] = 'priority' . $name . '_down';
}
+
+ return $formEls;
}
+
+ public function populate(array $values)
+ {
+ $last_priority = $this->getValue('current_priority');
+ parent::populate($values);
+ $this->getElement('current_priority')->setValue($last_priority);
+
+ }
+
+ 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;
+ }
+
+
+ private function isMarkedForDeletion($backendName)
+ {
+ return intval($this->getRequest()->getParam('backend_' . $backendName . '_remove', 0)) === 1;
+ }
+
+ private function addPersistentState()
+ {
+
+ $this->addElement(
+ 'hidden',
+ 'current_priority',
+ array(
+ 'name' => 'current_priority',
+ 'value' => join(',', $this->getAuthenticationOrder())
+ )
+ );
+ }
+
+
+
public function create()
{
- $this->addElement(
- 'submit',
- 'add_backend',
- array(
- 'label' => 'Add a new authentication provider',
- 'class' => 'btn'
- )
- );
- $pos = 0;
- foreach ($this->config as $name => $backend) {
+ $order = $this->getAuthenticationOrder();
- $type = strtolower($backend->get('backend'));
- if ($type === 'db') {
- $this->addProviderFormForDb($name, $backend);
- } elseif ($type === 'ldap') {
- $this->addProviderFormForLdap($name, $backend);
- } else {
- Logger::error('Unsupported backend found in authentication configuration: ' . $backend->get('backend'));
+ 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;
}
- $this->addPriorityButtons($name, $pos);
-
- $pos++;
+ if (!$this->isMarkedForDeletion($this->filterName($name))) {
+ $this->addProviderForm($name, $backend);
+ $this->addPriorityButtons($name, $order);
+ }
}
+
+ $this->addPersistentState();
+ $this->enableConditionalDecorator();
$this->setSubmitLabel('Save changes');
}
-}
\ No newline at end of file
+
+ public function getConfig()
+ {
+ $result = array();
+ foreach ($this->backendForms as $name) {
+
+ $name->populate($this->getRequest()->getParams());
+ $result += $name->getConfig();
+
+ }
+ return $result;
+ }
+
+ private function enableConditionalDecorator()
+ {
+ foreach ($this->getElements() as $element) {
+ $element->addDecorator(new ConditionalHidden());
+ }
+ }
+
+ private static function moveElementUp($key, array $array)
+ {
+ $swap = null;
+ for ($i=0; $iresources === null ) {
+ if ($this->resources === null) {
return DbAdapterFactory::getResources();
} else {
return $this->resources;
@@ -142,11 +142,16 @@ class GeneralForm extends Form
'value' => $env === 'development'
)
);
- $this->addElement(new Note(array(
- 'name' => 'note_env',
- 'value' => 'Set true to show more detailed errors and disable certain optimizations '
- . 'in order to make debugging easier.'
- )));
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'note_env',
+ 'value' => 'Set true to show more detailed errors '
+ . 'and disable certain optimizations '
+ . 'in order to make debugging easier.'
+ )
+ )
+ );
}
/**
@@ -159,7 +164,7 @@ class GeneralForm extends Form
private function addTimezoneSelection(Zend_Config $cfg)
{
$tzList = array();
- foreach(DateTimeZone::listIdentifiers() as $tz) {
+ foreach (DateTimeZone::listIdentifiers() as $tz) {
$tzList[$tz] = $tz;
}
@@ -173,11 +178,15 @@ class GeneralForm extends Form
'value' => $cfg->get('timezone', date_default_timezone_get())
)
);
- $this->addElement(new Note(array(
- 'name' => 'noteTimezone',
- 'value' => 'Select the timezone to be used as the default. User\'s can set their own timezone if'.
- ' they like to, but this is the timezone to be used as the default setting .'
- )));
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'noteTimezone',
+ 'value' => 'Select the timezone to be used as the default. User\'s can set their own timezone if'
+ . ' they like to, but this is the timezone to be used as the default setting .'
+ )
+ )
+ );
}
/**
@@ -193,13 +202,17 @@ class GeneralForm extends Form
array(
'label' => 'Module folder',
'required' => true,
- 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
+ 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
+ )
+ );
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'noteModuleFolder',
+ 'value' => 'Use this folder to activate modules (must be writable by your webserver)'
+ )
)
);
- $this->addElement(new Note(array(
- 'name' => 'noteModuleFolder',
- 'value' => 'Use this folder to activate modules (must be writable by your webserver)'
- )));
}
/**
@@ -209,7 +222,8 @@ class GeneralForm extends Form
*/
private function addDateFormatSettings(Zend_Config $cfg)
{
- $phpUrl = 'the official PHP documentation';
+ $phpUrl = ''
+ . 'the official PHP documentation';
$this->addElement(
'text',
@@ -220,10 +234,14 @@ class GeneralForm extends Form
'value' => $cfg->get('dateFormat', 'd/m/Y')
)
);
- $this->addElement(new Note(array(
- 'name' => 'noteDateFormat',
- 'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values'
- )));
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'noteDateFormat',
+ 'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values'
+ )
+ )
+ );
$this->addElement(
@@ -235,12 +253,22 @@ class GeneralForm extends Form
'value' => $cfg->get('timeFormat', 'g:i A')
)
);
- $this->addElement(new Note(array(
- 'name' => 'noteTimeFormat',
- 'value' => 'Display times according to this format. See ' . $phpUrl . ' for possible values'
- )));
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'noteTimeFormat',
+ 'value' => 'Display times according to this format. See '
+ . $phpUrl . ' for possible values'
+ )
+ )
+ );
}
+ /**
+ * 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');
@@ -271,8 +299,7 @@ class GeneralForm extends Form
)
);
$backends = array();
- foreach ($this->getResources() as $name => $resource)
- {
+ foreach ($this->getResources() as $name => $resource) {
if ($resource['type'] !== 'db') {
continue;
}
@@ -295,9 +322,11 @@ class GeneralForm extends Form
$txtPreferencesIniPath->addDecorator(new ConditionalHidden());
$txtPreferencesDbResource->addDecorator(new ConditionalHidden());
- $this->enableAutoSubmit(array(
- 'preferences_type'
- ));
+ $this->enableAutoSubmit(
+ array(
+ 'preferences_type'
+ )
+ );
}
/**
@@ -328,6 +357,11 @@ class GeneralForm extends Form
$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) {
@@ -357,5 +391,4 @@ class GeneralForm extends Form
return $cfg;
}
-
-}
\ No newline at end of file
+}
diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php
index 107e75ff2..962f2f152 100644
--- a/application/forms/Config/LoggingForm.php
+++ b/application/forms/Config/LoggingForm.php
@@ -83,6 +83,12 @@ class LoggingForm extends Form
}
+ /**
+ * Return true when logging is enabled according to the request and the configuration
+ *
+ * @param Zend_Config $config The logging section of the config.ini
+ * @return bool
+ */
private function loggingIsEnabled(Zend_Config $config)
{
$loggingRequestParam = $this->getRequest()->getParam('logging_enable', null);
@@ -146,13 +152,15 @@ class LoggingForm extends Form
)
);
- $this->addElement(new Note(
- array(
- 'name' => 'note_logging_app_path',
- 'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write'
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'note_logging_app_path',
+ 'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write'
. 'at this location'
+ )
)
- ));
+ );
$this->addElement(
'checkbox',
@@ -164,12 +172,14 @@ class LoggingForm extends Form
)
);
- $this->addElement(new Note(
- array(
- 'name' => 'note_logging_app_verbose',
- 'value'=> 'Check to write more verbose output to the icinga log file'
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'note_logging_app_verbose',
+ 'value'=> 'Check to write more verbose output to the icinga log file'
+ )
)
- ));
+ );
$this->addElement(
'checkbox',
@@ -180,12 +190,14 @@ class LoggingForm extends Form
'value' => $this->shouldDisplayDebugLog($debug)
)
);
- $this->addElement(new Note(
- array(
- 'name' => 'note_logging_use_debug',
- 'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)'
+ $this->addElement(
+ new Note(
+ array(
+ 'name' => 'note_logging_use_debug',
+ 'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)'
+ )
)
- ));
+ );
$textLoggingDebugPath = new Zend_Form_Element_Text(
@@ -215,5 +227,4 @@ class LoggingForm extends Form
$this->setSubmitLabel('Save changes');
}
-
-}
\ No newline at end of file
+}
diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml
index f0b046499..1e041a914 100644
--- a/application/views/scripts/config/authentication.phtml
+++ b/application/views/scripts/config/authentication.phtml
@@ -1,2 +1,20 @@
+ 'ldap')
+)->getAbsoluteUrl();
+
+$createDbBackend = Url::fromPath(
+ '/config/createAuthenticationBackend',
+ array('type' => 'db')
+)->getAbsoluteUrl();
+
+?>
= $this->tabs->render($this); ?>
+
+
= $this->form ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/authentication/show-configuration.phtml b/application/views/scripts/config/authentication/show-configuration.phtml
new file mode 100644
index 000000000..afc255224
--- /dev/null
+++ b/application/views/scripts/config/authentication/show-configuration.phtml
@@ -0,0 +1,30 @@
+= $this->tabs->render($this); ?>
+
+
+
Saving authentication.ini failed
+
+
+ Your authentication 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 authentication.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/authentication.ini) by yourself, you can open it and
+ insert the config manually:
+
+
\ No newline at end of file
diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php
index 593977d40..d31c235d3 100644
--- a/library/Icinga/Web/Form.php
+++ b/library/Icinga/Web/Form.php
@@ -309,6 +309,7 @@ abstract class Form extends Zend_Form
}
}
+
/**
* Disable CSRF counter measure and remove its field if already added
*
diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
index 7dc54a8fe..e3356d44c 100644
--- a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
+++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
@@ -53,7 +53,7 @@ class ConditionalHidden extends Zend_Form_Decorator_Abstract
*
* @return string The input tag and options XHTML.
*/
- public function render($content ='')
+ public function render($content = '')
{
$attributes = $this->getElement()->getAttribs();
$condition = isset($attributes['condition']) ? $attributes['condition'] : 1;
From 4810a0d47e40a77572ab8dab7e521441b65e8e31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Fri, 16 Aug 2013 16:46:58 +0200
Subject: [PATCH 06/20] Code style and test fixes
refs #3777
---
library/Icinga/Config/IniEditor.php | 130 +++++++++---------
.../forms/Config/GeneralFormTest.php | 17 ++-
2 files changed, 81 insertions(+), 66 deletions(-)
diff --git a/library/Icinga/Config/IniEditor.php b/library/Icinga/Config/IniEditor.php
index 42dd60380..085b1a425 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,15 @@ 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 $value The value
+ * @param $section The section to use
*
- * @return int The line of the array element.
+ * @return 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 +133,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 +146,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 +161,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 +184,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 +197,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)
{
@@ -260,8 +259,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)
{
@@ -271,14 +270,14 @@ class IniEditor
/**
* Update the line $lineNr
*
- * @param int $lineNr The line number of the target line
- * @param string $content The content to replace
+ * @param $lineNr The line number of the target line
+ * @param $toInsert The new line content
*/
private function updateLine($lineNr, $content)
{
$comment = $this->getComment($this->text[$lineNr]);
if (strlen($comment) > 0) {
- $comment = ' ; ' . trim($comment);
+ $comment = " ; " . trim($comment);
}
$this->text[$lineNr] = str_pad($content, 43) . $comment;
}
@@ -286,9 +285,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)
{
@@ -298,14 +297,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)
{
@@ -315,10 +314,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)
{
@@ -328,8 +327,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)
{
@@ -339,14 +339,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) {
@@ -374,15 +374,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;
}
@@ -390,15 +390,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;
}
@@ -407,9 +407,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)
{
@@ -426,13 +426,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) {
@@ -453,7 +454,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()
{
@@ -463,9 +464,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
*/
@@ -478,12 +479,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);
@@ -492,9 +491,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/test/php/application/forms/Config/GeneralFormTest.php b/test/php/application/forms/Config/GeneralFormTest.php
index 8bbfa565e..0ea5deb07 100644
--- a/test/php/application/forms/Config/GeneralFormTest.php
+++ b/test/php/application/forms/Config/GeneralFormTest.php
@@ -87,7 +87,11 @@ class GeneralFormTest extends \Test\Icinga\Web\Form\BaseFormTest
)
)
);
-
+ $form->setResources(
+ array(
+ 'db' => 'db'
+ )
+ );
$form->setConfigDir('/tmp');
$view = new Zend_View();
@@ -117,7 +121,13 @@ class GeneralFormTest extends \Test\Icinga\Web\Form\BaseFormTest
)
);
$form->setConfigDir('/tmp');
+ $form->setResources(
+ array(
+ 'db' => 'db'
+ )
+ );
$form->create();
+
$view = new Zend_View();
$this->assertFalse(
@@ -146,6 +156,11 @@ class GeneralFormTest extends \Test\Icinga\Web\Form\BaseFormTest
)
);
$form->setConfigDir('/tmp');
+ $form->setResources(
+ array(
+ 'db' => 'db'
+ )
+ );
$form->create();
$view = new Zend_View();
From 972bc9853ee9b4b13e21a9537f3afa6d2833bce3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jannis=20Mo=C3=9Fhammer?=
Date: Mon, 19 Aug 2013 18:25:20 +0200
Subject: [PATCH 07/20] Configuration interfaces for logging, authentication
and general configuration
- Added HelpText decorator
- Added Time and DateFormatValidator
- Added tests
refs #3777
---
application/controllers/ConfigController.php | 144 +++++---
.../Config/Authentication/DbBackendForm.php | 10 +-
.../Config/Authentication/LdapBackendForm.php | 31 +-
.../forms/Config/AuthenticationForm.php | 151 +++++++--
application/forms/Config/GeneralForm.php | 79 ++---
application/forms/Config/LoggingForm.php | 136 +++++---
.../views/scripts/config/authentication.phtml | 15 +
.../config/authentication/modify.phtml | 4 +
.../views/scripts/config/logging.phtml | 14 +
.../show-configuration.phtml | 10 +-
library/Icinga/Web/Form.php | 11 +-
.../Web/Form/Decorator/ConditionalHidden.php | 11 +-
.../Icinga/Web/Form/Decorator/HelpText.php | 63 ++++
.../Form/Validator/DateFormatValidator.php | 86 +++++
.../Form/Validator/TimeFormatValidator.php | 85 +++++
.../Form/Validator/WritablePathValidator.php | 72 ++++
.../forms/Command/AcknowledgeFormTest.php | 1 +
.../forms/Config/AuthenticationFormTest.php | 315 ++++++++++++++++++
.../forms/Config/LoggingFormTest.php | 214 ++++++++++++
.../library/Icinga/Web/Form/BaseFormTest.php | 45 ++-
20 files changed, 1276 insertions(+), 221 deletions(-)
create mode 100644 application/views/scripts/config/authentication/modify.phtml
rename application/views/scripts/config/{authentication => }/show-configuration.phtml (57%)
create mode 100644 library/Icinga/Web/Form/Decorator/HelpText.php
create mode 100644 library/Icinga/Web/Form/Validator/DateFormatValidator.php
create mode 100644 library/Icinga/Web/Form/Validator/TimeFormatValidator.php
create mode 100644 library/Icinga/Web/Form/Validator/WritablePathValidator.php
create mode 100644 test/php/application/forms/Config/AuthenticationFormTest.php
create mode 100644 test/php/application/forms/Config/LoggingFormTest.php
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index fb8e63f34..cb4bf6c85 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -31,6 +31,7 @@ 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;
@@ -55,32 +56,32 @@ class ConfigController extends BaseConfigController
return array(
'index' => new Tab(
array(
- "name" => "index",
- "title" => "Application",
- "url" => Url::fromPath("/config")
+ 'name' => 'index',
+ 'title' => 'Application',
+ 'url' => Url::fromPath('/config')
)
),
- "authentication" => new Tab(
+ 'authentication' => new Tab(
array(
- "name" => "auth",
- "title" => "Authentication",
- "url" => Url::fromPath('/config/authentication')
+ 'name' => 'auth',
+ 'title' => 'Authentication',
+ 'url' => Url::fromPath('/config/authentication')
)
),
- "logging" => new Tab(
+ 'logging' => new Tab(
array(
- "name" => "logging",
- "title" => "Logging",
- "url" => Url::fromPath("/config/logging")
+ 'name' => 'logging',
+ 'title' => 'Logging',
+ 'url' => Url::fromPath('/config/logging')
)
),
- "modules" => new Tab(
+ 'modules' => new Tab(
array(
- "name" => "modules",
- "title" => "Modules",
- "url" => Url::fromPath("/config/moduleoverview")
+ 'name' => 'modules',
+ 'title' => 'Modules',
+ 'url' => Url::fromPath('/config/moduleoverview')
)
)
);
@@ -88,7 +89,6 @@ class ConfigController extends BaseConfigController
/**
* Index action, entry point for configuration
- * @TODO: Implement configuration interface (#3777)
*/
public function indexAction()
{
@@ -96,26 +96,30 @@ class ConfigController extends BaseConfigController
$form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) {
- $cfg = IcingaConfig::app()->getConfigFile();
- $writer = new PreservingIniWriter(
- array(
- 'config' => $form->getConfig(),
- 'filename' => $cfg
- )
- );
- $writer->write();
+ 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 false;
+ }
+ $this->redirectNow('/config/logging');
+ }
$this->view->form = $form;
}
@@ -151,24 +155,6 @@ class ConfigController extends BaseConfigController
$this->redirectNow('config/moduleoverview?_render=body');
}
- private function writeAuthenticationFile(array $config)
- {
- $cfg = new Zend_Config($config);
- $writer = new Zend_Config_Writer_Ini(
- array(
- 'config' => $cfg,
- 'filename' => IcingaConfig::app('authentication')->getConfigFile()
- )
- );
- try {
- $writer->write();
- } catch (Exception $exc) {
- $this->view->exceptionMessage = $exc->getMessage();
- $this->view->iniConfigurationString = $writer->render();
- $this->render('authentication/show-configuration');
- }
- }
-
/**
* Action for creating a new authentication backend
*
@@ -181,10 +167,16 @@ class ConfigController extends BaseConfigController
$form->setRequest($this->_request);
if ($form->isSubmittedAndValid()) {
- $this->writeAuthenticationFile($form->getConfig());
+ $modifiedConfig = $form->getConfig();
+ if (empty($modifiedConfig)) {
+ $form->addError('You need at least one authentication backend.');
+ } else if (!$this->writeAuthenticationFile($modifiedConfig)) {
+ return;
+ } else {
+ $this->redirectNow('/config/authentication');
+ }
}
$this->view->form = $form;
-
}
/**
@@ -201,16 +193,72 @@ class ConfigController extends BaseConfigController
$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->writeAuthenticationFile($backendCfg);
}
$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 supllied writer or PreservingIniWriter if none is set
+ *
+ * @param array|Zend_Config $config The configuration to write
+ * @param string $file The filename to write to (without .ini)
+ * @param Zend_Config_Writer $writer An optional writer to use for persisting changes
+ *
+ * @return bool True when persisting succeeded, otherwise false
+ */
+ private function writeConfigFile($config, $file, $writer = null)
+ {
+ if (is_array($config)) {
+ $config = new Zend_Config($config);
+ }
+ if ($writer === null) {
+ $writer = new PreservingIniWriter(
+ array(
+ 'config' => $config,
+ 'filename' => IcingaConfig::app($file)->getConfigFile()
+ )
+ );
+ }
+ try {
+ $writer->write();
+ return true;
+ } catch (Exception $exc) {
+ $this->view->exceptionMessage = $exc->getMessage();
+ $this->view->iniConfigurationString = $writer->render();
+ $this->view->file = $file;
+ $this->render('show-configuration');
+ return false;
+ }
+ }
}
// @codingStandardsIgnoreEnd
diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php
index de2b0464f..b331bfa1b 100644
--- a/application/forms/Config/Authentication/DbBackendForm.php
+++ b/application/forms/Config/Authentication/DbBackendForm.php
@@ -76,10 +76,11 @@ class DbBackendForm extends BaseBackendForm
'text',
'backend_' . $name . '_name',
array(
- 'required' => true,
- 'allowEmpty' => false,
- 'label' => 'Backend name',
- 'value' => $this->getBackendName()
+ 'required' => true,
+ 'allowEmpty'=> false,
+ 'label' => 'Backend name',
+ 'helptext' => 'The name of this authentication provider',
+ 'value' => $this->getBackendName()
)
);
@@ -90,6 +91,7 @@ class DbBackendForm extends BaseBackendForm
'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()
)
diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php
index ea92c756b..51d9bbb51 100644
--- a/application/forms/Config/Authentication/LdapBackendForm.php
+++ b/application/forms/Config/Authentication/LdapBackendForm.php
@@ -56,10 +56,11 @@ class LdapBackendForm extends BaseBackendForm
'text',
'backend_'.$name.'_name',
array(
- 'required' => true,
- 'allowEmpty' => false,
- 'label' => 'Backend name',
- 'value' => $this->getBackendName()
+ 'required' => true,
+ 'allowEmpty'=> false,
+ 'label' => 'Backend name',
+ 'helptext' => 'The name of this authentication backend',
+ 'value' => $this->getBackendName()
)
);
@@ -67,10 +68,11 @@ class LdapBackendForm extends BaseBackendForm
'text',
'backend_' . $name . '_hostname',
array(
- 'label' => 'LDAP server host',
+ 'label' => 'LDAP server host',
'allowEmpty' => false,
- 'value' => $backend->get('hostname', 'localhost'),
- 'required' => true
+ 'value' => $backend->get('hostname', 'localhost'),
+ 'helptext' => 'The hostname or address of the LDAP server to use for authentication',
+ 'required' => true
)
);
@@ -79,7 +81,8 @@ class LdapBackendForm extends BaseBackendForm
'backend_' . $name . '_root_dn',
array(
'label' => 'LDAP root dn',
- 'value' => $backend->get('hostname', 'ou=people,dc=icinga,dc=org'),
+ 'value' => $backend->get('root_dn', 'ou=people,dc=icinga,dc=org'),
+ 'helptext' => 'The path where users can be found on the ldap server',
'required' => true
)
);
@@ -90,6 +93,7 @@ class LdapBackendForm extends BaseBackendForm
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
)
);
@@ -101,26 +105,29 @@ class LdapBackendForm extends BaseBackendForm
'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 . '_bind_user_class',
+ '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 . '_bind_user_name_attribute',
+ '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
)
);
@@ -147,8 +154,8 @@ class LdapBackendForm extends BaseBackendForm
'root_dn' => $this->getValue($prefix . 'root_dn'),
'bind_dn' => $this->getValue($prefix . 'bind_dn'),
'bind_pw' => $this->getValue($prefix . 'bind_pw'),
- 'bind_user_class' => $this->getValue($prefix . 'bind_user_class'),
- 'bind_user_name_attribute' => $this->getValue($prefix . 'bind_user_name_attribute')
+ '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
index 135ddefdc..93ad7d05d 100644
--- a/application/forms/Config/AuthenticationForm.php
+++ b/application/forms/Config/AuthenticationForm.php
@@ -32,17 +32,17 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga;
use \Icinga\Application\Logger;
use \Icinga\Application\DbAdapterFactory;
-use \Icinga\Form\Config\Authentication\DbBackendForm;
-use \Icinga\Form\Config\Authentication\LdapBackendForm;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note;
use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Config;
-use \Zend_Form_Element_Text;
-use \Zend_Form_Element_Select;
-use \Zend_Form_Element_Button;
+/**
+ * Form for modifying the authentication provider and order.
+ *
+ * This is a composite form from one or more forms under the Authentication folder
+ */
class AuthenticationForm extends Form
{
/**
@@ -59,7 +59,11 @@ class AuthenticationForm extends Form
*/
private $resources = null;
-
+ /**
+ * An array containing all provider subforms currently displayed
+ *
+ * @var array
+ */
private $backendForms = array();
@@ -84,7 +88,15 @@ class AuthenticationForm extends Form
$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(
@@ -101,6 +113,19 @@ class AuthenticationForm extends Form
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')));
@@ -117,49 +142,56 @@ class AuthenticationForm extends Form
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 $name => $element) {
- $this->addElement($element, $name);
+ 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))
+ 'up' => join(',', self::moveElementUp($name, $order)),
+ 'down' => join(',', self::moveElementDown($name, $order))
);
- if ($priorities["up"] != join(',', $order)) {
+ if ($priorities['up'] != join(',', $order)) {
$this->addElement(
'button',
'priority' . $name . '_up',
array(
'name' => 'priority',
'label' => 'Move up in authentication order',
- 'value' => $priorities["up"],
+ 'value' => $priorities['up'],
'type' => 'submit'
)
);
$formEls[] = 'priority' . $name . '_up';
}
- if ($priorities["down"] != join(',', $order)) {
+ if ($priorities['down'] != join(',', $order)) {
$this->addElement(
'button',
'priority' . $name . '_down',
array(
'name' => 'priority',
'label' => 'Move down in authentication order',
- 'value' => $priorities["down"],
+ 'value' => $priorities['down'],
'type' => 'submit'
)
);
@@ -169,7 +201,14 @@ class AuthenticationForm extends Form
return $formEls;
}
-
+ /**
+ * Overwrite for Zend_Form::populate in order to preserve the modified priority of the backends
+ *
+ * @param array $values The values to populate the form with
+ *
+ * @return void|\Zend_Form
+ * @see Zend_Form::populate
+ */
public function populate(array $values)
{
$last_priority = $this->getValue('current_priority');
@@ -178,7 +217,13 @@ class AuthenticationForm extends Form
}
- private function getAuthenticationOrder ()
+ /**
+ * Return an array containing all authentication providers in the order they should be used
+ *
+ * @return array An array containing the identifiers (section names) of the authentication backend in
+ * the order they should be persisted
+ */
+ private function getAuthenticationOrder()
{
$request = $this->getRequest();
$order = $request->getParam(
@@ -195,15 +240,26 @@ class AuthenticationForm extends Form
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',
@@ -214,8 +270,11 @@ class AuthenticationForm extends Form
);
}
-
-
+ /**
+ * Create the authentication provider configuration form
+ *
+ * @see IcingaForm::create()
+ */
public function create()
{
$order = $this->getAuthenticationOrder();
@@ -246,6 +305,11 @@ class AuthenticationForm extends Form
$this->setSubmitLabel('Save changes');
}
+ /**
+ * Return the configuration state defined by this form
+ *
+ * @return array
+ */
public function getConfig()
{
$result = array();
@@ -258,6 +322,11 @@ class AuthenticationForm extends Form
return $result;
}
+ /**
+ * Enable the "ConditionalHidden" Decorator for all elements in this form
+ *
+ * @see ConditionalHidden
+ */
private function enableConditionalDecorator()
{
foreach ($this->getElements() as $element) {
@@ -265,6 +334,21 @@ class AuthenticationForm extends Form
}
}
+ /**
+ * Static helper for moving an element in an array one slot up, if possible
+ *
+ * Example:
+ *
+ *
+ *
+ * @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;
@@ -280,6 +364,21 @@ class AuthenticationForm extends Form
return $array;
}
+ /**
+ * Static helper for moving an element in an array one slot up, if possible
+ *
+ * Example:
+ *
+ *
+ *
+ * @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;
diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php
index 404c925d3..be2f8c358 100644
--- a/application/forms/Config/GeneralForm.php
+++ b/application/forms/Config/GeneralForm.php
@@ -32,8 +32,10 @@ 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;
-use \Icinga\Web\Form\Element\Note;
use \DateTimeZone;
use \Zend_Config;
@@ -138,20 +140,14 @@ class GeneralForm extends Form
array(
'label' => 'Development mode',
'required' => true,
+ 'helptesxt' => 'Set true to show more detailed errors '
+ . 'and disable certain optimizations '
+ . 'in order to make debugging easier.',
'tooltip' => 'More verbose output',
'value' => $env === 'development'
)
);
- $this->addElement(
- new Note(
- array(
- 'name' => 'note_env',
- 'value' => 'Set true to show more detailed errors '
- . 'and disable certain optimizations '
- . 'in order to make debugging easier.'
- )
- )
- );
+
}
/**
@@ -167,6 +163,8 @@ class GeneralForm extends Form
foreach (DateTimeZone::listIdentifiers() as $tz) {
$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',
@@ -175,18 +173,10 @@ class GeneralForm extends Form
'label' => 'Default application timezone',
'required' => true,
'multiOptions' => $tzList,
+ 'helptext' => $helptext,
'value' => $cfg->get('timezone', date_default_timezone_get())
)
);
- $this->addElement(
- new Note(
- array(
- 'name' => 'noteTimezone',
- 'value' => 'Select the timezone to be used as the default. User\'s can set their own timezone if'
- . ' they like to, but this is the timezone to be used as the default setting .'
- )
- )
- );
}
/**
@@ -202,17 +192,10 @@ class GeneralForm extends Form
array(
'label' => 'Module folder',
'required' => true,
+ 'helptext' => 'Use this folder to activate modules (must be writable by your webserver)',
'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules')
)
);
- $this->addElement(
- new Note(
- array(
- 'name' => 'noteModuleFolder',
- 'value' => 'Use this folder to activate modules (must be writable by your webserver)'
- )
- )
- );
}
/**
@@ -225,43 +208,29 @@ class GeneralForm extends Form
$phpUrl = ''
. 'the official PHP documentation';
- $this->addElement(
- 'text',
- 'date_format',
+ $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(
- new Note(
- array(
- 'name' => 'noteDateFormat',
- 'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values'
- )
+ 'value' => $cfg->get('dateFormat', 'd/m/Y')
)
);
+ $this->addElement($txtDefaultDateFormat);
+ $txtDefaultDateFormat->addValidator(new DateFormatValidator());
-
- $this->addElement(
- 'text',
- 'time_format',
+ $txtDefaultTimeFormat = new Zend_Form_Element_Text(
array(
+ 'name' => 'time_format',
'label' => 'Time format',
'required' => true,
- 'value' => $cfg->get('timeFormat', 'g:i A')
- )
- );
- $this->addElement(
- new Note(
- array(
- 'name' => 'noteTimeFormat',
- 'value' => 'Display times according to this format. See '
- . $phpUrl . ' for possible values'
- )
+ '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);
}
/**
@@ -316,7 +285,7 @@ class GeneralForm extends Form
'multiOptions' => $backends
)
);
-
+ $txtPreferencesIniPath->addValidator(new WritablePathValidator());
$this->addElement($txtPreferencesIniPath);
$this->addElement($txtPreferencesDbResource);
diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php
index 962f2f152..ca302b4e5 100644
--- a/application/forms/Config/LoggingForm.php
+++ b/application/forms/Config/LoggingForm.php
@@ -32,6 +32,7 @@ use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Icinga;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note;
+use \Icinga\Web\Form\Validator\WritablePathValidator;
use \Icinga\Web\Form\Decorator\ConditionalHidden;
use \Zend_Config;
use \Zend_Form_Element_Text;
@@ -49,6 +50,13 @@ class LoggingForm extends Form
*/
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
*
@@ -61,6 +69,32 @@ class LoggingForm extends Form
$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
*
@@ -74,7 +108,7 @@ class LoggingForm extends Form
*/
private function shouldDisplayDebugLog(Zend_Config $config)
{
- $debugParam = $this->getRequest()->getParam('logging_use_debug', null);
+ $debugParam = $this->getRequest()->getParam('logging_debug_enable', null);
if ($debugParam !== null) {
return intval($debugParam) === 1;
} else {
@@ -101,6 +135,8 @@ class LoggingForm extends Form
}
/**
+ * Create this logging configuration form
+ *
* @see Form::create()
*/
public function create()
@@ -127,7 +163,7 @@ class LoggingForm extends Form
'value' => $this->loggingIsEnabled($logging)
)
);
- if (!$this->loggingIsEnabled($debug)) {
+ if (!$this->loggingIsEnabled($logging)) {
$this->addElement(
new Note(
array(
@@ -142,25 +178,19 @@ class LoggingForm extends Form
return;
}
- $this->addElement(
- 'text',
- 'logging_app_path',
+
+ $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')
)
);
-
- $this->addElement(
- new Note(
- array(
- 'name' => 'note_logging_app_path',
- 'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write'
- . 'at this location'
- )
- )
- );
+ $txtLogPath->addValidator(new WritablePathValidator());
+ $this->addElement($txtLogPath);
$this->addElement(
'checkbox',
@@ -168,63 +198,73 @@ class LoggingForm extends Form
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(
- new Note(
- array(
- 'name' => 'note_logging_app_verbose',
- 'value'=> 'Check to write more verbose output to the icinga log file'
- )
- )
- );
-
$this->addElement(
'checkbox',
- 'logging_use_debug',
+ '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)
)
);
- $this->addElement(
- new Note(
- array(
- 'name' => 'note_logging_use_debug',
- 'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)'
- )
- )
- );
-
$textLoggingDebugPath = new Zend_Form_Element_Text(
array(
- 'name' => 'logging_debug_path',
+ 'name' => 'logging_debug_target',
'label' => 'Debug log path',
- 'required' => true,
+ 'required' => $this->shouldDisplayDebugLog($debug),
'condition' => $this->shouldDisplayDebugLog($debug),
- 'value' => $debug->get('target')
- )
- );
- $loggingPathNote = new Note(
- array(
- 'name' => 'note_logging_debug_path',
- 'value' => 'Set the path to the debug log',
- '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);
- $this->addElement($loggingPathNote);
-
$textLoggingDebugPath->addDecorator($decorator);
- $loggingPathNote->addDecorator($decorator);
- $this->enableAutoSubmit(array('logging_use_debug', 'logging_enable'));
+
+ $this->enableAutoSubmit(array('logging_debug_enable', 'logging_enable'));
$this->setSubmitLabel('Save changes');
}
+
+ /**
+ * Return a Zend_Config object containing the state defined in this form
+ *
+ * @return Zend_Config The config defined in this form
+ */
+ public function getConfig()
+ {
+ if ($this->config === null) {
+ $this->config = new Zend_Config(array());
+ }
+ if ($this->config->logging === null) {
+ $this->config->logging = new Zend_Config(array());
+ }
+ if ($this->config->logging->debug === null) {
+ $this->config->logging->debug = new Zend_Config(array());
+
+ }
+
+ $values = $this->getValues();
+ $cfg = $this->config->toArray();
+
+ $cfg['logging']['enable'] = intval($values['logging_enable']);
+ $cfg['logging']['type'] = 'stream';
+ $cfg['logging']['verbose'] = $values['logging_app_verbose'];
+ $cfg['logging']['target'] = $values['logging_app_target'];
+
+ $cfg['logging']['debug']['enable'] = intval($values['logging_debug_enable']);
+ $cfg['logging']['debug']['type'] = 'stream';
+ $cfg['logging']['debug']['target'] = $values['logging_debug_target'];
+ return new Zend_Config($cfg);
+ }
}
diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml
index 1e041a914..8e4f8e864 100644
--- a/application/views/scripts/config/authentication.phtml
+++ b/application/views/scripts/config/authentication.phtml
@@ -13,6 +13,21 @@ $createDbBackend = Url::fromPath(
?>
= $this->tabs->render($this); ?>
+form->getErrorMessages();
+ if (!empty($errors)):
+?>
+
+
There are errors in your configuration
+
+
+
+
= $error ?>
+
+
+
+
+
Create a new LDAP authentication backend Create a new DB authentication backend
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/logging.phtml b/application/views/scripts/config/logging.phtml
index aa8ca9f49..b09c06fb9 100644
--- a/application/views/scripts/config/logging.phtml
+++ b/application/views/scripts/config/logging.phtml
@@ -1,3 +1,17 @@
= $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/authentication/show-configuration.phtml b/application/views/scripts/config/show-configuration.phtml
similarity index 57%
rename from application/views/scripts/config/authentication/show-configuration.phtml
rename to application/views/scripts/config/show-configuration.phtml
index afc255224..87a86b51f 100644
--- a/application/views/scripts/config/authentication/show-configuration.phtml
+++ b/application/views/scripts/config/show-configuration.phtml
@@ -1,14 +1,14 @@
= $this->tabs->render($this); ?>
- Your authentication configuration couldn't be stored (error: "= $this->exceptionMessage; ?>"). This could have one or more
- of the following reasons:
+ 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 authentication.ini file
+
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
@@ -17,7 +17,7 @@
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/authentication.ini) by yourself, you can open it and
+ In case you can access the configuration file (config/= $this->escape($this->file); ?>.ini) by yourself, you can open it and
insert the config manually:
diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php
index d31c235d3..14209a7c9 100644
--- a/library/Icinga/Web/Form.php
+++ b/library/Icinga/Web/Form.php
@@ -25,7 +25,7 @@
namespace Icinga\Web;
-use \Icinga\Web\Form\Decorator\ConditionalHidden;
+use \Icinga\Web\Form\Decorator\HelpText;
use \Zend_Controller_Request_Abstract;
use \Zend_Form_Element_Submit;
use \Zend_Form_Element_Reset;
@@ -197,7 +197,7 @@ abstract class Form extends Zend_Form
if (!$this->getAction() && $this->getRequest()) {
$this->setAction($this->getRequest()->getRequestUri());
}
-
+ $this->enableAdditionalDecorators();
$this->created = true;
}
}
@@ -387,6 +387,13 @@ abstract class Form extends Zend_Form
return $token === hash('sha256', $this->getSessionId() . $seed);
}
+ public function enableAdditionalDecorators()
+ {
+ foreach ($this->getElements() as $element) {
+ $element->addDecorator(new HelpText());
+ }
+ }
+
/**
* Generate a new (seed, token) pair
*
diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
index e3356d44c..d39b2f157 100644
--- a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
+++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php
@@ -26,6 +26,9 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
+namespace Icinga\Web\Form\Decorator;
+
+use \Zend_Form_Decorator_Abstract;
/**
* Decorator to hide elements using a >noscript< tag instead of
@@ -35,15 +38,11 @@
* (who can then automatically refresh their pages) but show them in
* case JavaScript is disabled
*/
-
-namespace Icinga\Web\Form\Decorator;
-
-use \Zend_Form_Decorator_Abstract;
-
class ConditionalHidden extends Zend_Form_Decorator_Abstract
{
/**
- * Generates a html number input
+ * Generate a field that will be wrapped in