Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce user search field to search users #4691

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions application/controllers/GroupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Reducible;
use Icinga\Data\UserSuggestions;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Config\UserGroup\AddMemberForm;
use Icinga\Forms\Config\UserGroup\UserGroupForm;
Expand All @@ -17,7 +18,7 @@
use Icinga\Web\Form;
use Icinga\Web\Notification;
use Icinga\Web\Url;
use Icinga\Web\Widget;
use ipl\Web\Url as IplUrl;

class GroupController extends AuthBackendController
{
Expand Down Expand Up @@ -224,24 +225,50 @@ public function addmemberAction()
{
$this->assertPermission('config/access-control/groups');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Extensible');
$backend = $this->getUserGroupBackend(
$this->params->getRequired('backend'),
'Icinga\Data\Extensible'
);

$form = new AddMemberForm();
$form->setDataSource($this->fetchUsers())
$form = (new AddMemberForm())
->setBackend($backend)
->setGroupName($groupName)
->setRedirectUrl(
Url::fromPath('group/show', array('backend' => $backend->getName(), 'group' => $groupName))
IplUrl::fromPath('group/show', ['backend' => $backend->getName(), 'group' => $groupName])
)
->setUidDisabled();
->setSuggestionUrl(IplUrl::fromPath(
'group/complete',
[
'_disableLayout' => true,
'showCompact' => true,
'backend' => $this->params->getRequired('backend'),
'group' => $groupName
]
));

try {
$form->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
$form->on(AddMemberForm::ON_SUCCESS, function ($form) {
$this->getResponse()->redirectAndExit($form->getRedirectUrl());
})->handleRequest($this->getServerRequest());

$this->addTitleTab($this->translate('New User Group Member'));
$this->addContent($form);
}

public function completeAction()
{
$backend = $this->getUserGroupBackend(
$this->params->getRequired('backend'),
'Icinga\Data\Extensible'
);

$groupName = $this->params->getRequired('group');

$this->renderForm($form, $this->translate('New User Group Member'));
$suggestions = (new UserSuggestions())
->setUserGroupName($groupName)
->setUserGroupBackend($backend)
->setUserBackends($this->loadUserBackends('Icinga\Data\Selectable'))
->forRequest($this->getServerRequest());
$this->getDocument()->addHtml($suggestions);
}

/**
Expand Down
119 changes: 18 additions & 101 deletions application/forms/Config/UserGroup/AddMemberForm.php
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
<?php
/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
/* Icinga Web 2 | (c) 2015 Icinga GmbH | GPLv2+ */

namespace Icinga\Forms\Config\UserGroup;

use Exception;
use Icinga\Data\Extensible;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Selectable;
use Icinga\Exception\NotFoundError;
use Icinga\Web\Form;
use Icinga\Web\Notification;
use ipl\Web\Control\SimpleSearchField;

/**
* Form for adding one or more group members
*/
class AddMemberForm extends Form
class AddMemberForm extends SimpleSearchField
{
/**
* The data source to fetch users from
*
* @var Selectable
*/
protected $ds;

/**
* The user group backend to use
*
Expand All @@ -37,19 +27,6 @@ class AddMemberForm extends Form
*/
protected $groupName;

/**
* Set the data source to fetch users from
*
* @param Selectable $ds
*
* @return $this
*/
public function setDataSource(Selectable $ds)
{
$this->ds = $ds;
return $this;
}

/**
* Set the user group backend to use
*
Expand All @@ -76,107 +53,47 @@ public function setGroupName($groupName)
return $this;
}

/**
* Create and add elements to this form
*
* @param array $formData The data sent by the user
*/
public function createElements(array $formData)
{
// TODO(jom): Fetching already existing members to prevent the user from mistakenly creating duplicate
// memberships (no matter whether the data source permits it or not, a member does never need to be
// added more than once) should be kept at backend level (GroupController::fetchUsers) but this does
// not work currently as our ldap protocol stuff is unable to handle our filter implementation..
$members = $this->backend
->select()
->from('group_membership', array('user_name'))
->where('group_name', $this->groupName)
->fetchColumn();
$filter = empty($members) ? Filter::matchAll() : Filter::not(Filter::where('user_name', $members));

$users = $this->ds->select()->from('user', array('user_name'))->applyFilter($filter)->fetchColumn();
if (! empty($users)) {
$this->addElement(
'multiselect',
'user_name',
array(
'multiOptions' => array_combine($users, $users),
'label' => $this->translate('Backend Users'),
'description' => $this->translate(
'Select one or more users (fetched from your user backends) to add as group member'
),
'class' => 'grant-permissions'
)
);
}

$this->addElement(
'textarea',
'users',
array(
'required' => empty($users),
'label' => $this->translate('Users'),
'description' => $this->translate(
'Provide one or more usernames separated by comma to add as group member'
)
)
);

$this->setTitle(sprintf($this->translate('Add members for group %s'), $this->groupName));
$this->setSubmitLabel($this->translate('Add'));
}

/**
* Insert the members for the group
*
* @return bool
*/
public function onSuccess()
{
$userNames = $this->getValue('user_name') ?: array();
if (($users = $this->getValue('users'))) {
$userNames = array_merge($userNames, array_map('trim', explode(',', $users)));
}
$q = $this->getValue($this->getSearchParameter(), '');

$userNames = array_unique(array_filter(
array_map('trim', explode(self::TERM_SEPARATOR, rawurldecode($q)))
));

if (empty($userNames)) {
$this->info($this->translate(
'Please provide at least one username, either by choosing one '
. 'in the list or by manually typing one in the text box below'
));
return false;
Notification::info(t('Please provide at least one username'));

return;
}

$single = null;
foreach ($userNames as $userName) {
try {
$this->backend->insert(
'group_membership',
array(
[
'group_name' => $this->groupName,
'user_name' => $userName
)
]
);
} catch (NotFoundError $e) {
throw $e; // Trigger 404, the group name is initially accessed as GET parameter
} catch (Exception $e) {
Notification::error(sprintf(
$this->translate('Failed to add "%s" as group member for "%s"'),
t('Failed to add "%s" as group member for "%s"'),
$userName,
$this->groupName
));
$this->error($e->getMessage());
return false;

return;
}

$single = $single === null;
}

if ($single) {
Notification::success(sprintf($this->translate('Group member "%s" added successfully'), $userName));
Notification::success(sprintf(t('Group member "%s" added successfully'), $userName));
} else {
Notification::success($this->translate('Group members added successfully'));
Notification::success(t('Group members added successfully'));
}

return true;
}
}
Loading