From 64cb220930a7020c0d80644de3791f7d880ae6fa Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Mon, 27 Jul 2026 19:58:25 +0200 Subject: [PATCH 1/3] perf: Implemet ISearchableGroupBackend Signed-off-by: Carl Schwan --- lib/GroupBackend.php | 76 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 8c9e55ccd..2da2711a5 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -7,6 +7,7 @@ namespace OCA\User_SAML; +use OC\User\LazyUser; use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Group\Backend\ABackend; @@ -19,12 +20,27 @@ use OCP\Group\Backend\IGroupDetailsBackend; use OCP\Group\Backend\INamedBackend; use OCP\Group\Backend\IRemoveFromGroupBackend; +use OCP\Group\Backend\ISearchableGroupBackend; use OCP\Group\Backend\ISetDisplayNameBackend; use OCP\IDBConnection; +use OCP\IUserManager; +use OCP\Server; use PDO; use Psr\Log\LoggerInterface; -class GroupBackend extends ABackend implements IAddToGroupBackend, ICountUsersBackend, ICreateNamedGroupBackend, IDeleteGroupBackend, IGetDisplayNameBackend, IRemoveFromGroupBackend, ISetDisplayNameBackend, INamedBackend, IBatchMethodsBackend, IGroupDetailsBackend { +class GroupBackend extends ABackend implements + IAddToGroupBackend, + ICountUsersBackend, + ICreateNamedGroupBackend, + IDeleteGroupBackend, + IGetDisplayNameBackend, + IRemoveFromGroupBackend, + ISetDisplayNameBackend, + INamedBackend, + IBatchMethodsBackend, + IGroupDetailsBackend, + ISearchableGroupBackend { + /** @var array */ private array $groupCache = []; @@ -439,4 +455,62 @@ public function setupSearchQuery(string $search, IQueryBuilder $query): void { ); } } + + #[\Override] + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array { + $query = $this->dbc->getQueryBuilder(); + $query->select('g.uid', 'dn.value AS displayname') + ->from(self::TABLE_MEMBERS, 'g') + ->where($query->expr()->eq('gid', $query->createNamedParameter($gid))) + ->orderBy('g.uid', 'ASC'); + + // Join displayname and email from oc_accounts_data + $query->leftJoin('g', 'accounts_data', 'dn', + $query->expr()->andX( + $query->expr()->eq('dn.uid', 'g.uid'), + $query->expr()->eq('dn.name', $query->expr()->literal('displayname')) + ) + ); + + $query->leftJoin('g', 'accounts_data', 'em', + $query->expr()->andX( + $query->expr()->eq('em.uid', 'g.uid'), + $query->expr()->eq('em.name', $query->expr()->literal('email')) + ) + ); + + if ($search !== '') { + // sqlite doesn't like re-using a single named parameter here + $searchParam1 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); + $searchParam2 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); + $searchParam3 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); + + $query->andWhere( + $query->expr()->orX( + $query->expr()->ilike('g.uid', $searchParam1), + $query->expr()->ilike('dn.value', $searchParam2), + $query->expr()->ilike('em.value', $searchParam3) + ) + ) + ->orderBy('g.uid', 'ASC'); + } + + if ($limit !== -1) { + $query->setMaxResults($limit); + } + if ($offset !== 0) { + $query->setFirstResult($offset); + } + + $result = $query->executeQuery(); + + $users = []; + $userManager = Server::get(IUserManager::class); + while ($row = $result->fetch()) { + $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); + } + $result->closeCursor(); + + return $users; + } } From 8baba19c9ae7a99658b18a8e59a77389add44f7e Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Mon, 27 Jul 2026 20:16:32 +0200 Subject: [PATCH 2/3] refactor: Prepare code for createLazyUser Signed-off-by: Carl Schwan --- lib/GroupBackend.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 2da2711a5..8be75edf3 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -507,7 +507,11 @@ public function searchInGroup(string $gid, string $search = '', int $limit = -1, $users = []; $userManager = Server::get(IUserManager::class); while ($row = $result->fetch()) { - $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); + if (method_exists($userManager, 'createLazyUser')) { + $users[$row['uid']] = $userManager->createLazyUser($row['uid'], $row['displayname'] ?? null); + } else { + $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); + } } $result->closeCursor(); From 369fe8faae5c46f794d17709c02cad59fae7ac49 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Mon, 27 Jul 2026 20:18:09 +0200 Subject: [PATCH 3/3] refactor: Use getExistingUser if it exists Signed-off-by: Carl Schwan --- lib/GroupBackend.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 8be75edf3..522f8dda4 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -507,9 +507,10 @@ public function searchInGroup(string $gid, string $search = '', int $limit = -1, $users = []; $userManager = Server::get(IUserManager::class); while ($row = $result->fetch()) { - if (method_exists($userManager, 'createLazyUser')) { - $users[$row['uid']] = $userManager->createLazyUser($row['uid'], $row['displayname'] ?? null); + if (method_exists($userManager, 'getExistingUser')) { + $users[$row['uid']] = $userManager->getExistingUser($row['uid'], $row['displayname'] ?? null); } else { + /** @psalm-suppress UndefinedClass */ $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); } }