Merge branch 'bugfix/more-intuitive-admin-account-creation-8704'

fixes #8704
This commit is contained in:
Johannes Meyer 2015-06-30 11:39:33 +02:00
commit 19be028981
3 changed files with 100 additions and 184 deletions

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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 {