diff --git a/l10n/de.js b/l10n/de.js index a1231789fd9834466a4536c30f5412e9c33bf299..ff9a990a65ae05c63fb89c9d49d488ae7253357d 100644 --- a/l10n/de.js +++ b/l10n/de.js @@ -32,6 +32,7 @@ OC.L10N.register( "Could not verify recovery email because the token is invalid": "Wiederherstellungs-E-Mail konnte nicht überprüft werden, da das Token ungültig ist", "Unverified recovery email:": "Nicht überprüfte Wiederherstellungs-E-Mail:", "Please set a recovery email address.": "Bitte geben Sie eine Wiederherstellungs-E-Mail-Adresse an.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an.", + "Too many verification emails.": "Zu viele Bestätigungs-E-Mails." }, "nplurals=2; plural=n != 1;"); diff --git a/l10n/de.json b/l10n/de.json index d7eed7378b6535e358b6be042d0a70cd1f1f3245..c2cfc90bdcf340b5c0f9c1361726028673d56a82 100644 --- a/l10n/de.json +++ b/l10n/de.json @@ -30,6 +30,7 @@ "Could not verify recovery email because the token is invalid": "Wiederherstellungs-E-Mail konnte nicht überprüft werden, da das Token ungültig ist", "Unverified recovery email:": "Nicht überprüfte Wiederherstellungs-E-Mail:", "Please set a recovery email address.": "Bitte geben Sie eine Wiederherstellungs-E-Mail-Adresse an.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an.", + "Too many verification emails.": "Zu viele Bestätigungs-E-Mails." },"pluralForm" :"nplurals=2; plural=n != 1;" } \ No newline at end of file diff --git a/l10n/de_DE.js b/l10n/de_DE.js index a1231789fd9834466a4536c30f5412e9c33bf299..ff9a990a65ae05c63fb89c9d49d488ae7253357d 100644 --- a/l10n/de_DE.js +++ b/l10n/de_DE.js @@ -32,6 +32,7 @@ OC.L10N.register( "Could not verify recovery email because the token is invalid": "Wiederherstellungs-E-Mail konnte nicht überprüft werden, da das Token ungültig ist", "Unverified recovery email:": "Nicht überprüfte Wiederherstellungs-E-Mail:", "Please set a recovery email address.": "Bitte geben Sie eine Wiederherstellungs-E-Mail-Adresse an.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an.", + "Too many verification emails.": "Zu viele Bestätigungs-E-Mails." }, "nplurals=2; plural=n != 1;"); diff --git a/l10n/de_DE.json b/l10n/de_DE.json index d7eed7378b6535e358b6be042d0a70cd1f1f3245..c2cfc90bdcf340b5c0f9c1361726028673d56a82 100644 --- a/l10n/de_DE.json +++ b/l10n/de_DE.json @@ -30,6 +30,7 @@ "Could not verify recovery email because the token is invalid": "Wiederherstellungs-E-Mail konnte nicht überprüft werden, da das Token ungültig ist", "Unverified recovery email:": "Nicht überprüfte Wiederherstellungs-E-Mail:", "Please set a recovery email address.": "Bitte geben Sie eine Wiederherstellungs-E-Mail-Adresse an.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Die Domäne dieser E-Mailadresse ist auf der Sperrliste. Bitte geben Sie eine andere E-Mailadresse an.", + "Too many verification emails.": "Zu viele Bestätigungs-E-Mails." },"pluralForm" :"nplurals=2; plural=n != 1;" } \ No newline at end of file diff --git a/l10n/en.js b/l10n/en.js index 3b7fc65536152a37b37773347c7ce5d9e1827c53..00b1f85bd541e7160b7114f4778575885448e804 100644 --- a/l10n/en.js +++ b/l10n/en.js @@ -29,6 +29,7 @@ OC.L10N.register( "Please verify your recovery email address to fully enjoy your murena.io account.": "Please verify your recovery email address to fully enjoy your murena.io account.", "VERIFY RECOVERY EMAIL NOW": "VERIFY RECOVERY EMAIL NOW", "Please set a recovery email address.": "Please set a recovery email address.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "The domain of this email address is blacklisted. Please provide another recovery address." + "The domain of this email address is blacklisted. Please provide another recovery address.": "The domain of this email address is blacklisted. Please provide another recovery address.", + "Too many verification emails.": "Too many verification emails." }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/en.json b/l10n/en.json index 46c1dbfb6f8a7f09915acc47927a71ab52d41a48..cea2af76c0f418e189d6038e89d2b5a4d4372514 100644 --- a/l10n/en.json +++ b/l10n/en.json @@ -30,7 +30,8 @@ "Please verify your recovery email address to fully enjoy your murena.io account.": "Please verify your recovery email address to fully enjoy your murena.io account.", "VERIFY RECOVERY EMAIL NOW": "VERIFY RECOVERY EMAIL NOW", "Please set a recovery email address.": "Please set a recovery email address.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "The domain of this email address is blacklisted. Please provide another recovery address." + "The domain of this email address is blacklisted. Please provide another recovery address.": "The domain of this email address is blacklisted. Please provide another recovery address.", + "Too many verification emails.": "Too many verification emails." }, "pluralForm": "nplurals=2; plural=(n != 1);" } \ No newline at end of file diff --git a/l10n/es.js b/l10n/es.js index 1d0f7c118123682d3339d3e31db3a6ab5a2266bd..0d05bd8fe24db2c8383cf1c833cb85f96d924972 100644 --- a/l10n/es.js +++ b/l10n/es.js @@ -32,6 +32,7 @@ OC.L10N.register( "Could not verify recovery email because the token is invalid": "No se pudo verificar el correo electrónico de recuperación porque el token no es válido", "Unverified recovery email:": "Correo electrónico de recuperación no verificado:", "Please set a recovery email address.": "Por favor configura un correo electrónico para recuperación.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "El dominio de esta dirección de correo electrónico está en lista negra. Por favor, proporciona otra dirección de recuperación." + "The domain of this email address is blacklisted. Please provide another recovery address.": "El dominio de esta dirección de correo electrónico está en lista negra. Por favor, proporciona otra dirección de recuperación.", + "Too many verification emails.": "Demasiados correos electrónicos de verificación." }, "nplurals=2; plural=n != 1;"); diff --git a/l10n/es.json b/l10n/es.json index a235c024d21d92155e01ea2f3c63f26bd70e9056..819dd12e0c7c80ba7d5258c4346ec2b506e6d8eb 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -30,7 +30,8 @@ "Could not verify recovery email because the token is invalid": "No se pudo verificar el correo electrónico de recuperación porque el token no es válido", "Unverified recovery email:": "Correo electrónico de recuperación no verificado:", "Please set a recovery email address.": "Por favor configura un correo electrónico para recuperación.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "El dominio de esta dirección de correo electrónico está en lista negra. Por favor, proporciona otra dirección de recuperación." + "The domain of this email address is blacklisted. Please provide another recovery address.": "El dominio de esta dirección de correo electrónico está en lista negra. Por favor, proporciona otra dirección de recuperación.", + "Too many verification emails.": "Demasiados correos electrónicos de verificación." },"pluralForm" :"nplurals=2; plural=n != 1;" } \ No newline at end of file diff --git a/l10n/fr.js b/l10n/fr.js index 44f37aec0b2aef4de1f86bc91424fe04fb634df4..30855998927abd9c5274b044768204fe5a78df2c 100644 --- a/l10n/fr.js +++ b/l10n/fr.js @@ -32,6 +32,7 @@ OC.L10N.register( "Could not verify recovery email because the token is invalid": "Impossible de vérifier l'e-mail de récupération car le jeton n'est pas valide.", "Unverified recovery email:": "E-mail de récupération non vérifié :", "Please set a recovery email address.": "Merci d'ajouter une adresse e-mail de récupération.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Le domain de cette adresse e-mail est sur liste noire. Merci de bien vouloir fournir une autre adresse de récupération." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Le domain de cette adresse e-mail est sur liste noire. Merci de bien vouloir fournir une autre adresse de récupération.", + "Too many verification emails.": "Trop de courriels de vérification." }, "nplurals=2; plural=n > 1;"); diff --git a/l10n/fr.json b/l10n/fr.json index c49d475a9ce895df3258361770d63c9814a8d7a1..55ec89497c7947ed479d9f2ad613515a2a36646c 100644 --- a/l10n/fr.json +++ b/l10n/fr.json @@ -30,7 +30,8 @@ "Could not verify recovery email because the token is invalid": "Impossible de vérifier l'e-mail de récupération car le jeton n'est pas valide.", "Unverified recovery email:": "E-mail de récupération non vérifié :", "Please set a recovery email address.": "Merci d'ajouter une adresse e-mail de récupération.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Le domain de cette adresse e-mail est sur liste noire. Merci de bien vouloir fournir une autre adresse de récupération." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Le domain de cette adresse e-mail est sur liste noire. Merci de bien vouloir fournir une autre adresse de récupération.", + "Too many verification emails.": "Too many verification emails." },"pluralForm" :"nplurals=2; plural=n > 1;" } \ No newline at end of file diff --git a/l10n/it.js b/l10n/it.js index eaa598a4c9591aba9bb2000eaba3163f034222e3..ebc19398064af9721ac9d84c0adf9acc2ab85bd0 100644 --- a/l10n/it.js +++ b/l10n/it.js @@ -32,6 +32,7 @@ OC.L10N.register( "Could not verify recovery email because the token is invalid": "Impossibile verificare l'e-mail di recovery perché il token non è valido", "Unverified recovery email:": "E-mail di recovery non verificata:", "Please set a recovery email address.": "Imposta un indirizzo e-mail di recovery.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Il dominio cui appartiene questo indirizzo e-mail è contenuto in una black list. Inserisci un indirizzo di recovery differente." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Il dominio cui appartiene questo indirizzo e-mail è contenuto in una black list. Inserisci un indirizzo di recovery differente.", + "Too many verification emails.": "Troppe e-mail di verifica." }, "nplurals=2; plural=n != 1;"); diff --git a/l10n/it.json b/l10n/it.json index 653ed50c54f09bc74ee5432397f829766ac133c4..665127d62679a60c0709665a50d1859e8eb1e969 100644 --- a/l10n/it.json +++ b/l10n/it.json @@ -30,6 +30,7 @@ "Could not verify recovery email because the token is invalid": "Impossibile verificare l'e-mail di recovery perché il token non è valido", "Unverified recovery email:": "E-mail di recovery non verificata:", "Please set a recovery email address.": "Imposta un indirizzo e-mail di recovery.", - "The domain of this email address is blacklisted. Please provide another recovery address.": "Il dominio cui appartiene questo indirizzo e-mail è contenuto in una black list. Inserisci un indirizzo di recovery differente." + "The domain of this email address is blacklisted. Please provide another recovery address.": "Il dominio cui appartiene questo indirizzo e-mail è contenuto in una black list. Inserisci un indirizzo di recovery differente.", + "Too many verification emails.": "Too many verification emails." },"pluralForm" :"nplurals=2; plural=n != 1;" } \ No newline at end of file diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index 776fd4388b2749c783dd6e8ea89ac4b2a39f2971..d572ed5ab32ad5baf6cfd99be6dadb9c3611acec 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -30,6 +30,7 @@ use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException; use OCA\EmailRecovery\Exception\RecoveryEmailAlreadyFoundException; use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException; +use OCA\EmailRecovery\Exception\TooManyVerificationAttemptsException; use OCA\EmailRecovery\Service\RecoveryEmailService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; @@ -156,7 +157,26 @@ class EmailRecoveryController extends Controller { $response->setData(['message' => $this->l->t('Recovery email is verified.')]); return $response; } - $this->recoveryEmailService->sendVerificationEmail($userId, $recoveryEmail); + try { + if ($this->recoveryEmailService->limitVerficationEmail($userId, $recoveryEmail)) { + $this->recoveryEmailService->sendVerificationEmail($userId, $recoveryEmail); + } + } catch (TooManyVerificationAttemptsException $e) { + $this->logger->error('Too many verification attempts for user {userId} and email {email}: {message}', [ + 'userId' => $userId, + 'email' => $recoveryEmail, + 'message' => $e->getMessage() + ]); + $response->setStatus(429); + $response->setData(['message' => $this->l->t('Too many verification emails.')]); + } catch (Exception $e) { + $this->logger->error('Error sending verification email for user {userId} and recovery email {email}: {message}', [ + 'userId' => $userId, + 'email' => $recoveryEmail, + 'message' => $e->getMessage() + ]); + $response->setStatus(500); + } return $response; } diff --git a/lib/Exception/TooManyVerificationAttemptsException.php b/lib/Exception/TooManyVerificationAttemptsException.php new file mode 100644 index 0000000000000000000000000000000000000000..62db28e707d45e7042587fdc21c42612b255f48f --- /dev/null +++ b/lib/Exception/TooManyVerificationAttemptsException.php @@ -0,0 +1,11 @@ +logger = $logger; $this->config = $config; $this->appName = $appName; $this->LDAPConnectionService = $LDAPConnectionService; + $this->session = $session; $this->userManager = $userManager; $this->mailer = $mailer; $this->l10nFactory = $l10nFactory; @@ -79,6 +83,30 @@ class RecoveryEmailService { public function deleteUnverifiedRecoveryEmail(string $username) : void { $this->config->deleteUserValue($username, $this->appName, 'unverified-recovery-email'); } + public function limitVerficationEmail(string $username, string $recoveryEmail) : bool { + $user = $this->userManager->get($username); + $email = $user->getEMailAddress(); + + $attempts = $this->session->get(self::ATTEMPT_KEY); + if (!is_array($attempts)) { + $attempts = []; + } + $currentTime = time(); + + // Filter out attempts older than 1 hour (3600 seconds) + $attempts = array_filter($attempts, function ($attemptTime) use ($currentTime) { + return ($currentTime - $attemptTime) <= 3600; + }); + + if (count($attempts) >= 3) { + $this->logger->info("User ID $username has exceeded the maximum number of verification attempts."); + throw new TooManyVerificationAttemptsException(); + } + $attempts[] = $currentTime; + $this->session->set(self::ATTEMPT_KEY, $attempts); + + return true; + } public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool { $user = $this->userManager->get($username); $email = $user->getEMailAddress(); diff --git a/src/App.vue b/src/App.vue index 49573a6433d388df2056e8a26a2b9dc327f15aac..504f0a01a383cb31566551a13c1f567acebf142c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -97,6 +97,9 @@ export default { this.errorKey = '' this.recoveryEmailVerificationStatus = true } + if (err.response.status === 429) { + this.recoveryEmailVerificationStatus = false + } } this.showError = true }).finally(() => {