Merge pull request #32360 from nextcloud/backport/stable24/share_search_tweaks

This commit is contained in:
John Molakvoæ 2022-05-13 20:15:26 +02:00 committed by GitHub
commit f02ccc6d29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 55 additions and 25 deletions

View file

@ -270,6 +270,8 @@ class Principal implements BackendInterface {
$limitEnumerationGroup = $this->shareManager->limitEnumerationToGroups();
$limitEnumerationPhone = $this->shareManager->limitEnumerationToPhone();
$allowEnumerationFullMatch = $this->shareManager->allowEnumerationFullMatch();
$ignoreSecondDisplayName = $this->shareManager->ignoreSecondDisplayName();
$matchEmail = $this->shareManager->matchEmail();
// If sharing is restricted to group members only,
// return only members that have groups in common
@ -298,7 +300,7 @@ class Principal implements BackendInterface {
switch ($prop) {
case '{http://sabredav.org/ns}email-address':
if (!$allowEnumeration) {
if ($allowEnumerationFullMatch) {
if ($allowEnumerationFullMatch && $matchEmail) {
$users = $this->userManager->getByEmail($value);
} else {
$users = [];
@ -349,8 +351,9 @@ class Principal implements BackendInterface {
if ($allowEnumerationFullMatch) {
$lowerSearch = strtolower($value);
$users = $this->userManager->searchDisplayName($value, $searchLimit);
$users = \array_filter($users, static function (IUser $user) use ($lowerSearch) {
return strtolower($user->getDisplayName()) === $lowerSearch;
$users = \array_filter($users, static function (IUser $user) use ($lowerSearch, $ignoreSecondDisplayName) {
$lowerDisplayName = strtolower($user->getDisplayName());
return $lowerDisplayName === $lowerSearch || ($ignoreSecondDisplayName && trim(preg_replace('/ \(.*\)$/', '', $lowerDisplayName)) === $lowerSearch);
});
} else {
$users = [];

View file

@ -662,6 +662,10 @@ class PrincipalTest extends TestCase {
->method('allowEnumerationFullMatch')
->willReturn(true);
$this->shareManager->expects($this->once())
->method('matchEmail')
->willReturn(true);
$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->willReturn('user2');
$user2->method('getDisplayName')->willReturn('User 2');

View file

@ -90,6 +90,7 @@ class Sharing implements IDelegatedSettings {
'restrictUserEnumerationToPhone' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no'),
'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'),
'restrictUserEnumerationFullMatchUserId' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes'),
'restrictUserEnumerationFullMatchEmail' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes'),
'restrictUserEnumerationFullMatchIgnoreSecondDisplayName' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no'),
'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(false),
'passwordExcludedGroups' => $excludedPasswordGroupsList,

View file

@ -157,6 +157,7 @@ window.addEventListener('DOMContentLoaded', () => {
$('#shareapi_restrict_user_enumeration_full_match').on('change', function() {
$('#shareapi_restrict_user_enumeration_full_match_userid_setting').toggleClass('hidden', !this.checked)
$('#shareapi_restrict_user_enumeration_full_match_email_setting').toggleClass('hidden', !this.checked)
$('#shareapi_restrict_user_enumeration_full_match_ignore_second_display_name_setting').toggleClass('hidden', !this.checked)
})

View file

@ -247,24 +247,6 @@
} ?> />
<label for="shareapi_restrict_user_enumeration_full_match"><?php p($l->t('Allow autocompletion when entering the full name or email address (ignoring missing phonebook match and being in the same group)'));?></label><br />
</p>
<p id="shareapi_restrict_user_enumeration_full_match_userid_setting" class="double-indent <?php if ($_['shareAPIEnabled'] === 'no' || $_['restrictUserEnumerationFullMatch'] === 'no') {
p('hidden');
}?>">
<input type="checkbox" name="shareapi_restrict_user_enumeration_full_match_userid" value="1" id="shareapi_restrict_user_enumeration_full_match_userid" class="checkbox"
<?php if ($_['restrictUserEnumerationFullMatchUserId'] === 'yes') {
print_unescaped('checked="checked"');
} ?> />
<label for="shareapi_restrict_user_enumeration_full_match_userid"><?php p($l->t('Match username when restricting to full match'));?></label><br />
</p>
<p id="shareapi_restrict_user_enumeration_full_match_ignore_second_display_name_setting" class="double-indent <?php if ($_['shareAPIEnabled'] === 'no' || $_['restrictUserEnumerationFullMatch'] === 'no') {
p('hidden');
}?>">
<input type="checkbox" name="shareapi_restrict_user_enumeration_full_match_ignore_second_display_name" value="1" id="shareapi_restrict_user_enumeration_full_match_ignore_second_display_name" class="checkbox"
<?php if ($_['restrictUserEnumerationFullMatchIgnoreSecondDisplayName'] === 'yes') {
print_unescaped('checked="checked"');
} ?> />
<label for="shareapi_restrict_user_enumeration_full_match_ignore_second_display_name"><?php p($l->t('Ignore second display name in parentheses if any (example: "First display name (second ignored display name)")'));?></label><br />
</p>
<p>
<input type="checkbox" id="publicShareDisclaimer" class="checkbox noJSAutoUpdate"

View file

@ -84,6 +84,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_userid', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no', 'no'],
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'no'],
@ -119,6 +120,7 @@ class SharingTest extends TestCase {
'restrictUserEnumerationToPhone' => 'no',
'restrictUserEnumerationFullMatch' => 'yes',
'restrictUserEnumerationFullMatchUserId' => 'yes',
'restrictUserEnumerationFullMatchEmail' => 'yes',
'restrictUserEnumerationFullMatchIgnoreSecondDisplayName' => 'no',
'enforceLinkPassword' => false,
'onlyShareWithGroupMembers' => false,
@ -163,6 +165,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_userid', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no', 'no'],
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'no'],
@ -198,6 +201,7 @@ class SharingTest extends TestCase {
'restrictUserEnumerationToPhone' => 'no',
'restrictUserEnumerationFullMatch' => 'yes',
'restrictUserEnumerationFullMatchUserId' => 'yes',
'restrictUserEnumerationFullMatchEmail' => 'yes',
'restrictUserEnumerationFullMatchIgnoreSecondDisplayName' => 'no',
'enforceLinkPassword' => false,
'onlyShareWithGroupMembers' => false,

View file

@ -123,6 +123,7 @@ EOF;
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_to_phone');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_userid');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_email');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name');
$this->deleteServerConfig('core', 'shareapi_only_share_with_group_members');
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -51,6 +51,8 @@ class MailPlugin implements ISearchPlugin {
protected $shareeEnumerationPhone;
/* @var bool */
protected $shareeEnumerationFullMatch;
/* @var bool */
protected $shareeEnumerationFullMatchEmail;
/** @var IManager */
private $contactsManager;
@ -88,12 +90,17 @@ class MailPlugin implements ISearchPlugin {
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$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->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
}
/**
* {@inheritdoc}
*/
public function search($search, $limit, $offset, ISearchResult $searchResult) {
if ($this->shareeEnumerationFullMatch && !$this->shareeEnumerationFullMatchEmail) {
return false;
}
$currentUserId = $this->userSession->getUser()->getUID();
$result = $userResults = ['wide' => [], 'exact' => []];

View file

@ -57,6 +57,8 @@ class UserPlugin implements ISearchPlugin {
/* @var bool */
protected $shareeEnumerationFullMatchUserId;
/* @var bool */
protected $shareeEnumerationFullMatchEmail;
/* @var bool */
protected $shareeEnumerationFullMatchIgnoreSecondDisplayName;
/** @var IConfig */
@ -92,6 +94,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_userid', '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_display_name', 'no') === 'yes';
}
@ -185,7 +188,7 @@ class UserPlugin implements ISearchPlugin {
$lowerSearch !== '' && (strtolower($uid) === $lowerSearch ||
strtolower($userDisplayName) === $lowerSearch ||
($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch) ||
strtolower($userEmail ?? '') === $lowerSearch)
($this->shareeEnumerationFullMatchEmail && strtolower($userEmail ?? '') === $lowerSearch))
) {
if (strtolower($uid) === $lowerSearch) {
$foundUserById = true;

View file

@ -1963,6 +1963,14 @@ class Manager implements IManager {
return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
}
public function matchEmail(): bool {
return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
}
public function ignoreSecondDisplayName(): bool {
return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no') === 'yes';
}
public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool {
if ($this->allowEnumerationFullMatch()) {
return true;

View file

@ -454,6 +454,22 @@ interface IManager {
*/
public function allowEnumerationFullMatch(): bool;
/**
* Check if the search should match the email
*
* @return bool
* @since 25.0.0
*/
public function matchEmail(): bool;
/**
* Check if the search should ignore the second in parentheses display name if there is any
*
* @return bool
* @since 25.0.0
*/
public function ignoreSecondDisplayName(): bool;
/**
* Check if the current user can enumerate the target user
*