UserBackendConfigForm: Adjust how to process requests...

...and use sub-forms, finally.

refs #9602
This commit is contained in:
Johannes Meyer 2015-07-23 16:18:09 +02:00
parent 910dee199f
commit 4e3da3a6eb
9 changed files with 370 additions and 324 deletions

View File

@ -5,6 +5,8 @@ use Icinga\Application\Config;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Application\Modules\Module; use Icinga\Application\Modules\Module;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Config\UserBackendConfigForm; use Icinga\Forms\Config\UserBackendConfigForm;
use Icinga\Forms\Config\UserBackendReorderForm; use Icinga\Forms\Config\UserBackendReorderForm;
use Icinga\Forms\Config\GeneralConfigForm; use Icinga\Forms\Config\GeneralConfigForm;
@ -193,80 +195,130 @@ class ConfigController extends Controller
} }
/** /**
* Action for creating a new user backend * Create a new user backend
*/ */
public function createuserbackendAction() public function createuserbackendAction()
{ {
$this->assertPermission('config/application/userbackend'); $this->assertPermission('config/application/userbackend');
$form = new UserBackendConfigForm(); $form = new UserBackendConfigForm();
$form->setRedirectUrl('config/userbackend');
$form->setTitle($this->translate('Create New User Backend')); $form->setTitle($this->translate('Create New User Backend'));
$form->addDescription($this->translate( $form->addDescription($this->translate(
'Create a new backend for authenticating your users. This backend' 'Create a new backend for authenticating your users. This backend'
. ' will be added at the end of your authentication order.' . ' will be added at the end of your authentication order.'
)); ));
$form->setIniConfig(Config::app('authentication')); $form->setIniConfig(Config::app('authentication'));
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
$form->setRedirectUrl('config/userbackend'); try {
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
} catch (ConfigurationError $e) {
if ($this->hasPermission('config/application/resources')) {
Notification::error($e->getMessage());
$this->redirectNow('config/createresource');
}
throw $e; // No permission for resource configuration, show the error
}
$form->setOnSuccess(function (UserBackendConfigForm $form) {
try {
$form->add(array_filter($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
}
if ($form->save()) {
Notification::success(t('User backend successfully created'));
return true;
}
return false;
});
$form->handleRequest(); $form->handleRequest();
$this->view->form = $form; $this->view->form = $form;
$this->render('userbackend/create'); $this->render('form');
} }
/** /**
* Action for editing user backends * Edit a user backend
*/ */
public function edituserbackendAction() public function edituserbackendAction()
{ {
$this->assertPermission('config/application/userbackend'); $this->assertPermission('config/application/userbackend');
$backendName = $this->params->getRequired('backend');
$form = new UserBackendConfigForm(); $form = new UserBackendConfigForm();
$form->setTitle($this->translate('Edit User Backend'));
$form->setIniConfig(Config::app('authentication'));
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
$form->setRedirectUrl('config/userbackend');
$form->setAction(Url::fromRequest()); $form->setAction(Url::fromRequest());
$form->handleRequest(); $form->setRedirectUrl('config/userbackend');
$form->setTitle(sprintf($this->translate('Edit User Backend %s'), $backendName));
$form->setIniConfig(Config::app('authentication'));
$form->setOnSuccess(function (UserBackendConfigForm $form) use ($backendName) {
try {
$form->edit($backendName, array_map(
function ($v) {
return $v !== '' ? $v : null;
},
$form->getValues()
));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
}
if ($form->save()) {
Notification::success(sprintf(t('User backend "%s" successfully updated'), $backendName));
return true;
}
return false;
});
try {
$form->load($backendName);
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
$form->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('User backend "%s" not found'), $backendName));
}
$this->view->form = $form; $this->view->form = $form;
$this->render('userbackend/modify'); $this->render('form');
} }
/** /**
* Action for removing a user backend * Display a confirmation form to remove the backend identified by the 'backend' parameter
*/ */
public function removeuserbackendAction() public function removeuserbackendAction()
{ {
$this->assertPermission('config/application/userbackend'); $this->assertPermission('config/application/userbackend');
$form = new ConfirmRemovalForm(array( $backendName = $this->params->getRequired('backend');
'onSuccess' => function ($form) {
$configForm = new UserBackendConfigForm();
$configForm->setIniConfig(Config::app('authentication'));
$authBackend = $form->getRequest()->getQuery('backend');
try { $backendForm = new UserBackendConfigForm();
$configForm->remove($authBackend); $backendForm->setIniConfig(Config::app('authentication'));
} catch (InvalidArgumentException $e) { $form = new ConfirmRemovalForm();
Notification::error($e->getMessage());
return false;
}
if ($configForm->save()) {
Notification::success(sprintf(
t('User backend "%s" has been successfully removed'),
$authBackend
));
} else {
return false;
}
}
));
$form->setTitle($this->translate('Remove User Backend'));
$form->setRedirectUrl('config/userbackend'); $form->setRedirectUrl('config/userbackend');
$form->setAction(Url::fromRequest()); $form->setTitle(sprintf($this->translate('Remove User Backend %s'), $backendName));
$form->setOnSuccess(function (ConfirmRemovalForm $form) use ($backendName, $backendForm) {
try {
$backendForm->delete($backendName);
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
}
if ($backendForm->save()) {
Notification::success(sprintf(t('User backend "%s" successfully removed'), $backendName));
return true;
}
return false;
});
$form->handleRequest(); $form->handleRequest();
$this->view->form = $form; $this->view->form = $form;
$this->render('userbackend/remove'); $this->render('form');
} }
/** /**

View File

@ -3,11 +3,7 @@
namespace Icinga\Forms\Config\UserBackend; namespace Icinga\Forms\Config\UserBackend;
use Exception;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Data\ConfigObject;
use Icinga\Data\ResourceFactory;
use Icinga\Authentication\User\DbUserBackend;
/** /**
* Form class for adding/modifying database user backends * Form class for adding/modifying database user backends
@ -43,7 +39,9 @@ class DbBackendForm extends Form
} }
/** /**
* @see Form::createElements() * Create and add elements to this form
*
* @param array $formData
*/ */
public function createElements(array $formData) public function createElements(array $formData)
{ {
@ -56,6 +54,20 @@ class DbBackendForm extends Form
'description' => $this->translate( 'description' => $this->translate(
'The name of this authentication provider that is used to differentiate it from others' 'The name of this authentication provider that is used to differentiate it from others'
), ),
'validators' => array(
array(
'Regex',
false,
array(
'pattern' => '/^[^\\[\\]:]+$/',
'messages' => array(
'regexNotMatch' => $this->translate(
'The name cannot contain \'[\', \']\' or \':\'.'
)
)
)
)
)
) )
); );
$this->addElement( $this->addElement(
@ -67,7 +79,7 @@ class DbBackendForm extends Form
'description' => $this->translate( 'description' => $this->translate(
'The database connection to use for authenticating with this provider' 'The database connection to use for authenticating with this provider'
), ),
'multiOptions' => false === empty($this->resources) 'multiOptions' => !empty($this->resources)
? array_combine($this->resources, $this->resources) ? array_combine($this->resources, $this->resources)
: array() : array()
) )
@ -80,49 +92,5 @@ class DbBackendForm extends Form
'value' => 'db' 'value' => 'db'
) )
); );
return $this;
}
/**
* Validate that the selected resource is a valid database user backend
*
* @see Form::onSuccess()
*/
public function onSuccess()
{
if (false === static::isValidUserBackend($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 static function isValidUserBackend(Form $form)
{
$backend = new DbUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
$result = $backend->inspect();
if ($result->hasError()) {
$form->addError(sprintf($form->translate('Using the specified backend failed: %s'), $result->getError()));
}
// TODO: display diagnostics in $result->toArray() to the user
return ! $result->hasError();
}
/**
* Return the configuration for the chosen resource
*
* @return ConfigObject
*/
public function getResourceConfig()
{
return ResourceFactory::getResourceConfig($this->getValue('resource'));
} }
} }

