icingaweb2/application/controllers/GroupController.php

394 lines
14 KiB
PHP

<?php
/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
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\Exception\NotFoundError;
use Icinga\Forms\Config\UserGroup\AddMemberForm;
use Icinga\Forms\Config\UserGroup\UserGroupForm;
use Icinga\User;
use Icinga\Web\Controller\AuthBackendController;
use Icinga\Web\Form;
use Icinga\Web\Notification;
use Icinga\Web\Url;
use Icinga\Web\Widget;
class GroupController extends AuthBackendController
{
/**
* List all user groups of a single backend
*/
public function listAction()
{
$this->assertPermission('config/authentication/groups/show');
$this->createListTabs()->activate('group/list');
$backendNames = array_map(
function ($b) {
return $b->getName();
},
$this->loadUserGroupBackends('Icinga\Data\Selectable')
);
if (empty($backendNames)) {
return;
}
$this->view->backendSelection = new Form();
$this->view->backendSelection->setAttrib('class', 'backend-selection');
$this->view->backendSelection->setUidDisabled();
$this->view->backendSelection->setMethod('GET');
$this->view->backendSelection->setTokenDisabled();
$this->view->backendSelection->addElement(
'select',
'backend',
array(
'autosubmit' => true,
'label' => $this->translate('User Group Backend'),
'multiOptions' => array_combine($backendNames, $backendNames),
'value' => $this->params->get('backend')
)
);
$backend = $this->getUserGroupBackend($this->params->get('backend'));
if ($backend === null) {
$this->view->backend = null;
return;
}
$query = $backend->select(array('group_name'));
$this->view->groups = $query;
$this->view->backend = $backend;
$this->setupPaginationControl($query);
$this->setupFilterControl($query);
$this->setupLimitControl();
$this->setupSortControl(
array(
'group_name' => $this->translate('User Group'),
'created_at' => $this->translate('Created at'),
'last_modified' => $this->translate('Last modified')
),
$query
);
}
/**
* Show a group
*/
public function showAction()
{
$this->assertPermission('config/authentication/groups/show');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'));
$group = $backend->select(array(
'group_name',
'created_at',
'last_modified'
))->where('group_name', $groupName)->fetchRow();
if ($group === false) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
$members = $backend
->select()
->from('group_membership', array('user_name'))
->where('group_name', $groupName);
$this->setupFilterControl($members, null, array('user'), array('group'));
$this->setupPaginationControl($members);
$this->setupLimitControl();
$this->setupSortControl(
array(
'user_name' => $this->translate('Username'),
'created_at' => $this->translate('Created at'),
'last_modified' => $this->translate('Last modified')
),
$members
);
$this->view->group = $group;
$this->view->backend = $backend;
$this->view->members = $members;
$this->createShowTabs($backend->getName(), $groupName)->activate('group/show');
if ($this->hasPermission('config/authentication/groups/edit') && $backend instanceof Reducible) {
$removeForm = new Form();
$removeForm->setUidDisabled();
$removeForm->setAction(
Url::fromPath('group/removemember', array('backend' => $backend->getName(), 'group' => $groupName))
);
$removeForm->addElement('hidden', 'user_name', array(
'isArray' => true,
'decorators' => array('ViewHelper')
));
$removeForm->addElement('hidden', 'redirect', array(
'value' => Url::fromPath('group/show', array(
'backend' => $backend->getName(),
'group' => $groupName
)),
'decorators' => array('ViewHelper')
));
$removeForm->addElement('button', 'btn_submit', array(
'escape' => false,
'type' => 'submit',
'class' => 'link-button spinner',
'value' => 'btn_submit',
'decorators' => array('ViewHelper'),
'label' => $this->view->icon('trash'),
'title' => $this->translate('Remove this member')
));
$this->view->removeForm = $removeForm;
}
}
/**
* Add a group
*/
public function addAction()
{
$this->assertPermission('config/authentication/groups/add');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Extensible');
$form = new UserGroupForm();
$form->setRedirectUrl(Url::fromPath('group/list', array('backend' => $backend->getName())));
$form->setRepository($backend);
$form->add()->handleRequest();
$this->renderForm($form, $this->translate('New User Group'));
}
/**
* Edit a group
*/
public function editAction()
{
$this->assertPermission('config/authentication/groups/edit');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Updatable');
$form = new UserGroupForm();
$form->setRedirectUrl(
Url::fromPath('group/show', array('backend' => $backend->getName(), 'group' => $groupName))
);
$form->setRepository($backend);
try {
$form->edit($groupName)->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
$this->renderForm($form, $this->translate('Update User Group'));
}
/**
* Remove a group
*/
public function removeAction()
{
$this->assertPermission('config/authentication/groups/remove');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Reducible');
$form = new UserGroupForm();
$form->setRedirectUrl(Url::fromPath('group/list', array('backend' => $backend->getName())));
$form->setRepository($backend);
try {
$form->remove($groupName)->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
$this->renderForm($form, $this->translate('Remove User Group'));
}
/**
* Add a group member
*/
public function addmemberAction()
{
$this->assertPermission('config/authentication/groups/edit');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Extensible');
$form = new AddMemberForm();
$form->setDataSource($this->fetchUsers())
->setBackend($backend)
->setGroupName($groupName)
->setRedirectUrl(
Url::fromPath('group/show', array('backend' => $backend->getName(), 'group' => $groupName))
)
->setUidDisabled();
try {
$form->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
$this->renderForm($form, $this->translate('New User Group Member'));
}
/**
* Remove a group member
*/
public function removememberAction()
{
$this->assertPermission('config/authentication/groups/edit');
$this->assertHttpMethod('POST');
$groupName = $this->params->getRequired('group');
$backend = $this->getUserGroupBackend($this->params->getRequired('backend'), 'Icinga\Data\Reducible');
$form = new Form(array(
'onSuccess' => function ($form) use ($groupName, $backend) {
foreach ($form->getValue('user_name') as $userName) {
try {
$backend->delete(
'group_membership',
Filter::matchAll(
Filter::where('group_name', $groupName),
Filter::where('user_name', $userName)
)
);
Notification::success(sprintf(
t('User "%s" has been removed from group "%s"'),
$userName,
$groupName
));
} catch (NotFoundError $e) {
throw $e;
} catch (Exception $e) {
Notification::error($e->getMessage());
}
}
$redirect = $form->getValue('redirect');
if (! empty($redirect)) {
$form->setRedirectUrl(htmlspecialchars_decode($redirect));
}
return true;
}
));
$form->setUidDisabled();
$form->setSubmitLabel('btn_submit'); // Required to ensure that isSubmitted() is called
$form->addElement('hidden', 'user_name', array('required' => true, 'isArray' => true));
$form->addElement('hidden', 'redirect');
try {
$form->handleRequest();
} catch (NotFoundError $_) {
$this->httpNotFound(sprintf($this->translate('Group "%s" not found'), $groupName));
}
}
/**
* Fetch and return all users from all user backends
*
* @return ArrayDatasource
*/
protected function fetchUsers()
{
$users = array();
foreach ($this->loadUserBackends('Icinga\Data\Selectable') as $backend) {
try {
if ($backend instanceof DomainAwareInterface) {
$domain = $backend->getDomain();
} else {
$domain = null;
}
foreach ($backend->select(array('user_name')) as $user) {
$userObj = new User($user->user_name);
if ($domain !== null) {
if ($userObj->hasDomain() && $userObj->getDomain() !== $domain) {
// Users listed in a user backend which is configured to be responsible for a domain should
// not have a domain in their username. Ultimately, if the username has a domain, it must
// not differ from the backend's domain. We could log here - but hey, who cares :)
continue;
} else {
$userObj->setDomain($domain);
}
}
$user->user_name = $userObj->getUsername();
$users[] = $user;
}
} catch (Exception $e) {
Logger::error($e);
Notification::warning(sprintf(
$this->translate('Failed to fetch any users from backend %s. Please check your log'),
$backend->getName()
));
}
}
return new ArrayDatasource($users);
}
/**
* Create the tabs to display when showing a group
*
* @param string $backendName
* @param string $groupName
*/
protected function createShowTabs($backendName, $groupName)
{
$tabs = $this->getTabs();
$tabs->add(
'group/show',
array(
'title' => sprintf($this->translate('Show group %s'), $groupName),
'label' => $this->translate('Group'),
'url' => Url::fromPath('group/show', array('backend' => $backendName, 'group' => $groupName))
)
);
return $tabs;
}
/**
* Create the tabs to display when listing groups
*/
protected function createListTabs()
{
$tabs = $this->getTabs();
$tabs->add(
'role/list',
array(
'baseTarget' => '_main',
'label' => $this->translate('Roles'),
'title' => $this->translate(
'Configure roles to permit or restrict users and groups accessing Icinga Web 2'
),
'url' => 'role/list'
)
);
$tabs->add(
'user/list',
array(
'title' => $this->translate('List users of authentication backends'),
'label' => $this->translate('Users'),
'url' => 'user/list'
)
);
$tabs->add(
'group/list',
array(
'title' => $this->translate('List groups of user group backends'),
'label' => $this->translate('User Groups'),
'url' => 'group/list'
)
);
return $tabs;
}
}