Merge branch 'bugfix/more-intuitive-admin-account-creation-8704'
fixes #8704
This commit is contained in:
commit
19be028981
|
@ -5,6 +5,8 @@ namespace Icinga\Module\Setup\Forms;
|
|||
|
||||
use Exception;
|
||||
use Icinga\Authentication\User\UserBackend;
|
||||
use Icinga\Authentication\User\DbUserBackend;
|
||||
use Icinga\Authentication\User\LdapUserBackend;
|
||||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Web\Form;
|
||||
|
||||
|
@ -33,7 +35,10 @@ class AdminAccountPage extends Form
|
|||
public function init()
|
||||
{
|
||||
$this->setName('setup_admin_account');
|
||||
$this->setViewScript('form/setup-admin-account.phtml');
|
||||
$this->setTitle($this->translate('Administration', 'setup.page.title'));
|
||||
$this->addDescription($this->translate(
|
||||
'Now it\'s time to configure your first administrative account for Icinga Web 2.'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,14 +73,53 @@ class AdminAccountPage extends Form
|
|||
public function createElements(array $formData)
|
||||
{
|
||||
$choices = array();
|
||||
|
||||
if ($this->backendConfig['backend'] !== 'db') {
|
||||
$choices['by_name'] = $this->translate('By Name', 'setup.admin');
|
||||
$choice = isset($formData['user_type']) ? $formData['user_type'] : 'by_name';
|
||||
} else {
|
||||
$choices['new_user'] = $this->translate('New User', 'setup.admin');
|
||||
$choice = isset($formData['user_type']) ? $formData['user_type'] : 'new_user';
|
||||
}
|
||||
|
||||
if (in_array($this->backendConfig['backend'], array('db', 'ldap', 'msldap'))) {
|
||||
$users = $this->fetchUsers();
|
||||
if (! empty($users)) {
|
||||
$choices['existing_user'] = $this->translate('Existing User', 'setup.admin');
|
||||
}
|
||||
}
|
||||
|
||||
if (count($choices) > 1) {
|
||||
$this->addDescription($this->translate(
|
||||
'Below are several options you can choose from for how to define the desired account.'
|
||||
));
|
||||
$this->addElement(
|
||||
'select',
|
||||
'user_type',
|
||||
array(
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'label' => $this->translate('Type Of Definition'),
|
||||
'multiOptions' => $choices,
|
||||
'value' => $choice
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->addElement(
|
||||
'hidden',
|
||||
'user_type',
|
||||
array(
|
||||
'required' => true,
|
||||
'value' => key($choices)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($choice === 'by_name') {
|
||||
$this->addElement(
|
||||
'text',
|
||||
'by_name',
|
||||
array(
|
||||
'required' => !isset($formData['user_type']) || $formData['user_type'] === 'by_name',
|
||||
'required' => true,
|
||||
'value' => $this->getUsername(),
|
||||
'label' => $this->translate('Username'),
|
||||
'description' => $this->translate(
|
||||
|
@ -84,53 +128,35 @@ class AdminAccountPage extends Form
|
|||
)
|
||||
)
|
||||
);
|
||||
if (! $this->request->isXmlHttpRequest()) {
|
||||
// In case JS is disabled we must not provide client side validation as
|
||||
// the user is required to input data even he has changed his mind
|
||||
$this->getElement('by_name')->setAttrib('required', null);
|
||||
$this->getElement('by_name')->setAttrib('aria-required', null);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($this->backendConfig['backend'], array('db', 'ldap', 'msldap'))) {
|
||||
$users = $this->fetchUsers();
|
||||
if (false === empty($users)) {
|
||||
$choices['existing_user'] = $this->translate('Existing User');
|
||||
$this->addElement(
|
||||
'select',
|
||||
'existing_user',
|
||||
array(
|
||||
'required' => isset($formData['user_type']) && $formData['user_type'] === 'existing_user',
|
||||
'label' => $this->translate('Username'),
|
||||
'description' => sprintf(
|
||||
$this->translate(
|
||||
'Choose a user reported by the %s backend as the initial administrative account',
|
||||
'setup.admin'
|
||||
),
|
||||
$this->backendConfig['backend'] === 'db'
|
||||
? $this->translate('database', 'setup.admin.authbackend')
|
||||
: 'LDAP'
|
||||
if ($choice === 'existing_user') {
|
||||
$this->addElement(
|
||||
'select',
|
||||
'existing_user',
|
||||
array(
|
||||
'required' => true,
|
||||
'label' => $this->translate('Username'),
|
||||
'description' => sprintf(
|
||||
$this->translate(
|
||||
'Choose a user reported by the %s backend as the initial administrative account',
|
||||
'setup.admin'
|
||||
),
|
||||
'multiOptions' => array_combine($users, $users)
|
||||
)
|
||||
);
|
||||
if (! $this->request->isXmlHttpRequest()) {
|
||||
// In case JS is disabled we must not provide client side validation as
|
||||
// the user is required to input data even he has changed his mind
|
||||
$this->getElement('existing_user')->setAttrib('required', null);
|
||||
$this->getElement('existing_user')->setAttrib('aria-required', null);
|
||||
}
|
||||
}
|
||||
$this->backendConfig['backend'] === 'db'
|
||||
? $this->translate('database', 'setup.admin.authbackend')
|
||||
: 'LDAP'
|
||||
),
|
||||
'multiOptions' => array_combine($users, $users)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->backendConfig['backend'] === 'db') {
|
||||
$choices['new_user'] = $this->translate('New User');
|
||||
$required = isset($formData['user_type']) && $formData['user_type'] === 'new_user';
|
||||
if ($choice === 'new_user') {
|
||||
$this->addElement(
|
||||
'text',
|
||||
'new_user',
|
||||
array(
|
||||
'required' => $required,
|
||||
'required' => true,
|
||||
'label' => $this->translate('Username'),
|
||||
'description' => $this->translate(
|
||||
'Enter the username to be used when creating an initial administrative account'
|
||||
|
@ -141,7 +167,7 @@ class AdminAccountPage extends Form
|
|||
'password',
|
||||
'new_user_password',
|
||||
array(
|
||||
'required' => $required,
|
||||
'required' => true,
|
||||
'label' => $this->translate('Password'),
|
||||
'description' => $this->translate('Enter the password to assign to the newly created account')
|
||||
)
|
||||
|
@ -150,44 +176,16 @@ class AdminAccountPage extends Form
|
|||
'password',
|
||||
'new_user_2ndpass',
|
||||
array(
|
||||
'required' => $required,
|
||||
'required' => true,
|
||||
'label' => $this->translate('Repeat password'),
|
||||
'description' => $this->translate('Please repeat the password given above to avoid typing errors'),
|
||||
'description' => $this->translate(
|
||||
'Please repeat the password given above to avoid typing errors'
|
||||
),
|
||||
'validators' => array(
|
||||
array('identical', false, array('new_user_password'))
|
||||
)
|
||||
)
|
||||
);
|
||||
if (! $this->request->isXmlHttpRequest()) {
|
||||
// In case JS is disabled we must not provide client side validation as
|
||||
// the user is required to input data even he has changed his mind
|
||||
foreach (array('new_user', 'new_user_password', 'new_user_2ndpass') as $elementName) {
|
||||
$this->getElement($elementName)->setAttrib('aria-required', null);
|
||||
$this->getElement($elementName)->setAttrib('required', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($choices) > 1) {
|
||||
$this->addElement(
|
||||
'radio',
|
||||
'user_type',
|
||||
array(
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'value' => key($choices),
|
||||
'multiOptions' => $choices
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->addElement(
|
||||
'hidden',
|
||||
'user_type',
|
||||
array(
|
||||
'required' => true,
|
||||
'value' => key($choices)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +202,7 @@ class AdminAccountPage extends Form
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($data['user_type'] === 'new_user' && array_search($data['new_user'], $this->fetchUsers()) !== false) {
|
||||
if ($data['user_type'] === 'new_user' && !$this->hasUser($data['new_user'])) {
|
||||
$this->getElement('new_user')->addError($this->translate('Username already exists.'));
|
||||
return false;
|
||||
}
|
||||
|
@ -212,26 +210,6 @@ class AdminAccountPage extends Form
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given values (possibly incomplete) are valid
|
||||
*
|
||||
* Unsets all empty text-inputs so that they are not being validated when auto-submitting the form.
|
||||
*
|
||||
* @param array $formData
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
public function isValidPartial(array $formData)
|
||||
{
|
||||
foreach (array('by_name', 'new_user', 'new_user_password', 'new_user_2ndpass') as $elementName) {
|
||||
if (isset($formData[$elementName]) && $formData[$elementName] === '') {
|
||||
unset($formData[$elementName]);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::isValidPartial($formData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the externally authenticated user
|
||||
*
|
||||
|
@ -254,21 +232,41 @@ class AdminAccountPage extends Form
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the names of all users this backend currently provides
|
||||
* Return the names of all users the backend currently provides
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function fetchUsers()
|
||||
{
|
||||
$config = new ConfigObject($this->backendConfig);
|
||||
$config->resource = $this->resourceConfig;
|
||||
$backend = UserBackend::create(null, $config);
|
||||
|
||||
try {
|
||||
return $backend->select(array('user_name'))->order('user_name', 'asc', true)->fetchColumn();
|
||||
return $this->createBackend()->select(array('user_name'))->order('user_name', 'asc', true)->fetchColumn();
|
||||
} catch (Exception $_) {
|
||||
// No need to handle anything special here. Error means no users found.
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the backend provides a user with the given name
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasUser($username)
|
||||
{
|
||||
return $this->createBackend()->select()->where('user_name', $username)->count() > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return the backend
|
||||
*
|
||||
* @return DbUserBackend|LdapUserBackend
|
||||
*/
|
||||
protected function createBackend()
|
||||
{
|
||||
$config = new ConfigObject($this->backendConfig);
|
||||
$config->resource = $this->resourceConfig;
|
||||
return UserBackend::create(null, $config);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Web\Wizard;
|
||||
|
||||
$radioElem = $form->getElement('user_type');
|
||||
$showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
|
||||
|
||||
?>
|
||||
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
|
||||
<h1><?= $this->translate('Administration', 'setup.page.title'); ?></h1>
|
||||
<ul class="descriptions">
|
||||
<li><?= $this->translatePlural(
|
||||
'Now it\'s time to configure your first administrative account for Icinga Web 2. Please follow the instructions below:',
|
||||
'Now it\'s time to configure your first administrative account for Icinga Web 2. Below are several options you can choose from. Select one and follow its instructions:',
|
||||
$showRadioBoxes ? count($radioElem->getMultiOptions()) : 1
|
||||
); ?></li>
|
||||
</ul>
|
||||
<?= $form->getElement('title'); ?>
|
||||
<?= $form->getElement('description'); ?>
|
||||
<?php if (($byNameElem = $form->getElement('by_name')) !== null): ?>
|
||||
<div>
|
||||
<div class="instructions">
|
||||
<?= $showRadioBoxes ? $byNameElem->setAttrib('data-related-radiobtn', 'by_name') : $byNameElem; ?>
|
||||
</div>
|
||||
<?php if ($showRadioBoxes): ?>
|
||||
<div class="radiobox">
|
||||
<label>
|
||||
<input type="radio" id="by_name" name="user_type" value="by_name"<?= $radioElem->getValue() === 'by_name' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
|
||||
<?= $radioElem->getMultiOption('by_name'); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if (($existingUserElem = $form->getElement('existing_user')) !== null): ?>
|
||||
<div>
|
||||
<div class="instructions">
|
||||
<?= $showRadioBoxes ? $existingUserElem->setAttrib('data-related-radiobtn', 'existing_user') : $existingUserElem; ?>
|
||||
</div>
|
||||
<?php if ($showRadioBoxes): ?>
|
||||
<div class="radiobox">
|
||||
<label>
|
||||
<input type="radio" id="existing_user" name="user_type" value="existing_user"<?= $radioElem->getValue() === 'existing_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
|
||||
<?= $radioElem->getMultiOption('existing_user'); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if (($newUserElem = $form->getElement('new_user')) !== null): ?>
|
||||
<div>
|
||||
<div class="instructions">
|
||||
<?= $showRadioBoxes ? $newUserElem->setAttrib('data-related-radiobtn', 'new_user') : $newUserElem; ?>
|
||||
<?= $form->getElement('new_user_password'); ?>
|
||||
<?= $form->getElement('new_user_2ndpass'); ?>
|
||||
</div>
|
||||
<?php if ($showRadioBoxes): ?>
|
||||
<div class="radiobox">
|
||||
<label>
|
||||
<input type="radio" id="new_user" name="user_type" value="new_user"<?= $radioElem->getValue() === 'new_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
|
||||
<?= $radioElem->getMultiOption('new_user'); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if (false === $showRadioBoxes): ?>
|
||||
<?= $radioElem; ?>
|
||||
<?php endif ?>
|
||||
<?= $form->getElement($form->getTokenElementName()); ?>
|
||||
<?= $form->getElement($form->getUidElementName()); ?>
|
||||
<div class="buttons">
|
||||
<?php
|
||||
$btn = clone $form->getElement(Wizard::BTN_NEXT);
|
||||
$btn->setAttrib('class', 'double');
|
||||
$btn->setAttrib('tabindex', -1);
|
||||
echo $btn;
|
||||
?>
|
||||
<?= $form->getElement(Wizard::BTN_PREV); ?>
|
||||
<?= $form->getElement(Wizard::BTN_NEXT); ?>
|
||||
</div>
|
||||
</form>
|
|
@ -232,7 +232,7 @@ select.grant-permissions {
|
|||
}
|
||||
|
||||
label ~ input, label ~ select {
|
||||
margin-left: 1.6em;
|
||||
margin-left: 1.35em;
|
||||
}
|
||||
|
||||
label + i ~ input, label + i ~ select {
|
||||
|
|
Loading…
Reference in New Issue