View File

@ -3,14 +3,7 @@
namespace Icinga\Forms\Config\UserBackend; namespace Icinga\Forms\Config\UserBackend;
use Exception;
use Icinga\Authentication\User\LdapUserBackend;
use Icinga\Data\Inspection;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Data\ConfigObject;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\AuthenticationException;
use Icinga\Authentication\User\UserBackend;
/** /**
* Form class for adding/modifying LDAP user backends * Form class for adding/modifying LDAP user backends
@ -46,7 +39,9 @@ class LdapBackendForm extends Form
} }
/** /**
* @see Form::createElements() * Create and add elements to this form
*
* @param array $formData
*/ */
public function createElements(array $formData) public function createElements(array $formData)
{ {
@ -60,6 +55,20 @@ class LdapBackendForm extends Form
'label' => $this->translate('Backend Name'), 'label' => $this->translate('Backend Name'),
'description' => $this->translate( 'description' => $this->translate(
'The name of this authentication provider that is used to differentiate it from others.' 'The name of this authentication provider that is used to differentiate it from others.'
),
'validators' => array(
array(
'Regex',
false,
array(
'pattern' => '/^[^\\[\\]:]+$/',
'messages' => array(
'regexNotMatch' => $this->translate(
'The name cannot contain \'[\', \']\' or \':\'.'
)
)
)
)
) )
) )
); );
@ -72,7 +81,7 @@ class LdapBackendForm extends Form
'description' => $this->translate( 'description' => $this->translate(
'The LDAP connection to use for authenticating with this provider.' 'The LDAP connection to use for authenticating with this provider.'
), ),
'multiOptions' => false === empty($this->resources) 'multiOptions' => !empty($this->resources)
? array_combine($this->resources, $this->resources) ? array_combine($this->resources, $this->resources)
: array() : array()
) )
@ -162,40 +171,5 @@ class LdapBackendForm extends Form
) )
) )
); );
return $this;
}
/**
* Validate that the selected resource is a valid ldap user backend
*
* @see Form::onSuccess()
*/
public function onSuccess()
{
if (false === static::isValidUserBackend($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 static function isValidUserBackend(Form $form)
{
/**
* @var $result Inspection
*/
$result = UserBackend::create(null, new ConfigObject($form->getValues()))->inspect();
if ($result->hasError()) {
$form->addError($result->getError());
}
// TODO: display diagnostics in $result->toArray() to the user
return ! $result->hasError();
} }
} }

