diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9215688d2bd974a84c78f531c7e85e7a8dfc0da1..ddd027878ac6b175479987d11552d1ecd6066abf 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -29,3 +29,20 @@ include:
ref: main
file: "nc-publish-app.yml"
+
+deploy:staging:
+ extends: .deploy:nextcloud-app
+ rules:
+ - if: $CI_COMMIT_BRANCH == "main"
+ when: manual
+ - if: $CI_COMMIT_BRANCH == "murena-main"
+ when: manual
+ - if: $CI_COMMIT_BRANCH == "production"
+ when: manual
+ - if: $CI_COMMIT_BRANCH == "dev/temp-logger"
+ when: manual
+ - if: $CI_COMMIT_TAG
+ when: manual
+ environment:
+ name: staging/01
+ url: $ENV_URL
\ No newline at end of file
diff --git a/lib/Command/RecoveryWarningNotificationCommand.php b/lib/Command/RecoveryWarningNotificationCommand.php
index b4120a7b421ef688ed00c7877c55ba41986a6086..1e8fa85cafea8b339a50c2f364e7934cc5b7431d 100644
--- a/lib/Command/RecoveryWarningNotificationCommand.php
+++ b/lib/Command/RecoveryWarningNotificationCommand.php
@@ -92,152 +92,253 @@ class RecoveryWarningNotificationCommand extends Command {
->addOption('test-mode', null, InputOption::VALUE_NONE, 'Enable test mode - process only limited number of users');
}
- protected function execute(InputInterface $input, OutputInterface $output): int {
- $disableAccounts = $input->getOption('disable-accounts');
- $deleteAccounts = $input->getOption('delete-accounts');
- $this->dryRun = $input->getOption('dry-run');
- $this->testMode = $input->getOption('test-mode');
+protected function execute(InputInterface $input, OutputInterface $output): int {
+ $overallStart = microtime(true);
+ $disableAccounts = $input->getOption('disable-accounts');
+ $deleteAccounts = $input->getOption('delete-accounts');
+ $this->dryRun = $input->getOption('dry-run');
+ $this->testMode = $input->getOption('test-mode');
+
+ $output->writeln('[email-recovery] start');
+ $output->writeln(' - disableAccounts=' . ((bool)$disableAccounts ? 'true' : 'false'));
+ $output->writeln(' - deleteAccounts=' . ((bool)$deleteAccounts ? 'true' : 'false'));
+ $output->writeln(' - dryRun=' . ($this->dryRun ? 'true' : 'false'));
+ $output->writeln(' - testMode=' . ($this->testMode ? 'true' : 'false'));
+
+ if ($this->dryRun) {
+ $output->writeln('Running in DRY-RUN mode - no actual actions will be taken');
+ }
- if ($this->dryRun) {
- $output->writeln('Running in DRY-RUN mode - no actual actions will be taken');
- }
+ if ($this->testMode) {
+ $output->writeln('Test mode enabled - processing only ' . $this->testModeUserLimit . ' users');
+ }
- if ($this->testMode) {
- $output->writeln('Test mode enabled - processing only ' . $this->testModeUserLimit . ' users');
+ try {
+ if (!$this->messageId) {
+ $output->writeln('Error: messageId not configured in recovery_warning_configs system configuration!');
+ return Command::FAILURE;
}
- try {
- if (!$this->messageId) {
- $output->writeln('Error: messageId not configured in recovery_warning_configs system configuration!');
- return Command::FAILURE;
- }
-
- // Initialize arrays
- $this->uids = [];
- $this->disableUids = [];
- $this->deleteUids = [];
-
- // Process users
- $this->identifyUnverifiedUsers($output);
- $this->sendNotificationsAndEmails($output);
+ // Initialize arrays
+ $this->uids = [];
+ $this->disableUids = [];
+ $this->deleteUids = [];
+
+ // Process users
+ $identifyStart = microtime(true);
+ $this->identifyUnverifiedUsers($output);
+ $output->writeln('[email-recovery] identifyUnverifiedUsers completed');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $identifyStart));
+ $output->writeln(' - notifyCandidates=' . count($this->uids));
+ $output->writeln(' - disableCandidates=' . count($this->disableUids));
+ $output->writeln(' - deleteCandidates=' . count($this->deleteUids));
+
+ $notifyStart = microtime(true);
+ $this->sendNotificationsAndEmails($output);
+ $output->writeln('[email-recovery] sendNotificationsAndEmails completed');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $notifyStart));
- if ($disableAccounts) {
- $this->disableUnverifiedUsers($output);
- }
+ if ($disableAccounts) {
+ $disableStart = microtime(true);
+ $this->disableUnverifiedUsers($output);
+ $output->writeln('[email-recovery] disableUnverifiedUsers completed');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $disableStart));
+ $output->writeln(' - disableCandidates=' . count($this->disableUids));
+ }
- if ($deleteAccounts) {
- $this->deleteExpiredDisabledUsers($output);
- }
-
- $output->writeln('=== Command Summary ===');
- $output->writeln(' - Users for notifications: ' . count($this->uids));
- $output->writeln(' - Users for disable: ' . count($this->disableUids));
- $output->writeln(' - Users for deletion: ' . count($this->deleteUids));
-
- $output->writeln('Recovery warning notification command completed successfully.');
- return Command::SUCCESS;
- } catch (\Throwable $e) {
- $output->writeln('Error: ' . $e->getMessage() . '');
- return Command::FAILURE;
+ if ($deleteAccounts) {
+ $deleteStart = microtime(true);
+ $this->deleteExpiredDisabledUsers($output);
+ $output->writeln('[email-recovery] deleteExpiredDisabledUsers completed');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $deleteStart));
+ $output->writeln(' - deleteCandidates=' . count($this->deleteUids));
}
+
+ $output->writeln('=== Command Summary ===');
+ $output->writeln(' - Users for notifications: ' . count($this->uids));
+ $output->writeln(' - Users for disable: ' . count($this->disableUids));
+ $output->writeln(' - Users for deletion: ' . count($this->deleteUids));
+
+ $overallDuration = microtime(true) - $overallStart;
+ $output->writeln('[email-recovery] completed');
+ $output->writeln(' - overallDurationMs=' . $this->toMs($overallDuration));
+ $output->writeln(' - notifyCandidates=' . count($this->uids));
+ $output->writeln(' - disableCandidates=' . count($this->disableUids));
+ $output->writeln(' - deleteCandidates=' . count($this->deleteUids));
+ $output->writeln('Recovery warning notification command completed successfully.');
+ return Command::SUCCESS;
+ } catch (\Throwable $e) {
+ $output->writeln('Error: ' . $e->getMessage() . '');
+ $output->writeln('[email-recovery] failed: ' . $e->getMessage() . '');
+ return Command::FAILURE;
}
+}
- private function identifyUnverifiedUsers(OutputInterface $output): void {
- $users = $this->config->getUsersForUserValue(Application::APP_ID, 'recovery-email', '');
- if (!is_array($users)) {
- $output->writeln('Error: Expected array for recovery-email users, got ' . gettype($users) . '');
- return;
- }
+private function identifyUnverifiedUsers(OutputInterface $output): void {
+ $stageStart = microtime(true);
+ $users = $this->config->getUsersForUserValue(Application::APP_ID, 'recovery-email', '');
+ if (!is_array($users)) {
+ $output->writeln('Error: Expected array for recovery-email users, got ' . gettype($users) . '');
+ return;
+ }
- // Limit to user-limit for test mode
- if ($this->testMode && count($users) > $this->testModeUserLimit) {
- $users = array_slice($users, 0, $this->testModeUserLimit);
- $output->writeln('Test mode: Limited to ' . $this->testModeUserLimit . ' users');
- }
+ // Limit to user-limit for test mode
+ if ($this->testMode && count($users) > $this->testModeUserLimit) {
+ $users = array_slice($users, 0, $this->testModeUserLimit);
+ $output->writeln('Test mode: Limited to ' . $this->testModeUserLimit . ' users');
+ }
- $processedCount = 0;
- $skippedCount = 0;
- $invalidCount = 0;
- $errorCount = 0;
+ $processedCount = 0;
+ $skippedCount = 0;
+ $invalidCount = 0;
+ $errorCount = 0;
- foreach ($users as $username) {
- try {
- $user = $this->userManager->get($username);
- if (!$user) {
- $invalidCount++;
- continue;
- }
+ // Aggregated timings (seconds)
+ $sumGetUser = 0.0;
+ $sumGetRecoveryEmail = 0.0;
+ $sumHasActiveSubscription = 0.0;
+ $sumConfigOps = 0.0;
- if (!$this->isUserValid($user)) {
- $invalidCount++;
- continue;
- }
+ foreach ($users as $username) {
+ try {
+ $userStart = microtime(true);
+ $t = microtime(true);
+ $user = $this->userManager->get($username);
+ $dtGetUser = microtime(true) - $t;
+ $sumGetUser += $dtGetUser;
+ if (!$user) {
+ $invalidCount++;
+ $output->writeln('[identify] user=' . $username . ' getUserMs=' . $this->toMs($dtGetUser) . ' invalid=1 totalMs=' . $this->toMs(microtime(true) - $userStart));
+ continue;
+ }
- $uid = $user->getUID();
- $emailAddress = $user->getEMailAddress();
+ $t = microtime(true);
+ $isValid = $this->isUserValid($user);
+ $dtIsValid = microtime(true) - $t;
+ if (!$isValid) {
+ $invalidCount++;
+ $output->writeln('[identify] user=' . $username . ' getUserMs=' . $this->toMs($dtGetUser) . ' isValidMs=' . $this->toMs($dtIsValid) . ' invalid=1 totalMs=' . $this->toMs(microtime(true) - $userStart));
+ continue;
+ }
- // Check if user has a VERIFIED recovery email
- $verifiedRecoveryEmail = $this->recoveryEmailService->getRecoveryEmail($username);
- if (!empty($verifiedRecoveryEmail)) {
- $skippedCount++;
- continue;
- }
+ $uid = $user->getUID();
+ $emailAddress = $user->getEMailAddress();
+
+ // Check if user has a VERIFIED recovery email
+ $t = microtime(true);
+ $verifiedRecoveryEmail = $this->recoveryEmailService->getRecoveryEmail($username);
+ $dtGetRecovery = microtime(true) - $t;
+ $sumGetRecoveryEmail += $dtGetRecovery;
+ if (!empty($verifiedRecoveryEmail)) {
+ $skippedCount++;
+ $output->writeln('[identify] user=' . $uid . ' getUserMs=' . $this->toMs($dtGetUser) . ' isValidMs=' . $this->toMs($dtIsValid) . ' getRecoveryMs=' . $this->toMs($dtGetRecovery) . ' skipped=verifiedRecoveryEmail totalMs=' . $this->toMs(microtime(true) - $userStart));
+ continue;
+ }
- // Check for active subscription
- if ($this->recoveryEmailService->hasActiveSubscription($emailAddress)) {
- $skippedCount++;
- continue;
- }
+ // Check for active subscription
+ $t = microtime(true);
+ $hasSub = $this->recoveryEmailService->hasActiveSubscription($emailAddress);
+ $dtHasSub = microtime(true) - $t;
+ $sumHasActiveSubscription += $dtHasSub;
+ if ($hasSub) {
+ $skippedCount++;
+ $output->writeln('[identify] user=' . $uid . ' getUserMs=' . $this->toMs($dtGetUser) . ' isValidMs=' . $this->toMs($dtIsValid) . ' getRecoveryMs=' . $this->toMs($dtGetRecovery) . ' hasSubMs=' . $this->toMs($dtHasSub) . ' skipped=hasSubscription totalMs=' . $this->toMs(microtime(true) - $userStart));
+ continue;
+ }
- // Get or set first run date
- $firstRunDate = $this->config->getUserValue($uid, Application::APP_ID, 'first-run-date', null);
- // Ensure firstRunDate is an integer timestamp
- $firstRunDate = $firstRunDate ? (int)$firstRunDate : null;
+ // Get or set first run date
+ $tCfg = microtime(true);
+ $firstRunDate = $this->config->getUserValue($uid, Application::APP_ID, 'first-run-date', null);
+ // Ensure firstRunDate is an integer timestamp
+ $firstRunDate = $firstRunDate ? (int)$firstRunDate : null;
- if ($firstRunDate === null) {
- $firstRunDate = time();
- $this->config->setUserValue($uid, Application::APP_ID, 'first-run-date', $firstRunDate);
- }
+ if ($firstRunDate === null) {
+ $firstRunDate = time();
+ $this->config->setUserValue($uid, Application::APP_ID, 'first-run-date', $firstRunDate);
+ }
+ $dtFirstRunOps = microtime(true) - $tCfg;
+ $sumConfigOps += $dtFirstRunOps;
- // Check if disable date is already set, if not set it
- $existingDisableDate = $this->recoveryEmailService->getUnverifiedUserDisableAt($uid);
+ // Check if disable date is already set, if not set it
+ $tCfg = microtime(true);
+ $existingDisableDate = $this->recoveryEmailService->getUnverifiedUserDisableAt($uid);
- if (empty($existingDisableDate)) {
- // Set the disable date using config variable
- $disableDate = date('Y-m-d', $firstRunDate + ($this->disableUserAfterUnverifiedDays * 24 * 60 * 60));
- $this->recoveryEmailService->setUnverifiedUserDisableAt($uid, $disableDate);
- }
+ if (empty($existingDisableDate)) {
+ // Set the disable date using config variable
+ $disableDate = date('Y-m-d', $firstRunDate + ($this->disableUserAfterUnverifiedDays * 24 * 60 * 60));
+ $this->recoveryEmailService->setUnverifiedUserDisableAt($uid, $disableDate);
+ }
+ $dtDisableOps = microtime(true) - $tCfg;
+ $sumConfigOps += $dtDisableOps;
- // Calculate age and process
- $age = (int) ((time() - $firstRunDate) / (24 * 60 * 60));
+ // Calculate age and process
+ $age = (int) ((time() - $firstRunDate) / (24 * 60 * 60));
- if (in_array($age, $this->reminderDaysSinceStart)) {
- $this->uids[] = $uid;
- }
-
- $this->identifyForDisable($user, $age);
- $this->identifyForDelete($user, $age);
+ if (in_array($age, $this->reminderDaysSinceStart)) {
+ $this->uids[] = $uid;
+ }
- $processedCount++;
- } catch (\Throwable $e) {
- $errorCount++;
- $output->writeln('Error processing user ' . $username . ': ' . $e->getMessage() . '');
- continue;
+ $t = microtime(true);
+ $this->identifyForDisable($user, $age);
+ $this->identifyForDelete($user, $age);
+ $dtFlags = microtime(true) - $t;
+
+ $output->writeln('[identify] user=' . $uid
+ . ' getUserMs=' . $this->toMs($dtGetUser)
+ . ' isValidMs=' . $this->toMs($dtIsValid)
+ . ' getRecoveryMs=' . $this->toMs($dtGetRecovery)
+ . ' hasSubMs=' . $this->toMs($dtHasSub)
+ . ' firstRunOpsMs=' . $this->toMs($dtFirstRunOps)
+ . ' disableOpsMs=' . $this->toMs($dtDisableOps)
+ . ' age=' . $age
+ . ' notify=' . (in_array($age, $this->reminderDaysSinceStart) ? '1' : '0')
+ . ' flagsMs=' . $this->toMs($dtFlags)
+ . ' totalMs=' . $this->toMs(microtime(true) - $userStart)
+ );
+
+ $processedCount++;
+ if ($processedCount % 1000 === 0) {
+ $elapsed = microtime(true) - $stageStart;
+ $output->writeln('[email-recovery] identify progress');
+ $output->writeln(' - processed=' . $processedCount);
+ $output->writeln(' - elapsedMs=' . $this->toMs($elapsed));
+ $output->writeln(' - rateUsersPerMin=' . (int)($processedCount / max($elapsed, 0.0001) * 60));
+ $output->writeln(' - memoryMb=' . (int)(memory_get_usage(true) / 1024 / 1024));
}
+ } catch (\Throwable $e) {
+ $errorCount++;
+ $output->writeln('Error processing user ' . $username . ': ' . $e->getMessage() . '');
+ $output->writeln('[email-recovery] Error processing user in identify for ' . $username . ': ' . $e->getMessage() . '');
+ continue;
}
-
- $output->writeln('User processing summary:');
- $output->writeln(' - Total users: ' . count($users));
- $output->writeln(' - Processed: ' . $processedCount);
- $output->writeln(' - Skipped: ' . $skippedCount);
- $output->writeln(' - Invalid: ' . $invalidCount);
- $output->writeln(' - Errors: ' . $errorCount);
- $output->writeln(' - For notifications: ' . count($this->uids));
- $output->writeln(' - For disable: ' . count($this->disableUids));
- $output->writeln(' - For deletion: ' . count($this->deleteUids));
}
+
+ $output->writeln('User processing summary:');
+ $output->writeln(' - Total users: ' . count($users));
+ $output->writeln(' - Processed: ' . $processedCount);
+ $output->writeln(' - Skipped: ' . $skippedCount);
+ $output->writeln(' - Invalid: ' . $invalidCount);
+ $output->writeln(' - Errors: ' . $errorCount);
+ $output->writeln(' - For notifications: ' . count($this->uids));
+ $output->writeln(' - For disable: ' . count($this->disableUids));
+ $output->writeln(' - For deletion: ' . count($this->deleteUids));
+ $output->writeln('[email-recovery] identifyUnverifiedUsers stats');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $stageStart));
+ $output->writeln(' - totalUsers=' . count($users));
+ $output->writeln(' - processed=' . $processedCount);
+ $output->writeln(' - skipped=' . $skippedCount);
+ $output->writeln(' - invalid=' . $invalidCount);
+ $output->writeln(' - errors=' . $errorCount);
+ $output->writeln(' - forNotifications=' . count($this->uids));
+ $output->writeln(' - forDisable=' . count($this->disableUids));
+ $output->writeln(' - forDeletion=' . count($this->deleteUids));
+ $output->writeln(' - avgGetUserMs=' . ($processedCount ? $this->toMs($sumGetUser / $processedCount) : 0));
+ $output->writeln(' - avgGetRecoveryEmailMs=' . ($processedCount ? $this->toMs($sumGetRecoveryEmail / $processedCount) : 0));
+ $output->writeln(' - avgHasActiveSubscriptionMs=' . ($processedCount ? $this->toMs($sumHasActiveSubscription / $processedCount) : 0));
+ $output->writeln(' - avgConfigOpsMs=' . ($processedCount ? $this->toMs($sumConfigOps / $processedCount) : 0));
+}
private function identifyForDisable($user, int $age): void {
if ($age >= $this->disableUserAfterUnverifiedDays) {
@@ -266,10 +367,15 @@ class RecoveryWarningNotificationCommand extends Command {
}
$output->writeln('Sending notifications and emails to ' . count($this->uids) . ' users...');
+ $output->writeln('[email-recovery] sendNotificationsAndEmails start');
+ $output->writeln(' - users=' . count($this->uids));
+ $stageStart = microtime(true);
+ $sumNotification = 0.0;
+ $sumEmail = 0.0;
try {
$notification = $this->prepareCloudNotification();
- $stats = $this->processUsersForNotificationsAndEmails($notification, $output);
+ $stats = $this->processUsersForNotificationsAndEmails($notification, $output, $sumNotification, $sumEmail);
$output->writeln('Notification/Email summary:');
$output->writeln(' - Notifications sent: ' . $stats['notificationSentCount']);
@@ -277,8 +383,18 @@ class RecoveryWarningNotificationCommand extends Command {
$output->writeln(' - Emails sent: ' . $stats['emailSentCount']);
$output->writeln(' - Emails failed: ' . $stats['emailFailedCount']);
$output->writeln(' - No email address: ' . $stats['noEmailCount']);
+ $output->writeln('[email-recovery] sendNotificationsAndEmails stats');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $stageStart));
+ $output->writeln(' - notificationsSent=' . $stats['notificationSentCount']);
+ $output->writeln(' - notificationsFailed=' . $stats['notificationFailedCount']);
+ $output->writeln(' - emailsSent=' . $stats['emailSentCount']);
+ $output->writeln(' - emailsFailed=' . $stats['emailFailedCount']);
+ $output->writeln(' - noEmail=' . $stats['noEmailCount']);
+ $output->writeln(' - avgNotifyMs=' . (($stats['notificationSentCount'] + $stats['notificationFailedCount']) ? $this->toMs($sumNotification / max(1, ($stats['notificationSentCount'] + $stats['notificationFailedCount']))) : 0));
+ $output->writeln(' - avgEmailMs=' . (($stats['emailSentCount'] + $stats['emailFailedCount']) ? $this->toMs($sumEmail / max(1, ($stats['emailSentCount'] + $stats['emailFailedCount']))) : 0));
} catch (\Throwable $e) {
$output->writeln('Error in sendNotificationsAndEmails: ' . $e->getMessage() . '');
+ $output->writeln('[email-recovery] Error in sendNotificationsAndEmails: ' . $e->getMessage() . '');
}
}
@@ -295,41 +411,55 @@ class RecoveryWarningNotificationCommand extends Command {
return $notification;
}
- private function processUsersForNotificationsAndEmails($notification, OutputInterface $output): array {
- $stats = [
- 'notificationSentCount' => 0,
- 'notificationFailedCount' => 0,
- 'emailSentCount' => 0,
- 'emailFailedCount' => 0,
- 'noEmailCount' => 0
- ];
-
- foreach ($this->uids as $uid) {
- try {
- $user = $this->userManager->get($uid);
- if (!$user) {
- $stats['notificationFailedCount']++;
- $stats['emailFailedCount']++;
- continue;
- }
-
- $username = $user->getDisplayName();
- $emailAddress = $user->getEMailAddress();
-
- // Send cloud notification
- $this->sendNotificationToUserIfValid($user, $notification, $stats, $output);
+private function processUsersForNotificationsAndEmails($notification, OutputInterface $output, float &$sumNotification, float &$sumEmail): array {
+ $stats = [
+ 'notificationSentCount' => 0,
+ 'notificationFailedCount' => 0,
+ 'emailSentCount' => 0,
+ 'emailFailedCount' => 0,
+ 'noEmailCount' => 0
+ ];
- // Send email
- $this->sendEmailToUserIfValid($user, $emailAddress, $stats, $output);
- } catch (\Throwable $e) {
+ foreach ($this->uids as $uid) {
+ try {
+ $userStart = microtime(true);
+ $user = $this->userManager->get($uid);
+ if (!$user) {
$stats['notificationFailedCount']++;
$stats['emailFailedCount']++;
+ $output->writeln('[notify] user=' . $uid . ' getUserMs=0 invalid=1 totalMs=' . $this->toMs(microtime(true) - $userStart));
+ continue;
}
- }
- return $stats;
+ $username = $user->getDisplayName();
+ $emailAddress = $user->getEMailAddress();
+
+ // Send cloud notification
+ $t = microtime(true);
+ $this->sendNotificationToUserIfValid($user, $notification, $stats, $output);
+ $dtNotify = microtime(true) - $t;
+ $sumNotification += $dtNotify;
+
+ // Send email
+ $t = microtime(true);
+ $this->sendEmailToUserIfValid($user, $emailAddress, $stats, $output);
+ $dtEmail = microtime(true) - $t;
+ $sumEmail += $dtEmail;
+
+ $output->writeln('[notify] user=' . $uid
+ . ' notifyMs=' . $this->toMs($dtNotify)
+ . ' emailMs=' . $this->toMs($dtEmail)
+ . ' totalMs=' . $this->toMs(microtime(true) - $userStart)
+ );
+ } catch (\Throwable $e) {
+ $stats['notificationFailedCount']++;
+ $stats['emailFailedCount']++;
+ }
}
+ return $stats;
+}
+
private function sendNotificationToUserIfValid($user, $notification, array &$stats, OutputInterface $output): void {
$username = $user->getDisplayName();
@@ -450,6 +580,7 @@ class RecoveryWarningNotificationCommand extends Command {
private function disableUnverifiedUsers(OutputInterface $output): void {
$disabledCount = 0;
$failedCount = 0;
+ $start = microtime(true);
foreach ($this->disableUids as $uid) {
try {
@@ -473,11 +604,17 @@ class RecoveryWarningNotificationCommand extends Command {
$failedCount++;
}
}
+
+ $output->writeln('[email-recovery] disableUnverifiedUsers stats');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $start));
+ $output->writeln(' - disabled=' . $disabledCount);
+ $output->writeln(' - failed=' . $failedCount);
}
private function deleteExpiredDisabledUsers(OutputInterface $output): void {
$deletedCount = 0;
$failedCount = 0;
+ $start = microtime(true);
foreach ($this->deleteUids as $uid) {
try {
@@ -503,6 +640,11 @@ class RecoveryWarningNotificationCommand extends Command {
$failedCount++;
}
}
+
+ $output->writeln('[email-recovery] deleteExpiredDisabledUsers stats');
+ $output->writeln(' - durationMs=' . $this->toMs(microtime(true) - $start));
+ $output->writeln(' - deleted=' . $deletedCount);
+ $output->writeln(' - failed=' . $failedCount);
}
private function isUserValid($user): bool {
@@ -513,4 +655,8 @@ class RecoveryWarningNotificationCommand extends Command {
$emailAddress = $user->getEMailAddress();
return $emailAddress && $this->mailer->validateMailAddress($emailAddress);
}
+
+private function toMs(float $seconds): int {
+ return (int) round($seconds * 1000);
+}
}
diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php
index 54db94367b9fe2371e3383dc00086f530f143b95..0cb6c15638a2362ac5ab9ac719c8d73dce90b254 100644
--- a/lib/Controller/EmailRecoveryController.php
+++ b/lib/Controller/EmailRecoveryController.php
@@ -34,6 +34,9 @@ use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException;
use OCA\EmailRecovery\Exception\TooManyVerificationAttemptsException;
use OCA\EmailRecovery\Service\RecoveryEmailService;
use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PublicPage;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
@@ -71,10 +74,7 @@ class EmailRecoveryController extends Controller {
$this->userManager = $userManager;
}
- /**
- * @NoAdminRequired
- */
-
+ #[NoAdminRequired]
public function getRecoveryEmail() {
$response = new JSONResponse();
$userId = $this->userSession->getUser()->getUID();
@@ -85,11 +85,9 @@ class EmailRecoveryController extends Controller {
return $response;
}
- /**
- * @NoAdminRequired
- * @PublicPage
- * @NoCSRFRequired
- */
+ #[NoAdminRequired]
+ #[PublicPage]
+ #[NoCSRFRequired]
public function verifyRecoveryEmail(string $token, string $userId): TemplateResponse {
try {
//decrypt email
@@ -126,10 +124,7 @@ class EmailRecoveryController extends Controller {
}
- /**
- * @NoAdminRequired
- */
-
+ #[NoAdminRequired]
public function setRecoveryEmail(string $recoveryEmail) {
$userId = $this->userSession->getUser()->getUID();
$response = new JSONResponse();
@@ -137,9 +132,7 @@ class EmailRecoveryController extends Controller {
return $response;
}
- /**
- * @NoAdminRequired
- */
+ #[NoAdminRequired]
public function resendRecoveryEmail(string $recoveryEmail) {
$response = new JSONResponse();
$response->setStatus(200);