diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index 423a59902..f5da2952a 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -6,19 +6,16 @@ use Icinga\Web\Controller\BaseConfigController;
use Icinga\Web\Widget\AlertMessageBox;
use Icinga\Web\Notification;
use Icinga\Application\Modules\Module;
-use Icinga\Web\Form;
use Icinga\Web\Widget;
use Icinga\Application\Icinga;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Form\Config\GeneralForm;
-use Icinga\Form\Config\Authentication\LdapBackendForm;
-use Icinga\Form\Config\Authentication\DbBackendForm;
-use Icinga\Form\Config\Authentication\AutologinBackendForm;
+use Icinga\Form\Config\AuthenticationBackendReorderForm;
+use Icinga\Form\Config\AuthenticationBackendConfigForm;
use Icinga\Form\Config\ResourceForm;
-use Icinga\Form\Config\LoggingForm;
use Icinga\Form\Config\ConfirmRemovalForm;
use Icinga\Config\PreservingIniWriter;
-use Icinga\Exception\ConfigurationError;
+use Icinga\Data\ResourceFactory;
/**
@@ -142,47 +139,17 @@ class ConfigController extends BaseConfigController
}
/**
- * Action for reordering authentication backends
+ * Action for listing and reordering authentication backends
*/
public function authenticationAction()
{
- $this->view->messageBox = new AlertMessageBox(true);
+ $form = new AuthenticationBackendReorderForm();
+ $form->setConfig(IcingaConfig::app('authentication'));
+ $form->handleRequest();
+
+ $this->view->form = $form;
$this->view->tabs->activate('authentication');
-
- $config = IcingaConfig::app('authentication');
- $backendOrder = array_keys($config->toArray());
- $form = new Form();
- $form->setName('form_reorder_authbackend');
- $request = $this->getRequest();
- if ($request->isPost()) {
- $requestData = $request->getPost();
- if ($form->isValid($requestData)) { // Validate the CSRF token
- $reordered = false;
- foreach ($backendOrder as $backendName) {
- if (isset($requestData[$backendName])) {
- array_splice($backendOrder, array_search($backendName, $backendOrder), 1);
- array_splice($backendOrder, $requestData[$backendName], 0, $backendName);
- $reordered = true;
- break;
- }
- }
-
- if ($reordered) {
- $reorderedConfig = array();
- foreach ($backendOrder as $backendName) {
- $reorderedConfig[$backendName] = $config->{$backendName};
- }
-
- if ($this->writeAuthenticationFile($reorderedConfig)) {
- Notification::success($this->translate('Authentication order updated!'));
- $this->redirectNow('config/authentication');
- }
- }
- }
- }
-
- $this->view->form = $form->create(); // Necessary in case its a GET request
- $this->view->backendNames = $backendOrder;
+ $this->render('authentication/reorder');
}
/**
@@ -190,172 +157,66 @@ class ConfigController extends BaseConfigController
*/
public function createauthenticationbackendAction()
{
- $this->view->messageBox = new AlertMessageBox(true);
- $this->view->tabs->activate('authentication');
+ $form = new AuthenticationBackendConfigForm();
+ $form->setConfig(IcingaConfig::app('authentication'));
+ $form->setResourceConfig(ResourceFactory::getResourceConfigs());
+ $form->setRedirectUrl('config/authentication');
+ $form->handleRequest();
- $backendType = $this->getRequest()->getParam('type');
- $authenticationConfig = IcingaConfig::app('authentication')->toArray();
- try {
- switch ($backendType) {
- case 'ldap':
- $form = new LdapBackendForm();
- break;
- case 'db':
- $form = new DbBackendForm();
- break;
- case 'autologin':
- foreach ($authenticationConfig as $ac) {
- if (array_key_exists('backend', $ac) && $ac['backend'] === 'autologin') {
- throw new ConfigurationError(
- $this->translate('An autologin backend already exists')
- );
- }
- }
- $form = new AutologinBackendForm();
- break;
- default:
- $this->addErrorMessage(sprintf(
- $this->translate('There is no backend type `%s\''),
- $backendType
- ));
- $this->redirectNow('config/configurationerror');
- }
- } catch (ConfigurationError $e) {
- $this->addErrorMessage($e->getMessage());
- $this->redirectNow('config/configurationerror');
- }
-
- $request = $this->getRequest();
- if ($request->isPost() && $form->isValid($request->getPost())) {
- list($backendName, $backendConfig) = $form->getBackendConfig();
- if (isset($authenticationConfig[$backendName])) {
- $this->addErrorMessage(
- $this->translate('Backend name already exists')
- );
- } else {
- $authenticationConfig[$backendName] = $backendConfig;
- if ($this->writeConfigFile($authenticationConfig, 'authentication')) {
- $this->addSuccessMessage(
- $this->translate('Backend Modification Written.')
- );
- $this->redirectNow('config/authentication');
- }
- }
- }
-
- $this->view->messageBox->addForm($form);
$this->view->form = $form;
+ $this->view->tabs->activate('authentication');
$this->render('authentication/create');
}
-
/**
- * Form for editing backends
- *
- * Mostly the same like the createAuthenticationBackendAction, but with additional checks for backend existence
- * and form population
+ * Action for editing authentication backends
*/
public function editauthenticationbackendAction()
{
- $this->view->messageBox = new AlertMessageBox(true);
+ $form = new AuthenticationBackendConfigForm();
+ $form->setConfig(IcingaConfig::app('authentication'));
+ $form->setResourceConfig(ResourceFactory::getResourceConfigs());
+ $form->setRedirectUrl('config/authentication');
+ $form->handleRequest();
- $configArray = IcingaConfig::app('authentication', true)->toArray();
- $authBackend = $this->getParam('auth_backend');
- if (false === isset($configArray[$authBackend])) {
- $this->addErrorMessage(
- $this->translate('Can\'t edit: Unknown Authentication Backend Provided')
- );
- $this->redirectNow('config/configurationerror');
- }
-
- if (false === array_key_exists('backend', $configArray[$authBackend])) {
- $this->addErrorMessage(sprintf(
- $this->translate('Backend "%s" has no `backend\' setting'),
- $authBackend
- ));
- $this->redirectNow('config/configurationerror');
- }
- $type = $configArray[$authBackend]['backend'];
- switch ($type) {
- case 'ldap':
- $form = new LdapBackendForm();
- break;
- case 'db':
- $form = new DbBackendForm();
- break;
- case 'autologin':
- $form = new AutologinBackendForm();
- break;
- default:
- $this->addErrorMessage(sprintf(
- $this->translate('Can\'t edit: backend type "%s" of given resource not supported.'),
- $type
- ));
- $this->redirectNow('config/configurationerror');
- }
-
- $request = $this->getRequest();
- if ($request->isPost()) {
- if ($form->isValid($request->getPost())) {
- list($backendName, $backendConfig) = $form->getBackendConfig();
- $configArray[$backendName] = $backendConfig;
- if ($backendName != $authBackend) {
- unset($configArray[$authBackend]);
- }
- if ($this->writeAuthenticationFile($configArray)) {
- // redirect to overview with success message
- Notification::success(sprintf(
- $this->translate('Backend "%s" saved'),
- $backendName
- ));
- $this->redirectNow('config/authentication');
- }
- return;
- }
- } else {
- $form->setBackendConfig($authBackend, $configArray[$authBackend]);
- }
-
- $this->view->messageBox->addForm($form);
- $this->view->name = $authBackend;
$this->view->form = $form;
+ $this->view->tabs->activate('authentication');
$this->render('authentication/modify');
}
/**
- * Action for removing a backend from the authentication list.
- *
- * Redirects to the overview after removal is finished
+ * Action for removing a backend from the authentication list
*/
public function removeauthenticationbackendAction()
{
- $this->view->messageBox = new AlertMessageBox(true);
+ $form = new ConfirmRemovalForm(array(
+ 'onSuccess' => function ($request) {
+ $configForm = new AuthenticationBackendConfigForm();
+ $configForm->setConfig(IcingaConfig::app('authentication'));
+ $authBackend = $request->getQuery('auth_backend');
- $configArray = IcingaConfig::app('authentication', true)->toArray();
- $authBackend = $this->getParam('auth_backend');
- if (false === array_key_exists($authBackend, $configArray)) {
- $this->addErrorMessage(
- $this->translate('Can\'t perform removal: Unknown authentication backend provided')
- );
- $this->redirectNow('config/configurationerror');
- }
+ try {
+ $configForm->remove($authBackend);
+ } catch (InvalidArgumentException $e) {
+ Notification::error($e->getMessage());
+ return;
+ }
- $form = new ConfirmRemovalForm();
- $request = $this->getRequest();
-
- if ($request->isPost() && $form->isValid($request->getPost())) {
- unset($configArray[$authBackend]);
- if ($this->writeAuthenticationFile($configArray)) {
- Notification::success(sprintf(
- $this->translate('Authentication Backend "%s" Removed'),
- $authBackend
- ));
- $this->redirectNow('config/authentication');
+ if ($configForm->save()) {
+ Notification::success(sprintf(
+ t('Authentication backend "%s" has been successfully removed'),
+ $authBackend
+ ));
+ } else {
+ return false;
+ }
}
- }
+ ));
+ $form->setRedirectUrl('config/authentication');
+ $form->handleRequest();
$this->view->form = $form;
- $this->view->name = $authBackend;
+ $this->view->tabs->activate('authentication');
$this->render('authentication/remove');
}
diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/AutologinBackendForm.php
index c3cf56fa7..662106bcd 100644
--- a/application/forms/Config/Authentication/AutologinBackendForm.php
+++ b/application/forms/Config/Authentication/AutologinBackendForm.php
@@ -5,19 +5,19 @@
namespace Icinga\Form\Config\Authentication;
use Zend_Validate_Callback;
+use Icinga\Web\Form;
/**
* Form class for adding/modifying autologin authentication backends
*/
-class AutologinBackendForm extends BaseBackendForm
+class AutologinBackendForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
- $this->setName('form_config_authentication_autologin');
- $this->setSubmitLabel(t('Save Changes'));
+ $this->setName('form_config_authbackend_autologin');
}
/**
@@ -31,7 +31,6 @@ class AutologinBackendForm extends BaseBackendForm
'name',
array(
'required' => true,
- 'allowEmpty' => false,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend'),
'validators' => array(
@@ -53,7 +52,6 @@ class AutologinBackendForm extends BaseBackendForm
'strip_username_regexp',
array(
'required' => true,
- 'allowEmpty' => false,
'label' => t('Backend Domain Pattern'),
'helptext' => t('The domain pattern of this authentication backend'),
'value' => '/\@[^$]+$/',
@@ -76,13 +74,15 @@ class AutologinBackendForm extends BaseBackendForm
}
/**
- * Validate the configuration state of this backend
+ * Validate the configuration by creating a backend and requesting the user count
*
- * Returns just true as autologins are being handled externally by the webserver.
+ * Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.)
*
- * @return true
+ * @param Form $form The form to fetch the configuration values from
+ *
+ * @return bool Whether validation succeeded or not
*/
- public function isValidAuthenticationBackend()
+ public function isValidAuthenticationBackend(Form $form)
{
return true;
}
diff --git a/application/forms/Config/Authentication/BaseBackendForm.php b/application/forms/Config/Authentication/BaseBackendForm.php
deleted file mode 100644
index 840b5f34c..000000000
--- a/application/forms/Config/Authentication/BaseBackendForm.php
+++ /dev/null
@@ -1,94 +0,0 @@
-isValidAuthenticationBackend()
- ) {
- $this->addForceCreationCheckbox();
- return false;
- }
-
- return true;
- }
-
- /**
- * Validate the configuration state of this backend with the concrete authentication backend.
- *
- * An implementation should not throw any exception, but use the add/setErrorMessages method
- * of Zend_Form. If the 'force_creation' checkbox is set, this method won't be called.
- *
- * @return bool Whether validation succeeded or not
- */
- abstract public function isValidAuthenticationBackend();
-
- /**
- * Return the backend's configuration values and its name
- *
- * The first value is the name and the second one the values as array.
- *
- * @return array
- */
- public function getBackendConfig()
- {
- $values = $this->getValues();
- $name = $values['name'];
- unset($values['name']);
- return array($name, $values);
- }
-
- /**
- * Populate the form with the given configuration values
- *
- * @param string $name The name of the backend
- * @param array $config The configuration values
- */
- public function setBackendConfig($name, array $config)
- {
- $config['name'] = $name;
- $this->populate($config);
- }
-
- /**
- * Add a checkbox to be displayed at the beginning of the form
- * which allows the user to skip the connection validation
- */
- protected function addForceCreationCheckbox()
- {
- $this->addElement(
- 'checkbox',
- 'force_creation',
- array(
- 'order' => 0,
- 'ignore' => true,
- 'label' => t('Force Changes'),
- 'helptext' => t('Check this box to enforce changes without connectivity validation')
- )
- );
- }
-}
diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php
index 521414094..7ec9c3c26 100644
--- a/application/forms/Config/Authentication/DbBackendForm.php
+++ b/application/forms/Config/Authentication/DbBackendForm.php
@@ -5,17 +5,18 @@
namespace Icinga\Form\Config\Authentication;
use Exception;
+use Icinga\Web\Form;
+use Icinga\Web\Request;
use Icinga\Data\ResourceFactory;
-use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\DbUserBackend;
/**
* Form class for adding/modifying database authentication backends
*/
-class DbBackendForm extends BaseBackendForm
+class DbBackendForm extends Form
{
/**
- * The available database resources prepared to be used as select input data
+ * The database resource names the user can choose from
*
* @var array
*/
@@ -23,28 +24,23 @@ class DbBackendForm extends BaseBackendForm
/**
* Initialize this form
- *
- * Populates $this->resources.
- *
- * @throws ConfigurationError In case no database resources can be found
*/
public function init()
{
- $this->setName('form_config_authentication_db');
- $this->setSubmitLabel(t('Save Changes'));
+ $this->setName('form_config_authbackend_db');
+ }
- $dbResources = array_keys(
- ResourceFactory::getResourceConfigs('db')->toArray()
- );
-
- if (empty($dbResources)) {
- throw new ConfigurationError(
- t('There are no database resources')
- );
- }
-
- // array_combine() is necessary in order to use the array as select input data
- $this->resources = array_combine($dbResources, $dbResources);
+ /**
+ * Set the resource names the user can choose from
+ *
+ * @param array $resources The resources to choose from
+ *
+ * @return self
+ */
+ public function setResources(array $resources)
+ {
+ $this->resources = $resources;
+ return $this;
}
/**
@@ -69,7 +65,9 @@ class DbBackendForm extends BaseBackendForm
'required' => true,
'label' => t('Database Connection'),
'helptext' => t('The database connection to use for authenticating with this provider'),
- 'multiOptions' => $this->resources
+ 'multiOptions' => false === empty($this->resources)
+ ? array_combine($this->resources, $this->resources)
+ : array()
)
),
$this->createElement(
@@ -84,25 +82,39 @@ class DbBackendForm extends BaseBackendForm
}
/**
- * Validate the current configuration by creating a backend and requesting the user count
+ * Validate that the selected resource is a valid database authentication backend
*
- * @return bool Whether validation succeeded or not
- *
- * @see BaseBackendForm::isValidAuthenticationBackend()
+ * @see Form::onSuccess()
*/
- public function isValidAuthenticationBackend()
+ public function onSuccess(Request $request)
{
+ if (false === $this->isValidAuthenticationBackend($this)) {
+ return false;
+ }
+ }
+
+ /**
+ * Validate the configuration by creating a backend and requesting the user count
+ *
+ * @param Form $form The form to fetch the configuration values from
+ *
+ * @return bool Whether validation succeeded or not
+ */
+ public function isValidAuthenticationBackend(Form $form)
+ {
+ $element = $form->getElement('resource');
+
try {
- $testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig(
- $this->getValue('resource')
- ));
+ $testConnection = ResourceFactory::createResource(
+ ResourceFactory::getResourceConfig($element->getValue())
+ );
$dbUserBackend = new DbUserBackend($testConnection);
if ($dbUserBackend->count() < 1) {
- $this->addErrorMessage(t('No users found under the specified database backend'));
+ $element->addError(t('No users found under the specified database backend'));
return false;
}
} catch (Exception $e) {
- $this->addErrorMessage(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
+ $element->addError(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
return false;
}
diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php
index ed261c1f9..af627df48 100644
--- a/application/forms/Config/Authentication/LdapBackendForm.php
+++ b/application/forms/Config/Authentication/LdapBackendForm.php
@@ -5,17 +5,17 @@
namespace Icinga\Form\Config\Authentication;
use Exception;
+use Icinga\Web\Form;
use Icinga\Data\ResourceFactory;
-use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\LdapUserBackend;
/**
- * Form for adding or modifying LDAP authentication backends
+ * Form class for adding/modifying LDAP authentication backends
*/
-class LdapBackendForm extends BaseBackendForm
+class LdapBackendForm extends Form
{
/**
- * The available ldap resources prepared to be used as select input data
+ * The ldap resource names the user can choose from
*
* @var array
*/
@@ -23,28 +23,23 @@ class LdapBackendForm extends BaseBackendForm
/**
* Initialize this form
- *
- * Populates $this->resources.
- *
- * @throws ConfigurationError In case no database resources can be found
*/
public function init()
{
- $this->setName('form_config_authentication_ldap');
- $this->setSubmitLabel(t('Save Changes'));
+ $this->setName('form_config_authbackend_ldap');
+ }
- $ldapResources = array_keys(
- ResourceFactory::getResourceConfigs('ldap')->toArray()
- );
-
- if (empty($ldapResources)) {
- throw new ConfigurationError(
- t('There are no LDAP resources')
- );
- }
-
- // array_combine() is necessary in order to use the array as select input data
- $this->resources = array_combine($ldapResources, $ldapResources);
+ /**
+ * Set the resource names the user can choose from
+ *
+ * @param array $resources The resources to choose from
+ *
+ * @return self
+ */
+ public function setResources(array $resources)
+ {
+ $this->resources = $resources;
+ return $this;
}
/**
@@ -69,7 +64,9 @@ class LdapBackendForm extends BaseBackendForm
'required' => true,
'label' => t('LDAP Resource'),
'helptext' => t('The resource to use for authenticating with this provider'),
- 'multiOptions' => $this->resources
+ 'multiOptions' => false === empty($this->resources)
+ ? array_combine($this->resources, $this->resources)
+ : array()
)
),
$this->createElement(
@@ -104,33 +101,39 @@ class LdapBackendForm extends BaseBackendForm
}
/**
- * Validate the current configuration by connecting to a backend and requesting the user count
+ * Validate that the selected resource is a valid ldap authentication backend
*
- * @return bool Whether validation succeeded or not
- *
- * @see BaseBackendForm::isValidAuthenticationBacken()
+ * @see Form::onSuccess()
*/
- public function isValidAuthenticationBackend()
+ public function onSuccess(Request $request)
{
- if (false === ResourceFactory::ldapAvailable()) {
- // It should be possible to run icingaweb without the php ldap extension. When the user
- // tries to create an ldap backend without ldap being installed we display an error.
- $this->addErrorMessage(t('Using ldap is not possible, the php extension "ldap" is not installed.'));
+ if (false === $this->isValidAuthenticationBackend($this)) {
return false;
}
+ }
+
+ /**
+ * Validate the configuration by creating a backend and requesting the user count
+ *
+ * @param Form $form The form to fetch the configuration values from
+ *
+ * @return bool Whether validation succeeded or not
+ */
+ public function isValidAuthenticationBackend(Form $form)
+ {
+ $element = $form->getElement('resource');
try {
- $backend = ResourceFactory::createResource(
- ResourceFactory::getResourceConfig($this->getValue('resource'))
+ $ldapUserBackend = new LdapUserBackend(
+ ResourceFactory::createResource(
+ ResourceFactory::getResourceConfig($element->getValue())
+ ),
+ $form->getElement('user_class')->getValue(),
+ $form->getElement('user_name_attribute')->getValue()
);
- $testConn = new LdapUserBackend(
- $backend,
- $this->getValue('user_class'),
- $this->getValue('user_name_attribute')
- );
- $testConn->assertAuthenticationPossible();
- } catch (Exception $exc) {
- $this->addErrorMessage(sprintf(t('Connection validation failed: %s'), $exc->getMessage()));
+ $ldapUserBackend->assertAuthenticationPossible();
+ } catch (Exception $e) {
+ $element->addError(sprintf(t('Connection validation failed: %s'), $e->getMessage()));
return false;
}
diff --git a/application/forms/Config/AuthenticationBackendConfigForm.php b/application/forms/Config/AuthenticationBackendConfigForm.php
new file mode 100644
index 000000000..6aeccdd20
--- /dev/null
+++ b/application/forms/Config/AuthenticationBackendConfigForm.php
@@ -0,0 +1,318 @@
+setName('form_config_authbackend');
+ $this->setSubmitLabel(t('Save Changes'));
+ }
+
+ /**
+ * Set the resource configuration to use
+ *
+ * @param Config $resources The resource configuration
+ *
+ * @return self
+ *
+ * @throws ConfigurationError In case no resources are available for authentication
+ */
+ public function setResourceConfig(Config $resourceConfig)
+ {
+ $resources = array();
+ foreach ($resourceConfig as $name => $resource) {
+ $resources[strtolower($resource->type)][] = $name;
+ }
+
+ if (empty($resources)) {
+ throw new ConfigurationError(t('Could not find any resources for authentication'));
+ }
+
+ $this->resources = $resources;
+ return $this;
+ }
+
+ /**
+ * Return a form object for the given backend type
+ *
+ * @param string $type The backend type for which to return a form
+ *
+ * @return Form
+ */
+ public function getBackendForm($type)
+ {
+ if ($type === 'db') {
+ $form = new DbBackendForm();
+ $form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
+ } elseif ($type === 'ldap') {
+ $form = new LdapBackendForm();
+ $form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
+ } elseif ($type === 'autologin') {
+ $form = new AutologinBackendForm();
+ } else {
+ throw new InvalidArgumentException(sprintf(t('Invalid backend type "%s" provided'), $type));
+ }
+
+ return $form;
+ }
+
+ /**
+ * Add a particular authentication backend
+ *
+ * The backend to add is identified by the array-key `name'.
+ *
+ * @param array $values The values to extend the configuration with
+ *
+ * @return self
+ *
+ * @throws InvalidArgumentException In case the backend does already exist
+ */
+ public function add(array $values)
+ {
+ $name = isset($values['name']) ? $values['name'] : '';
+ if (! $name) {
+ throw new InvalidArgumentException(t('Authentication backend name missing'));
+ } elseif ($this->config->get($name) !== null) {
+ throw new InvalidArgumentException(t('Authentication backend already exists'));
+ }
+
+ unset($values['name']);
+ $this->config->{$name} = $values;
+ return $this;
+ }
+
+ /**
+ * Edit a particular authentication backend
+ *
+ * @param string $name The name of the backend to edit
+ * @param array $values The values to edit the configuration with
+ *
+ * @return array The edited backend configuration
+ *
+ * @throws InvalidArgumentException In case the backend does not exist
+ */
+ public function edit($name, array $values)
+ {
+ if (! $name) {
+ throw new InvalidArgumentException(t('Old authentication backend name missing'));
+ } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
+ throw new InvalidArgumentException(t('New authentication backend name missing'));
+ } elseif (($backendConfig = $this->config->get($name)) === null) {
+ throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+ }
+
+ if ($newName !== $name) {
+ // Only remove the old entry if it has changed as the order gets screwed when editing backend names
+ unset($this->config->{$name});
+ }
+
+ unset($values['name']);
+ $this->config->{$newName} = array_merge($backendConfig->toArray(), $values);
+ return $this->config->{$newName};
+ }
+
+ /**
+ * Remove the given authentication backend
+ *
+ * @param string $name The name of the backend to remove
+ *
+ * @return array The removed backend configuration
+ *
+ * @throws InvalidArgumentException In case the backend does not exist
+ */
+ public function remove($name)
+ {
+ if (! $name) {
+ throw new InvalidArgumentException(t('Authentication backend name missing'));
+ } elseif (($backendConfig = $this->config->get($name)) === null) {
+ throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+ }
+
+ unset($this->config->{$name});
+ return $backendConfig;
+ }
+
+ /**
+ * Move the given authentication backend up or down in order
+ *
+ * @param string $name The name of the backend to be moved
+ * @param int $position The new (absolute) position of the backend
+ *
+ * @return self
+ *
+ * @throws InvalidArgumentException In case the backend does not exist
+ */
+ public function move($name, $position)
+ {
+ if (! $name) {
+ throw new InvalidArgumentException(t('Authentication backend name missing'));
+ } elseif ($this->config->get($name) === null) {
+ throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+ }
+
+ $backendOrder = $this->config->keys();
+ array_splice($backendOrder, array_search($name, $backendOrder), 1);
+ array_splice($backendOrder, $position, 0, $name);
+
+ $newConfig = array();
+ foreach ($backendOrder as $backendName) {
+ $newConfig[$backendName] = $this->config->get($backendName);
+ }
+
+ $config = new Config($newConfig);
+ $this->config = $config->setConfigFile($this->config->getConfigFile());
+ return $this;
+ }
+
+ /**
+ * Add or edit an authentication backend and save the configuration
+ *
+ * Performs a connectivity validation using the submitted values. A checkbox is
+ * added to the form to skip the check if it fails and redirection is aborted.
+ *
+ * @see Form::onSuccess()
+ */
+ public function onSuccess(Request $request)
+ {
+ if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
+ $backendForm = $this->getBackendForm($this->getElement('type')->getValue());
+ if (false === $backendForm->isValidAuthenticationBackend($this)) {
+ $this->addForceCreationCheckbox();
+ return false;
+ }
+ }
+
+ $authBackend = $request->getQuery('auth_backend');
+ try {
+ if ($authBackend === null) { // create new backend
+ $this->add($this->getValues());
+ $message = t('Authentication backend "%s" has been successfully created');
+ } else { // edit existing backend
+ $this->edit($authBackend, $this->getValues());
+ $message = t('Authentication backend "%s" has been successfully changed');
+ }
+ } catch (InvalidArgumentException $e) {
+ Notification::error($e->getMessage());
+ return;
+ }
+
+ if ($this->save()) {
+ Notification::success(sprintf($message, $this->getElement('name')->getValue()));
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Populate the form in case an authentication backend is being edited
+ *
+ * @see Form::onShow()
+ *
+ * @throws ConfigurationError In case the backend name is missing in the request or is invalid
+ */
+ public function onShow(Request $request)
+ {
+ $authBackend = $request->getQuery('auth_backend');
+ if ($authBackend !== null) {
+ if ($authBackend === '') {
+ throw new ConfigurationError(t('Authentication backend name missing'));
+ } elseif (false === isset($this->config->{$authBackend})) {
+ throw new ConfigurationError(t('Unknown authentication backend provided'));
+ } elseif (false === isset($this->config->{$authBackend}->backend)) {
+ throw new ConfigurationError(sprintf(t('Backend "%s" has no `backend\' setting'), $authBackend));
+ }
+
+ $configValues = $this->config->{$authBackend}->toArray();
+ $configValues['type'] = $configValues['backend'];
+ $configValues['name'] = $authBackend;
+ $this->populate($configValues);
+ }
+ }
+
+ /**
+ * Add a checkbox to be displayed at the beginning of the form
+ * which allows the user to skip the connection validation
+ */
+ protected function addForceCreationCheckbox()
+ {
+ $this->addElement(
+ 'checkbox',
+ 'force_creation',
+ array(
+ 'order' => 0,
+ 'ignore' => true,
+ 'label' => t('Force Changes'),
+ 'helptext' => t('Check this box to enforce changes without connectivity validation')
+ )
+ );
+ }
+
+ /**
+ * @see Form::createElements()
+ */
+ public function createElements(array $formData)
+ {
+ $backendTypes = array();
+ $backendType = isset($formData['type']) ? $formData['type'] : 'db';
+
+ if (isset($this->resources['db'])) {
+ $backendTypes['db'] = t('Database');
+ }
+ if (isset($this->resources['ldap']) && ($backendType === 'ldap' || ResourceFactory::ldapAvailable())) {
+ $backendTypes['ldap'] = 'LDAP';
+ }
+
+ $autologinBackends = array_filter(
+ $this->config->toArray(),
+ function ($authBackendCfg) {
+ return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
+ }
+ );
+ if ($backendType === 'autologin' || empty($autologinBackends)) {
+ $backendTypes['autologin'] = t('Autologin');
+ }
+
+ $typeSelection = $this->createElement(
+ 'select',
+ 'type',
+ array(
+ 'ignore' => true,
+ 'required' => true,
+ 'autosubmit' => true,
+ 'label' => t('Backend Type'),
+ 'helptext' => t('The type of the resource to use for this authenticaton backend'),
+ 'multiOptions' => $backendTypes
+ )
+ );
+
+ return array_merge(
+ array($typeSelection),
+ $this->getBackendForm($backendType)->createElements($formData)
+ );
+ }
+}
diff --git a/application/forms/Config/AuthenticationBackendReorderForm.php b/application/forms/Config/AuthenticationBackendReorderForm.php
new file mode 100644
index 000000000..d4be16c30
--- /dev/null
+++ b/application/forms/Config/AuthenticationBackendReorderForm.php
@@ -0,0 +1,68 @@
+setName('form_reorder_authbackend');
+ $this->setViewScript('form/reorder-authbackend.phtml');
+ }
+
+ /**
+ * Return the ordered backend names
+ *
+ * @return array
+ */
+ public function getBackendOrder()
+ {
+ return $this->config->keys();
+ }
+
+ /**
+ * Update the authentication backend order and save the configuration
+ *
+ * @see Form::onSuccess()
+ */
+ public function onSuccess(Request $request)
+ {
+ $formData = $this->getRequestData($request);
+ if (isset($formData['backend_newpos'])) {
+ $configForm = $this->getConfigForm();
+ list($backendName, $position) = explode('|', $formData['backend_newpos'], 2);
+
+ try {
+ if ($configForm->move($backendName, $position)->save()) {
+ Notification::success(t('Authentication order updated!'));
+ } else {
+ return false;
+ }
+ } catch (InvalidArgumentException $e) {
+ Notification::error($e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * Return the config form for authentication backends
+ *
+ * @return ConfigForm
+ */
+ protected function getConfigForm()
+ {
+ $form = new AuthenticationBackendConfigForm();
+ $form->setConfig($this->config);
+ return $form;
+ }
+}
diff --git a/application/views/scripts/config/authentication.phtml b/application/views/scripts/config/authentication.phtml
deleted file mode 100644
index 5f1be17bd..000000000
--- a/application/views/scripts/config/authentication.phtml
+++ /dev/null
@@ -1,57 +0,0 @@
-
- = $tabs; ?>
-
-
diff --git a/application/views/scripts/config/authentication/create.phtml b/application/views/scripts/config/authentication/create.phtml
index fd329b63a..52fcbceb3 100644
--- a/application/views/scripts/config/authentication/create.phtml
+++ b/application/views/scripts/config/authentication/create.phtml
@@ -1,15 +1,7 @@
-
-
- Create New Authentication Backend
-
-
-
-messageBox)): ?>
- = $this->messageBox->render() ?>
-
-
+= $this->translate('Create New Authentication Backend'); ?>
- Create a new backend for authenticating your users. This backend will be added at the end of your authentication order.
+ = $this->translate(
+ 'Create a new backend for authenticating your users. This backend will be added at the end of your authentication order.'
+ ); ?>
-
-= $this->form ?>
\ No newline at end of file
+= $form; ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/authentication/modify.phtml b/application/views/scripts/config/authentication/modify.phtml
index 4666ce686..19901ae5b 100644
--- a/application/views/scripts/config/authentication/modify.phtml
+++ b/application/views/scripts/config/authentication/modify.phtml
@@ -1,8 +1,2 @@
-
- translate('Edit Backend "%s"'),
- $this->escape($this->name)
- ); ?>
-
-= $messageBox; ?>
-= $this->form; ?>
+= $this->translate('Edit Backend'); ?>
+= $form; ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/authentication/remove.phtml b/application/views/scripts/config/authentication/remove.phtml
index 23b85f6d7..e1050db0d 100644
--- a/application/views/scripts/config/authentication/remove.phtml
+++ b/application/views/scripts/config/authentication/remove.phtml
@@ -1,8 +1,2 @@
-
- translate('Remove Backend "%s"'),
- $this->escape($name)
- ); ?>
-
-= $messageBox ?>
-= $form ?>
+= $this->translate('Remove Backend'); ?>
+= $form; ?>
\ No newline at end of file
diff --git a/application/views/scripts/config/authentication/reorder.phtml b/application/views/scripts/config/authentication/reorder.phtml
new file mode 100644
index 000000000..0ae7850eb
--- /dev/null
+++ b/application/views/scripts/config/authentication/reorder.phtml
@@ -0,0 +1,11 @@
+
+ = $tabs; ?>
+
+
\ No newline at end of file
diff --git a/application/views/scripts/form/reorder-authbackend.phtml b/application/views/scripts/form/reorder-authbackend.phtml
new file mode 100644
index 000000000..8153e17d2
--- /dev/null
+++ b/application/views/scripts/form/reorder-authbackend.phtml
@@ -0,0 +1,40 @@
+
\ No newline at end of file