View File

@ -4,26 +4,38 @@
namespace Icinga\Forms\Config; namespace Icinga\Forms\Config;
use InvalidArgumentException; use InvalidArgumentException;
use Icinga\Forms\ConfigForm;
use Icinga\Web\Notification;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Application\Platform; use Icinga\Authentication\User\UserBackend;
use Icinga\Data\ConfigObject;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotFoundError;
use Icinga\Data\ConfigObject;
use Icinga\Data\Inspectable;
use Icinga\Forms\ConfigForm;
use Icinga\Forms\Config\UserBackend\ExternalBackendForm;
use Icinga\Forms\Config\UserBackend\DbBackendForm; use Icinga\Forms\Config\UserBackend\DbBackendForm;
use Icinga\Forms\Config\UserBackend\LdapBackendForm; use Icinga\Forms\Config\UserBackend\LdapBackendForm;
use Icinga\Forms\Config\UserBackend\ExternalBackendForm; use Icinga\Web\Form;
/**
* Form for managing user backends
*/
class UserBackendConfigForm extends ConfigForm class UserBackendConfigForm extends ConfigForm
{ {
/** /**
* The available resources split by type * The available user backend resources split by type
* *
* @var array * @var array
*/ */
protected $resources; protected $resources;
/**
* The backend to load when displaying the form for the first time
*
* @var string
*/
protected $backendToLoad;
/** /**
* Initialize this form * Initialize this form
*/ */
@ -36,15 +48,39 @@ class UserBackendConfigForm extends ConfigForm
/** /**
* Set the resource configuration to use * Set the resource configuration to use
* *
* @param Config $resources The resource configuration * @param Config $resourceConfig The resource configuration
* *
* @return $this * @return $this
*
* @throws ConfigurationError In case there are no valid resources for authentication available
*/ */
public function setResourceConfig(Config $resourceConfig) public function setResourceConfig(Config $resourceConfig)
{ {
$resources = array(); $resources = array();
foreach ($resourceConfig as $name => $resource) { foreach ($resourceConfig as $name => $resource) {
$resources[strtolower($resource->type)][] = $name; if (in_array($resource->type, array('db', 'ldap'))) {
$resources[$resource->type][] = $name;
}
}
if (empty($resources)) {
$externalBackends = $this->config->toArray();
array_walk(
$externalBackends,
function (& $authBackendCfg) {
if (! isset($authBackendCfg['backend']) || $authBackendCfg['backend'] !== 'external') {
$authBackendCfg = null;
}
}
);
if (count(array_filter($externalBackends)) > 0 && (
$this->backendToLoad === null || !isset($externalBackends[$this->backendToLoad])
)) {
throw new ConfigurationError($this->translate(
'Could not find any valid user backend resources.'
. ' Please configure a resource for authentication first.'
));
}
} }
$this->resources = $resources; $this->resources = $resources;
@ -54,9 +90,11 @@ class UserBackendConfigForm extends ConfigForm
/** /**
* Return a form object for the given backend type * Return a form object for the given backend type
* *
* @param string $type The backend type for which to return a form * @param string $type The backend type for which to return a form
* *
* @return Form * @return Form
*
* @throws InvalidArgumentException In case the given backend type is invalid
*/ */
public function getBackendForm($type) public function getBackendForm($type)
{ {
@ -84,81 +122,103 @@ class UserBackendConfigForm extends ConfigForm
} }
/** /**
* Add a particular user backend * Populate the form with the given backend's config
* *
* The backend to add is identified by the array-key `name'. * @param string $name
*
* @param array $values The values to extend the configuration with
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException In case the backend does already exist * @throws NotFoundError In case no backend with the given name is found
*/ */
public function add(array $values) public function load($name)
{ {
$name = isset($values['name']) ? $values['name'] : ''; if (! $this->config->hasSection($name)) {
if (! $name) { throw new NotFoundError('No user backend called "%s" found', $name);
throw new InvalidArgumentException($this->translate('User backend name missing'));
} elseif ($this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('User backend already exists'));
} }
unset($values['name']); $this->backendToLoad = $name;
$this->config->setSection($name, $values);
return $this; return $this;
} }
/** /**
* Edit a particular user backend * Add a new user backend
* *
* @param string $name The name of the backend to edit * The backend to add is identified by the array-key `name'.
* @param array $values The values to edit the configuration with
* *
* @return array The edited backend configuration * @param array $data
* *
* @throws InvalidArgumentException In case the backend does not exist * @return $this
*
* @throws InvalidArgumentException In case $data does not contain a backend name
* @throws IcingaException In case a backend with the same name already exists
*/ */
public function edit($name, array $values) public function add(array $data)
{ {
if (! $name) { if (! isset($data['name'])) {
throw new InvalidArgumentException($this->translate('Old user backend name missing')); throw new InvalidArgumentException('Key \'name\' missing');
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
throw new InvalidArgumentException($this->translate('New user backend name missing'));
} elseif (! $this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('Unknown user backend provided'));
} }
$backendConfig = $this->config->getSection($name); $backendName = $data['name'];
if ($newName !== $name) { if ($this->config->hasSection($backendName)) {
// Only remove the old entry if it has changed as the order gets screwed when editing backend names throw new IcingaException(
$this->config->removeSection($name); $this->translate('A user backend with the name "%s" does already exist'),
$backendName
);
} }
unset($values['name']); unset($data['name']);
$this->config->setSection($newName, $backendConfig->merge($values)); $this->config->setSection($backendName, $data);
return $backendConfig; return $this;
} }
/** /**
* Remove the given user backend * Edit a user backend
* *
* @param string $name The name of the backend to remove * @param string $name
* @param array $data
* *
* @return array The removed backend configuration * @return $this
* *
* @throws InvalidArgumentException In case the backend does not exist * @throws NotFoundError In case no backend with the given name is found
*/ */
public function remove($name) public function edit($name, array $data)
{ {
if (! $name) { if (! $this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('user backend name missing')); throw new NotFoundError('No user backend called "%s" found', $name);
} elseif (! $this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('Unknown user backend provided'));
} }
$backendConfig = $this->config->getSection($name); $backendConfig = $this->config->getSection($name);
if (isset($data['name'])) {
if ($data['name'] !== $name) {
$this->config->removeSection($name);
$name = $data['name'];
}
unset($data['name']);
}
$backendConfig->merge($data);
foreach ($backendConfig->toArray() as $k => $v) {
if ($v === null) {
unset($backendConfig->$k);
}
}
$this->config->setSection($name, $backendConfig);
return $this;
}
/**
* Remove a user backend
*
* @param string $name
*
* @return $this
*/
public function delete($name)
{
$this->config->removeSection($name); $this->config->removeSection($name);
return $backendConfig; return $this;
} }
/** /**
@ -169,14 +229,12 @@ class UserBackendConfigForm extends ConfigForm
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException In case the backend does not exist * @throws NotFoundError In case no backend with the given name is found
*/ */
public function move($name, $position) public function move($name, $position)
{ {
if (! $name) { if (! $this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('User backend name missing')); throw new NotFoundError('No user backend called "%s" found', $name);
} elseif (! $this->config->hasSection($name)) {
throw new InvalidArgumentException($this->translate('Unknown user backend provided'));
} }
$backendOrder = $this->config->keys(); $backendOrder = $this->config->keys();
@ -194,105 +252,9 @@ class UserBackendConfigForm extends ConfigForm
} }
/** /**
* Add or edit an user backend and save the configuration * Create and add elements to this form
* *
* Performs a connectivity validation using the submitted values. A checkbox is * @param array $formData
* added to the form to skip the check if it fails and redirection is aborted.
*
* @see Form::onSuccess()
*/
public function onSuccess()
{
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
$backendForm = $this->getBackendForm($this->getElement('type')->getValue());
if (false === $backendForm::isValidUserBackend($this)) {
$this->addElement($this->getForceCreationCheckbox());
return false;
}
}
$authBackend = $this->request->getQuery('backend');
try {
if ($authBackend === null) { // create new backend
$this->add($this->getValues());
$message = $this->translate('User backend "%s" has been successfully created');
} else { // edit existing backend
$this->edit($authBackend, $this->getValues());
$message = $this->translate('User 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 user backend is being edited
*
* @see Form::onRequest()
*
* @throws ConfigurationError In case the backend name is missing in the request or is invalid
*/
public function onRequest()
{
$authBackend = $this->request->getQuery('backend');
if ($authBackend !== null) {
if ($authBackend === '') {
throw new ConfigurationError($this->translate('User backend name missing'));
} elseif (! $this->config->hasSection($authBackend)) {
throw new ConfigurationError($this->translate('Unknown user backend provided'));
} elseif ($this->config->getSection($authBackend)->backend === null) {
throw new ConfigurationError(
sprintf($this->translate('Backend "%s" has no `backend\' setting'), $authBackend)
);
}
$configValues = $this->config->getSection($authBackend)->toArray();
$configValues['type'] = $configValues['backend'];
$configValues['name'] = $authBackend;
$this->populate($configValues);
} elseif (empty($this->resources)) {
$externalBackends = array_filter(
$this->config->toArray(),
function ($authBackendCfg) {
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external';
}
);
if (false === empty($externalBackends)) {
throw new ConfigurationError($this->translate('Could not find any resources for authentication'));
}
}
}
/**
* Return a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*
* @return Zend_Form_Element
*/
protected function getForceCreationCheckbox()
{
return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => $this->translate('Force Changes'),
'description' => $this->translate('Check this box to enforce changes without connectivity validation')
)
);
}
/**
* @see Form::createElements()
*/ */
public function createElements(array $formData) public function createElements(array $formData)
{ {
@ -302,7 +264,7 @@ class UserBackendConfigForm extends ConfigForm
if (isset($this->resources['db'])) { if (isset($this->resources['db'])) {
$backendTypes['db'] = $this->translate('Database'); $backendTypes['db'] = $this->translate('Database');
} }
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) { if (isset($this->resources['ldap'])) {
$backendTypes['ldap'] = 'LDAP'; $backendTypes['ldap'] = 'LDAP';
$backendTypes['msldap'] = 'ActiveDirectory'; $backendTypes['msldap'] = 'ActiveDirectory';
} }
@ -336,21 +298,107 @@ class UserBackendConfigForm extends ConfigForm
) )
); );
if (isset($formData['force_creation']) && $formData['force_creation']) { if (isset($formData['skip_validation']) && $formData['skip_validation']) {
// In case another error occured and the checkbox was displayed before // In case another error occured and the checkbox was displayed before
$this->addElement($this->getForceCreationCheckbox()); $this->addSkipValidationCheckbox();
} }
$this->addElements($this->getBackendForm($backendType)->createElements($formData)->getElements()); $this->addSubForm($this->getBackendForm($backendType)->create($formData), 'backend_form');
} }
/** /**
* Return the configuration for the chosen resource * Populate the configuration of the backend to load
*
* @return ConfigObject
*/ */
public function getResourceConfig() public function onRequest()
{ {
return ResourceFactory::getResourceConfig($this->getValue('resource')); if ($this->backendToLoad) {
$data = $this->config->getSection($this->backendToLoad)->toArray();
$data['name'] = $this->backendToLoad;
$data['type'] = $data['backend'];
$this->populate($data);
}
}
/**
* Retrieve all form element values
*
* @param bool $suppressArrayNotation Ignored
*
* @return array
*/
public function getValues($suppressArrayNotation = false)
{
$values = parent::getValues();
$values = array_merge($values, $values['backend_form']);
unset($values['backend_form']);
return $values;
}
/**
* Return whether the given values are valid
*
* @param array $formData The data to validate
*
* @return bool
*/
public function isValid($formData)
{
if (! parent::isValid($formData)) {
return false;
}
if (($el = $this->getElement('skip_validation')) === null || false === $el->isChecked()) {
$backendForm = $this->getBackendForm($this->getValue('type'));
if (! static::isValidUserBackend($this)) {
if ($el === null) {
$this->addSkipValidationCheckbox();
}
return false;
}
}
return true;
}
/**
* Validate the configuration by creating a backend and running its inspection checks
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether inspection succeeded or not
*/
public static function isValidUserBackend(Form $form)
{
$backend = UserBackend::create(null, new ConfigObject($form->getValues()));
if ($backend instanceof Inspectable) {
$inspection = $backend->inspect();
if ($inspection->hasError()) {
$form->error($inspection->getError());
return false;
}
}
return true;
}
/**
* Add a checkbox to the form by which the user can skip the connection validation
*/
protected function addSkipValidationCheckbox()
{
$this->addElement(
'checkbox',
'skip_validation',
array(
'order' => 0,
'ignore' => true,
'required' => true,
'label' => $this->translate('Skip Validation'),
'description' => $this->translate(
'Check this box to enforce changes without validating that authentication is possible.'
)
)
);
} }
} }

