diff --git a/application/controllers/RoleController.php b/application/controllers/RoleController.php index c0df218ab..f3f6591f6 100644 --- a/application/controllers/RoleController.php +++ b/application/controllers/RoleController.php @@ -5,15 +5,22 @@ namespace Icinga\Controllers; use Exception; use GuzzleHttp\Psr7\ServerRequest; +use Icinga\Authentication\AdmissionLoader; +use Icinga\Authentication\Auth; use Icinga\Authentication\RolesConfig; use Icinga\Data\Selectable; use Icinga\Exception\NotFoundError; use Icinga\Forms\Security\RoleForm; +use Icinga\Module\Icingadb\Widget\EmptyState; use Icinga\Repository\Repository; use Icinga\Security\SecurityException; +use Icinga\User; use Icinga\Web\Controller\AuthBackendController; +use Icinga\Web\View\PrivilegeAudit; use Icinga\Web\Widget\SingleValueSearchControl; +use ipl\Html\Html; use ipl\Web\Url; +use ipl\Web\Widget\Link; /** * Manage user permissions and restrictions based on roles @@ -137,7 +144,9 @@ class RoleController extends AuthBackendController { $this->assertPermission('config/access-control/roles'); $this->createListTabs()->activate('role/audit'); + $this->view->title = t('Audit'); + $roleName = $this->params->get('role'); $type = $this->params->has('group') ? 'group' : 'user'; $name = $this->params->get($type); @@ -167,7 +176,68 @@ class RoleController extends AuthBackendController $this->redirectNow(Url::fromPath('role/audit', $params)); })->handleRequest(ServerRequest::fromGlobals()); - $this->content->add($form); + $this->addControl($form); + + if (! $name) { + $this->addContent(new EmptyState(t('No user or group selected.'))); + return; + } + + if ($type === 'user') { + $header = Html::tag('h2', sprintf(t('Privilege Audit for User "%s"'), $name)); + + $user = new User($name); + $user->setAdditional('backend_name', $backend); + Auth::getInstance()->setupUser($user); + } else { + $header = Html::tag('h2', sprintf(t('Privilege Audit for Group "%s"'), $name)); + + $user = new User((string) time()); + $user->setGroups([$name]); + (new AdmissionLoader())->applyRoles($user); + } + + $chosenRole = null; + $assignedRoles = array_filter($user->getRoles(), function ($role) use ($user, &$chosenRole, $roleName) { + if (! in_array($role->getName(), $user->getAdditional('assigned_roles'), true)) { + return false; + } + + if ($role->getName() === $roleName) { + $chosenRole = $role; + } + + return true; + }); + + $this->addControl(Html::tag( + 'ul', + ['class' => 'privilege-audit-role-control'], + [ + Html::tag('li', $roleName ? null : ['class' => 'active'], new Link( + t('All roles'), + Url::fromRequest()->without('role'), + ['class' => 'button-link', 'title' => t('Show privileges of all roles')] + )), + array_map(function ($role) use ($roleName) { + return Html::tag( + 'li', + $role->getName() === $roleName ? ['class' => 'active'] : null, + new Link( + $role->getName(), + Url::fromRequest()->setParam('role', $role->getName()), + [ + 'class' => 'button-link', + 'title' => sprintf(t('Only show privileges of role %s'), $role->getName()) + ] + ) + ); + }, $assignedRoles) + ] + )); + + $this->addControl($header); + $this->addContent(new PrivilegeAudit($chosenRole !== null ? [$chosenRole] : $assignedRoles)); } public function suggestRoleMemberAction() diff --git a/public/css/icinga/audit.less b/public/css/icinga/audit.less index d65f89ca5..fae337cec 100644 --- a/public/css/icinga/audit.less +++ b/public/css/icinga/audit.less @@ -1,5 +1,18 @@ // Style +.privilege-audit-role-control { + list-style-type: none; + + li { + .rounded-corners(3px); + border: 1px solid @low-sat-blue; + + &.active { + border-color: @icinga-blue; + } + } +} + .privilege-audit { &, ul, ol { list-style-type: none; @@ -103,6 +116,22 @@ // Layout +.privilege-audit-role-control { + display: inline-flex; + flex-wrap: wrap; + + margin: 0 0 0 1em; + padding: 0; + + li { + margin-top: @vertical-padding; + + &:not(:first-child) { + margin-left: .5em; + } + } +} + .privilege-audit { &, ul, ol { margin: 0;