浏览代码

Add a setting to restrict returning a full match unless in phonebook or same group

Signed-off-by: Joas Schilling <coding@schilljs.com>
tags/v22.0.0beta1
Joas Schilling 3 年前
父节点
当前提交
5b53b6f977
没有帐户链接到提交者的电子邮件

+ 23
- 13
apps/dav/lib/Connector/Sabre/Principal.php 查看文件

@@ -263,6 +263,7 @@ class Principal implements BackendInterface {
$allowEnumeration = $this->shareManager->allowEnumeration();
$limitEnumerationGroup = $this->shareManager->limitEnumerationToGroups();
$limitEnumerationPhone = $this->shareManager->limitEnumerationToPhone();
$allowEnumerationFullMatch = $this->shareManager->allowEnumerationFullMatch();

// If sharing is restricted to group members only,
// return only members that have groups in common
@@ -290,15 +291,19 @@ class Principal implements BackendInterface {
foreach ($searchProperties as $prop => $value) {
switch ($prop) {
case '{http://sabredav.org/ns}email-address':
$users = $this->userManager->getByEmail($value);

if (!$allowEnumeration) {
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getEMailAddress() === $value;
});
if ($allowEnumerationFullMatch) {
$users = $this->userManager->getByEmail($value);
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getEMailAddress() === $value;
});
} else {
$users = [];
}
} else {
$users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $currentUserGroups) {
if ($user->getEMailAddress() === $value) {
$users = $this->userManager->getByEmail($value);
$users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $allowEnumerationFullMatch, $currentUserGroups) {
if ($allowEnumerationFullMatch && $user->getEMailAddress() === $value) {
return true;
}

@@ -336,15 +341,20 @@ class Principal implements BackendInterface {
break;

case '{DAV:}displayname':
$users = $this->userManager->searchDisplayName($value, $searchLimit);

if (!$allowEnumeration) {
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getDisplayName() === $value;
});
if ($allowEnumerationFullMatch) {
$users = $this->userManager->searchDisplayName($value, $searchLimit);
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getDisplayName() === $value;
});
} else {
$users = [];
}
} else {
$users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $currentUserGroups) {
if ($user->getDisplayName() === $value) {
$users = $this->userManager->searchDisplayName($value, $searchLimit);
$users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $allowEnumerationFullMatch, $currentUserGroups) {
if ($allowEnumerationFullMatch && $user->getDisplayName() === $value) {
return true;
}


+ 51
- 0
apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php 查看文件

@@ -570,6 +570,10 @@ class PrincipalTest extends TestCase {
->method('shareWithGroupMembersOnly')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('allowEnumerationFullMatch')
->willReturn(true);

$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->willReturn('user2');
$user2->method('getDisplayName')->willReturn('User 2');
@@ -592,6 +596,27 @@ class PrincipalTest extends TestCase {
['{DAV:}displayname' => 'User 2']));
}

public function testSearchPrincipalWithEnumerationDisabledDisplaynameOnFullMatch() {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
->willReturn(true);

$this->shareManager->expects($this->once())
->method('allowEnumeration')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('shareWithGroupMembersOnly')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('allowEnumerationFullMatch')
->willReturn(false);

$this->assertEquals([], $this->connector->searchPrincipals('principals/users',
['{DAV:}displayname' => 'User 2']));
}

public function testSearchPrincipalWithEnumerationDisabledEmail() {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
@@ -605,6 +630,10 @@ class PrincipalTest extends TestCase {
->method('shareWithGroupMembersOnly')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('allowEnumerationFullMatch')
->willReturn(true);

$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->willReturn('user2');
$user2->method('getDisplayName')->willReturn('User 2');
@@ -627,6 +656,28 @@ class PrincipalTest extends TestCase {
['{http://sabredav.org/ns}email-address' => 'user2@foo.bar']));
}

public function testSearchPrincipalWithEnumerationDisabledEmailOnFullMatch() {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
->willReturn(true);

$this->shareManager->expects($this->once())
->method('allowEnumeration')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('shareWithGroupMembersOnly')
->willReturn(false);

$this->shareManager->expects($this->once())
->method('allowEnumerationFullMatch')
->willReturn(false);


$this->assertEquals([], $this->connector->searchPrincipals('principals/users',
['{http://sabredav.org/ns}email-address' => 'user2@foo.bar']));
}

public function testSearchPrincipalWithEnumerationLimitedDisplayname() {
$this->shareManager->expects($this->at(0))
->method('shareAPIEnabled')

+ 1
- 0
apps/settings/lib/Settings/Admin/Sharing.php 查看文件

@@ -74,6 +74,7 @@ class Sharing implements ISettings {
'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'),
'restrictUserEnumerationToGroup' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no'),
'restrictUserEnumerationToPhone' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no'),
'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'),
'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(),
'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(),
'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'),

