Skip to content

Commit

Permalink
Introduce search field to add member to the user group
Browse files Browse the repository at this point in the history
  • Loading branch information
sukhwinder33445 committed Mar 8, 2022
1 parent 0437107 commit eced130
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 124 deletions.
44 changes: 33 additions & 11 deletions application/controllers/GroupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
namespace Icinga\Controllers;

use Exception;
use GuzzleHttp\Psr7\ServerRequest;
use Icinga\Application\Logger;
use Icinga\Authentication\User\DomainAwareInterface;
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,10 +19,11 @@
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
{
protected $urlParams;
public function init()
{
$this->view->title = $this->translate('User Groups');
Expand Down Expand Up @@ -225,23 +228,42 @@ public function addmemberAction()
$this->assertPermission('config/access-control/groups');
$groupName = $this->params->getRequired('group');
$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))
)
->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());
});
$form->handleRequest(ServerRequest::fromGlobals());

$this->setTitle($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();
$suggestions->setUserGroupName($groupName);
$suggestions->setUserGroupBackend($backend);
$suggestions->setBackends($this->loadUserBackends('Icinga\Data\Selectable'));
$suggestions->forRequest(ServerRequest::fromGlobals());
$this->getDocument()->add($suggestions);
}

/**
Expand Down
132 changes: 19 additions & 113 deletions application/forms/Config/UserGroup/AddMemberForm.php
Original file line number Diff line number Diff line change
@@ -1,129 +1,39 @@
<?php
/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
/* Icinga Web 2 | (c) 2022 Icinga Development Team | 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;

/**
* 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
*
* @var Extensible
*/
protected $backend;

/**
* The group to add members for
*
* @var string
*/
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
*
* @param Extensible $backend
*
* @return $this
* @param mixed $backend
*/
public function setBackend(Extensible $backend)
public function setBackend($backend)
{
$this->backend = $backend;

return $this;
}

/**
* Set the group to add members for
*
* @param string $groupName
*
* @return $this
* @param mixed $groupName
*/
public function setGroupName($groupName)
{
$this->groupName = $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'));
return $this;
}

/**
Expand All @@ -133,48 +43,44 @@ public function createElements(array $formData)
*/
public function onSuccess()
{
$userNames = $this->getValue('user_name') ?: array();
if (($users = $this->getValue('users'))) {
$userNames = array_merge($userNames, array_map('trim', explode(',', $users)));
}

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'
));
$q = $this->getValue($this->getSearchParameter());
if (empty($q)) {
Notification::error(t('Please provide at least one username'));
return false;
}

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

$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;
}

$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;
Expand Down
Loading

0 comments on commit eced130

Please sign in to comment.