diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php index 0564fb29d9b..468e64793fc 100644 --- a/apps/settings/lib/Settings/Admin/Sharing.php +++ b/apps/settings/lib/Settings/Admin/Sharing.php @@ -55,6 +55,7 @@ class Sharing implements IDelegatedSettings { 'restrictUserEnumerationToPhone' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_to_phone'), 'restrictUserEnumerationFullMatch' => $this->shareManager->allowEnumerationFullMatch(), 'restrictUserEnumerationFullMatchUserId' => $this->shareManager->matchUserId(), + 'restrictUserEnumerationFullMatchDisplayname' => $this->shareManager->matchDisplayName(), 'restrictUserEnumerationFullMatchEmail' => $this->shareManager->matchEmail(), 'restrictUserEnumerationFullMatchIgnoreSecondDN' => $this->shareManager->ignoreSecondDisplayName(), 'enforceLinksPassword' => Util::isPublicLinkPasswordRequired(false), diff --git a/apps/settings/src/components/AdminSettingsSharingForm.vue b/apps/settings/src/components/AdminSettingsSharingForm.vue index 8d8afb6e068..fc3fb410207 100644 --- a/apps/settings/src/components/AdminSettingsSharingForm.vue +++ b/apps/settings/src/components/AdminSettingsSharingForm.vue @@ -230,6 +230,9 @@ {{ t('settings', 'Also allow autocompletion on full match of the user ID') }} + + {{ t('settings', 'Also allow autocompletion on full match of the display name') }} + {{ t('settings', 'Also allow autocompletion on full match of the user email') }} @@ -291,6 +294,7 @@ interface IShareSettings { restrictUserEnumerationToPhone: boolean restrictUserEnumerationFullMatch: boolean restrictUserEnumerationFullMatchUserId: boolean + restrictUserEnumerationFullMatchDisplayname: boolean restrictUserEnumerationFullMatchEmail: boolean restrictUserEnumerationFullMatchIgnoreSecondDN: boolean enforceLinksPassword: boolean diff --git a/apps/settings/tests/Settings/Admin/SharingTest.php b/apps/settings/tests/Settings/Admin/SharingTest.php index 3cc4b6a24d6..4b9745ea599 100644 --- a/apps/settings/tests/Settings/Admin/SharingTest.php +++ b/apps/settings/tests/Settings/Admin/SharingTest.php @@ -77,6 +77,7 @@ class SharingTest extends TestCase { ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_user_id', 'yes', 'yes'], + ['core', 'shareapi_restrict_user_enumeration_full_match_displayname', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no', 'no'], ['core', 'shareapi_enabled', 'yes', 'yes'], @@ -120,6 +121,7 @@ class SharingTest extends TestCase { 'restrictUserEnumerationToPhone' => false, 'restrictUserEnumerationFullMatch' => true, 'restrictUserEnumerationFullMatchUserId' => true, + 'restrictUserEnumerationFullMatchDisplayname' => true, 'restrictUserEnumerationFullMatchEmail' => true, 'restrictUserEnumerationFullMatchIgnoreSecondDN' => false, 'enforceLinksPassword' => false, @@ -172,6 +174,7 @@ class SharingTest extends TestCase { ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_user_id', 'yes', 'yes'], + ['core', 'shareapi_restrict_user_enumeration_full_match_displayname', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no', 'no'], ['core', 'shareapi_enabled', 'yes', 'yes'], @@ -217,6 +220,7 @@ class SharingTest extends TestCase { 'restrictUserEnumerationToPhone' => false, 'restrictUserEnumerationFullMatch' => true, 'restrictUserEnumerationFullMatchUserId' => true, + 'restrictUserEnumerationFullMatchDisplayname' => true, 'restrictUserEnumerationFullMatchEmail' => true, 'restrictUserEnumerationFullMatchIgnoreSecondDN' => false, 'enforceLinksPassword' => false, diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index 7b9cf206b9b..6ff0c717145 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -31,6 +31,8 @@ class UserPlugin implements ISearchPlugin { protected bool $shareeEnumerationFullMatchUserId; + protected bool $shareeEnumerationfullMatchDisplayname; + protected bool $shareeEnumerationFullMatchEmail; protected bool $shareeEnumerationFullMatchIgnoreSecondDisplayName; @@ -50,6 +52,7 @@ class UserPlugin implements ISearchPlugin { $this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes'; $this->shareeEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes'; $this->shareeEnumerationFullMatchUserId = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_user_id', 'yes') === 'yes'; + $this->shareeEnumerationfullMatchDisplayname = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_displayname', 'yes') === 'yes'; $this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes'; $this->shareeEnumerationFullMatchIgnoreSecondDisplayName = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes'; @@ -112,7 +115,7 @@ class UserPlugin implements ISearchPlugin { } // additionally we need to add full matches - if ($this->shareeEnumerationFullMatch) { + if ($this->shareeEnumerationFullMatch && $this->shareeEnumerationfullMatchDisplayname) { $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); foreach ($usersTmp as $user) { if ($user->isEnabled() && mb_strtolower($user->getDisplayName()) === mb_strtolower($search)) { @@ -160,7 +163,7 @@ class UserPlugin implements ISearchPlugin { && $lowerSearch !== '' && ( strtolower($uid) === $lowerSearch - || strtolower($userDisplayName) === $lowerSearch + || ($this->shareeEnumerationfullMatchDisplayname && strtolower($userDisplayName) === $lowerSearch) || ($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch) || ($this->shareeEnumerationFullMatchEmail && strtolower($userEmail ?? '') === $lowerSearch) ) diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 010765af3c4..1dada16de4e 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -1742,6 +1742,10 @@ class Manager implements IManager { return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_user_id', 'yes') === 'yes'; } + public function matchDisplayName(): bool { + return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_displayname', 'yes') === 'yes'; + } + #[Override] public function ignoreSecondDisplayName(): bool { return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes'; diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php index 40c11c90be0..92bd7b825f3 100644 --- a/lib/public/Share/IManager.php +++ b/lib/public/Share/IManager.php @@ -427,6 +427,14 @@ interface IManager { */ public function matchUserId(): bool; + /** + * When `allowEnumerationFullMatch` is enabled and `matchDisplayName` is set, + * then also return results for full display name matches. + * + * @since 33.0.0 + */ + public function matchDisplayName(): bool; + /** * When `allowEnumerationFullMatch` is enabled and `ignoreSecondDisplayName` is set, * then the search should ignore matches on the second displayname and only use the first.