-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Respect user enumeration settings in user status lists #27879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,9 @@ | |
| use OCA\UserStatus\Exception\StatusMessageTooLongException; | ||
| use OCP\AppFramework\Db\DoesNotExistException; | ||
| use OCP\AppFramework\Utility\ITimeFactory; | ||
| use OCP\IConfig; | ||
| use OCP\IGroupManager; | ||
| use OCP\IUserSession; | ||
| use OCP\UserStatus\IUserStatus; | ||
|
|
||
| /** | ||
|
|
@@ -56,6 +59,18 @@ class StatusService { | |
| /** @var EmojiService */ | ||
| private $emojiService; | ||
|
|
||
| /** @var IUserSession */ | ||
| private $userSession; | ||
|
|
||
| /** @var IGroupManager */ | ||
| private $groupManager; | ||
|
|
||
| /** @var bool */ | ||
| private $shareeEnumeration; | ||
|
|
||
| /** @var bool */ | ||
| private $shareeEnumerationInGroupOnly; | ||
|
|
||
| /** | ||
| * List of priorities ordered by their priority | ||
| */ | ||
|
|
@@ -88,17 +103,27 @@ class StatusService { | |
| * | ||
| * @param UserStatusMapper $mapper | ||
| * @param ITimeFactory $timeFactory | ||
| * @param PredefinedStatusService $defaultStatusService, | ||
| * @param PredefinedStatusService $defaultStatusService | ||
| * @param EmojiService $emojiService | ||
| * @param IUserSession $userSession | ||
| * @param IGroupManager $groupManager | ||
| * @param IConfig $config | ||
| */ | ||
| public function __construct(UserStatusMapper $mapper, | ||
| ITimeFactory $timeFactory, | ||
| PredefinedStatusService $defaultStatusService, | ||
| EmojiService $emojiService) { | ||
| EmojiService $emojiService, | ||
| IUserSession $userSession, | ||
| IGroupManager $groupManager, | ||
| IConfig $config) { | ||
| $this->mapper = $mapper; | ||
| $this->timeFactory = $timeFactory; | ||
| $this->predefinedStatusService = $defaultStatusService; | ||
| $this->emojiService = $emojiService; | ||
| $this->userSession = $userSession; | ||
| $this->groupManager = $groupManager; | ||
| $this->shareeEnumeration = $config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; | ||
| $this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes'; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -107,6 +132,19 @@ public function __construct(UserStatusMapper $mapper, | |
| * @return UserStatus[] | ||
| */ | ||
| public function findAll(?int $limit = null, ?int $offset = null): array { | ||
| // Return empty array if user enumeration is disabled | ||
| if (!$this->shareeEnumeration) { | ||
| return []; | ||
| } | ||
|
|
||
| // Return only users from common groups if user enumeration is limited to groups | ||
| if ($this->shareeEnumerationInGroupOnly) { | ||
| $userIds = $this->userIdsByGroups(); | ||
| return array_map(function ($status) { | ||
| return $this->processStatus($status); | ||
| }, $this->mapper->findByUserIds($userIds, $limit, $offset)); | ||
| } | ||
|
|
||
| return array_map(function ($status) { | ||
| return $this->processStatus($status); | ||
| }, $this->mapper->findAll($limit, $offset)); | ||
|
|
@@ -118,6 +156,19 @@ public function findAll(?int $limit = null, ?int $offset = null): array { | |
| * @return array | ||
| */ | ||
| public function findAllRecentStatusChanges(?int $limit = null, ?int $offset = null): array { | ||
| // Return empty array if user enumeration is disabled | ||
| if (!$this->shareeEnumeration) { | ||
| return []; | ||
| } | ||
|
|
||
| // Return only users from common groups if user enumeration is limited to groups | ||
| if ($this->shareeEnumerationInGroupOnly) { | ||
| $userIds = $this->userIdsByGroups(); | ||
| return array_map(function ($status) { | ||
| return $this->processStatus($status); | ||
| }, $this->mapper->findRecentByUserIds($userIds, $limit, $offset)); | ||
| } | ||
|
|
||
| return array_map(function ($status) { | ||
| return $this->processStatus($status); | ||
| }, $this->mapper->findAllRecent($limit, $offset)); | ||
|
|
@@ -328,6 +379,26 @@ public function removeUserStatus(string $userId): bool { | |
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * @return string[] | ||
| */ | ||
| private function userIdsByGroups(): array { | ||
| $usersByGroups = []; | ||
|
|
||
| $currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser()); | ||
| foreach ($currentUserGroups as $userGroupId) { | ||
| $usersInGroup = $this->groupManager->displayNamesInGroup($userGroupId); | ||
| foreach ($usersInGroup as $userId => $displayName) { | ||
| $userId = (string)$userId; | ||
| if (!in_array($userId, $usersByGroups, true)) { | ||
| $usersByGroups[] = $userId; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return $usersByGroups; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this does not scale. We need to do it in another way. In worst case someone is in hundreds of (automated) groups, you run hundreds of queries to generate the user list to then later know that they don't even have a status set or something. Can't we do it similar to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mhhh, you certainly have an argument here 😬 But I'm unsure whether the other way around scales better: It's rather unlikely that the desired 8 users from shared groups with recent status changes are amongh the first 100. So in many cases we'll end up iterating over all users with recent status changes. And for each user we have to check whether they're in a shared group. So I see two approaches and I'm not sure which one scales better:
@nickvergessen you're way more experienced, so I'd trust you on what scales better on common setups/instances. Besides: I'm not sure what you mean with your reference to |
||
| } | ||
|
|
||
| /** | ||
| * Processes a status to check if custom message is still | ||
| * up to date and provides translated default status if needed | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.