diff --git a/apps/settings/lib/Controller/UsersController.php b/apps/settings/lib/Controller/UsersController.php index 2e3b0d80ebcfc..46c149a1fed95 100644 --- a/apps/settings/lib/Controller/UsersController.php +++ b/apps/settings/lib/Controller/UsersController.php @@ -166,7 +166,7 @@ public function usersList(): TemplateResponse { $recentUsersGroup = [ 'id' => '__nc_internal_recent', 'name' => $this->l10n->t('Recently active'), - 'usercount' => $userCount, + 'usercount' => $this->userManager->countSeenUsers(), ]; $disabledUsersGroup = [ diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index a2f622dcbe839..d89fb803c81da 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -742,45 +742,49 @@ public function validateUserId(string $uid, bool $checkDataDirectory = false): v /** * Gets the list of user ids sorted by lastLogin, from most recent to least recent * - * @param int|null $limit how many users to fetch + * @param int|null $limit how many users to fetch (default: 25, max: 100) * @param int $offset from which offset to fetch * @param string $search search users based on search params * @return list list of user IDs */ public function getLastLoggedInUsers(?int $limit = null, int $offset = 0, string $search = ''): array { + // We can't load all users who already logged in + $limit = min(100, $limit ?: 25); + $connection = \OC::$server->getDatabaseConnection(); $queryBuilder = $connection->getQueryBuilder(); $queryBuilder->select('login.userid') ->from('preferences', 'login') ->where($queryBuilder->expr()->eq('login.appid', $queryBuilder->expr()->literal('login'))) ->andWhere($queryBuilder->expr()->eq('login.configkey', $queryBuilder->expr()->literal('lastLogin'))) - ->orderBy('login.configvalue', 'DESC') ->setFirstResult($offset) - ->setMaxResults($limit); + ->setMaxResults($limit) + ->orderBy('login.configvalue', 'DESC') + ->addOrderBy($queryBuilder->func()->lower('login.userid'), 'ASC'); if ($search === '') { - $queryBuilder->addOrderBy($queryBuilder->func()->lower('userid'), 'ASC'); - } else { - $queryBuilder->leftJoin('login', 'preferences', 'email', $queryBuilder->expr()->andX( - $queryBuilder->expr()->eq('login.userid', 'email.userid'), - $queryBuilder->expr()->eq('email.appid', $queryBuilder->expr()->literal('settings')), - $queryBuilder->expr()->eq('email.configkey', $queryBuilder->expr()->literal('email')), - )); - $queryBuilder->join('login', 'users', 'user', $queryBuilder->expr()->eq('login.userid', 'user.uid')); - $queryBuilder->andWhere($queryBuilder->expr()->orX( - $queryBuilder->expr()->iLike('uid', $queryBuilder->createPositionalParameter('%' . $connection->escapeLikeParameter($search) . '%')), - $queryBuilder->expr()->iLike('displayname', $queryBuilder->createPositionalParameter('%' . $connection->escapeLikeParameter($search) . '%')), - $queryBuilder->expr()->iLike('email.configvalue', $queryBuilder->createPositionalParameter('%' . $connection->escapeLikeParameter($search) . '%')), - )); - $queryBuilder->addOrderBy('uid_lower', 'ASC'); + return $queryBuilder + ->executeQuery() + ->fetchAll(\PDO::FETCH_COLUMN); } - $result = $queryBuilder->executeQuery(); - /** @var list $uids */ - $uids = $result->fetchAll(\PDO::FETCH_COLUMN); - $result->closeCursor(); + $queryBuilder->leftJoin('login', 'preferences', 'email', $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('login.userid', 'email.userid'), + $queryBuilder->expr()->eq('email.appid', $queryBuilder->expr()->literal('settings')), + $queryBuilder->expr()->eq('email.configkey', $queryBuilder->expr()->literal('email')), + )); - return $uids; + $displayNameMatches = $this->searchDisplayName($search); + $matchedUids = array_map(static fn (IUser $u): string => $u->getUID(), $displayNameMatches); + + return $queryBuilder + ->andWhere($queryBuilder->expr()->orX( + $queryBuilder->expr()->iLike('login.userid', $queryBuilder->createPositionalParameter('%' . $connection->escapeLikeParameter($search) . '%')), + $queryBuilder->expr()->iLike('email.configvalue', $queryBuilder->createPositionalParameter('%' . $connection->escapeLikeParameter($search) . '%')), + $queryBuilder->expr()->in('login.userid', $queryBuilder->createNamedParameter($matchedUids, IQueryBuilder::PARAM_STR_ARRAY)), + )) + ->executeQuery() + ->fetchAll(\PDO::FETCH_COLUMN); } private function verifyUid(string $uid, bool $checkDataDirectory = false): bool { diff --git a/tests/lib/User/ManagerTest.php b/tests/lib/User/ManagerTest.php index 39f1f1cef227e..13f27406c68b3 100644 --- a/tests/lib/User/ManagerTest.php +++ b/tests/lib/User/ManagerTest.php @@ -16,6 +16,7 @@ use OCP\ICacheFactory; use OCP\IConfig; use OCP\IUser; +use OCP\IUserManager; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -579,7 +580,7 @@ public function testCountUsersTwoBackends(): void { } public function testCountUsersOnlyDisabled(): void { - $manager = \OC::$server->getUserManager(); + $manager = \OCP\Server::get(IUserManager::class); // count other users in the db before adding our own $countBefore = $manager->countDisabledUsers(); @@ -604,7 +605,7 @@ public function testCountUsersOnlyDisabled(): void { } public function testCountUsersOnlySeen(): void { - $manager = \OC::$server->getUserManager(); + $manager = \OCP\Server::get(IUserManager::class); // count other users in the db before adding our own $countBefore = $manager->countSeenUsers(); @@ -630,7 +631,7 @@ public function testCountUsersOnlySeen(): void { } public function testCallForSeenUsers(): void { - $manager = \OC::$server->getUserManager(); + $manager = \OCP\Server::get(IUserManager::class); // count other users in the db before adding our own $count = 0; $function = function (IUser $user) use (&$count) { @@ -664,8 +665,12 @@ public function testCallForSeenUsers(): void { } public function testRecentlyActive(): void { - $manager = \OCP\Server::get(IUserManager::class); $config = \OCP\Server::get(IConfig::class); + $manager = \OCP\Server::get(IUserManager::class); + // Restore backend, otherwise test fail when launching all tests in tests/lib + $backend = \OCP\Server::get(Database::class); + $manager->clearBackends(); + $manager->registerBackend($backend); // Create some users $now = (string)time();