Merge pull request #16035 from nextcloud/share-search-hide-on-match

dont show remote and email options if we have an exact match for local user email
This commit is contained in:
blizzz 2020-04-09 00:08:34 +02:00 committed by GitHub
commit e9795d01f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 70 deletions

View File

@ -85,6 +85,13 @@ class Search implements ISearch {
$searchResult->unsetResult($emailType); $searchResult->unsetResult($emailType);
} }
// if we have an exact local user match, there is no need to show the remote and email matches
$userType = new SearchResultType('users');
if($searchResult->hasExactIdMatch($userType)) {
$searchResult->unsetResult($remoteType);
$searchResult->unsetResult($emailType);
}
return [$searchResult->asArray(), (bool)$hasMoreResults]; return [$searchResult->asArray(), (bool)$hasMoreResults];
} }

View File

@ -32,6 +32,7 @@ use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult; use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType; use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
use OCP\IUserManager; use OCP\IUserManager;
@ -75,11 +76,11 @@ class UserPlugin implements ISearchPlugin {
$userGroups = []; $userGroups = [];
if ($this->shareWithGroupOnly) { if ($this->shareWithGroupOnly) {
// Search in all the groups this user is part of // Search in all the groups this user is part of
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser()); $userGroups = $this->groupManager->getUserGroups($this->userSession->getUser());
foreach ($userGroups as $userGroup) { foreach ($userGroups as $userGroup) {
$usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $limit, $offset); $usersInGroup = $userGroup->searchDisplayName($search, $limit, $offset);
foreach ($usersTmp as $uid => $userDisplayName) { foreach ($usersInGroup as $user) {
$users[(string) $uid] = $userDisplayName; $users[$user->getUID()] = $user;
} }
} }
} else { } else {
@ -88,7 +89,7 @@ class UserPlugin implements ISearchPlugin {
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser()); $currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
foreach ($usersTmp as $user) { foreach ($usersTmp as $user) {
if ($user->isEnabled()) { // Don't keep deactivated users if ($user->isEnabled()) { // Don't keep deactivated users
$users[(string) $user->getUID()] = $user->getDisplayName(); $users[$user->getUID()] = $user;
$addToWideResults = false; $addToWideResults = false;
if ($this->shareeEnumeration && !$this->shareeEnumerationInGroupOnly) { if ($this->shareeEnumeration && !$this->shareeEnumerationInGroupOnly) {
@ -123,9 +124,15 @@ class UserPlugin implements ISearchPlugin {
$foundUserById = false; $foundUserById = false;
$lowerSearch = strtolower($search); $lowerSearch = strtolower($search);
foreach ($users as $uid => $userDisplayName) { foreach ($users as $uid => $user) {
$userDisplayName = $user->getDisplayName();
$userEmail = $user->getEMailAddress();
$uid = (string) $uid; $uid = (string) $uid;
if (strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch) { if (
strtolower($uid) === $lowerSearch ||
strtolower($userDisplayName) === $lowerSearch ||
strtolower($userEmail) === $lowerSearch
) {
if (strtolower($uid) === $lowerSearch) { if (strtolower($uid) === $lowerSearch) {
$foundUserById = true; $foundUserById = true;
} }
@ -156,7 +163,10 @@ class UserPlugin implements ISearchPlugin {
if ($this->shareWithGroupOnly) { if ($this->shareWithGroupOnly) {
// Only add, if we have a common group // Only add, if we have a common group
$commonGroups = array_intersect($userGroups, $this->groupManager->getUserGroupIds($user)); $userGroupIds = array_map(function(IGroup $group) {
return $group->getGID();
}, $userGroups);
$commonGroups = array_intersect($userGroupIds, $this->groupManager->getUserGroupIds($user));
$addUser = !empty($commonGroups); $addUser = !empty($commonGroups);
} }
@ -179,6 +189,9 @@ class UserPlugin implements ISearchPlugin {
$type = new SearchResultType('users'); $type = new SearchResultType('users');
$searchResult->addResultSet($type, $result['wide'], $result['exact']); $searchResult->addResultSet($type, $result['wide'], $result['exact']);
if (count($result['exact'])) {
$searchResult->markExactIdMatch($type);
}
return $hasMoreResults; return $hasMoreResults;
} }

View File

@ -27,6 +27,7 @@ use OC\Collaboration\Collaborators\SearchResult;
use OC\Collaboration\Collaborators\UserPlugin; use OC\Collaboration\Collaborators\UserPlugin;
use OCP\Collaboration\Collaborators\ISearchResult; use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
use OCP\IUserManager; use OCP\IUserManager;
@ -93,9 +94,8 @@ class UserPluginTest extends TestCase {
$this->config->expects($this->any()) $this->config->expects($this->any())
->method('getAppValue') ->method('getAppValue')
->willReturnCallback( ->willReturnCallback(
function($appName, $key, $default) function ($appName, $key, $default)
use ($shareWithGroupOnly, $shareeEnumeration, $shareeEnumerationLimitToGroup) use ($shareWithGroupOnly, $shareeEnumeration, $shareeEnumerationLimitToGroup) {
{
if ($appName === 'core' && $key === 'shareapi_only_share_with_group_members') { if ($appName === 'core' && $key === 'shareapi_only_share_with_group_members') {
return $shareWithGroupOnly ? 'yes' : 'no'; return $shareWithGroupOnly ? 'yes' : 'no';
} else if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') { } else if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
@ -127,6 +127,16 @@ class UserPluginTest extends TestCase {
return $user; return $user;
} }
public function getGroupMock($gid) {
$group = $this->createMock(IGroup::class);
$group->expects($this->any())
->method('getGID')
->willReturn($gid);
return $group;
}
public function dataGetUsers() { public function dataGetUsers() {
return [ return [
['test', false, true, [], [], [], [], true, false], ['test', false, true, [], [], [], [], true, false],
@ -137,33 +147,33 @@ class UserPluginTest extends TestCase {
'test', false, true, [], [], 'test', false, true, [], [],
[ [
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test') ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', false, false, [], [], 'test', false, false, [], [],
[ [
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test') ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', true, true, [], [], 'test', true, true, [], [],
[], [], true, $this->getUserMock('test', 'Test') [], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', true, false, [], [], 'test', true, false, [], [],
[], [], true, $this->getUserMock('test', 'Test') [], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]], 'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]],
[ [
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test') ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]], 'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]],
[ [
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test') ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', 'test',
@ -267,7 +277,7 @@ class UserPluginTest extends TestCase {
true, true,
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, ['test1' => 'Test One']], ['abc', 'test', 2, 0, [$this->getUserMock('test1', 'Test One')]],
['xyz', 'test', 2, 0, []], ['xyz', 'test', 2, 0, []],
], ],
[], [],
@ -283,7 +293,7 @@ class UserPluginTest extends TestCase {
false, false,
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, ['test1' => 'Test One']], ['abc', 'test', 2, 0, [$this->getUserMock('test1', 'Test One')]],
['xyz', 'test', 2, 0, []], ['xyz', 'test', 2, 0, []],
], ],
[], [],
@ -298,12 +308,12 @@ class UserPluginTest extends TestCase {
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, [ ['abc', 'test', 2, 0, [
'test1' => 'Test One', $this->getUserMock('test1', 'Test One'),
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
['xyz', 'test', 2, 0, [ ['xyz', 'test', 2, 0, [
'test1' => 'Test One', $this->getUserMock('test1', 'Test One'),
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
], ],
[], [],
@ -321,12 +331,12 @@ class UserPluginTest extends TestCase {
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, [ ['abc', 'test', 2, 0, [
'test1' => 'Test One', $this->getUserMock('test1', 'Test One'),
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
['xyz', 'test', 2, 0, [ ['xyz', 'test', 2, 0, [
'test1' => 'Test One', $this->getUserMock('test1', 'Test One'),
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
], ],
[], [],
@ -341,10 +351,10 @@ class UserPluginTest extends TestCase {
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, [ ['abc', 'test', 2, 0, [
'test' => 'Test One', $this->getUserMock('test', 'Test One'),
]], ]],
['xyz', 'test', 2, 0, [ ['xyz', 'test', 2, 0, [
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
], ],
[ [
@ -363,10 +373,10 @@ class UserPluginTest extends TestCase {
['abc', 'xyz'], ['abc', 'xyz'],
[ [
['abc', 'test', 2, 0, [ ['abc', 'test', 2, 0, [
'test' => 'Test One', $this->getUserMock('test', 'Test One'),
]], ]],
['xyz', 'test', 2, 0, [ ['xyz', 'test', 2, 0, [
'test2' => 'Test Two', $this->getUserMock('test2', 'Test Two'),
]], ]],
], ],
[ [
@ -410,31 +420,36 @@ class UserPluginTest extends TestCase {
->method('getUser') ->method('getUser')
->willReturn($this->user); ->willReturn($this->user);
if(!$shareWithGroupOnly) { if (!$shareWithGroupOnly) {
$this->userManager->expects($this->once()) $this->userManager->expects($this->once())
->method('searchDisplayName') ->method('searchDisplayName')
->with($searchTerm, $this->limit, $this->offset) ->with($searchTerm, $this->limit, $this->offset)
->willReturn($userResponse); ->willReturn($userResponse);
} else { } else {
$groups = array_combine($groupResponse, array_map(function ($gid) {
return $this->getGroupMock($gid);
}, $groupResponse));
if ($singleUser !== false) { if ($singleUser !== false) {
$this->groupManager->expects($this->exactly(2)) $this->groupManager->method('getUserGroups')
->method('getUserGroupIds') ->with($this->user)
->withConsecutive( ->willReturn($groups);
[$this->user],
[$singleUser] $this->groupManager->method('getUserGroupIds')
) ->with($singleUser)
->willReturn($groupResponse); ->willReturn($groupResponse);
} else { } else {
$this->groupManager->expects($this->once()) $this->groupManager->expects($this->once())
->method('getUserGroupIds') ->method('getUserGroups')
->with($this->user) ->with($this->user)
->willReturn($groupResponse); ->willReturn($groups);
} }
$this->groupManager->expects($this->exactly(sizeof($groupResponse))) foreach ($userResponse as $groupDefinition) {
->method('displayNamesInGroup') [$gid, $search, $limit, $offset, $users] = $groupDefinition;
->with($this->anything(), $searchTerm, $this->limit, $this->offset) $groups[$gid]->method('searchDisplayName')
->willReturnMap($userResponse); ->with($search, $limit, $offset)
->willReturn($users);
}
} }
if ($singleUser !== false) { if ($singleUser !== false) {
@ -457,24 +472,24 @@ class UserPluginTest extends TestCase {
$inputUsers = [ $inputUsers = [
'alice' => 'Alice', 'alice' => 'Alice',
'bob' => 'Bob', 'bob' => 'Bob',
'carol' => 'Carol' 'carol' => 'Carol',
]; ];
return [ return [
[ [
$inputUsers, $inputUsers,
['alice', 'carol'], ['alice', 'carol'],
'bob' 'bob',
], ],
[ [
$inputUsers, $inputUsers,
['alice', 'bob', 'carol'], ['alice', 'bob', 'carol'],
'dave' 'dave',
], ],
[ [
$inputUsers, $inputUsers,
['alice', 'bob', 'carol'], ['alice', 'bob', 'carol'],
null null,
] ],
]; ];
} }
@ -489,8 +504,8 @@ class UserPluginTest extends TestCase {
$this->session->expects($this->once()) $this->session->expects($this->once())
->method('getUser') ->method('getUser')
->willReturnCallback(function() use ($currentUserId) { ->willReturnCallback(function () use ($currentUserId) {
if($currentUserId !== null) { if ($currentUserId !== null) {
return $this->getUserMock($currentUserId, $currentUserId); return $this->getUserMock($currentUserId, $currentUserId);
} }
return null; return null;
@ -506,55 +521,55 @@ class UserPluginTest extends TestCase {
'test', 'test',
['groupA'], ['groupA'],
[ [
[ 'uid' => 'test1', 'groups' => ['groupA'] ], ['uid' => 'test1', 'groups' => ['groupA']],
[ 'uid' => 'test2', 'groups' => ['groupB'] ] ['uid' => 'test2', 'groups' => ['groupB']],
], ],
['test1'] ['test1'],
], ],
[ [
'test', 'test',
['groupA'], ['groupA'],
[ [
[ 'uid' => 'test1', 'groups' => ['groupA'] ], ['uid' => 'test1', 'groups' => ['groupA']],
[ 'uid' => 'test2', 'groups' => ['groupB', 'groupA'] ] ['uid' => 'test2', 'groups' => ['groupB', 'groupA']],
], ],
['test1', 'test2'] ['test1', 'test2'],
], ],
[ [
'test', 'test',
['groupA'], ['groupA'],
[ [
[ 'uid' => 'test1', 'groups' => ['groupA', 'groupC'] ], ['uid' => 'test1', 'groups' => ['groupA', 'groupC']],
[ 'uid' => 'test2', 'groups' => ['groupB', 'groupA'] ] ['uid' => 'test2', 'groups' => ['groupB', 'groupA']],
], ],
['test1', 'test2'] ['test1', 'test2'],
], ],
[ [
'test', 'test',
['groupC', 'groupB'], ['groupC', 'groupB'],
[ [
[ 'uid' => 'test1', 'groups' => ['groupA', 'groupC'] ], ['uid' => 'test1', 'groups' => ['groupA', 'groupC']],
[ 'uid' => 'test2', 'groups' => ['groupB', 'groupA'] ] ['uid' => 'test2', 'groups' => ['groupB', 'groupA']],
], ],
['test1', 'test2'] ['test1', 'test2'],
], ],
[ [
'test', 'test',
[], [],
[ [
[ 'uid' => 'test1', 'groups' => ['groupA'] ], ['uid' => 'test1', 'groups' => ['groupA']],
[ 'uid' => 'test2', 'groups' => ['groupB', 'groupA'] ] ['uid' => 'test2', 'groups' => ['groupB', 'groupA']],
], ],
[] [],
], ],
[ [
'test', 'test',
['groupC', 'groupB'], ['groupC', 'groupB'],
[ [
[ 'uid' => 'test1', 'groups' => [] ], ['uid' => 'test1', 'groups' => []],
[ 'uid' => 'test2', 'groups' => [] ] ['uid' => 'test2', 'groups' => []],
], ],
[] [],
], ],
]; ];
} }
@ -570,7 +585,7 @@ class UserPluginTest extends TestCase {
}, $matchingUsers); }, $matchingUsers);
$mappedResult = array_map(function ($user) { $mappedResult = array_map(function ($user) {
return ['label' => $user, 'value' => [ 'shareType' => 0, 'shareWith' => $user ]]; return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user]];
}, $result); }, $result);
$this->userManager->expects($this->once()) $this->userManager->expects($this->once())