aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorCôme Chilliet <91878298+come-nc@users.noreply.github.com>2025-01-16 17:25:01 +0100
committerGitHub <noreply@github.com>2025-01-16 17:25:01 +0100
commit626bc7220b4feb61b6ef097087be4d44c2a8a570 (patch)
treea550035bd3a7acb4b08c4eeab5883342a9b5122a /lib
parent8b46ec2abbe3280dd8c9e50152a5b4be382098ca (diff)
parent892f815d2e82e771c36aeb67aeee46d5a0d0938c (diff)
downloadnextcloud-server-626bc7220b4feb61b6ef097087be4d44c2a8a570.tar.gz
nextcloud-server-626bc7220b4feb61b6ef097087be4d44c2a8a570.zip
Merge pull request #50171 from nextcloud/enh/limit-ldap-user-count
Limit ldap user count
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php3
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Support/Subscription/Registry.php21
-rw-r--r--lib/private/User/Database.php8
-rw-r--r--lib/private/User/Manager.php32
-rw-r--r--lib/public/IUserManager.php10
-rw-r--r--lib/public/User/Backend/ICountUsersBackend.php1
-rw-r--r--lib/public/User/Backend/ILimitAwareCountUsersBackend.php23
9 files changed, 74 insertions, 26 deletions
diff --git a/lib/base.php b/lib/base.php
index b0334ecd729..25f978df836 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -279,8 +279,7 @@ class OC {
}
if (!$tooBig) {
// count users
- $stats = Server::get(\OCP\IUserManager::class)->countUsers();
- $totalUsers = array_sum($stats);
+ $totalUsers = Server::get(\OCP\IUserManager::class)->countUsersTotal(51);
$tooBig = ($totalUsers > 50);
}
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 9916a0eb262..dab71032ccc 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -892,6 +892,7 @@ return array(
'OCP\\User\\Backend\\IGetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/IGetDisplayNameBackend.php',
'OCP\\User\\Backend\\IGetHomeBackend' => $baseDir . '/lib/public/User/Backend/IGetHomeBackend.php',
'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php',
+ 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => $baseDir . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php',
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
'OCP\\User\\Backend\\IPasswordHashBackend' => $baseDir . '/lib/public/User/Backend/IPasswordHashBackend.php',
'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 3c617b14053..00d3b2c2b5a 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -933,6 +933,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\User\\Backend\\IGetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetDisplayNameBackend.php',
'OCP\\User\\Backend\\IGetHomeBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetHomeBackend.php',
'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php',
+ 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php',
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
'OCP\\User\\Backend\\IPasswordHashBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordHashBackend.php',
'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php',
diff --git a/lib/private/Support/Subscription/Registry.php b/lib/private/Support/Subscription/Registry.php
index 3d3daa97abb..5eed6885f78 100644
--- a/lib/private/Support/Subscription/Registry.php
+++ b/lib/private/Support/Subscription/Registry.php
@@ -8,7 +8,6 @@ declare(strict_types=1);
*/
namespace OC\Support\Subscription;
-use OC\User\Backend;
use OCP\AppFramework\QueryException;
use OCP\IConfig;
use OCP\IGroupManager;
@@ -19,8 +18,6 @@ use OCP\Support\Subscription\Exception\AlreadyRegisteredException;
use OCP\Support\Subscription\IRegistry;
use OCP\Support\Subscription\ISubscription;
use OCP\Support\Subscription\ISupportedApps;
-use OCP\User\Backend\ICountMappedUsersBackend;
-use OCP\User\Backend\ICountUsersBackend;
use Psr\Log\LoggerInterface;
class Registry implements IRegistry {
@@ -167,22 +164,8 @@ class Registry implements IRegistry {
}
private function getUserCount(): int {
- $userCount = 0;
- $backends = $this->userManager->getBackends();
- foreach ($backends as $backend) {
- if ($backend instanceof ICountMappedUsersBackend) {
- $userCount += $backend->countMappedUsers();
- } elseif ($backend->implementsActions(Backend::COUNT_USERS)) {
- /** @var ICountUsersBackend $backend */
- $backendUsers = $backend->countUsers();
- if ($backendUsers !== false) {
- $userCount += $backendUsers;
- } else {
- // TODO what if the user count can't be determined?
- $this->logger->warning('Can not determine user count for ' . get_class($backend), ['app' => 'lib']);
- }
- }
- }
+ /* We cannot limit because we substract disabled users afterward. But we limit to mapped users so should be not too expensive. */
+ $userCount = (int)$this->userManager->countUsersTotal(0, true);
$disabledUsers = $this->config->getUsersForUserValue('core', 'enabled', 'false');
$disabledUsersCount = count($disabledUsers);
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index d2ec835a25d..d82a3be81e5 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -17,11 +17,11 @@ use OCP\Security\Events\ValidatePasswordPolicyEvent;
use OCP\Security\IHasher;
use OCP\User\Backend\ABackend;
use OCP\User\Backend\ICheckPasswordBackend;
-use OCP\User\Backend\ICountUsersBackend;
use OCP\User\Backend\ICreateUserBackend;
use OCP\User\Backend\IGetDisplayNameBackend;
use OCP\User\Backend\IGetHomeBackend;
use OCP\User\Backend\IGetRealUIDBackend;
+use OCP\User\Backend\ILimitAwareCountUsersBackend;
use OCP\User\Backend\IPasswordHashBackend;
use OCP\User\Backend\ISearchKnownUsersBackend;
use OCP\User\Backend\ISetDisplayNameBackend;
@@ -37,7 +37,7 @@ class Database extends ABackend implements
IGetDisplayNameBackend,
ICheckPasswordBackend,
IGetHomeBackend,
- ICountUsersBackend,
+ ILimitAwareCountUsersBackend,
ISearchKnownUsersBackend,
IGetRealUIDBackend,
IPasswordHashBackend {
@@ -463,10 +463,8 @@ class Database extends ABackend implements
/**
* counts the users in the database
- *
- * @return int|false
*/
- public function countUsers() {
+ public function countUsers(int $limit = 0): int|false {
$this->fixDI();
$query = $this->dbConn->getQueryBuilder();
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index 7f5b06cc5f6..aa2acb55782 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -24,8 +24,10 @@ use OCP\L10N\IFactory;
use OCP\Server;
use OCP\Support\Subscription\IAssertion;
use OCP\User\Backend\ICheckPasswordBackend;
+use OCP\User\Backend\ICountMappedUsersBackend;
use OCP\User\Backend\ICountUsersBackend;
use OCP\User\Backend\IGetRealUIDBackend;
+use OCP\User\Backend\ILimitAwareCountUsersBackend;
use OCP\User\Backend\IProvideEnabledStateBackend;
use OCP\User\Backend\ISearchKnownUsersBackend;
use OCP\User\Events\BeforeUserCreatedEvent;
@@ -488,6 +490,36 @@ class Manager extends PublicEmitter implements IUserManager {
return $userCountStatistics;
}
+ public function countUsersTotal(int $limit = 0, bool $onlyMappedUsers = false): int|false {
+ $userCount = false;
+
+ foreach ($this->backends as $backend) {
+ if ($onlyMappedUsers && $backend instanceof ICountMappedUsersBackend) {
+ $backendUsers = $backend->countMappedUsers();
+ } elseif ($backend instanceof ILimitAwareCountUsersBackend) {
+ $backendUsers = $backend->countUsers($limit);
+ } elseif ($backend instanceof ICountUsersBackend || $backend->implementsActions(Backend::COUNT_USERS)) {
+ /** @var ICountUsersBackend $backend */
+ $backendUsers = $backend->countUsers();
+ } else {
+ $this->logger->debug('Skip backend for user count: ' . get_class($backend));
+ continue;
+ }
+ if ($backendUsers !== false) {
+ $userCount = (int)$userCount + $backendUsers;
+ if ($limit > 0) {
+ if ($userCount >= $limit) {
+ break;
+ }
+ $limit -= $userCount;
+ }
+ } else {
+ $this->logger->warning('Can not determine user count for ' . get_class($backend));
+ }
+ }
+ return $userCount;
+ }
+
/**
* returns how many users per backend exist in the requested groups (if supported by backend)
*
diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php
index 091ccd89048..50eaa9c98b7 100644
--- a/lib/public/IUserManager.php
+++ b/lib/public/IUserManager.php
@@ -164,6 +164,16 @@ interface IUserManager {
public function countUsers();
/**
+ * Get how many users exists in total, whithin limit
+ *
+ * @param int $limit Limit the count to avoid resource waste. 0 to disable
+ * @param bool $onlyMappedUsers Count mapped users instead of all users for compatible backends
+ *
+ * @since 31.0.0
+ */
+ public function countUsersTotal(int $limit = 0, bool $onlyMappedUsers = false): int|false;
+
+ /**
* @param \Closure $callback
* @psalm-param \Closure(\OCP\IUser):void $callback
* @param string $search
diff --git a/lib/public/User/Backend/ICountUsersBackend.php b/lib/public/User/Backend/ICountUsersBackend.php
index e337147dd14..194cf465cbe 100644
--- a/lib/public/User/Backend/ICountUsersBackend.php
+++ b/lib/public/User/Backend/ICountUsersBackend.php
@@ -10,6 +10,7 @@ namespace OCP\User\Backend;
/**
* @since 14.0.0
+ * @deprecated 31.0.0 use and implement ILimitAwareCountUsersBackend instead.
*/
interface ICountUsersBackend {
/**
diff --git a/lib/public/User/Backend/ILimitAwareCountUsersBackend.php b/lib/public/User/Backend/ILimitAwareCountUsersBackend.php
new file mode 100644
index 00000000000..a59c0bd8e04
--- /dev/null
+++ b/lib/public/User/Backend/ILimitAwareCountUsersBackend.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCP\User\Backend;
+
+/**
+ * @since 31.0.0
+ */
+interface ILimitAwareCountUsersBackend extends ICountUsersBackend {
+ /**
+ * @since 31.0.0
+ *
+ * @param int $limit Limit to stop counting users if there are more than $limit. 0 to disable limiting.
+ * @return int|false The number of users (may be limited to $limit) on success false on failure
+ */
+ public function countUsers(int $limit = 0): int|false;
+}