View File

@ -3,9 +3,9 @@
namespace Icinga\Forms\Config; namespace Icinga\Forms\Config;
use InvalidArgumentException;
use Icinga\Web\Notification;
use Icinga\Forms\ConfigForm; use Icinga\Forms\ConfigForm;
use Icinga\Exception\NotFoundError;
use Icinga\Web\Notification;
class UserBackendReorderForm extends ConfigForm class UserBackendReorderForm extends ConfigForm
{ {
@ -29,7 +29,9 @@ class UserBackendReorderForm extends ConfigForm
} }
/** /**
* @see Form::createElements() * Create and add elements to this form
*
* @param array $formData
*/ */
public function createElements(array $formData) public function createElements(array $formData)
{ {
@ -39,8 +41,6 @@ class UserBackendReorderForm extends ConfigForm
/** /**
* Update the user backend order and save the configuration * Update the user backend order and save the configuration
*
* @see Form::onSuccess()
*/ */
public function onSuccess() public function onSuccess()
{ {
@ -55,8 +55,8 @@ class UserBackendReorderForm extends ConfigForm
} else { } else {
return false; return false;
} }
} catch (InvalidArgumentException $e) { } catch (NotFoundError $_) {
Notification::error($e->getMessage()); Notification::error(sprintf($this->translate('User backend "%s" not found'), $backendName));
} }
} }
} }

