diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index b2e3ea55b..93b655090 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -31,6 +31,7 @@ use \Icinga\Web\Controller\BaseConfigController; use \Icinga\Web\Widget\Tab; use \Icinga\Web\Url; +use \Icinga\Web\Widget\Tabs; use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder; use \Icinga\Application\Icinga; use \Icinga\Application\Config as IcingaConfig; @@ -39,6 +40,7 @@ use \Icinga\Form\Config\GeneralForm; use \Icinga\Form\Config\Authentication\ReorderForm; use \Icinga\Form\Config\Authentication\LdapBackendForm; use \Icinga\Form\Config\Authentication\DbBackendForm; +use \Icinga\Form\Config\Resource\EditResourceForm; use \Icinga\Form\Config\LoggingForm; use \Icinga\Form\Config\ConfirmRemovalForm; use \Icinga\Config\PreservingIniWriter; @@ -240,7 +242,11 @@ class ConfigController extends BaseConfigController if ($form->isSubmittedAndValid()) { $backendCfg = IcingaConfig::app('authentication')->toArray(); + foreach ($backendCfg as $backendName => $settings) { + unset($backendCfg[$backendName]['name']); + } foreach ($form->getConfig() as $backendName => $settings) { + unset($settings->{'name'}); if (isset($backendCfg[$backendName])) { $this->view->errorMessage = 'Backend name already exists'; $this->view->form = $form; @@ -308,6 +314,7 @@ class ConfigController extends BaseConfigController if ($backendName != $authBackend) { unset($backendCfg[$authBackend]); } + unset($settings['name']); } if ($this->writeAuthenticationFile($backendCfg)) { // redirect to overview with success message @@ -356,45 +363,100 @@ class ConfigController extends BaseConfigController } $this->view->form = $form; - $this->view->name = $authBackend; $this->render('authentication/remove'); } public function resourceAction($showOnly = false) { - $this->view->resources = ResourceFactory::getResourceConfigs()->toArray(); - $this->view->createActions = array(); + + $this->view->resources = IcingaConfig::app('resources', true)->toArray(); $this->render('resource'); } public function createresourceAction() { $this->view->resourceTypes = $this->resourceTypes; + $resources = IcingaConfig::app('resources', true); + $form = new EditResourceForm(); + $form->setRequest($this->_request); + if ($form->isSubmittedAndValid()) { + $name = $form->getName(); + if (isset($resources->{$name})) { + $this->view->errorMessage = 'Resource name "' . $name .'" already in use.'; + $this->view->form = $form; + $this->render('resource/create'); + return; + } + $resources->{$name} = $form->getConfig(); + if ($this->writeConfigFile($resources, 'resources')) { + $this->view->successMessage = 'Resource "' . $name . '" created.'; + $this->resourceAction(true); + } + return; + } + $this->view->form = $form; $this->render('resource/create'); } public function editresourceAction() { - $resources = ResourceFactory::getResourceConfigs()->toArray(); - $name = $resources[$this->getParam('resource')]; - if (!isset($resources[$name])) { + $resources = ResourceFactory::getResourceConfigs(); + $name = $this->getParam('resource'); + if ($resources->get($name) === null) { $this->view->errorMessage = 'Can\'t edit: Unknown Resource Provided'; $this->resourceAction(true); return; } + $form = new EditResourceForm(); + if ($this->_request->isPost() === false) { + $form->setOldName($name); + $form->setName($name); + } + $form->setRequest($this->_request); + $form->setResource($resources->get($name)); + if ($form->isSubmittedAndValid()) { + $oldName = $form->getOldName(); + $name = $form->getName(); + if ($oldName !== $name) { + unset($resources->{$oldName}); + } + $resources->{$name} = $form->getConfig(); + if ($this->writeConfigFile($resources, 'resources')) { + $this->view->successMessage = 'Resource "' . $name . '" created.'; + $this->resourceAction(true); + } + return; + } + $this->view->form = $form; + $this->view->name = $name; $this->render('resource/modify'); } public function removeresourceAction() { $resources = ResourceFactory::getResourceConfigs()->toArray(); - $name = $resources[$this->getParam('resource')]; + $name = $this->getParam('resource'); if (!isset($resources[$name])) { - $this->view->errorMessage = 'Can\'t remove: Unknown Resource Provided'; + $this->view->errorMessage = 'Can\'t remove: Unknown resource provided'; $this->resourceAction(true); return; } + + $form = new ConfirmRemovalForm(); + $form->setRequest($this->getRequest()); + $form->setRemoveTarget('resource', $name); + if ($form->isSubmittedAndValid()) { + unset($resources[$name]); + if ($this->writeConfigFile($resources, 'resources')) { + $this->view->successMessage = 'Resource "' . $name . '" removed'; + $this->resourceAction(true); + } + return; + } + + $this->view->name = $name; + $this->view->form = $form; $this->render('resource/remove'); } diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php index 5a48b9d90..8d716f170 100644 --- a/application/forms/Config/Authentication/LdapBackendForm.php +++ b/application/forms/Config/Authentication/LdapBackendForm.php @@ -130,12 +130,6 @@ class LdapBackendForm extends BaseBackendForm 'resource' => $this->getValue($prefix . 'resource'), 'user_class' => $this->getValue($prefix . 'user_class'), 'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute') - /* - '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'), - */ ); return array( $section => $cfg diff --git a/application/forms/Config/Resource/CreateResourceForm.php b/application/forms/Config/Resource/CreateResourceForm.php new file mode 100644 index 000000000..43e5b2e63 --- /dev/null +++ b/application/forms/Config/Resource/CreateResourceForm.php @@ -0,0 +1,12 @@ + - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Form\Config\Backend; - -use \Zend_Config; -use \Icinga\Web\Form; -use \Icinga\Application\Icinga; -use Icinga\Data\ResourceFactory; - -/** - * Form for modifying a monitoring backend - */ -class EditResourceForm extends Form -{ - /** - * The currently edited resource. - * - * @var Zend_Config - */ - private $resource; - - private $name; - - private function addDbForm() - { - - } - - private function addStatusdatForm() - { - $this->addElement( - 'text', - 'backend_statusdat_statusfile', - array ( - 'label' => 'Status.dat File', - 'value' => $this->backend->status_file, - 'required' => true, - 'helptext' => 'Location of your icinga status.dat file' - ) - ); - $this->addElement( - 'text', - 'backend_statusdat_objectfile', - array ( - 'label' => 'Objects.cache File', - 'value' => $this->backend->status_file, - 'required' => true, - 'helptext' => 'Location of your icinga objects.cache file' - ) - ); - } - - private function addLivestatusForm() - { - $this->addElement( - 'text', - 'backend_livestatus_socket', - array( - 'label' => 'Livestatus Socket Location', - 'required' => true, - 'helptext' => 'The path to your livestatus socket used for querying monitoring data', - 'value' => $this->backend->socket, - ) - ); - } - - private function addLdapForm() - { - $this->addElement( - 'text', - 'resource_' . $this->name . '_hostname', - array( - 'label' => 'LDAP Server Host', - 'allowEmpty' => false, - 'value' => $this->resource->get('hostname', 'localhost'), - 'helptext' => 'The hostname or address of the LDAP server to use for authentication', - 'required' => true - ) - ); - - $this->addElement( - 'text', - 'resource_' . $this->name . '_root_dn', - array( - 'label' => 'LDAP Root DN', - 'value' => $this->resource->get('root_dn', 'ou=people,dc=icinga,dc=org'), - 'helptext' => 'The path where users can be found on the ldap server', - 'required' => true - ) - ); - - $this->addElement( - 'text', - 'resource_' . $this->name . '_bind_dn', - array( - 'label' => 'LDAP Bind DN', - 'value' => $this->resource->get('bind_dn', 'cn=admin,cn=config'), - 'helptext' => 'The user dn to use for querying the ldap server', - 'required' => true - ) - ); - - $this->addElement( - 'password', - 'resource_' . $this->name . '_bind_pw', - array( - 'label' => 'LDAP Bind Password', - 'renderPassword' => true, - 'value' => $this->resource->get('bind_pw', 'admin'), - 'helptext' => 'The password to use for querying the ldap server', - 'required' => true - ) - ); - } - - /** - * Add a select box for choosing the type to use for this backend - */ - private function addTypeSelectionBox() - { - $this->addElement( - 'select', - 'resource_type', - array( - 'label' => 'Resource Type', - 'value' => $this->resource->type, - 'required' => true, - 'helptext' => 'Choose the type of resource you want to create.', - 'multiOptions' => array( - 'db' => 'SQL Database', - 'ldap' => 'Ldap', - 'statusdat' => 'Status.dat', - 'livestatus' => 'Livestatus' - ) - ) - ); - $this->enableAutoSubmit(array('resource_type')); - } - - public function create() - { - $this->addTypeSelectionBox(); - switch ($this->getRequest()->getParam('resource_type', $this->resource->type)) { - case 'db': - break; - case 'statusdat': - break; - case 'livestatus': - break; - case 'ldap': - break; - } - $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); - } -} diff --git a/application/forms/Config/Resource/EditResourceForm.php b/application/forms/Config/Resource/EditResourceForm.php new file mode 100644 index 000000000..800720097 --- /dev/null +++ b/application/forms/Config/Resource/EditResourceForm.php @@ -0,0 +1,457 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Form\Config\Resource; + +use Icinga\Exception\ProgrammingError; +use Icinga\Protocol\Ldap\Exception; +use \Zend_Config; +use \Icinga\Web\Form; +use \Icinga\Web\Form\Decorator\HelpText; +use \Icinga\Application\Logger; +use \Icinga\Application\Icinga; +use Icinga\Data\ResourceFactory; + +/** + * Form for modifying a monitoring backend + */ +class EditResourceForm extends Form +{ + /** + * The currently edited resource. + * + * @var Zend_Config + */ + private $resource; + + /** + * @var string + */ + private $name = ''; + + /** + * @var string + */ + private $oldName = ''; + + /** + * Return the current resource name. + * + * @param string $name + * + * @return void|\Zend_Form + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return null|string + */ + public function getName() + { + return $this->getValue('resource_all_name'); + } + + /** + * Set the original name of the resource. This value is persisted using + * a hidden field. + * + * @param $name + */ + public function setOldName($name) + { + $this->oldName = $name; + } + + /** + * Get the resource name that was initially set. + */ + public function getOldName() + { + return $this->getValue('resource_all_name_old'); + } + + private function addDbForm() + { + $this->addElement( + 'select', + 'resource_db_db', + array( + 'label' => 'Database Type', + 'value' => $this->getResource()->get('db', 'mysql'), + 'required' => true, + 'helptext' => 'The type of SQL database you want to create.', + 'multiOptions' => array( + 'mysql' => 'MySQL', + 'pgsql' => 'PostgreSQL' + //'oracle' => 'Oracle' + ) + ) + ); + + $this->addElement( + 'text', + 'resource_db_host', + array ( + 'label' => 'Host', + 'value' => $this->getResource()->get('host', 'localhost'), + 'required' => true, + 'helptext' => 'The hostname of the database.' + ) + ); + + $this->addElement( + 'text', + 'resource_db_port', + array( + 'label' => 'Port', + 'value' => $this->getResource()->get('port', 3306), + 'required' => true, + 'validators' => array( + array('regex', false, '/^[0-9]+$/') + ), + 'helptext' => 'The port number to use.' + ) + ); + + $this->addElement( + 'text', + 'resource_db_username', + array ( + 'label' => 'Username', + 'value' => $this->getResource()->get('username', ''), + 'required' => true, + 'helptext' => 'The user name to use for authentication.' + ) + ); + + $this->addElement( + 'password', + 'resource_db_password', + array( + 'label' => 'Password', + 'renderPassword' => true, + 'value' => $this->getResource()->get('password', ''), + 'helptext' => 'The password to use for authentication', + 'required' => true + ) + ); + } + + private function addStatusdatForm() + { + $this->addElement( + 'text', + 'resource_statusdat_status_file', + array( + 'label' => 'Status.dat File', + 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/status.dat'), + 'required' => true, + 'helptext' => 'Location of your icinga status.dat file' + ) + ); + $this->addElement( + 'text', + 'resource_statusdat_object_file', + array( + 'label' => 'Objects.cache File', + 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/objects.cache'), + 'required' => true, + 'helptext' => 'Location of your icinga objects.cache file' + ) + ); + } + + private function addLivestatusForm() + { + $this->addElement( + 'text', + 'resource_livestatus_socket', + array( + 'label' => 'Livestatus Socket Location', + 'required' => true, + 'helptext' => 'The path to your livestatus socket used for querying monitoring data', + 'value' => $this->getResource()->socket, + ) + ); + } + + private function addLdapForm() + { + $this->addElement( + 'text', + 'resource_ldap_hostname', + array( + 'label' => 'LDAP Server Host', + 'allowEmpty' => false, + 'value' => $this->getResource()->get('hostname', 'localhost'), + 'helptext' => 'The hostname or address of the LDAP server to use for authentication', + 'required' => true + ) + ); + + $this->addElement( + 'text', + 'resource_ldap_root_dn', + array( + 'label' => 'LDAP Root DN', + 'value' => $this->getResource()->get('root_dn', 'ou=people,dc=icinga,dc=org'), + 'helptext' => 'The path where users can be found on the ldap server', + 'required' => true + ) + ); + + $this->addElement( + 'text', + 'resource_ldap_bind_dn', + array( + 'label' => 'LDAP Bind DN', + 'value' => $this->getResource()->get('bind_dn', 'cn=admin,cn=config'), + 'helptext' => 'The user dn to use for querying the ldap server', + 'required' => true + ) + ); + + $this->addElement( + 'password', + 'resource_ldap_bind_pw', + array( + 'label' => 'LDAP Bind Password', + 'renderPassword' => true, + 'value' => $this->getResource()->get('bind_pw', ''), + 'helptext' => 'The password to use for querying the ldap server', + 'required' => true + ) + ); + } + + /** + * Set the resource configuration to edit. + * + * @param Zend_Config $resource + */ + public function setResource(Zend_Config $resource) + { + $this->resource = $resource; + } + + /** + * Get the current resource configuration. + * + * @return Zend_Config + */ + public function getResource() + { + if (!isset($this->resource)) { + // Init empty resource + $this->resource = new Zend_Config( + array('type' => 'db') + ); + } + return $this->resource; + } + + /** + * Add a field to change the resource name and one hidden field + * to save the previous resource name. + */ + private function addNameFields() + { + $this->addElement( + 'text', + 'resource_all_name', + array( + 'label' => 'Resource Name', + 'value' => $this->name, + 'helptext' => 'The unique name of this resource', + 'required' => true + ) + ); + $this->addElement( + 'hidden', + 'resource_all_name_old', + array( + 'value' => $this->oldName + ) + ); + } + + /** + * Add checkbox at the beginning of the form which allows to skip logic connection validation + */ + private function addForceCreationCheckbox() + { + $checkbox = new \Zend_Form_Element_Checkbox( + array( + 'name' => 'backend_force_creation', + 'label' => 'Force Changes', + 'helptext' => 'Check this box to enforce changes without connectivity validation', + 'order' => 0 + ) + ); + $checkbox->addDecorator(new HelpText()); + $this->addElement($checkbox); + } + + /** + * Add a select box for choosing the type to use for this backend + */ + private function addTypeSelectionBox() + { + $this->addElement( + 'select', + 'resource_type', + array( + 'label' => 'Resource Type', + 'value' => $this->getResource()->type, + 'required' => true, + 'helptext' => 'The type of resource.', + 'multiOptions' => array( + 'db' => 'SQL Database', + 'ldap' => 'Ldap', + 'statusdat' => 'Status.dat', + 'livestatus' => 'Livestatus' + ) + ) + ); + $this->enableAutoSubmit(array('resource_type')); + } + + /** + * Validate this form with the Zend validation mechanism and perform a validation of the connection. + * + * If validation fails, the 'backend_force_creation' checkbox is prepended to the form to allow users to + * skip the logic connection validation. + * + * @param array $data The form input to validate + * + * @return bool True when validation succeeded, false if not + */ + public function isValid($data) + { + if (!parent::isValid($data)) { + return false; + } + if ($this->getRequest()->getPost('backend_force_creation')) { + return true; + } + if (!$this->isValidResource()) { + $this->addForceCreationCheckbox(); + return false; + } + return true; + } + + /** + * Test if the changed resource is a valid resource, by instantiating it and + * checking if connection is possible. + * + * @return bool True when connection to the resource is possible. + */ + private function isValidResource() + { + try { + $config = $this->getConfig(); + switch ($config->type) { + case 'db': + $resource = ResourceFactory::createResource($config); + $resource->getConnection()->getConnection(); + break; + case 'statusdat': + if ( + !file_exists($config->object_file) || + !file_exists($config->status_file) + ) { + return false; + } + break; + case 'livestatus': + // TODO: Implement check + break; + case 'ldap': + $resource = ResourceFactory::createResource($config); + $resource->connect(); + break; + } + } catch (\Exception $exc) { + return false; + } + return true; + } + + public function create() + { + $this->addNameFields(); + $this->addTypeSelectionBox(); + switch ($this->getRequest()->getParam('resource_type', $this->getResource()->type)) { + case 'db': + $this->addDbForm(); + break; + case 'statusdat': + $this->addStatusdatForm(); + break; + case 'livestatus': + $this->addLivestatusForm(); + break; + case 'ldap': + $this->addLdapForm(); + break; + } + $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); + } + + /** + * Return a configuration containing the backend settings entered in this form + * + * @return Zend_Config The updated configuration for this backend + */ + public function getConfig() + { + $values = $this->getValues(); + $type = $values['resource_type']; + $result = array('type' => $type); + foreach ($values as $key => $value) { + if ( + $key !== 'resource_type' && + $key !== 'resource_all_name' && + $key !== 'resource_all_name_old' + ) { + $configKey = explode('_', $key, 3); + if (sizeof($configKey) < 3) { + Logger::warn('EditResourceForm: invalid form key "' . $key . '" was ignored.'); + continue; + } + $result[$configKey[2]] = $value; + } + } + return new Zend_Config($result); + } +} diff --git a/application/views/scripts/config/authentication/create.phtml b/application/views/scripts/config/authentication/create.phtml index 4980295c6..69e0b4bd3 100644 --- a/application/views/scripts/config/authentication/create.phtml +++ b/application/views/scripts/config/authentication/create.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Create New Authentication Backend diff --git a/application/views/scripts/config/authentication/modify.phtml b/application/views/scripts/config/authentication/modify.phtml index 273b8dcef..298cbdd6e 100644 --- a/application/views/scripts/config/authentication/modify.phtml +++ b/application/views/scripts/config/authentication/modify.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Edit Backend "escape($this->name); ?>" diff --git a/application/views/scripts/config/authentication/remove.phtml b/application/views/scripts/config/authentication/remove.phtml index 703038314..9187195d5 100644 --- a/application/views/scripts/config/authentication/remove.phtml +++ b/application/views/scripts/config/authentication/remove.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Remove Backend "escape($this->name); ?>" diff --git a/application/views/scripts/config/resource.phtml b/application/views/scripts/config/resource.phtml index 6bb38727d..4c167aeef 100644 --- a/application/views/scripts/config/resource.phtml +++ b/application/views/scripts/config/resource.phtml @@ -12,14 +12,19 @@ $createResource = $this->href('/config/createresource'); - successMessage): ?>
escape($this->successMessage); ?>
+flashMessages): ?> +
+ + escape($this->flashMessages); ?> +
+
Create Resource diff --git a/application/views/scripts/config/resource/create.phtml b/application/views/scripts/config/resource/create.phtml index ee7d9b610..6ad1bcb4c 100644 --- a/application/views/scripts/config/resource/create.phtml +++ b/application/views/scripts/config/resource/create.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Create New Resource @@ -12,7 +10,7 @@

- Create a new backend for authenticating your users. This backend will be added at the end of your authentication order. + Create a new resource to describes a data sourc

form ?> \ No newline at end of file diff --git a/application/views/scripts/config/resource/modify.phtml b/application/views/scripts/config/resource/modify.phtml index 481e4349b..9956c3cdf 100644 --- a/application/views/scripts/config/resource/modify.phtml +++ b/application/views/scripts/config/resource/modify.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Edit Resource "escape($this->name); ?>" diff --git a/application/views/scripts/config/resource/remove.phtml b/application/views/scripts/config/resource/remove.phtml index 4ccaea397..0502cc709 100644 --- a/application/views/scripts/config/resource/remove.phtml +++ b/application/views/scripts/config/resource/remove.phtml @@ -1,5 +1,3 @@ -tabs->render($this); ?> -

Remove Resource "escape($this->name); ?>" diff --git a/library/Icinga/Config/PreservingIniWriter.php b/library/Icinga/Config/PreservingIniWriter.php index e785bbece..a33811cc4 100644 --- a/library/Icinga/Config/PreservingIniWriter.php +++ b/library/Icinga/Config/PreservingIniWriter.php @@ -50,9 +50,8 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract /** * Create a new PreservingIniWriter * - * @param array $options Contains the options that should be used for the ConfigWriter - * in an associative array. Supports all options of Zend_Config_Writer and additional - * options for setting the formatting for the internal IniEditor: + * @param array $options Supports all options of Zend_Config_Writer and additional + * options for the internal IniEditor: * * valueIndentation: The indentation level of the values * * commentIndentation: The indentation level of the comments * * sectionSeparators: The amount of newlines between sections diff --git a/library/Icinga/Web/Controller/BaseConfigController.php b/library/Icinga/Web/Controller/BaseConfigController.php index bfa34a56a..86e108cbc 100644 --- a/library/Icinga/Web/Controller/BaseConfigController.php +++ b/library/Icinga/Web/Controller/BaseConfigController.php @@ -42,6 +42,11 @@ use \Icinga\Application\Icinga; */ class BaseConfigController extends ActionController { + /** + * @var Zend_Controller_Action_Helper_FlashMessenger + */ + protected $flashManager; + /* * Return an array of tabs provided by this configuration controller. * @@ -63,5 +68,6 @@ class BaseConfigController extends ActionController { parent::init(); $this->view->tabs = ControllerTabCollector::collectControllerTabs('ConfigController'); + $this->view->flashMessages = $this->_request->getParam('flash_message'); } }