+ 10
- 1
apps/settings/templates/settings/admin/sharing.php 查看文件

@@ -163,7 +163,7 @@
<?php if ($_['allowShareDialogUserEnumeration'] === 'yes') {
print_unescaped('checked="checked"');
} ?> />
<label for="shareapi_allow_share_dialog_user_enumeration"><?php p($l->t('Allow username autocompletion in share dialog (if this is disabled the full username or email address needs to be entered)'));?></label><br />
<label for="shareapi_allow_share_dialog_user_enumeration"><?php p($l->t('Allow username autocompletion in share dialog'));?></label><br />
</p>

<p id="shareapi_restrict_user_enumeration_to_group_setting" class="indent <?php if ($_['shareAPIEnabled'] === 'no' || $_['allowShareDialogUserEnumeration'] === 'no') {
@@ -190,6 +190,15 @@
}?>">
<em><?php p($l->t('If autocompletion "same group" and "phonebook matches" are enabled a match in either is enough to show the user.'));?></em><br />
</p>
<p id="shareapi_restrict_user_enumeration_full_match_setting" class="indent <?php if ($_['shareAPIEnabled'] === 'no') {
p('hidden');
}?>">
<input type="checkbox" name="shareapi_restrict_user_enumeration_full_match" value="1" id="shareapi_restrict_user_enumeration_full_match" class="checkbox"
<?php if ($_['restrictUserEnumerationFullMatch'] === 'yes') {
print_unescaped('checked="checked"');
} ?> />
<label for="shareapi_restrict_user_enumeration_full_match"><?php p($l->t('Allow username autocompletion when entering the full name or email address (ignoring missing phonebook match and being in the same group)'));?></label><br />
</p>

<p>
<input type="checkbox" id="publicShareDisclaimer" class="checkbox noJSAutoUpdate"

+ 4
- 0
apps/settings/tests/Settings/Admin/SharingTest.php 查看文件

