diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2021-03-17 15:22:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-17 15:22:03 +0100 |
commit | 0d46fafd41a739c74a500d6149af23deb9d70155 (patch) | |
tree | fc14e854db1f5850d4dcdd389c4768b806c96d16 /lib | |
parent | d011df6aa7a38fdfafe6bc0acddebe9e156918d8 (diff) | |
parent | cf434d5107acc95d8a6afad15707e3e4fc33bbc9 (diff) | |
download | nextcloud-server-0d46fafd41a739c74a500d6149af23deb9d70155.tar.gz nextcloud-server-0d46fafd41a739c74a500d6149af23deb9d70155.zip |
Merge pull request #26161 from nextcloud/bugfix/noid/improve-matching-of-phonebook-searches
Improve search results when only phonebook-matches can we autocompleted
Diffstat (limited to 'lib')
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 2 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 2 | ||||
-rw-r--r-- | lib/private/Collaboration/Collaborators/UserPlugin.php | 27 | ||||
-rw-r--r-- | lib/private/User/Backend.php | 4 | ||||
-rw-r--r-- | lib/private/User/Database.php | 48 | ||||
-rw-r--r-- | lib/private/User/Manager.php | 36 | ||||
-rw-r--r-- | lib/public/IUserManager.php | 12 | ||||
-rw-r--r-- | lib/public/User/Backend/IGetRealUIDBackend.php | 2 | ||||
-rw-r--r-- | lib/public/User/Backend/ISearchKnownUsersBackend.php | 43 | ||||
-rw-r--r-- | lib/public/UserInterface.php | 4 |
10 files changed, 170 insertions, 10 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 65f050ed265..86d24ad031c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -534,6 +534,7 @@ return array( 'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php', + 'OCP\\User\\Backend\\ISearchKnownUsersBackend' => $baseDir . '/lib/public/User/Backend/ISearchKnownUsersBackend.php', 'OCP\\User\\Backend\\ISetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/ISetDisplayNameBackend.php', 'OCP\\User\\Backend\\ISetPasswordBackend' => $baseDir . '/lib/public/User/Backend/ISetPasswordBackend.php', 'OCP\\User\\Events\\BeforePasswordUpdatedEvent' => $baseDir . '/lib/public/User/Events/BeforePasswordUpdatedEvent.php', @@ -949,6 +950,7 @@ return array( 'OC\\Core\\Migrations\\Version21000Date20201202095923' => $baseDir . '/core/Migrations/Version21000Date20201202095923.php', 'OC\\Core\\Migrations\\Version21000Date20210119195004' => $baseDir . '/core/Migrations/Version21000Date20210119195004.php', 'OC\\Core\\Migrations\\Version21000Date20210309185126' => $baseDir . '/core/Migrations/Version21000Date20210309185126.php', + 'OC\\Core\\Migrations\\Version21000Date20210309185127' => $baseDir . '/core/Migrations/Version21000Date20210309185127.php', 'OC\\Core\\Migrations\\Version22000Date20210216080825' => $baseDir . '/core/Migrations/Version22000Date20210216080825.php', 'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index de07f1831bb..5cf2b9a2cb0 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -563,6 +563,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php', + 'OCP\\User\\Backend\\ISearchKnownUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISearchKnownUsersBackend.php', 'OCP\\User\\Backend\\ISetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetDisplayNameBackend.php', 'OCP\\User\\Backend\\ISetPasswordBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetPasswordBackend.php', 'OCP\\User\\Events\\BeforePasswordUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforePasswordUpdatedEvent.php', @@ -978,6 +979,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Migrations\\Version21000Date20201202095923' => __DIR__ . '/../../..' . '/core/Migrations/Version21000Date20201202095923.php', 'OC\\Core\\Migrations\\Version21000Date20210119195004' => __DIR__ . '/../../..' . '/core/Migrations/Version21000Date20210119195004.php', 'OC\\Core\\Migrations\\Version21000Date20210309185126' => __DIR__ . '/../../..' . '/core/Migrations/Version21000Date20210309185126.php', + 'OC\\Core\\Migrations\\Version21000Date20210309185127' => __DIR__ . '/../../..' . '/core/Migrations/Version21000Date20210309185127.php', 'OC\\Core\\Migrations\\Version22000Date20210216080825' => __DIR__ . '/../../..' . '/core/Migrations/Version22000Date20210216080825.php', 'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php', diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index 06a8c6f0efd..12ed3e98932 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -97,7 +97,7 @@ class UserPlugin implements ISearchPlugin { $currentUserId = $this->userSession->getUser()->getUID(); $currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser()); - if ($this->shareWithGroupOnly) { + if ($this->shareWithGroupOnly || $this->shareeEnumerationInGroupOnly) { // Search in all the groups this user is part of foreach ($currentUserGroups as $userGroupId) { $usersInGroup = $this->groupManager->displayNamesInGroup($userGroupId, $search, $limit, $offset); @@ -114,9 +114,32 @@ class UserPlugin implements ISearchPlugin { $hasMoreResults = true; } } + + if (!$this->shareWithGroupOnly && $this->shareeEnumerationPhone) { + $usersTmp = $this->userManager->searchKnownUsersByDisplayName($currentUserId, $search, $limit, $offset); + if (!empty($usersTmp)) { + foreach ($usersTmp as $user) { + if ($user->isEnabled()) { // Don't keep deactivated users + $users[$user->getUID()] = $user; + } + } + + uasort($users, function ($a, $b) { + /** + * @var \OC\User\User $a + * @var \OC\User\User $b + */ + return strcasecmp($a->getDisplayName(), $b->getDisplayName()); + }); + } + } } else { // Search in all users - $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); + if ($this->shareeEnumerationPhone) { + $usersTmp = $this->userManager->searchKnownUsersByDisplayName($currentUserId, $search, $limit, $offset); + } else { + $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); + } foreach ($usersTmp as $user) { if ($user->isEnabled()) { // Don't keep deactivated users $users[$user->getUID()] = $user; diff --git a/lib/private/User/Backend.php b/lib/private/User/Backend.php index c87dc5d2d50..d70d13673cb 100644 --- a/lib/private/User/Backend.php +++ b/lib/private/User/Backend.php @@ -143,8 +143,8 @@ abstract class Backend implements UserInterface { * Get a list of all display names and user ids. * * @param string $search - * @param string|null $limit - * @param string|null $offset + * @param int|null $limit + * @param int|null $offset * @return array an array of all displayNames (value) and the corresponding uids (key) */ public function getDisplayNames($search = '', $limit = null, $offset = null) { diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 85e22d196e4..6c04a1b900e 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -70,6 +70,7 @@ use OCP\User\Backend\ICreateUserBackend; use OCP\User\Backend\IGetDisplayNameBackend; use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; @@ -84,6 +85,7 @@ class Database extends ABackend implements ICheckPasswordBackend, IGetHomeBackend, ICountUsersBackend, + ISearchKnownUsersBackend, IGetRealUIDBackend { /** @var CappedMemoryCache */ private $cache; @@ -254,8 +256,8 @@ class Database extends ABackend implements * Get a list of all display names and user ids. * * @param string $search - * @param string|null $limit - * @param string|null $offset + * @param int|null $limit + * @param int|null $offset * @return array an array of all displayNames (value) and the corresponding uids (key) */ public function getDisplayNames($search = '', $limit = null, $offset = null) { @@ -277,7 +279,47 @@ class Database extends ABackend implements ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) ->orderBy($query->func()->lower('displayname'), 'ASC') - ->orderBy('uid_lower', 'ASC') + ->addOrderBy('uid_lower', 'ASC') + ->setMaxResults($limit) + ->setFirstResult($offset); + + $result = $query->execute(); + $displayNames = []; + while ($row = $result->fetch()) { + $displayNames[(string)$row['uid']] = (string)$row['displayname']; + } + + return $displayNames; + } + + /** + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return array + * @since 21.0.1 + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array { + $limit = $this->fixLimit($limit); + + $this->fixDI(); + + $query = $this->dbConn->getQueryBuilder(); + + $query->select('u.uid', 'u.displayname') + ->from($this->table, 'u') + ->leftJoin('u', 'known_users', 'k', $query->expr()->andX( + $query->expr()->eq('k.known_user', 'u.uid'), + $query->expr()->eq('k.known_to', $query->createNamedParameter($searcher)) + )) + ->where($query->expr()->eq('k.known_to', $query->createNamedParameter($searcher))) + ->andWhere($query->expr()->orX( + $query->expr()->iLike('u.uid', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')), + $query->expr()->iLike('u.displayname', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')) + )) + ->orderBy('u.displayname', 'ASC') + ->addOrderBy('u.uid_lower', 'ASC') ->setMaxResults($limit) ->setFirstResult($offset); diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 5223a80a2fd..59c007b6b59 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -47,6 +47,7 @@ use OCP\IUserBackend; use OCP\IUserManager; use OCP\Support\Subscription\IRegistry; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\UserCreatedEvent; use OCP\UserInterface; @@ -330,6 +331,41 @@ class Manager extends PublicEmitter implements IUserManager { } /** + * Search known users (from phonebook sync) by displayName + * + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return IUser[] + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array { + $users = []; + foreach ($this->backends as $backend) { + if ($backend instanceof ISearchKnownUsersBackend) { + $backendUsers = $backend->searchKnownUsersByDisplayName($searcher, $pattern, $limit, $offset); + } else { + // Better than nothing, but filtering after pagination can remove lots of results. + $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); + } + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid => $displayName) { + $users[] = $this->getUserObject($uid, $backend); + } + } + } + + usort($users, function ($a, $b) { + /** + * @var IUser $a + * @var IUser $b + */ + return strcasecmp($a->getDisplayName(), $b->getDisplayName()); + }); + return $users; + } + + /** * @param string $uid * @param string $password * @throws \InvalidArgumentException diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php index e8a7fc7827d..6963bb5ddbc 100644 --- a/lib/public/IUserManager.php +++ b/lib/public/IUserManager.php @@ -127,6 +127,18 @@ interface IUserManager { public function searchDisplayName($pattern, $limit = null, $offset = null); /** + * Search known users (from phonebook sync) by displayName + * + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return IUser[] + * @since 21.0.1 + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array; + + /** * @param string $uid * @param string $password * @throws \InvalidArgumentException diff --git a/lib/public/User/Backend/IGetRealUIDBackend.php b/lib/public/User/Backend/IGetRealUIDBackend.php index d724426e176..cc290eb6dc0 100644 --- a/lib/public/User/Backend/IGetRealUIDBackend.php +++ b/lib/public/User/Backend/IGetRealUIDBackend.php @@ -33,7 +33,7 @@ interface IGetRealUIDBackend { /** * Some backends accept different UIDs than what is the internal UID to be used. - * For example the database backend accepts differnt cased UIDs in all the functions + * For example the database backend accepts different cased UIDs in all the functions * but the internal UID that is to be used should be correctly cased. * * This little function makes sure that the used UID will be correct hen using the user object diff --git a/lib/public/User/Backend/ISearchKnownUsersBackend.php b/lib/public/User/Backend/ISearchKnownUsersBackend.php new file mode 100644 index 00000000000..89c7a49cd30 --- /dev/null +++ b/lib/public/User/Backend/ISearchKnownUsersBackend.php @@ -0,0 +1,43 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com> + * + * @author Joas Schilling <coding@schilljs.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\User\Backend; + +/** + * @since 21.0.1 + */ +interface ISearchKnownUsersBackend { + + /** + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return array + * @since 21.0.1 + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array; +} diff --git a/lib/public/UserInterface.php b/lib/public/UserInterface.php index 0479041e8de..42a18cca103 100644 --- a/lib/public/UserInterface.php +++ b/lib/public/UserInterface.php @@ -92,8 +92,8 @@ interface UserInterface { * Get a list of all display names and user ids. * * @param string $search - * @param string|null $limit - * @param string|null $offset + * @param int|null $limit + * @param int|null $offset * @return array an array of all displayNames (value) and the corresponding uids (key) * @since 4.5.0 */ |