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.