@@ -74,6 +74,7 @@ class SharingTest extends TestCase {
['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'],
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'no'],
['core', 'shareapi_expire_after_n_days', '7', '7'],
@@ -98,6 +99,7 @@ class SharingTest extends TestCase {
'allowShareDialogUserEnumeration' => 'yes',
'restrictUserEnumerationToGroup' => 'no',
'restrictUserEnumerationToPhone' => 'no',
'restrictUserEnumerationFullMatch' => 'yes',
'enforceLinkPassword' => false,
'onlyShareWithGroupMembers' => false,
'shareAPIEnabled' => 'yes',
@@ -132,6 +134,7 @@ class SharingTest extends TestCase {
['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'],
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'no'],
['core', 'shareapi_expire_after_n_days', '7', '7'],
@@ -156,6 +159,7 @@ class SharingTest extends TestCase {
'allowShareDialogUserEnumeration' => 'yes',
'restrictUserEnumerationToGroup' => 'no',
'restrictUserEnumerationToPhone' => 'no',
'restrictUserEnumerationFullMatch' => 'yes',
'enforceLinkPassword' => false,
'onlyShareWithGroupMembers' => false,
'shareAPIEnabled' => 'yes',

+ 36
- 0
build/integration/collaboration_features/autocomplete.feature 查看文件

@@ -3,6 +3,7 @@ Feature: autocomplete
Given using api version "2"
And group "commongroup" exists
And user "admin" belongs to group "commongroup"
And user "auto" exists
And user "autocomplete" exists
And user "autocomplete2" exists
And user "autocomplete2" belongs to group "commongroup"
@@ -20,9 +21,15 @@ Feature: autocomplete
When parameter "shareapi_allow_share_dialog_user_enumeration" of app "core" is set to "no"
Then get autocomplete for "auto"
| id | source |
| auto | users |
Then get autocomplete for "autocomplete"
| id | source |
| autocomplete | users |
When parameter "shareapi_restrict_user_enumeration_full_match" of app "core" is set to "no"
Then get autocomplete for "auto"
| id | source |
Then get autocomplete for "autocomplete"
| id | source |


Scenario: getting autocomplete with limited enumeration by group
@@ -30,6 +37,7 @@ Feature: autocomplete
When parameter "shareapi_restrict_user_enumeration_to_group" of app "core" is set to "yes"
Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete2 | users |
Then get autocomplete for "autocomplete"
| id | source |
@@ -38,6 +46,13 @@ Feature: autocomplete
Then get autocomplete for "autocomplete2"
| id | source |
| autocomplete2 | users |
When parameter "shareapi_restrict_user_enumeration_full_match" of app "core" is set to "no"
Then get autocomplete for "autocomplete"
| id | source |
| autocomplete2 | users |
Then get autocomplete for "autocomplete2"
| id | source |
| autocomplete2 | users |


Scenario: getting autocomplete with limited enumeration by phone
@@ -45,6 +60,7 @@ Feature: autocomplete
When parameter "shareapi_restrict_user_enumeration_to_phone" of app "core" is set to "yes"
Then get autocomplete for "auto"
| id | source |
| auto | users |

# autocomplete stores their phone number
Given As an "autocomplete"
@@ -57,10 +73,17 @@ Feature: autocomplete
Given As an "admin"
Then get autocomplete for "auto"
| id | source |
| auto | users |

# admin populates they have the phone number
When search users by phone for region "DE" with
| random-string1 | 0711 / 252 428-90 |
Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete | users |

When parameter "shareapi_restrict_user_enumeration_full_match" of app "core" is set to "no"
Then get autocomplete for "auto"
| id | source |
| autocomplete | users |
@@ -83,6 +106,13 @@ Feature: autocomplete
When search users by phone for region "DE" with
| random-string1 | 0711 / 252 428-90 |

Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete | users |
| autocomplete2 | users |

When parameter "shareapi_restrict_user_enumeration_full_match" of app "core" is set to "no"
Then get autocomplete for "auto"
| id | source |
| autocomplete | users |
@@ -108,6 +138,7 @@ Feature: autocomplete

Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete | users |
| autocomplete2 | users |
When parameter "shareapi_only_share_with_group_members" of app "core" is set to "yes"
@@ -121,6 +152,7 @@ Feature: autocomplete
When parameter "shareapi_restrict_user_enumeration_to_phone" of app "core" is set to "yes"
Then get autocomplete for "auto"
| id | source |
| auto | users |

# autocomplete stores their phone number
Given As an "autocomplete"
@@ -133,12 +165,14 @@ Feature: autocomplete
Given As an "admin"
Then get autocomplete for "auto"
| id | source |
| auto | users |

# admin populates they have the phone number
When search users by phone for region "DE" with
| random-string1 | 0711 / 252 428-90 |
Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete | users |

# autocomplete changes their phone number
@@ -152,12 +186,14 @@ Feature: autocomplete
Given As an "admin"
Then get autocomplete for "auto"
| id | source |
| auto | users |

# admin populates they have the new phone number
When search users by phone for region "DE" with
| random-string1 | 0711 / 252 428-91 |
Then get autocomplete for "auto"
| id | source |
| auto | users |
| autocomplete | users |



+ 1
- 0
build/integration/features/bootstrap/CollaborationContext.php 查看文件

@@ -66,6 +66,7 @@ class CollaborationContext implements Context {
$this->deleteServerConfig('core', 'shareapi_allow_share_dialog_user_enumeration');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_to_group');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_to_phone');
$this->deleteServerConfig('core', 'shareapi_restrict_user_enumeration_full_match');
$this->deleteServerConfig('core', 'shareapi_only_share_with_group_members');
}
}

+ 4
- 1
lib/private/Collaboration/Collaborators/MailPlugin.php 查看文件

