From d79463e9605fcb1bef250ab3e9cf717227fe04ed Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Willms <tleilax+studip@gmail.com> Date: Wed, 22 Mar 2023 12:27:53 +0000 Subject: [PATCH] implement RolePersistence::getUsersWithRoleByName() and RolePersistence::getUsersWithRoleById(), fixes #2014 Closes #2014 Merge request studip/studip!1311 --- app/controllers/admin/role.php | 24 +++++----- app/views/admin/role/show_role.php | 24 +++++----- lib/plugins/db/RolePersistence.class.php | 56 ++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 24 deletions(-) diff --git a/app/controllers/admin/role.php b/app/controllers/admin/role.php index 513bcbd9c78..c316021cd88 100644 --- a/app/controllers/admin/role.php +++ b/app/controllers/admin/role.php @@ -288,18 +288,17 @@ class Admin_RoleController extends AuthenticatedController $this->roleid = ''; if ($roleid) { - $sql = "SELECT DISTINCT Vorname,Nachname,user_id,username,perms - FROM auth_user_md5 - JOIN roles_user ON userid = user_id - WHERE roleid = ? - ORDER BY Nachname, Vorname"; - $statement = DBManager::get()->prepare($sql); - $statement->execute([$roleid]); - - $users = $statement->fetchAll(PDO::FETCH_ASSOC); - foreach ($users as $key => $user) { - $institutes = new SimpleCollection(Institute::findMany(RolePersistence::getAssignedRoleInstitutes($user['user_id'], $roleid))); - $users[$key]['institutes'] = $institutes->orderBy('name')->pluck('name'); + $this->users = RolePersistence::getUsersWithRoleById($roleid); + + $this->user_institutes = []; + foreach ($this->users as $user) { + $this->user_institutes[$user->id] = Institute::findAndMapMany( + function (Institute $institute) { + return $institute->name; + }, + RolePersistence::getAssignedRoleInstitutes($user['user_id'], $roleid), + 'ORDER BY name' + ); } $plugins = PluginManager::getInstance()->getPluginInfos(); @@ -311,7 +310,6 @@ class Admin_RoleController extends AuthenticatedController $this->implicit_count = RolePersistence::countImplicitUsers($roleid); - $this->users = $users; $this->plugins = $plugins; $this->role = self::getRole($roleid); $this->roleid = $roleid; diff --git a/app/views/admin/role/show_role.php b/app/views/admin/role/show_role.php index e01a952cdb3..196f9bf20b6 100644 --- a/app/views/admin/role/show_role.php +++ b/app/views/admin/role/show_role.php @@ -5,7 +5,8 @@ * @var string $roleid * @var Role[] $roles * @var QuickSearch $mps - * @var array $users + * @var User[] $users + * @var array $user_institutes * @var array $plugins * @var int $implicit_count */ @@ -90,29 +91,30 @@ use Studip\Button; <? foreach (array_values($users) as $index => $user): ?> <tr> <td> - <input type="checkbox" name="ids[]" value="<?= $user['user_id'] ?>"> + <input type="checkbox" name="ids[]" value="<?= htmlReady($user->id) ?>"> </td> <td style="text-align: right;"> <?= $index + 1 ?>. </td> <td> - <a href="<?= $controller->url_for('admin/role/assign_role', $user['user_id']) ?>"> - <?= htmlReady(sprintf('%s %s (%s)', $user['Vorname'], $user['Nachname'], $user['username'])) ?> + <a href="<?= $controller->link_for('admin/role/assign_role', $user->id) ?>"> + <?= htmlReady(sprintf('%s %s (%s)', $user->vorname, $user->nachname, $user->username)) ?> </a> </td> - <td><?= $user['perms'] ?></td> + <td><?= htmlReady($user->perms) ?></td> <td> - <? $institutes = join(', ', $user['institutes']); ?> + <? $institutes = join(', ', $user_institutes[$user->id]); ?> <?= htmlReady(mb_substr($institutes, 0, 60)) ?> <? if (mb_strlen($institutes) > 60): ?> - ...<?= tooltipIcon(join("\n", $user['institutes']))?> + ...<?= tooltipIcon(join("\n", $user_institutes[$user->id]))?> <? endif ?> </td> <td class="actions"> - <?= Icon::create('trash', 'clickable', ['title' => _('Rolle entziehen')]) - ->asInput([ - "data-confirm" => _('Soll dieser Person wirklich die Rolle entzogen werden?'), - "formaction" => $controller->url_for('admin/role/remove_user/'.$roleid.'/'.$user['user_id'])]) ?> + <?= Icon::create('trash')->asInput([ + 'title' => _('Rolle entziehen'), + 'data-confirm' => _('Soll dieser Person wirklich die Rolle entzogen werden?'), + 'formaction' => $controller->url_for('admin/role/remove_user', $roleid, $user->id), + ]) ?> </td> </tr> <? endforeach; ?> diff --git a/lib/plugins/db/RolePersistence.class.php b/lib/plugins/db/RolePersistence.class.php index 3514ca6c6d3..85f47a2a17b 100644 --- a/lib/plugins/db/RolePersistence.class.php +++ b/lib/plugins/db/RolePersistence.class.php @@ -525,6 +525,62 @@ class RolePersistence )); } + /** + * Returns all users that have a specific role - given by it's name. + * + * @param string $role_name Name of the role + * @param bool $only_explicit Only select explicit assignments from table + * `roles_user` if true, otherwise also select + * by perm defined in table `roles_studipperms` + * + * @return User[] + */ + public static function getUsersWithRoleByName(string $role_name, bool $only_explicit = true): array + { + $role_id = self::getRoleIdByName($role_name); + if ($role_id === false) { + throw new Exception("Unknown role name {$role_name}"); + } + + return self::getUsersWithRoleById($role_id, $only_explicit); + } + + /** + * Returns all users that have a specific role - given by it's id. + * + * @param int $role_id Id of the role + * @param bool $only_explicit Only select explicit assignments from table + * `roles_user` if true, otherwise also select + * by perm defined in table `roles_studipperms` + * + * @return User[] + */ + public static function getUsersWithRoleById(int $role_id, bool $only_explicit = true): array + { + $query = "SELECT `userid` AS `user_id` + FROM `roles_user` + WHERE `roleid` = :role_id"; + + if (!$only_explicit) { + $query = "SELECT DISTINCT `user_id` + FROM ( + {$query} + + UNION ALL + + SELECT `user_id` + FROM `roles_studipperms` AS `rsp` + JOIN `auth_user_md5` AS `aum` + ON (`rsp`.`permname` = `aum`.`perms`) + WHERE `rsp`.`roleid` = :role_id + ) AS tmp"; + } + + $user_ids = DBManager::get()->fetchFirst($query, [':role_id' => $role_id]); + + return User::findMany($user_ids); + } + /** * Returns statistic values for each role: * -- GitLab