View File

@ -1,6 +0,0 @@
<div class="controls">
<?= $this->tabs->showOnlyCloseButton() ?>
</div>
<div class="content">
<?= $form; ?>
</div>

View File

@ -1,6 +0,0 @@
<div class="controls">
<?= $this->tabs->showOnlyCloseButton() ?>
</div>
<div class="content">
<?= $form; ?>
</div>

View File

@ -3,11 +3,12 @@
namespace Icinga\Module\Setup\Forms; namespace Icinga\Module\Setup\Forms;
use Icinga\Web\Form; use Icinga\Data\ConfigObject;
use Icinga\Forms\Config\UserBackendConfigForm;
use Icinga\Forms\Config\UserBackend\DbBackendForm; use Icinga\Forms\Config\UserBackend\DbBackendForm;
use Icinga\Forms\Config\UserBackend\LdapBackendForm; use Icinga\Forms\Config\UserBackend\LdapBackendForm;
use Icinga\Forms\Config\UserBackend\ExternalBackendForm; use Icinga\Forms\Config\UserBackend\ExternalBackendForm;
use Icinga\Data\ConfigObject; use Icinga\Web\Form;
/** /**
* Wizard page to define authentication backend specific details * Wizard page to define authentication backend specific details
@ -66,14 +67,14 @@ class AuthBackendPage extends Form
$this->setRequiredCue(null); $this->setRequiredCue(null);
$backendForm = new DbBackendForm(); $backendForm = new DbBackendForm();
$backendForm->setRequiredCue(null); $backendForm->setRequiredCue(null);
$backendForm->createElements($formData)->removeElement('resource'); $backendForm->create($formData)->removeElement('resource');
$this->addDescription($this->translate( $this->addDescription($this->translate(
'As you\'ve chosen to use a database for authentication all you need ' 'As you\'ve chosen to use a database for authentication all you need '
. 'to do now is defining a name for your first authentication backend.' . 'to do now is defining a name for your first authentication backend.'
)); ));
} elseif ($this->config['type'] === 'ldap') { } elseif ($this->config['type'] === 'ldap') {
$backendForm = new LdapBackendForm(); $backendForm = new LdapBackendForm();
$backendForm->createElements($formData)->removeElement('resource'); $backendForm->create($formData)->removeElement('resource');
$this->addDescription($this->translate( $this->addDescription($this->translate(
'Before you are able to authenticate using the LDAP connection defined earlier you need to' '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.' . ' provide some more information so that Icinga Web 2 is able to locate account details.'
@ -97,15 +98,30 @@ class AuthBackendPage extends Form
); );
} else { // $this->config['type'] === 'external' } else { // $this->config['type'] === 'external'
$backendForm = new ExternalBackendForm(); $backendForm = new ExternalBackendForm();
$backendForm->createElements($formData); $backendForm->create($formData);
$this->addDescription($this->translate( $this->addDescription($this->translate(
'You\'ve chosen to authenticate using a web server\'s mechanism so it may be necessary' 'You\'ve chosen to authenticate using a web server\'s mechanism so it may be necessary'
. ' to adjust usernames before any permissions, restrictions, etc. are being applied.' . ' to adjust usernames before any permissions, restrictions, etc. are being applied.'
)); ));
} }
$this->addElements($backendForm->getElements()); $backendForm->getElement('name')->setValue('icingaweb2');
$this->getElement('name')->setValue('icingaweb2'); $this->addSubForm($backendForm, 'backend_form');
}
/**
* Retrieve all form element values
*
* @param bool $suppressArrayNotation Ignored
*
* @return array
*/
public function getValues($suppressArrayNotation = false)
{
$values = parent::getValues();
$values = array_merge($values, $values['backend_form']);
unset($values['backend_form']);
return $values;
} }
/** /**
@ -117,11 +133,11 @@ class AuthBackendPage extends Form
*/ */
public function isValid($data) public function isValid($data)
{ {
if (false === parent::isValid($data)) { if (! parent::isValid($data)) {
return false; return false;
} }
if ($this->config['type'] === 'ldap' && ( !isset($data['skip_validation']) || $data['skip_validation'] == 0)) { if ($this->config['type'] === 'ldap' && (! isset($data['skip_validation']) || $data['skip_validation'] == 0)) {
$self = clone $this; $self = clone $this;
$self->addElement( $self->addElement(
'text', 'text',
@ -130,7 +146,7 @@ class AuthBackendPage extends Form
'value' => $this->getResourceConfig() 'value' => $this->getResourceConfig()
) )
); );
if (! LdapBackendForm::isValidUserBackend($self)) { if (! UserBackendConfigForm::isValidUserBackend($self)) {
$this->addSkipValidationCheckbox(); $this->addSkipValidationCheckbox();
return false; return false;
} }