@@ -49,6 +49,8 @@ class MailPlugin implements ISearchPlugin {
protected $shareeEnumerationInGroupOnly;
/* @var bool */
protected $shareeEnumerationPhone;
/* @var bool */
protected $shareeEnumerationFullMatch;

/** @var IManager */
private $contactsManager;
@@ -81,6 +83,7 @@ class MailPlugin implements ISearchPlugin {
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$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';
}

/**
@@ -137,7 +140,7 @@ class MailPlugin implements ISearchPlugin {
continue;
}
}
if ($exactEmailMatch) {
if ($exactEmailMatch && $this->shareeEnumerationFullMatch) {
try {
$cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
} catch (\InvalidArgumentException $e) {

+ 5
- 1
lib/private/Collaboration/Collaborators/UserPlugin.php 查看文件

@@ -53,6 +53,8 @@ class UserPlugin implements ISearchPlugin {
protected $shareeEnumerationInGroupOnly;
/* @var bool */
protected $shareeEnumerationPhone;
/* @var bool */
protected $shareeEnumerationFullMatch;

/** @var IConfig */
private $config;
@@ -85,6 +87,7 @@ class UserPlugin implements ISearchPlugin {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$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';
}

public function search($search, $limit, $offset, ISearchResult $searchResult) {
@@ -150,6 +153,7 @@ class UserPlugin implements ISearchPlugin {


if (
$this->shareeEnumerationFullMatch &&
$lowerSearch !== '' && (strtolower($uid) === $lowerSearch ||
strtolower($userDisplayName) === $lowerSearch ||
strtolower($userEmail) === $lowerSearch)
@@ -202,7 +206,7 @@ class UserPlugin implements ISearchPlugin {
}
}

if ($offset === 0 && !$foundUserById) {
if ($this->shareeEnumerationFullMatch && $offset === 0 && !$foundUserById) {
// On page one we try if the search result has a direct hit on the
// user id and if so, we add that to the exact match list
$user = $this->userManager->get($search);

+ 6
- 1
lib/private/Contacts/ContactsMenu/ContactsStore.php 查看文件

@@ -124,6 +124,7 @@ class ContactsStore implements IContactsStore {
$disallowEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') !== 'yes';
$restrictEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$restrictEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$allowEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes';

// whether to filter out local users
@@ -146,7 +147,7 @@ class ContactsStore implements IContactsStore {

$selfUID = $self->getUID();

return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $filter) {
return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $allowEnumerationFullMatch, $filter) {
if ($entry->getProperty('UID') === $selfUID) {
return false;
}
@@ -160,6 +161,10 @@ class ContactsStore implements IContactsStore {

// Prevent enumerating local users
if ($disallowEnumeration) {
if (!$allowEnumerationFullMatch) {
return false;
}

$filterUser = true;

$mailAddresses = $entry->getEMailAddresses();

+ 4
- 0
lib/private/Share20/Manager.php 查看文件

@@ -1834,6 +1834,10 @@ class Manager implements IManager {
$this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
}

public function allowEnumerationFullMatch(): bool {
return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
}

/**
* Copied from \OC_Util::isSharingDisabledForUser
*

+ 8
- 0
lib/public/Share/IManager.php 查看文件

@@ -392,6 +392,14 @@ interface IManager {
*/
public function limitEnumerationToPhone(): bool;

/**
* Check if user enumeration is allowed to return on full match
*
* @return bool
* @since 21.0.1
*/
public function allowEnumerationFullMatch(): bool;

/**
* Check if sharing is disabled for the given user
*

+ 90
- 3
tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php 查看文件

@@ -683,9 +683,12 @@ class ContactsStoreTest extends TestCase {
}

public function testGetContactsWithFilter() {
$this->config->expects($this->at(0))->method('getAppValue')
->with($this->equalTo('core'), $this->equalTo('shareapi_allow_share_dialog_user_enumeration'), $this->equalTo('yes'))
->willReturn('no');
$this->config
->method('getAppValue')
->willReturnMap([
['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'],
['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'],
]);

/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */
$user = $this->createMock(IUser::class);
@@ -766,6 +769,90 @@ class ContactsStoreTest extends TestCase {
], $entry[0]->getEMailAddresses());
}

public function testGetContactsWithFilterWithoutFullMatch() {
$this->config
->method('getAppValue')
->willReturnMap([
['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'],
['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'no'],
]);

/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */
$user = $this->createMock(IUser::class);
$this->contactsManager->expects($this->any())
->method('search')
->willReturn([
[
'UID' => 'a567',
'FN' => 'Darren Roner',
'EMAIL' => [
'darren@roner.au',
],
'isLocalSystemBook' => true,
],
[
'UID' => 'john',
'FN' => 'John Doe',
'EMAIL' => [
'john@example.com',
],
'isLocalSystemBook' => true,
],
[
'FN' => 'Anne D',
'EMAIL' => [
'anne@example.com',
],
'isLocalSystemBook' => false,
],
]);
$user->expects($this->any())
->method('getUID')
->willReturn('user123');

// Complete match on UID should not match
$entry = $this->contactsStore->getContacts($user, 'a567');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());

// Partial match on UID should not match
$entry = $this->contactsStore->getContacts($user, 'a56');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());

// Complete match on email should not match
$entry = $this->contactsStore->getContacts($user, 'john@example.com');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());

// Partial match on email should not match
$entry = $this->contactsStore->getContacts($user, 'john@example.co');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());

// Match on FN should not match
$entry = $this->contactsStore->getContacts($user, 'Darren Roner');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());

// Don't filter users in local addressbook
$entry = $this->contactsStore->getContacts($user, 'Anne D');
$this->assertSame(1, count($entry));
$this->assertEquals([
'anne@example.com'
], $entry[0]->getEMailAddresses());
}

public function testFindOneUser() {
$this->config->expects($this->at(0))->method('getAppValue')
->with($this->equalTo('core'), $this->equalTo('shareapi_allow_share_dialog_user_enumeration'), $this->equalTo('yes'))

正在加载...
取消
保存