diff options
Diffstat (limited to 'application/controllers/GroupController.php')
-rw-r--r-- | application/controllers/GroupController.php | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/application/controllers/GroupController.php b/application/controllers/GroupController.php new file mode 100644 index 0000000..d18397c --- /dev/null +++ b/application/controllers/GroupController.php @@ -0,0 +1,418 @@ +<?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 +{ + public function init() + { + $this->view->title = $this->translate('User Groups'); + + parent::init(); + } + + /** + * List all user groups of a single backend + */ + public function listAction() + { + $this->assertPermission('config/access-control/groups'); + $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 icinga-controls'); + $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/access-control/groups'); + $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/access-control/groups') && $backend instanceof Reducible) { + $removeForm = new Form(); + $removeForm->setUidDisabled(); + $removeForm->setAttrib('class', 'inline'); + $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/access-control/groups'); + $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/access-control/groups'); + $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/access-control/groups'); + $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/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()) + ->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/access-control/groups'); + $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(); + + if ($this->hasPermission('config/access-control/roles')) { + $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( + 'role/audit', + [ + 'title' => $this->translate('Audit a user\'s or group\'s privileges'), + 'label' => $this->translate('Audit'), + 'url' => 'role/audit', + 'baseTarget' => '_main', + ] + ); + } + + if ($this->hasPermission('config/access-control/users')) { + $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; + } +} |