Limit enumeration in principal search

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl 2020-02-20 18:52:23 +01:00
parent 8edc824526
commit 0fa897fcfc
2 changed files with 150 additions and 1 deletions

View File

@ -245,7 +245,8 @@ class Principal implements BackendInterface {
return []; return [];
} }
$allowEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; $allowEnumeration = $this->shareManager->allowEnumeration();
$limitEnumeration = $this->shareManager->limitEnumerationToGroups();
// If sharing is restricted to group members only, // If sharing is restricted to group members only,
// return only members that have groups in common // return only members that have groups in common
@ -259,6 +260,14 @@ class Principal implements BackendInterface {
$restrictGroups = $this->groupManager->getUserGroupIds($user); $restrictGroups = $this->groupManager->getUserGroupIds($user);
} }
$currentUserGroups = [];
if ($limitEnumeration) {
$currentUser = $this->userSession->getUser();
if ($currentUser) {
$currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
}
}
foreach ($searchProperties as $prop => $value) { foreach ($searchProperties as $prop => $value) {
switch ($prop) { switch ($prop) {
case '{http://sabredav.org/ns}email-address': case '{http://sabredav.org/ns}email-address':
@ -270,6 +279,15 @@ class Principal implements BackendInterface {
}); });
} }
if ($limitEnumeration) {
$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
return !empty(array_intersect(
$this->groupManager->getUserGroupIds($user),
$currentUserGroups
)) || $user->getEMailAddress() === $value;
});
}
$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) { $results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
// is sharing restricted to groups only? // is sharing restricted to groups only?
if ($restrictGroups !== false) { if ($restrictGroups !== false) {
@ -293,6 +311,15 @@ class Principal implements BackendInterface {
}); });
} }
if ($limitEnumeration) {
$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
return !empty(array_intersect(
$this->groupManager->getUserGroupIds($user),
$currentUserGroups
)) || $user->getDisplayName() === $value;
});
}
$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) { $results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
// is sharing restricted to groups only? // is sharing restricted to groups only?
if ($restrictGroups !== false) { if ($restrictGroups !== false) {

View File

@ -624,6 +624,128 @@ class PrincipalTest extends TestCase {
['{http://sabredav.org/ns}email-address' => 'user2@foo.bar'])); ['{http://sabredav.org/ns}email-address' => 'user2@foo.bar']));
} }
public function testSearchPrincipalWithEnumerationLimitedDisplayname() {
$this->shareManager->expects($this->at(0))
->method('shareAPIEnabled')
->will($this->returnValue(true));
$this->shareManager->expects($this->at(1))
->method('allowEnumeration')
->willReturn(true);
$this->shareManager->expects($this->at(2))
->method('limitEnumerationToGroups')
->willReturn(true);
$this->shareManager->expects($this->once())
->method('shareWithGroupMembersOnly')
->will($this->returnValue(false));
$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->will($this->returnValue('user2'));
$user2->method('getDisplayName')->will($this->returnValue('User 2'));
$user2->method('getEMailAddress')->will($this->returnValue('user2@foo.bar'));
$user3 = $this->createMock(IUser::class);
$user3->method('getUID')->will($this->returnValue('user3'));
$user3->method('getDisplayName')->will($this->returnValue('User 22'));
$user3->method('getEMailAddress')->will($this->returnValue('user2@foo.bar123'));
$user4 = $this->createMock(IUser::class);
$user4->method('getUID')->will($this->returnValue('user4'));
$user4->method('getDisplayName')->will($this->returnValue('User 222'));
$user4->method('getEMailAddress')->will($this->returnValue('user2@foo.bar456'));
$this->userSession->expects($this->at(0))
->method('getUser')
->willReturn($user2);
$this->groupManager->expects($this->at(0))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(1))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(2))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(3))
->method('getUserGroupIds')
->willReturn(['group2']);
$this->userManager->expects($this->at(0))
->method('searchDisplayName')
->with('User')
->willReturn([$user2, $user3, $user4]);
$this->assertEquals([
'principals/users/user2',
'principals/users/user3',
], $this->connector->searchPrincipals('principals/users',
['{DAV:}displayname' => 'User']));
}
public function testSearchPrincipalWithEnumerationLimitedMail() {
$this->shareManager->expects($this->at(0))
->method('shareAPIEnabled')
->will($this->returnValue(true));
$this->shareManager->expects($this->at(1))
->method('allowEnumeration')
->willReturn(true);
$this->shareManager->expects($this->at(2))
->method('limitEnumerationToGroups')
->willReturn(true);
$this->shareManager->expects($this->once())
->method('shareWithGroupMembersOnly')
->will($this->returnValue(false));
$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->will($this->returnValue('user2'));
$user2->method('getDisplayName')->will($this->returnValue('User 2'));
$user2->method('getEMailAddress')->will($this->returnValue('user2@foo.bar'));
$user3 = $this->createMock(IUser::class);
$user3->method('getUID')->will($this->returnValue('user3'));
$user3->method('getDisplayName')->will($this->returnValue('User 22'));
$user3->method('getEMailAddress')->will($this->returnValue('user2@foo.bar123'));
$user4 = $this->createMock(IUser::class);
$user4->method('getUID')->will($this->returnValue('user4'));
$user4->method('getDisplayName')->will($this->returnValue('User 222'));
$user4->method('getEMailAddress')->will($this->returnValue('user2@foo.bar456'));
$this->userSession->expects($this->at(0))
->method('getUser')
->willReturn($user2);
$this->groupManager->expects($this->at(0))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(1))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(2))
->method('getUserGroupIds')
->willReturn(['group1']);
$this->groupManager->expects($this->at(3))
->method('getUserGroupIds')
->willReturn(['group2']);
$this->userManager->expects($this->at(0))
->method('getByEmail')
->with('user')
->willReturn([$user2, $user3, $user4]);
$this->assertEquals([
'principals/users/user2',
'principals/users/user3'
], $this->connector->searchPrincipals('principals/users',
['{http://sabredav.org/ns}email-address' => 'user']));
}
public function testFindByUriSharingApiDisabled() { public function testFindByUriSharingApiDisabled() {
$this->shareManager->expects($this->once()) $this->shareManager->expects($this->once())
->method('shareApiEnabled') ->method('shareApiEnabled')