From 518ac987991ce2fa642382a65c172a96580eb83a Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 7 Jul 2025 10:39:16 +0530 Subject: [PATCH 01/23] Sync Missing Users to Common Database --- README.md | 29 +++- appinfo/info.xml | 1 + lib/Command/SyncMissingUsersToCommon.php | 186 +++++++++++++++++++++++ lib/Service/LDAPConnectionService.php | 54 +++++++ 4 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 lib/Command/SyncMissingUsersToCommon.php diff --git a/README.md b/README.md index a81343a3..e70405bc 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ ## Fix Missing Email Addresses -- This app provides a command to fix missing email addresses by querying LDAP and setting them in NextCloud ### Usage @@ -61,6 +60,34 @@ occ ecloud-accounts:fix-missing-emails --users=user1 --users=user2 --dry-run 4. Sets only the email address in NextCloud (quota remains unchanged) 5. Provides detailed output of the process and any errors encountered +## Sync Missing Users to Common Database + +- This app provides a command to sync users that exist in NextCloud but are missing from the common database +- The command fetches user metadata from LDAP and adds missing users to the common database + +### Usage + +```bash +# Sync all missing users (dry run first) +occ ecloud-accounts:sync-missing-users-to-common --dry-run + +# Sync all missing users +occ ecloud-accounts:sync-missing-users-to-common + +# Sync specific users (multiple --users arguments) +occ ecloud-accounts:sync-missing-users-to-common --users=user1 --users=user2 --users=user3 + +# Sync specific users with dry run and custom IP +occ ecloud-accounts:sync-missing-users-to-common --users=user1 --users=user2 --dry-run --ip-address=192.168.1.100 +``` + +### What it does + +1. Queries NextCloud database to find all users +2. Checks which users are missing from the common database +3. For each missing user, fetches metadata from LDAP (displayName, recoveryMailAddress, etc.) +4. Adds the user to the common database with the fetched metadata + ## Support Please open issues here : https://gitlab.e.foundation/e/backlog/issues diff --git a/appinfo/info.xml b/appinfo/info.xml index 4c4d4c41..84e0badd 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -29,5 +29,6 @@ OCA\EcloudAccounts\Command\MigrateWebmailAddressbooks OCA\EcloudAccounts\Command\MapActiveAttributetoLDAP OCA\EcloudAccounts\Command\FixMissingEmails + OCA\EcloudAccounts\Command\SyncMissingUsersToCommon diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php new file mode 100644 index 00000000..fedb2581 --- /dev/null +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -0,0 +1,186 @@ +ldapConnectionService = $ldapConnectionService; + $this->userService = $userService; + $this->dbConnection = $dbConnection; + $this->userManager = $userManager; + } + + protected function configure(): void { + $this + ->setName(Application::APP_ID . ':sync-missing-users-to-common') + ->setDescription('Syncs missing users from NextCloud to common database by fetching metadata from LDAP') + ->addOption( + 'users', + null, + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'Users to sync (can be specified multiple times, e.g., --users=user1 --users=user2)', + [] + ) + ->addOption( + 'dry-run', + null, + InputOption::VALUE_NONE, + 'Show what would be done without making changes' + ) + ->addOption( + 'ip-address', + null, + InputOption::VALUE_OPTIONAL, + 'IP address to use for all users (defaults to 127.0.0.1)', + '127.0.0.1' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + try { + $isDryRun = $input->getOption('dry-run'); + $usernames = $input->getOption('users'); + $ipAddress = $input->getOption('ip-address'); + + if ($isDryRun) { + $output->writeln('DRY RUN MODE - No changes will be made'); + } + + // Get users missing from common database + $missingUsers = $this->getMissingUsersFromCommon($usernames); + + if (empty($missingUsers)) { + $output->writeln('No users found missing from common database.'); + return 0; + } + + $output->writeln(sprintf('Found %d users missing from common database.', count($missingUsers))); + + $successCount = 0; + $errorCount = 0; + + foreach ($missingUsers as $username) { + try { + $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); + $successCount++; + } catch (Exception $e) { + $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); + $errorCount++; + } + } + + $output->writeln(sprintf('Processed %d users successfully, %d errors.', $successCount, $errorCount)); + return 0; + } catch (Exception $e) { + $output->writeln(sprintf('Error: %s', $e->getMessage())); + return 1; + } + } + + /** + * Get users that exist in NextCloud but are missing from common database + * + * @param array $usernames Array of usernames to check (if empty, all users will be processed) + * @return array Array of usernames missing from common database + */ + private function getMissingUsersFromCommon(array $usernames = []): array { + $query = $this->dbConnection->getQueryBuilder(); + $query->select('a.uid') + ->from('accounts', 'a'); + + if (!empty($usernames)) { + $placeholders = []; + foreach ($usernames as $username) { + $placeholders[] = $query->createNamedParameter($username); + } + $query->where($query->expr()->in('a.uid', $placeholders)); + } + + $result = null; + $users = []; + try { + $result = $query->execute(); + while ($row = $result->fetch()) { + $users[] = $row['uid']; + } + } finally { + if ($result !== null) { + $result->closeCursor(); + } + } + + // Filter out users that already exist in common database + $missingUsers = []; + foreach ($users as $username) { + if (!$this->userService->isUsernameTaken($username)) { + $missingUsers[] = $username; + } + } + + return $missingUsers; + } + + /** + * Sync a specific user to the common database + * + * @param string $username The username to sync + * @param string $ipAddress The IP address to use + * @param bool $isDryRun Whether this is a dry run + * @param OutputInterface $output The output interface for writing messages + * @return void + */ + private function syncUserToCommon(string $username, string $ipAddress, bool $isDryRun, OutputInterface $output): void { + $output->writeln(sprintf('Processing user: %s', $username)); + + // Check if user exists and is on LDAP backend + $user = $this->userManager->get($username); + if (!$user) { + throw new Exception("User not found in NextCloud"); + } + + if (!$this->ldapConnectionService->isUserOnLDAPBackend($user)) { + throw new Exception("User is not on LDAP backend"); + } + + // Get user metadata from LDAP + $userMetadata = $this->ldapConnectionService->getUserMetadata($username); + + $output->writeln(sprintf(' Found user in LDAP: %s (%s)', $userMetadata['displayName'], $userMetadata['mailAddress'])); + + if (!$isDryRun) { + // Add user to common database + $this->userService->addUsernameToCommonDataStore( + $username, + $ipAddress, + $userMetadata['recoveryMailAddress'] + ); + $output->writeln(sprintf(' ✓ User synced successfully to common database: %s', $username)); + } else { + $output->writeln(sprintf(' Would sync user to common database with recovery email: %s', $userMetadata['recoveryMailAddress'])); + } + } +} diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php index b63fb339..41cc66bd 100644 --- a/lib/Service/LDAPConnectionService.php +++ b/lib/Service/LDAPConnectionService.php @@ -161,4 +161,58 @@ class LDAPConnectionService { return $mailAddress; } + + /** + * Get comprehensive user metadata from LDAP + * + * @param string $username The username to search for + * @return array User metadata including displayName, recoveryMailAddress, etc. + * @throws Exception If LDAP is not enabled or user not found + */ + public function getUserMetadata(string $username): array { + if (!$this->isLDAPEnabled()) { + throw new Exception('LDAP backend is not enabled'); + } + + $conn = $this->getLDAPConnection(); + $userDn = $this->username2dn($username); + + if ($userDn === false) { + throw new Exception('Could not find DN for username: ' . $username); + } + + $attributes = [ + 'mailAddress', + 'displayName', + 'recoveryMailAddress', + 'username', + 'active', + 'mailActive' + ]; + + $result = ldap_read($conn, $userDn, '(objectClass=*)', $attributes); + + if (!$result) { + $this->closeLDAPConnection($conn); + throw new Exception('Could not read user entry from LDAP for username: ' . $username); + } + + $entries = ldap_get_entries($conn, $result); + $this->closeLDAPConnection($conn); + + if ($entries['count'] === 0) { + throw new Exception('User not found in LDAP: ' . $username); + } + + $entry = $entries[0]; + + return [ + 'username' => $entry['username'][0] ?? $username, + 'displayName' => $entry['displayname'][0] ?? $username, + 'mailAddress' => $entry['mailaddress'][0] ?? null, + 'recoveryMailAddress' => $entry['recoverymailaddress'][0] ?? '', + 'active' => $entry['active'][0] ?? 'TRUE', + 'mailActive' => $entry['mailactive'][0] ?? 'TRUE' + ]; + } } -- GitLab From a20e45401ac1b8b16bea165d99788c3a2deb3e60 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 7 Jul 2025 12:22:02 +0530 Subject: [PATCH 02/23] added changes in function --- lib/Command/SyncMissingUsersToCommon.php | 37 +++++++++--------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index fedb2581..79dbcccc 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -8,7 +8,7 @@ use Exception; use OCA\EcloudAccounts\AppInfo\Application; use OCA\EcloudAccounts\Service\LDAPConnectionService; use OCA\EcloudAccounts\Service\UserService; -use OCP\IDBConnection; +use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -18,19 +18,16 @@ use Symfony\Component\Console\Output\OutputInterface; class SyncMissingUsersToCommon extends Command { private LDAPConnectionService $ldapConnectionService; private UserService $userService; - private IDBConnection $dbConnection; private IUserManager $userManager; public function __construct( LDAPConnectionService $ldapConnectionService, UserService $userService, - IDBConnection $dbConnection, IUserManager $userManager ) { parent::__construct(); $this->ldapConnectionService = $ldapConnectionService; $this->userService = $userService; - $this->dbConnection = $dbConnection; $this->userManager = $userManager; } @@ -108,29 +105,21 @@ class SyncMissingUsersToCommon extends Command { * @return array Array of usernames missing from common database */ private function getMissingUsersFromCommon(array $usernames = []): array { - $query = $this->dbConnection->getQueryBuilder(); - $query->select('a.uid') - ->from('accounts', 'a'); - + $users = []; + if (!empty($usernames)) { - $placeholders = []; + // Get specific users foreach ($usernames as $username) { - $placeholders[] = $query->createNamedParameter($username); - } - $query->where($query->expr()->in('a.uid', $placeholders)); - } - - $result = null; - $users = []; - try { - $result = $query->execute(); - while ($row = $result->fetch()) { - $users[] = $row['uid']; - } - } finally { - if ($result !== null) { - $result->closeCursor(); + $user = $this->userManager->get($username); + if ($user) { + $users[] = $user->getUID(); + } } + } else { + // Get all users + $this->userManager->callForSeenUsers(function (IUser $user) use (&$users) { + $users[] = $user->getUID(); + }); } // Filter out users that already exist in common database -- GitLab From 96d3979203cb0e4f7ed1f3e2de15bf2768c71728 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 7 Jul 2025 12:41:44 +0530 Subject: [PATCH 03/23] jump to 10.0.7 --- README.md | 1 + appinfo/info.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e70405bc..1378930d 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ ## Fix Missing Email Addresses +- This app provides a command to fix missing email addresses by querying LDAP and setting them in NextCloud ### Usage diff --git a/appinfo/info.xml b/appinfo/info.xml index 84e0badd..14e89381 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -10,7 +10,7 @@ - 10.0.6 + 10.0.7 agpl Murena SAS EcloudAccounts -- GitLab From 39b6b5dd9883edacd0cb12ea085937efbed0ef90 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 7 Jul 2025 15:11:38 +0530 Subject: [PATCH 04/23] Cleanup: remove unused LDAP fields, store blank ip_address if not set --- lib/Command/SyncMissingUsersToCommon.php | 9 +++++++-- lib/Service/LDAPConnectionService.php | 4 +--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 79dbcccc..3541e94e 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -52,8 +52,8 @@ class SyncMissingUsersToCommon extends Command { 'ip-address', null, InputOption::VALUE_OPTIONAL, - 'IP address to use for all users (defaults to 127.0.0.1)', - '127.0.0.1' + 'IP address to use for all users (store blank if not set)', + null ); } @@ -63,6 +63,11 @@ class SyncMissingUsersToCommon extends Command { $usernames = $input->getOption('users'); $ipAddress = $input->getOption('ip-address'); + // If ipAddress is null, store blank string + if ($ipAddress === null) { + $ipAddress = ''; + } + if ($isDryRun) { $output->writeln('DRY RUN MODE - No changes will be made'); } diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php index 41cc66bd..443bbe2a 100644 --- a/lib/Service/LDAPConnectionService.php +++ b/lib/Service/LDAPConnectionService.php @@ -210,9 +210,7 @@ class LDAPConnectionService { 'username' => $entry['username'][0] ?? $username, 'displayName' => $entry['displayname'][0] ?? $username, 'mailAddress' => $entry['mailaddress'][0] ?? null, - 'recoveryMailAddress' => $entry['recoverymailaddress'][0] ?? '', - 'active' => $entry['active'][0] ?? 'TRUE', - 'mailActive' => $entry['mailactive'][0] ?? 'TRUE' + 'recoveryMailAddress' => $entry['recoverymailaddress'][0] ?? '' ]; } } -- GitLab From 822475f8d9f6c0b66fa446e4f324091be4f286d2 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Mon, 7 Jul 2025 16:38:09 +0530 Subject: [PATCH 05/23] Add sleep after every 100 users to reduce memory load --- lib/Command/SyncMissingUsersToCommon.php | 113 ++++++++++++----------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 3541e94e..c439bd3d 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -72,30 +72,66 @@ class SyncMissingUsersToCommon extends Command { $output->writeln('DRY RUN MODE - No changes will be made'); } - // Get users missing from common database - $missingUsers = $this->getMissingUsersFromCommon($usernames); - - if (empty($missingUsers)) { - $output->writeln('No users found missing from common database.'); - return 0; - } - - $output->writeln(sprintf('Found %d users missing from common database.', count($missingUsers))); - - $successCount = 0; - $errorCount = 0; - - foreach ($missingUsers as $username) { - try { - $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); - $successCount++; - } catch (Exception $e) { - $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); - $errorCount++; + $totalProcessed = 0; + $totalSuccess = 0; + $totalErrors = 0; + + if (!empty($usernames)) { + // Process specific users + $output->writeln(sprintf('Processing %d specific users', count($usernames))); + + foreach ($usernames as $username) { + $user = $this->userManager->get($username); + if (!$user) { + $output->writeln(sprintf('User not found: %s', $username)); + $totalErrors++; + continue; + } + + if ($this->userService->isUsernameTaken($username)) { + $output->writeln(sprintf('User already exists in common database: %s', $username)); + continue; + } + + try { + $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); + $totalSuccess++; + } catch (Exception $e) { + $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); + $totalErrors++; + } + $totalProcessed++; } + } else { + // Process all users + $output->writeln('Processing all users from NextCloud'); + + $this->userManager->callForSeenUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$totalProcessed, &$totalSuccess, &$totalErrors) { + $username = $user->getUID(); + + // Check if user is missing from common database + if ($this->userService->isUsernameTaken($username)) { + return; // Skip if already exists + } + + try { + $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); + $totalSuccess++; + } catch (Exception $e) { + $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); + $totalErrors++; + } + $totalProcessed++; + + // Show progress every 100 users + if ($totalProcessed % 100 === 0) { + $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $totalProcessed, $totalSuccess, $totalErrors)); + sleep(1); // Pause for 1 second to allow memory to refresh + } + }); } - $output->writeln(sprintf('Processed %d users successfully, %d errors.', $successCount, $errorCount)); + $output->writeln(sprintf('Final result: %d users processed, %d success, %d errors.', $totalProcessed, $totalSuccess, $totalErrors)); return 0; } catch (Exception $e) { $output->writeln(sprintf('Error: %s', $e->getMessage())); @@ -103,41 +139,6 @@ class SyncMissingUsersToCommon extends Command { } } - /** - * Get users that exist in NextCloud but are missing from common database - * - * @param array $usernames Array of usernames to check (if empty, all users will be processed) - * @return array Array of usernames missing from common database - */ - private function getMissingUsersFromCommon(array $usernames = []): array { - $users = []; - - if (!empty($usernames)) { - // Get specific users - foreach ($usernames as $username) { - $user = $this->userManager->get($username); - if ($user) { - $users[] = $user->getUID(); - } - } - } else { - // Get all users - $this->userManager->callForSeenUsers(function (IUser $user) use (&$users) { - $users[] = $user->getUID(); - }); - } - - // Filter out users that already exist in common database - $missingUsers = []; - foreach ($users as $username) { - if (!$this->userService->isUsernameTaken($username)) { - $missingUsers[] = $username; - } - } - - return $missingUsers; - } - /** * Sync a specific user to the common database * -- GitLab From f55dec903540277ec21972e4bcfbd7a83f9a4bd3 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 11:25:38 +0530 Subject: [PATCH 06/23] refactored code to make execute short --- appinfo/info.xml | 2 +- lib/Command/SyncMissingUsersToCommon.php | 175 ++++++++++++++--------- 2 files changed, 110 insertions(+), 67 deletions(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index 14e89381..e2145280 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -10,7 +10,7 @@ - 10.0.7 + 10.1.0 agpl Murena SAS EcloudAccounts diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index c439bd3d..87ab95a6 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -61,77 +61,15 @@ class SyncMissingUsersToCommon extends Command { try { $isDryRun = $input->getOption('dry-run'); $usernames = $input->getOption('users'); - $ipAddress = $input->getOption('ip-address'); - - // If ipAddress is null, store blank string - if ($ipAddress === null) { - $ipAddress = ''; - } + $ipAddress = $this->normalizeIpAddress($input->getOption('ip-address')); if ($isDryRun) { $output->writeln('DRY RUN MODE - No changes will be made'); } - $totalProcessed = 0; - $totalSuccess = 0; - $totalErrors = 0; - - if (!empty($usernames)) { - // Process specific users - $output->writeln(sprintf('Processing %d specific users', count($usernames))); - - foreach ($usernames as $username) { - $user = $this->userManager->get($username); - if (!$user) { - $output->writeln(sprintf('User not found: %s', $username)); - $totalErrors++; - continue; - } - - if ($this->userService->isUsernameTaken($username)) { - $output->writeln(sprintf('User already exists in common database: %s', $username)); - continue; - } - - try { - $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); - $totalSuccess++; - } catch (Exception $e) { - $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); - $totalErrors++; - } - $totalProcessed++; - } - } else { - // Process all users - $output->writeln('Processing all users from NextCloud'); - - $this->userManager->callForSeenUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$totalProcessed, &$totalSuccess, &$totalErrors) { - $username = $user->getUID(); - - // Check if user is missing from common database - if ($this->userService->isUsernameTaken($username)) { - return; // Skip if already exists - } - - try { - $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); - $totalSuccess++; - } catch (Exception $e) { - $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); - $totalErrors++; - } - $totalProcessed++; - - // Show progress every 100 users - if ($totalProcessed % 100 === 0) { - $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $totalProcessed, $totalSuccess, $totalErrors)); - sleep(1); // Pause for 1 second to allow memory to refresh - } - }); - } - - $output->writeln(sprintf('Final result: %d users processed, %d success, %d errors.', $totalProcessed, $totalSuccess, $totalErrors)); + $stats = $this->processUsers($usernames, $ipAddress, $isDryRun, $output); + $this->displayFinalResults($stats, $output); + return 0; } catch (Exception $e) { $output->writeln(sprintf('Error: %s', $e->getMessage())); @@ -139,6 +77,111 @@ class SyncMissingUsersToCommon extends Command { } } + /** + * Normalize IP address input - convert null to empty string + */ + private function normalizeIpAddress(?string $ipAddress): string { + return $ipAddress ?? ''; + } + + /** + * Process users based on whether specific users are provided or all users + */ + private function processUsers(array $usernames, string $ipAddress, bool $isDryRun, OutputInterface $output): array { + $stats = [ + 'processed' => 0, + 'success' => 0, + 'errors' => 0 + ]; + + if (!empty($usernames)) { + $this->processSpecificUsers($usernames, $ipAddress, $isDryRun, $output, $stats); + } else { + $this->processAllUsers($ipAddress, $isDryRun, $output, $stats); + } + + return $stats; + } + + /** + * Process a list of specific users + */ + private function processSpecificUsers(array $usernames, string $ipAddress, bool $isDryRun, OutputInterface $output, array &$stats): void { + $output->writeln(sprintf('Processing %d specific users', count($usernames))); + + foreach ($usernames as $username) { + $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); + } + } + + /** + * Process all users from NextCloud + */ + private function processAllUsers(string $ipAddress, bool $isDryRun, OutputInterface $output, array &$stats): void { + $output->writeln('Processing all users from NextCloud'); + + $this->userManager->callForSeenUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { + $username = $user->getUID(); + + // Check if user is missing from common database + if ($this->userService->isUsernameTaken($username)) { + return; // Skip if already exists + } + + $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); + if ($stats['processed'] % 100 === 0) { + $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', + $stats['processed'], $stats['success'], $stats['errors'])); + sleep(1); // Pause for 1 second to allow memory to refresh + } + }); + } + + /** + * Process a single user + */ + private function processSingleUser(string $username, string $ipAddress, bool $isDryRun, OutputInterface $output, array &$stats): void { + $user = $this->userManager->get($username); + if (!$user) { + $output->writeln(sprintf('User not found: %s', $username)); + $stats['errors']++; + return; + } + + if ($this->userService->isUsernameTaken($username)) { + $output->writeln(sprintf('User already exists in common database: %s', $username)); + return; + } + + try { + $this->syncUserToCommon($username, $ipAddress, $isDryRun, $output); + $stats['success']++; + } catch (Exception $e) { + $output->writeln(sprintf('Error syncing user %s: %s', $username, $e->getMessage())); + $stats['errors']++; + } + $stats['processed']++; + } + + /** + * Show progress every 100 users + */ + private function showProgressIfNeeded(array $stats, OutputInterface $output): void { + if ($stats['processed'] % 100 === 0) { + $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', + $stats['processed'], $stats['success'], $stats['errors'])); + sleep(1); // Pause for 1 second to allow memory to refresh + } + } + + /** + * Display final results + */ + private function displayFinalResults(array $stats, OutputInterface $output): void { + $output->writeln(sprintf('Final result: %d users processed, %d success, %d errors.', + $stats['processed'], $stats['success'], $stats['errors'])); + } + /** * Sync a specific user to the common database * -- GitLab From 8ef4e3b8edf204dded1964da7f9db20d14ceb0c5 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 11:32:15 +0530 Subject: [PATCH 07/23] removed unncessary attributes --- lib/Command/SyncMissingUsersToCommon.php | 13 +------------ lib/Service/LDAPConnectionService.php | 14 +++++--------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 87ab95a6..48cb8f21 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -163,17 +163,6 @@ class SyncMissingUsersToCommon extends Command { $stats['processed']++; } - /** - * Show progress every 100 users - */ - private function showProgressIfNeeded(array $stats, OutputInterface $output): void { - if ($stats['processed'] % 100 === 0) { - $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', - $stats['processed'], $stats['success'], $stats['errors'])); - sleep(1); // Pause for 1 second to allow memory to refresh - } - } - /** * Display final results */ @@ -207,7 +196,7 @@ class SyncMissingUsersToCommon extends Command { // Get user metadata from LDAP $userMetadata = $this->ldapConnectionService->getUserMetadata($username); - $output->writeln(sprintf(' Found user in LDAP: %s (%s)', $userMetadata['displayName'], $userMetadata['mailAddress'])); + $output->writeln(sprintf(' Found user in LDAP: %s (created: %s)', $userMetadata['usernameWithoutDomain'], $userMetadata['createTimestamp'])); if (!$isDryRun) { // Add user to common database diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php index 443bbe2a..f0e9fa55 100644 --- a/lib/Service/LDAPConnectionService.php +++ b/lib/Service/LDAPConnectionService.php @@ -182,12 +182,9 @@ class LDAPConnectionService { } $attributes = [ - 'mailAddress', - 'displayName', - 'recoveryMailAddress', - 'username', - 'active', - 'mailActive' + 'createTimestamp', + 'usernameWithoutDomain', + 'recoveryMailAddress' ]; $result = ldap_read($conn, $userDn, '(objectClass=*)', $attributes); @@ -207,9 +204,8 @@ class LDAPConnectionService { $entry = $entries[0]; return [ - 'username' => $entry['username'][0] ?? $username, - 'displayName' => $entry['displayname'][0] ?? $username, - 'mailAddress' => $entry['mailaddress'][0] ?? null, + 'createTimestamp' => $entry['createtimestamp'][0] ?? '', + 'usernameWithoutDomain' => $entry['usernamewithoutdomain'][0] ?? $username, 'recoveryMailAddress' => $entry['recoverymailaddress'][0] ?? '' ]; } -- GitLab From 701b591667131d7a98ef73f78e05bf1bd06d6053 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 12:51:51 +0530 Subject: [PATCH 08/23] added timestamp --- lib/Command/SyncMissingUsersToCommon.php | 5 +++-- lib/Service/UserService.php | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 48cb8f21..97490335 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -203,11 +203,12 @@ class SyncMissingUsersToCommon extends Command { $this->userService->addUsernameToCommonDataStore( $username, $ipAddress, - $userMetadata['recoveryMailAddress'] + $userMetadata['recoveryMailAddress'], + $userMetadata['createTimestamp'] ); $output->writeln(sprintf(' ✓ User synced successfully to common database: %s', $username)); } else { - $output->writeln(sprintf(' Would sync user to common database with recovery email: %s', $userMetadata['recoveryMailAddress'])); + $output->writeln(sprintf(' Would sync user to common database with recovery email: %s and created_at: %s', $userMetadata['recoveryMailAddress'], $userMetadata['createTimestamp'])); } } } diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php index 1cd8fece..7e339329 100644 --- a/lib/Service/UserService.php +++ b/lib/Service/UserService.php @@ -439,10 +439,11 @@ class UserService { * @param string $username The username to add to the common data store. * @param string $ipAddress IP Address of user * @param string $recoveryEmail A recovery Email of user + * @param string|null $createdAt The creation timestamp (optional, defaults to current time) * * @throws AddUsernameToCommonStoreException If an error occurs while adding the username to the common data store. */ - public function addUsernameToCommonDataStore(string $username, string $ipAddress, string $recoveryEmail) : void { + public function addUsernameToCommonDataStore(string $username, string $ipAddress, string $recoveryEmail, ?string $createdAt = null) : void { $commonServicesURL = $this->apiConfig['commonServicesURL']; $commonApiVersion = $this->apiConfig['commonApiVersion']; @@ -458,6 +459,11 @@ class UserService { 'recoveryEmail' => $recoveryEmail ]; + // Add createdAt parameter if provided, otherwise let the API use current time + if ($createdAt !== null) { + $params['created_at'] = $createdAt; + } + $token = $this->apiConfig['commonServicesToken']; $headers = [ "Authorization: Bearer $token" -- GitLab From a208cc9f021ae3e1e4e7725592e808af33801c7e Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 13:30:32 +0530 Subject: [PATCH 09/23] added unset and removed sleep --- lib/Command/SyncMissingUsersToCommon.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 97490335..b63f81c8 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -125,14 +125,15 @@ class SyncMissingUsersToCommon extends Command { // Check if user is missing from common database if ($this->userService->isUsernameTaken($username)) { + unset($user); return; // Skip if already exists } $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); + unset($user); if ($stats['processed'] % 100 === 0) { $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $stats['processed'], $stats['success'], $stats['errors'])); - sleep(1); // Pause for 1 second to allow memory to refresh } }); } -- GitLab From d973ac050d280802cef166b66ad6bc0647fd8893 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 13:34:09 +0530 Subject: [PATCH 10/23] removed unset --- lib/Command/SyncMissingUsersToCommon.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index b63f81c8..609c83c3 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -125,12 +125,10 @@ class SyncMissingUsersToCommon extends Command { // Check if user is missing from common database if ($this->userService->isUsernameTaken($username)) { - unset($user); return; // Skip if already exists } $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); - unset($user); if ($stats['processed'] % 100 === 0) { $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $stats['processed'], $stats['success'], $stats['errors'])); -- GitLab From 22b33994c376bf8f3952c26fec90dc936e884703 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 14:36:24 +0530 Subject: [PATCH 11/23] issue in conversion --- lib/Command/SyncMissingUsersToCommon.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 609c83c3..1d105423 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -195,7 +195,17 @@ class SyncMissingUsersToCommon extends Command { // Get user metadata from LDAP $userMetadata = $this->ldapConnectionService->getUserMetadata($username); - $output->writeln(sprintf(' Found user in LDAP: %s (created: %s)', $userMetadata['usernameWithoutDomain'], $userMetadata['createTimestamp'])); + // Convert LDAP createTimestamp to ISO 8601 (Y-m-d\TH:i:s\Z) + $ldapTimestamp = $userMetadata['createTimestamp'] ?? null; + $createdAt = $ldapTimestamp; + if ($ldapTimestamp) { + $dateTime = \DateTime::createFromFormat('YmdHis\Z', $ldapTimestamp, new \DateTimeZone('UTC')); + if ($dateTime !== false) { + $createdAt = $dateTime->format('c'); // ISO 8601 + } + } + + $output->writeln(sprintf(' Found user in LDAP: %s (created: %s)', $userMetadata['usernameWithoutDomain'], $createdAt)); if (!$isDryRun) { // Add user to common database @@ -203,11 +213,11 @@ class SyncMissingUsersToCommon extends Command { $username, $ipAddress, $userMetadata['recoveryMailAddress'], - $userMetadata['createTimestamp'] + $createdAt ); $output->writeln(sprintf(' ✓ User synced successfully to common database: %s', $username)); } else { - $output->writeln(sprintf(' Would sync user to common database with recovery email: %s and created_at: %s', $userMetadata['recoveryMailAddress'], $userMetadata['createTimestamp'])); + $output->writeln(sprintf(' Would sync user to common database with recovery email: %s and created_at: %s', $userMetadata['recoveryMailAddress'], $createdAt)); } } } -- GitLab From f7947e4e634f218b1de445657c1261d83aabe194 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 14:47:52 +0530 Subject: [PATCH 12/23] createTimestamp mysql --- lib/Command/SyncMissingUsersToCommon.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 1d105423..0c16ef80 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -195,13 +195,14 @@ class SyncMissingUsersToCommon extends Command { // Get user metadata from LDAP $userMetadata = $this->ldapConnectionService->getUserMetadata($username); - // Convert LDAP createTimestamp to ISO 8601 (Y-m-d\TH:i:s\Z) + // Convert LDAP createTimestamp to MySQL datetime format $ldapTimestamp = $userMetadata['createTimestamp'] ?? null; $createdAt = $ldapTimestamp; + if ($ldapTimestamp) { $dateTime = \DateTime::createFromFormat('YmdHis\Z', $ldapTimestamp, new \DateTimeZone('UTC')); if ($dateTime !== false) { - $createdAt = $dateTime->format('c'); // ISO 8601 + $createdAt = $dateTime->format('Y-m-d H:i:s'); // Format compatible with MySQL } } -- GitLab From 8109e889ac3eb722fa49121f0d77e5178c0d5c6b Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 19:16:10 +0530 Subject: [PATCH 13/23] callForAllUsers replaced --- lib/Command/SyncMissingUsersToCommon.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 0c16ef80..7c25e517 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -119,10 +119,9 @@ class SyncMissingUsersToCommon extends Command { */ private function processAllUsers(string $ipAddress, bool $isDryRun, OutputInterface $output, array &$stats): void { $output->writeln('Processing all users from NextCloud'); - - $this->userManager->callForSeenUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { + + $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { $username = $user->getUID(); - // Check if user is missing from common database if ($this->userService->isUsernameTaken($username)) { return; // Skip if already exists -- GitLab From 79a9ca74b7573282d0b7c2b25220456ea4f6e88a Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 19:48:51 +0530 Subject: [PATCH 14/23] remove domain from username --- lib/Command/SyncMissingUsersToCommon.php | 9 ++++++--- lib/Service/UserService.php | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 7c25e517..b61415d5 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -194,6 +194,9 @@ class SyncMissingUsersToCommon extends Command { // Get user metadata from LDAP $userMetadata = $this->ldapConnectionService->getUserMetadata($username); + // Remove domain from username using UserService + $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); + // Convert LDAP createTimestamp to MySQL datetime format $ldapTimestamp = $userMetadata['createTimestamp'] ?? null; $createdAt = $ldapTimestamp; @@ -205,17 +208,17 @@ class SyncMissingUsersToCommon extends Command { } } - $output->writeln(sprintf(' Found user in LDAP: %s (created: %s)', $userMetadata['usernameWithoutDomain'], $createdAt)); + $output->writeln(sprintf(' Found user in LDAP: %s (created: %s)', $usernameWithoutDomain, $createdAt)); if (!$isDryRun) { // Add user to common database $this->userService->addUsernameToCommonDataStore( - $username, + $usernameWithoutDomain, $ipAddress, $userMetadata['recoveryMailAddress'], $createdAt ); - $output->writeln(sprintf(' ✓ User synced successfully to common database: %s', $username)); + $output->writeln(sprintf(' ✓ User synced successfully to common database: %s', $usernameWithoutDomain)); } else { $output->writeln(sprintf(' Would sync user to common database with recovery email: %s and created_at: %s', $userMetadata['recoveryMailAddress'], $createdAt)); } diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php index 7e339329..1a770066 100644 --- a/lib/Service/UserService.php +++ b/lib/Service/UserService.php @@ -490,4 +490,14 @@ class UserService { private function getDefaultQuota() { return $this->config->getSystemValueInt('default_quota_in_megabytes', 1024); } + /** + * Remove legacy domain from username if present + */ + public function stripLegacyDomainFromUsername(string $username): string { + $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); + if ($legacyDomain && str_ends_with($username, '@' . $legacyDomain)) { + return substr($username, 0, -strlen('@' . $legacyDomain)); + } + return $username; + } } -- GitLab From c31eddb6922d8b80f9692bb344a6a83ce4f71b38 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 19:56:40 +0530 Subject: [PATCH 15/23] removed checking str-replace; used ldap instead --- lib/Command/SyncMissingUsersToCommon.php | 4 ++-- lib/Service/UserService.php | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index b61415d5..84dc50bb 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -194,8 +194,8 @@ class SyncMissingUsersToCommon extends Command { // Get user metadata from LDAP $userMetadata = $this->ldapConnectionService->getUserMetadata($username); - // Remove domain from username using UserService - $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); + // Use usernameWithoutDomain from LDAP metadata + $usernameWithoutDomain = $userMetadata['usernameWithoutDomain']; // Convert LDAP createTimestamp to MySQL datetime format $ldapTimestamp = $userMetadata['createTimestamp'] ?? null; diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php index 1a770066..7e339329 100644 --- a/lib/Service/UserService.php +++ b/lib/Service/UserService.php @@ -490,14 +490,4 @@ class UserService { private function getDefaultQuota() { return $this->config->getSystemValueInt('default_quota_in_megabytes', 1024); } - /** - * Remove legacy domain from username if present - */ - public function stripLegacyDomainFromUsername(string $username): string { - $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); - if ($legacyDomain && str_ends_with($username, '@' . $legacyDomain)) { - return substr($username, 0, -strlen('@' . $legacyDomain)); - } - return $username; - } } -- GitLab From 5d33f500c9de60d796cf59fb7bd6ff9cb8cb1a16 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 8 Jul 2025 20:00:00 +0530 Subject: [PATCH 16/23] Apply 1 suggestion(s) to 1 file(s) Co-authored-by: Akhil --- lib/Service/LDAPConnectionService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php index f0e9fa55..48a173da 100644 --- a/lib/Service/LDAPConnectionService.php +++ b/lib/Service/LDAPConnectionService.php @@ -205,7 +205,7 @@ class LDAPConnectionService { return [ 'createTimestamp' => $entry['createtimestamp'][0] ?? '', - 'usernameWithoutDomain' => $entry['usernamewithoutdomain'][0] ?? $username, + 'usernameWithoutDomain' => $entry['usernamewithoutdomain'][0], 'recoveryMailAddress' => $entry['recoverymailaddress'][0] ?? '' ]; } -- GitLab From 6347ca61b2b289715aeb73333e433acc70eda434 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:00:27 +0530 Subject: [PATCH 17/23] check at condition --- lib/Command/SyncMissingUsersToCommon.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 84dc50bb..ed65d0c9 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -122,8 +122,11 @@ class SyncMissingUsersToCommon extends Command { $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { $username = $user->getUID(); + // Get user metadata from LDAP to obtain usernameWithoutDomain + $userMetadata = $this->ldapConnectionService->getUserMetadata($username); + $usernameWithoutDomain = $userMetadata['usernameWithoutDomain'] ?? $username; // Check if user is missing from common database - if ($this->userService->isUsernameTaken($username)) { + if ($this->userService->isUsernameTaken($usernameWithoutDomain)) { return; // Skip if already exists } -- GitLab From 4dbad921833ff59d820a0339d31ed2f963312eaa Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:09:21 +0530 Subject: [PATCH 18/23] check at isusernametaken function --- lib/Command/SyncMissingUsersToCommon.php | 4 +++- lib/Service/UserService.php | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index ed65d0c9..f76316d3 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -122,10 +122,12 @@ class SyncMissingUsersToCommon extends Command { $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { $username = $user->getUID(); + // Get user metadata from LDAP to obtain usernameWithoutDomain $userMetadata = $this->ldapConnectionService->getUserMetadata($username); $usernameWithoutDomain = $userMetadata['usernameWithoutDomain'] ?? $username; - // Check if user is missing from common database + // Strip legacy domain from username before checking in common DB + $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); if ($this->userService->isUsernameTaken($usernameWithoutDomain)) { return; // Skip if already exists } diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php index 7e339329..04966466 100644 --- a/lib/Service/UserService.php +++ b/lib/Service/UserService.php @@ -490,4 +490,11 @@ class UserService { private function getDefaultQuota() { return $this->config->getSystemValueInt('default_quota_in_megabytes', 1024); } + /** + * Remove legacy domain from username if present + */ + public function stripLegacyDomainFromUsername(string $username): string { + $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); + return str_ireplace('@' . $legacyDomain, '', $username); + } } -- GitLab From e277355a7cd17eb2c208cfe520be15a7fc9de4bd Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:10:43 +0530 Subject: [PATCH 19/23] stripped data --- lib/Command/SyncMissingUsersToCommon.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index f76316d3..574f4567 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -123,9 +123,6 @@ class SyncMissingUsersToCommon extends Command { $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { $username = $user->getUID(); - // Get user metadata from LDAP to obtain usernameWithoutDomain - $userMetadata = $this->ldapConnectionService->getUserMetadata($username); - $usernameWithoutDomain = $userMetadata['usernameWithoutDomain'] ?? $username; // Strip legacy domain from username before checking in common DB $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); if ($this->userService->isUsernameTaken($usernameWithoutDomain)) { -- GitLab From cc954aa17497807b865fea041c5b8bf8ad5d78b4 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:26:20 +0530 Subject: [PATCH 20/23] check for isUsernameTaken --- lib/Command/SyncMissingUsersToCommon.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 574f4567..44195d21 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -148,9 +148,10 @@ class SyncMissingUsersToCommon extends Command { return; } - if ($this->userService->isUsernameTaken($username)) { - $output->writeln(sprintf('User already exists in common database: %s', $username)); - return; + // Strip legacy domain from username before checking in common DB + $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); + if ($this->userService->isUsernameTaken($usernameWithoutDomain)) { + return; // Skip if already exists } try { -- GitLab From f6174ff2db0152bb7ea89d31b441b792e4a48579 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:33:35 +0530 Subject: [PATCH 21/23] removed redundant --- lib/Command/SyncMissingUsersToCommon.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 44195d21..a4927c6e 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -122,12 +122,6 @@ class SyncMissingUsersToCommon extends Command { $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { $username = $user->getUID(); - - // Strip legacy domain from username before checking in common DB - $usernameWithoutDomain = $this->userService->stripLegacyDomainFromUsername($username); - if ($this->userService->isUsernameTaken($usernameWithoutDomain)) { - return; // Skip if already exists - } $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); if ($stats['processed'] % 100 === 0) { -- GitLab From 81148dd7e1e39b06edeee37fcdccc56b68c09682 Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:52:36 +0530 Subject: [PATCH 22/23] added count --- lib/Command/SyncMissingUsersToCommon.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index a4927c6e..7d794a55 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -118,17 +118,20 @@ class SyncMissingUsersToCommon extends Command { * Process all users from NextCloud */ private function processAllUsers(string $ipAddress, bool $isDryRun, OutputInterface $output, array &$stats): void { - $output->writeln('Processing all users from NextCloud'); - - $this->userManager->callForAllUsers(function (IUser $user) use ($ipAddress, $isDryRun, $output, &$stats) { - $username = $user->getUID(); + $allUsers = []; + $this->userManager->callForAllUsers(function (IUser $user) use (&$allUsers) { + $allUsers[] = $user; + }); + $totalUsers = count($allUsers); + $output->writeln(sprintf('Processing all users from NextCloud (total: %d)', $totalUsers)); - $this->processSingleUser($username, $ipAddress, $isDryRun, $output, $stats); + foreach ($allUsers as $user) { + $this->processSingleUser($user->getUID(), $ipAddress, $isDryRun, $output, $stats); if ($stats['processed'] % 100 === 0) { $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $stats['processed'], $stats['success'], $stats['errors'])); } - }); + } } /** -- GitLab From 88caf4c59b47daeac940b2d4c96e2aa8bf83a21e Mon Sep 17 00:00:00 2001 From: theronakpatel Date: Tue, 8 Jul 2025 20:58:52 +0530 Subject: [PATCH 23/23] processed changes --- lib/Command/SyncMissingUsersToCommon.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Command/SyncMissingUsersToCommon.php b/lib/Command/SyncMissingUsersToCommon.php index 7d794a55..5df790f5 100644 --- a/lib/Command/SyncMissingUsersToCommon.php +++ b/lib/Command/SyncMissingUsersToCommon.php @@ -125,11 +125,14 @@ class SyncMissingUsersToCommon extends Command { $totalUsers = count($allUsers); $output->writeln(sprintf('Processing all users from NextCloud (total: %d)', $totalUsers)); + $lastProcessed = 0; foreach ($allUsers as $user) { + $before = $stats['processed']; $this->processSingleUser($user->getUID(), $ipAddress, $isDryRun, $output, $stats); - if ($stats['processed'] % 100 === 0) { + if ($stats['processed'] > 0 && $stats['processed'] % 100 === 0 && $stats['processed'] !== $lastProcessed) { $output->writeln(sprintf('Progress: %d processed, %d success, %d errors', $stats['processed'], $stats['success'], $stats['errors'])); + $lastProcessed = $stats['processed']; } } } -- GitLab