diff --git a/library/Icinga/Authentication/User/UserBackend.php b/library/Icinga/Authentication/User/UserBackend.php index 63b5bbcd7..3b8e21071 100644 --- a/library/Icinga/Authentication/User/UserBackend.php +++ b/library/Icinga/Authentication/User/UserBackend.php @@ -207,12 +207,7 @@ class UserBackend implements ConfigAwareFactory ); } - if ($backendConfig->resource instanceof ConfigObject) { - $resource = ResourceFactory::createResource($backendConfig->resource); - } else { - $resource = ResourceFactory::create($backendConfig->resource); - } - + $resource = ResourceFactory::create($backendConfig->resource); switch ($backendType) { case 'db': $backend = new DbUserBackend($resource); diff --git a/modules/monitoring/application/forms/Setup/IdoResourcePage.php b/modules/monitoring/application/forms/Setup/IdoResourcePage.php index ea244d057..e0b74c3ac 100644 --- a/modules/monitoring/application/forms/Setup/IdoResourcePage.php +++ b/modules/monitoring/application/forms/Setup/IdoResourcePage.php @@ -21,6 +21,7 @@ class IdoResourcePage extends Form $this->addDescription($this->translate( 'Please fill out the connection details below to access the IDO database of your monitoring environment.' )); + $this->setValidatePartial(true); } /** @@ -96,6 +97,52 @@ class IdoResourcePage extends Form return true; } + /** + * Run the configured backend's inspection checks and show the result, if necessary + * + * This will only run any validation if the user pushed the 'backend_validation' button. + * + * @param array $formData + * + * @return bool + */ + public function isValidPartial(array $formData) + { + if (isset($formData['backend_validation']) && parent::isValid($formData)) { + $inspection = ResourceConfigForm::inspectResource($this); + if ($inspection !== null) { + $join = function ($e) use (& $join) { + return is_string($e) ? $e : join("\n", array_map($join, $e)); + }; + $this->addElement( + 'note', + 'inspection_output', + array( + 'order' => 0, + 'value' => '' . $this->translate('Validation Log') . "\n\n" + . join("\n", array_map($join, $inspection->toArray())), + 'decorators' => array( + 'ViewHelper', + array('HtmlTag', array('tag' => 'pre', 'class' => 'log-output')), + ) + ) + ); + + if ($inspection->hasError()) { + $this->warning(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $inspection->getError() + )); + return false; + } + } + + $this->info($this->translate('The configuration has been successfully validated.')); + } + + return true; + } + /** * Add a checkbox to the form by which the user can skip the resource validation * diff --git a/modules/monitoring/library/Monitoring/MonitoringWizard.php b/modules/monitoring/library/Monitoring/MonitoringWizard.php index b91129d10..0a224610c 100644 --- a/modules/monitoring/library/Monitoring/MonitoringWizard.php +++ b/modules/monitoring/library/Monitoring/MonitoringWizard.php @@ -114,6 +114,19 @@ class MonitoringWizard extends Wizard implements SetupWizard mt('monitoring', 'Setup the monitoring module for Icinga Web 2', 'setup.summary.btn.finish') ); } + + if ($page->getName() === 'setup_monitoring_ido') { + $page->addElement( + 'submit', + 'backend_validation', + array( + 'ignore' => true, + 'label' => t('Validate Configuration'), + 'decorators' => array('ViewHelper') + ) + ); + $page->getDisplayGroup('buttons')->addElement($page->getElement('backend_validation')); + } } /** diff --git a/modules/setup/application/forms/AuthBackendPage.php b/modules/setup/application/forms/AuthBackendPage.php index c9116fbb5..dfd185a70 100644 --- a/modules/setup/application/forms/AuthBackendPage.php +++ b/modules/setup/application/forms/AuthBackendPage.php @@ -3,7 +3,8 @@ namespace Icinga\Module\Setup\Forms; -use Icinga\Data\ConfigObject; +use Icinga\Application\Config; +use Icinga\Data\ResourceFactory; use Icinga\Forms\Config\UserBackendConfigForm; use Icinga\Forms\Config\UserBackend\DbBackendForm; use Icinga\Forms\Config\UserBackend\LdapBackendForm; @@ -29,6 +30,7 @@ class AuthBackendPage extends Form { $this->setName('setup_authentication_backend'); $this->setTitle($this->translate('Authentication Backend', 'setup.page.title')); + $this->setValidatePartial(true); } /** @@ -40,22 +42,18 @@ class AuthBackendPage extends Form */ public function setResourceConfig(array $config) { + $resourceConfig = new Config(); + $resourceConfig->setSection($config['name'], $config); + ResourceFactory::setConfig($resourceConfig); + $this->config = $config; return $this; } /** - * Return the resource configuration as Config object + * Create and add elements to this form * - * @return ConfigObject - */ - public function getResourceConfig() - { - return new ConfigObject($this->config); - } - - /** - * @see Form::createElements() + * @param array $formData */ public function createElements(array $formData) { @@ -74,7 +72,9 @@ class AuthBackendPage extends Form )); } elseif ($this->config['type'] === 'ldap') { $backendForm = new LdapBackendForm(); - $backendForm->create($formData)->removeElement('resource'); + $backendForm->setResources(array($this->config['name'])); + $backendForm->create($formData); + $backendForm->getElement('resource')->setIgnore(true); $this->addDescription($this->translate( 'Before you are able to authenticate using the LDAP connection defined earlier you need to' . ' provide some more information so that Icinga Web 2 is able to locate account details.' @@ -140,13 +140,7 @@ class AuthBackendPage extends Form if ($this->config['type'] === 'ldap' && (! isset($data['skip_validation']) || $data['skip_validation'] == 0)) { $self = clone $this; - $self->addElement( - 'text', - 'resource', - array( - 'value' => $this->getResourceConfig() - ) - ); + $self->getSubForm('backend_form')->getElement('resource')->setIgnore(false); $inspection = UserBackendConfigForm::inspectUserBackend($self); if ($inspection && $inspection->hasError()) { $this->error($inspection->getError()); @@ -158,6 +152,54 @@ class AuthBackendPage extends Form return true; } + /** + * Run the configured backend's inspection checks and show the result, if necessary + * + * This will only run any validation if the user pushed the 'backend_validation' button. + * + * @param array $formData + * + * @return bool + */ + public function isValidPartial(array $formData) + { + if (isset($formData['backend_validation']) && parent::isValid($formData)) { + $self = clone $this; + $self->getSubForm('backend_form')->getElement('resource')->setIgnore(false); + $inspection = UserBackendConfigForm::inspectUserBackend($self); + if ($inspection !== null) { + $join = function ($e) use (& $join) { + return is_string($e) ? $e : join("\n", array_map($join, $e)); + }; + $this->addElement( + 'note', + 'inspection_output', + array( + 'order' => 0, + 'value' => '' . $this->translate('Validation Log') . "\n\n" + . join("\n", array_map($join, $inspection->toArray())), + 'decorators' => array( + 'ViewHelper', + array('HtmlTag', array('tag' => 'pre', 'class' => 'log-output')), + ) + ) + ); + + if ($inspection->hasError()) { + $this->warning(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $inspection->getError() + )); + return false; + } + } + + $this->info($this->translate('The configuration has been successfully validated.')); + } + + return true; + } + /** * Add a checkbox to this form by which the user can skip the authentication validation */ diff --git a/modules/setup/application/forms/DbResourcePage.php b/modules/setup/application/forms/DbResourcePage.php index e9967f350..a0faf932d 100644 --- a/modules/setup/application/forms/DbResourcePage.php +++ b/modules/setup/application/forms/DbResourcePage.php @@ -23,6 +23,7 @@ class DbResourcePage extends Form 'Now please configure your database resource. Note that the database itself does not need to' . ' exist at this time as it is going to be created once the wizard is about to be finished.' )); + $this->setValidatePartial(true); } /** @@ -84,6 +85,35 @@ class DbResourcePage extends Form return true; } + /** + * Check whether it's possible to connect to the database server + * + * This will only run the check if the user pushed the 'backend_validation' button. + * + * @param array $formData + * + * @return bool + */ + public function isValidPartial(array $formData) + { + if (isset($formData['backend_validation']) && parent::isValid($formData)) { + try { + $db = new DbTool($this->getValues()); + $db->checkConnectivity(); + } catch (PDOException $e) { + $this->warning(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $e->getMessage() + )); + return false; + } + + $this->info($this->translate('The configuration has been successfully validated.')); + } + + return true; + } + /** * Add a checkbox to the form by which the user can skip the connection validation */ diff --git a/modules/setup/application/forms/LdapResourcePage.php b/modules/setup/application/forms/LdapResourcePage.php index 316b66f31..2c558dfbb 100644 --- a/modules/setup/application/forms/LdapResourcePage.php +++ b/modules/setup/application/forms/LdapResourcePage.php @@ -23,6 +23,7 @@ class LdapResourcePage extends Form 'Now please configure your AD/LDAP resource. This will later ' . 'be used to authenticate users logging in to Icinga Web 2.' )); + $this->setValidatePartial(true); } /** @@ -82,6 +83,52 @@ class LdapResourcePage extends Form return true; } + /** + * Run the configured backend's inspection checks and show the result, if necessary + * + * This will only run any validation if the user pushed the 'backend_validation' button. + * + * @param array $formData + * + * @return bool + */ + public function isValidPartial(array $formData) + { + if (isset($formData['backend_validation']) && parent::isValid($formData)) { + $inspection = ResourceConfigForm::inspectResource($this); + if ($inspection !== null) { + $join = function ($e) use (& $join) { + return is_string($e) ? $e : join("\n", array_map($join, $e)); + }; + $this->addElement( + 'note', + 'inspection_output', + array( + 'order' => 0, + 'value' => '' . $this->translate('Validation Log') . "\n\n" + . join("\n", array_map($join, $inspection->toArray())), + 'decorators' => array( + 'ViewHelper', + array('HtmlTag', array('tag' => 'pre', 'class' => 'log-output')), + ) + ) + ); + + if ($inspection->hasError()) { + $this->warning(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $inspection->getError() + )); + return false; + } + } + + $this->info($this->translate('The configuration has been successfully validated.')); + } + + return true; + } + /** * Add a checkbox to the form by which the user can skip the connection validation */ diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index 6c73a933f..72faa801a 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -320,6 +320,27 @@ class WebWizard extends Wizard implements SetupWizard } elseif ($index === count($pages) - 1) { $page->getElement(static::BTN_NEXT)->setLabel(mt('setup', 'Setup Icinga Web 2', 'setup.summary.btn.finish')); } + + $authData = $this->getPageData('setup_authentication_type'); + $veto = $page->getName() === 'setup_authentication_backend' && $authData['type'] === 'db'; + if (! $veto && in_array($page->getName(), array( + 'setup_authentication_backend', + 'setup_auth_db_resource', + 'setup_config_db_resource', + 'setup_ldap_resource', + 'setup_monitoring_ido' + ))) { + $page->addElement( + 'submit', + 'backend_validation', + array( + 'ignore' => true, + 'label' => t('Validate Configuration'), + 'decorators' => array('ViewHelper') + ) + ); + $page->getDisplayGroup('buttons')->addElement($page->getElement('backend_validation')); + } } /** diff --git a/public/js/icinga/behavior/actiontable.js b/public/js/icinga/behavior/actiontable.js index d3df54614..3f1cf1f9e 100644 --- a/public/js/icinga/behavior/actiontable.js +++ b/public/js/icinga/behavior/actiontable.js @@ -43,7 +43,7 @@ * Handle the selection of an action table * * @param table {HTMLElement} The table - * @param {Icinga} + * @param icinga {Icinga} * * @constructor */ @@ -158,7 +158,6 @@ return; } var self = this; - var url = this.getMultiselectionUrl(); this.rowActions() .filter( function (i, el) { @@ -283,14 +282,7 @@ var ActionTable = function (icinga) { Icinga.EventListener.call(this, icinga); - - /** - * The hash that is currently being loaded - * - * @var String - */ - this.loadingHash = null; - + /** * If currently loading * @@ -364,7 +356,7 @@ } self.icinga.history.pushUrl(state); - // re draw all table selections + // redraw all table selections self.tables().each(function () { new Selection(this, self.icinga).refresh(); }); @@ -375,22 +367,46 @@ }; /** - * Ensure that + * Render the selection and prepare selection rows */ ActionTable.prototype.onRendered = function(evt) { var container = evt.target; var self = evt.data.self; - // draw all selections + // initialize all rows with the correct link + $('table.action tr', container).each(function(idx, el) { + // IE will not ignore user-select unless we cancel selectstart + $(el).on('selectstart', false); + + var $a = $('a[href].rowaction', el).first(); + if ($a.length) { + // TODO: Find out whether we leak memory on IE with this: + $(el).attr('href', $a.attr('href')); + return; + } + $a = $('a[href]', el).first(); + if ($a.length) { + $(el).attr('href', $a.attr('href')); + } + }); + + // draw all active selections that have disappeared on reload self.tables().each(function(i, el) { new Selection(el, self.icinga).refresh(); }); - // update displayed selection count + // update displayed selection counter var table = new Selection(self.tables(container).first()); $(container).find('.selection-info-count').text(table.selections().size()); }; + ActionTable.prototype.clearAll = function () { + var self = this; + this.tables().each(function () { + new Selection(this, self.icinga).clear(); + }); + }; + Icinga.Behaviors.ActionTable = ActionTable; }) (Icinga, jQuery); diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 000ecf103..3ea40b3d7 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -40,20 +40,6 @@ icinga.loader.loadUrl(url, $(el)).autorefresh = true; }); - // Set first links href in a action table tr as row href: - $('table.action tr', el).each(function(idx, el) { - var $a = $('a[href].rowaction', el).first(); - if ($a.length) { - // TODO: Find out whether we leak memory on IE with this: - $(el).attr('href', $a.attr('href')); - return; - } - $a = $('a[href]', el).first(); - if ($a.length) { - $(el).attr('href', $a.attr('href')); - } - }); - $('td.state span.timesince').attr('title', null); var moduleName = el.data('icingaModule'); @@ -441,7 +427,6 @@ } else { icinga.ui.layout1col(); } - $('table tr[href].active').removeClass('active'); icinga.history.pushCurrentState(); } } diff --git a/public/js/icinga/ui.js b/public/js/icinga/ui.js index d2f9ab138..4ab802ca7 100644 --- a/public/js/icinga/ui.js +++ b/public/js/icinga/ui.js @@ -241,6 +241,9 @@ $('#layout').removeClass('twocols'); this.closeContainer($('#col2')); this.disableCloseButtons(); + + // one-column layouts never have any selection active + this.icinga.behaviors.actiontable.clearAll(); }, closeContainer: function($c) {