From cab2069fa25bfc5df17a498fda63e29a9a9bf304 Mon Sep 17 00:00:00 2001 From: Baptiste Fotia Date: Thu, 4 Apr 2024 11:51:16 +0200 Subject: [PATCH] feat(Service,Share): Limit the search to members Limit the search to members of the same group except for specific groups. I splited the code in 2 classes : - GroupMembersOnlyChecker : To check if the checkbox for the "Allow apps to use the Share API" and check if groups are listed from the multiselect. - ShareMembersOnlyFilter : to get the members only the same group or excepted a few groups from the multiselect. Return users with common groups. Except users belonging to groups listed in the drop-down list (`Settings > Share > Restrict users to only share with users in their groups > Ingore the following groups when cheking group membership`). Signed-off-by: Baptiste Fotia --- lib/Service/WorkspaceService.php | 43 +++++-------- lib/Share/Group/GroupMembersOnlyChecker.php | 49 +++++++++++++++ lib/Share/Group/ShareMembersOnlyFilter.php | 70 +++++++++++++++++++++ 3 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 lib/Share/Group/GroupMembersOnlyChecker.php create mode 100644 lib/Share/Group/ShareMembersOnlyFilter.php diff --git a/lib/Service/WorkspaceService.php b/lib/Service/WorkspaceService.php index f54da3958..6a71e0fb0 100644 --- a/lib/Service/WorkspaceService.php +++ b/lib/Service/WorkspaceService.php @@ -28,8 +28,9 @@ use OCA\Workspace\Db\SpaceMapper; use OCA\Workspace\Service\Group\UserGroup; use OCA\Workspace\Service\Group\WorkspaceManagerGroup; +use OCA\Workspace\Share\Group\GroupMembersOnlyChecker; +use OCA\Workspace\Share\Group\ShareMembersOnlyFilter; use OCP\IGroupManager; -use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Share\IManager; @@ -43,7 +44,9 @@ public function __construct( private IUserSession $userSession, private LoggerInterface $logger, private SpaceMapper $spaceMapper, - private UserService $userService + private UserService $userService, + private ShareMembersOnlyFilter $shareMembersFilter, + private GroupMembersOnlyChecker $memberGroupOnlyChecker ) { } @@ -87,24 +90,6 @@ private function searchUsers(string $term): array { return $users; } - /** - * @param IUser[] $users - * @return IUser[] - */ - private function getUsersFromGroupsOnly(array $users): array { - $usersFromGroups = []; - $userSession = $this->userSession->getUser(); - $groupsOfUserSession = $this->groupManager->getUserGroups($userSession); - foreach ($groupsOfUserSession as $group) { - $usersFromGroups = array_merge($usersFromGroups, $group->getUsers()); - } - - $usersFromGroups = array_filter($usersFromGroups, function ($user) use ($users) { - return in_array($user, $users); - }); - - return $usersFromGroups; - } /** * Returns a list of users whose name matches $term @@ -125,8 +110,14 @@ public function autoComplete(string $term, array|string $space): array { } } - if ($this->shareManager->shareWithGroupMembersOnly()) { - $users = $this->getUsersFromGroupsOnly($users); + if ($this->memberGroupOnlyChecker->checkboxIsChecked()) { + $users = $this->shareMembersFilter->filterUsersGroupOnly($users); + } + + if ($this->memberGroupOnlyChecker->groupsExcludeSelected()) { + if ($this->memberGroupOnlyChecker->checkMemberInGroupExcluded()) { + $users = $this->shareMembersFilter->excludeGroupsList($users); + } } // transform in a format suitable for the app @@ -170,7 +161,7 @@ public function addUsersInfo(string|array $workspace): array { // Caution: It is important to add users from the workspace's user group before adding the users // from the workspace's manager group, as users may be members of both groups $this->logger->debug('Adding users information to workspace'); - $users = array(); + $users = []; $group = $this->groupManager->get(UserGroup::get($workspace['id'])); // TODO Handle is_null($group) better (remove workspace from list?) if (!is_null($group)) { @@ -199,13 +190,13 @@ public function addUsersInfo(string|array $workspace): array { * */ public function addGroupsInfo(array|string $workspace): array { - $groups = array(); + $groups = []; foreach (array_keys($workspace['groups']) as $gid) { $NCGroup = $this->groupManager->get($gid); - $groups[$gid] = array( + $groups[$gid] = [ 'gid' => $NCGroup->getGID(), 'displayName' => $NCGroup->getDisplayName() - ); + ]; } $workspace['groups'] = $groups; diff --git a/lib/Share/Group/GroupMembersOnlyChecker.php b/lib/Share/Group/GroupMembersOnlyChecker.php new file mode 100644 index 000000000..906b61e03 --- /dev/null +++ b/lib/Share/Group/GroupMembersOnlyChecker.php @@ -0,0 +1,49 @@ +shareManager->shareWithGroupMembersOnly(); + } + + public function groupsExcludeSelected(): bool { + if ( + method_exists( + $this->shareManager, + "shareWithGroupMembersOnlyExcludeGroupsList" + ) + ) { + return $this->shareManager->shareWithGroupMembersOnly() + && !empty($this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList()); + } + + return false; + } + + public function checkMemberInGroupExcluded(): bool { + $excludedGroups = $this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList(); + + $userSession = $this->userSession->getUser(); + $uid = $userSession->getUID(); + + foreach ($excludedGroups as $gid) { + if ($this->groupManager->isInGroup($uid, $gid)) { + return true; + } + } + + return false; + } +} diff --git a/lib/Share/Group/ShareMembersOnlyFilter.php b/lib/Share/Group/ShareMembersOnlyFilter.php new file mode 100644 index 000000000..59cef13e8 --- /dev/null +++ b/lib/Share/Group/ShareMembersOnlyFilter.php @@ -0,0 +1,70 @@ + Share > Restrict users to only share with users in their groups > Ingore the following groups when cheking group membership`). + */ + public function excludeGroupsList(array $users): array { + $usersNotExclude = []; + + if (method_exists($this->shareManager, "shareWithGroupMembersOnlyExcludeGroupsList")) { + $excludedGroups = $this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList(); + $userSession = $this->userSession->getUser(); + $groupsOfUserSession = $this->groupManager->getUserGroups($userSession); + $groupnamesOfUserSession = array_map(fn ($group) => $group->getGID(), $groupsOfUserSession); + + if (!empty($excludedGroups)) { + $usersNotExclude = array_filter($users, function ($user) use ($excludedGroups, $groupnamesOfUserSession) { + $groups = $this->groupManager->getUserGroups($user); + $groupnames = array_values(array_map(fn ($group) => $group->getGID(), $groups)); + $commonGroups = array_intersect($groupnamesOfUserSession, $groupnames); + return count(array_diff($commonGroups, $excludedGroups)) !== 0; + }); + } + + return $usersNotExclude; + } + } + + /** + * @param IUser[] $users + * + * @return IUser[] + */ + public function filterUsersGroupOnly(array $users): array { + $usersInTheSameGroup = []; + $userSession = $this->userSession->getUser(); + $groupsOfUserSession = $this->groupManager->getUserGroups($userSession); + + foreach ($groupsOfUserSession as $group) { + $usersInTheSameGroup = array_merge($usersInTheSameGroup, $group->getUsers()); + } + + $usersInTheSameGroup = array_filter( + $users, + function ($user) use ($usersInTheSameGroup) { + $usernames = array_values(array_map(fn ($user) => $user->getUID(), $usersInTheSameGroup)); + return in_array($user->getUID(), $usernames); + }); + + return $usersInTheSameGroup; + } +}