From 2b6a1aad31382221e4e6ad6e45229d86c8c39657 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 19:55:34 +0530 Subject: [PATCH 01/53] Moving ecloud-account code to email-recovery --- lib/Exception/BlacklistedEmailException.php | 4 + .../RecoveryEmailValidationException.php | 9 + lib/Listeners/UserChangedListener.php | 89 ++++++++++ lib/Service/BlackListService.php | 168 ++++++++++++++++++ lib/Service/LDAPConnectionService.php | 107 +++++++++++ lib/Service/RecoveryEmailService.php | 140 +++++++++++++++ 6 files changed, 517 insertions(+) create mode 100644 lib/Exception/RecoveryEmailValidationException.php create mode 100644 lib/Listeners/UserChangedListener.php create mode 100644 lib/Service/BlackListService.php create mode 100644 lib/Service/LDAPConnectionService.php diff --git a/lib/Exception/BlacklistedEmailException.php b/lib/Exception/BlacklistedEmailException.php index a6d2235..cfa1580 100644 --- a/lib/Exception/BlacklistedEmailException.php +++ b/lib/Exception/BlacklistedEmailException.php @@ -2,9 +2,13 @@ namespace OCA\EmailRecovery\Exception; +<<<<<<< Updated upstream use Exception; class BlacklistedEmailException extends Exception { +======= +class BlacklistedEmailException extends \Exception { +>>>>>>> Stashed changes public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } diff --git a/lib/Exception/RecoveryEmailValidationException.php b/lib/Exception/RecoveryEmailValidationException.php new file mode 100644 index 0000000..dd73eed --- /dev/null +++ b/lib/Exception/RecoveryEmailValidationException.php @@ -0,0 +1,9 @@ +util = $util; + $this->mailboxMapper = $mailboxMapper; + $this->logger = $logger; + $this->blackListService = $blackListService; + } + + public function handle(Event $event): void { + if (!($event instanceof UserChangedEvent)) { + return; + } + + $feature = $event->getFeature(); + $user = $event->getUser(); + $username = $user->getUID(); + $newValue = $event->getValue(); + + if ($feature === self::QUOTA_FEATURE) { + $updatedQuota = $event->getValue(); + $quotaInBytes = (int) $this->util->computerFileSize($updatedQuota); + $backend = $user->getBackend()->getBackendName(); + + $this->updateQuota($username, $backend, $quotaInBytes); + } + + if ($feature === self::RECOVERY_EMAIL_FEATURE) { + $recoveryEmail = $event->getValue(); + $recoveryEmailAttribute = [ + 'recoveryMailAddress' => $recoveryEmail + ]; + + $this->blackListService->updateAttributesInLDAP($username, $recoveryEmailAttribute); + } + + if ($feature === self::ENABLED_FEATURE) { + try { + $this->blackListService->mapActiveAttributesInLDAP($username, $newValue); + } catch (Exception $e) { + $this->logger->logException('Failed to update LDAP attributes for user: ' . $username, ['exception' => $e]); + } + } + } + + private function updateQuota(string $username, string $backend, int $quotaInBytes) { + try { + if ($backend === 'SQL raw') { + $this->mailboxMapper->updateMailboxQuota($username, $quotaInBytes); + } + if ($backend === 'LDAP') { + $quotaAttribute = [ + 'quota' => $quotaInBytes + ]; + $this->blackListService->updateAttributesInLDAP($username, $quotaAttribute); + } + } catch (Exception $e) { + $this->logger->error("Error setting quota for user $username " . $e->getMessage()); + } + } +} diff --git a/lib/Service/BlackListService.php b/lib/Service/BlackListService.php new file mode 100644 index 0000000..97a07e5 --- /dev/null +++ b/lib/Service/BlackListService.php @@ -0,0 +1,168 @@ +logger = $logger; + $this->l10nFactory = $l10nFactory; + $this->LDAPConnectionService = $LDAPConnectionService; + $this->appData = $appData; + $this->appName = $appName; + } + + public function mapActiveAttributesInLDAP(string $username, bool $isEnabled): void + { + $userActiveAttributes = $this->getActiveAttributes($isEnabled); + $this->updateAttributesInLDAP($username, $userActiveAttributes); + } + + private function getActiveAttributes(bool $isEnabled): array + { + return [ + 'active' => $isEnabled ? 'TRUE' : 'FALSE', + 'mailActive' => $isEnabled ? 'TRUE' : 'FALSE', + ]; + } + + public function updateAttributesInLDAP(string $username, array $attributes): void + { + if (!$this->LDAPConnectionService->isLDAPEnabled()) { + return; + } + + $conn = $this->LDAPConnectionService->getLDAPConnection(); + $userDn = $this->LDAPConnectionService->username2dn($username); + + if ($userDn === false) { + throw new Exception('Could not find DN for username: ' . $username); + } + + if (!ldap_modify($conn, $userDn, $attributes)) { + throw new Exception('Could not modify user ' . $username . ' entry at LDAP server. Attributes: ' . print_r($attributes, true)); + } + + $this->LDAPConnectionService->closeLDAPConnection($conn); + } + /** + * Check if an email domain is blacklisted against a JSON list of disposable email domains. + * + * @param string $email The email address to check. + * @return bool True if the email domain is blacklisted, false otherwise. + */ + public function isBlacklistedEmail(string $email): bool + { + if (!$this->ensureDocumentsFolder()) { + return false; + } + $blacklistedDomains = $this->getBlacklistedDomainData(); + if (empty($blacklistedDomains)) { + return false; + } + $emailParts = explode('@', $email); + $emailDomain = strtolower(end($emailParts)); + return in_array($emailDomain, $blacklistedDomains); + } + /** + * Update the blacklisted domains data by fetching it from a URL and saving it locally. + * + * @return void + */ + public function updateBlacklistedDomains(): void + { + $blacklisted_domain_url = self::BLACKLISTED_DOMAINS_URL; + $json_data = file_get_contents($blacklisted_domain_url); + $this->setBlacklistedDomainsData($json_data); + } + /** + * Store blacklisted domain data in a file within AppData. + * + * @param string $data The data to be stored in the file. + * @return void + */ + private function setBlacklistedDomainsData(string $data): void + { + $file = $this->getBlacklistedDomainsFile(); + $file->putContent($data); + } + /** + * Retrieve the blacklisted domain file path + * + * @return ISimpleFile + */ + private function getBlacklistedDomainsFile(): ISimpleFile + { + try { + $currentFolder = $this->appData->getFolder('/'); + } catch (NotFoundException $e) { + $currentFolder = $this->appData->newFolder('/'); + } + $filename = self::BLACKLISTED_DOMAINS_FILE_NAME; + if ($currentFolder->fileExists($filename)) { + return $currentFolder->getFile($filename); + } + return $currentFolder->newFile($filename); + } + /** + * Retrieve the blacklisted domain data. + * + * @return array The array of blacklisted domains. + */ + public function getBlacklistedDomainData(): array + { + $document = self::BLACKLISTED_DOMAINS_FILE_NAME; + $file = $this->getBlacklistedDomainsFile(); + try { + $blacklistedDomainsInJson = $file->getContent(); + if (empty($blacklistedDomainsInJson)) { + return []; + } + return json_decode($blacklistedDomainsInJson, true, 512, JSON_THROW_ON_ERROR); + } catch (NotFoundException $e) { + $this->logger->warning('Blacklisted domains file ' . $document . ' not found!'); + return []; + } catch (\Throwable $e) { + $this->logger->warning('Error decoding blacklisted domains file ' . $document . ': ' . $e->getMessage()); + return []; + } + } + + /** + * Ensure the specified folder exists within AppData. + * + * @return bool + */ + private function ensureDocumentsFolder(): bool + { + try { + $this->appData->getFolder('/'); + } catch (NotFoundException $e) { + $this->logger->error($this->appName . ' AppData folder not found!'); + return false; + } catch (\RuntimeException $e) { + $this->logger->error($this->appName . ' AppData folder not found! Runtime Error: ' . $e->getMessage()); + return false; + } + return true; + } +} diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php new file mode 100644 index 0000000..58c3be6 --- /dev/null +++ b/lib/Service/LDAPConnectionService.php @@ -0,0 +1,107 @@ +userManager = $userManager; + $this->getConfigurationFromBackend(); + $ldapConfigPrefixes = $ldapBackendHelper->getServerConfigurationPrefixes(true); + $prefix = array_shift($ldapConfigPrefixes); + $this->ldapConfig = new Configuration($prefix); + $this->config = $config; + } + + + private function getConfigurationFromBackend() { + // We don't actually need user id to get access from backend + $uid = ''; + $backends = $this->userManager->getBackends(); + foreach ($backends as $backend) { + if ($backend->getBackendName() === 'LDAP') { + $this->access = $backend->getLDAPAccess($uid); + $connection = $this->access->getConnection(); + $configuration = $connection->getConfiguration(); + + if ($configuration['ldap_configuration_active']) { + $this->ldapEnabled = true; + $this->configuration = $configuration; + break; + } + } + } + } + + public function isUserOnLDAPBackend($user) { + $backend = $user->getBackend(); + return $backend->getBackendName() === 'LDAP'; + } + + public function isLDAPEnabled(): bool { + return $this->ldapEnabled; + } + + public function username2dn(string $username) { + return $this->access->username2dn($username); + } + public function getLDAPConnection() { + if (!$this->ldapEnabled) { + throw new Exception('LDAP backend is not enabled'); + } + + $adminDn = $this->configuration['ldap_dn']; + $adminPassword = $this->configuration['ldap_agent_password']; + $host = $this->configuration['ldap_host']; + $port = intval($this->configuration['ldap_port']); + + $conn = ldap_connect($host, $port); + ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3); + ldap_bind($conn, $adminDn, $adminPassword); + + if (!$conn) { + throw new Exception('Could not connect to LDAP server!'); + } + return $conn; + } + + public function closeLDAPConnection($conn): void { + ldap_close($conn); + } + + public function getLDAPAccess() { + if (!$this->access) { + throw new Exception('Access not defined!'); + } + return $this->access; + } + + public function getLDAPBaseUsers(): array { + $bases = $this->ldapConfig->ldapBaseUsers; + if (empty($bases)) { + $bases = $this->ldapConfig->ldapBase; + } + return $bases; + } + public function getDisplayNameAttribute(): string { + return $this->ldapConfig->ldapUserDisplayName; + } + public function getLdapQuota() { + return $this->config->getSystemValue('default_quota', '1024'); + } +} diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 455ea00..6ae860d 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Service; use Exception; +<<<<<<< Updated upstream use OCA\EcloudAccounts\Service\LDAPConnectionService; use OCA\EmailRecovery\Exception\BlacklistedEmailException; use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; @@ -114,6 +115,56 @@ class RecoveryEmailService { $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); $mainDomain = $this->config->getSystemValue('main_domain', ''); +======= +use OCP\ILogger; +use OCP\IConfig; +use OCP\IUserManager; +use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; +use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException; +use OCA\EmailRecovery\Service\LDAPConnectionService; +use OCA\EmailRecovery\Service\BlackListService; +use OCA\EmailRecovery\Exception\BlacklistedEmailException; +use OCA\EmailRecovery\Exception\RecoveryEmailValidationException; + +class RecoveryEmailService +{ + private $LDAPConnectionService; + private $config; + private $appName; + private $userManager; + private $blackListService; + private $logger; + + public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, BlackListService $blackListService) + { + $this->logger = $logger; + $this->config = $config; + $this->appName = $appName; + $this->LDAPConnectionService = $LDAPConnectionService; + $this->userManager = $userManager; + $this->blackListService = $blackListService; + } + public function getRecoveryEmail(string $username) : string + { + return $this->config->getUserValue($username, $this->appName, 'recovery-email', ''); + } + public function setRecoveryEmail(string $uid, string $recoveryEmail): void { + $this->config->setUserValue($uid, $this->appName, 'recovery-email', $recoveryEmail); + } + public function setUnverifiedRecoveryEmail(string $uid, string $recoveryEmail): void { + $this->config->setUserValue($uid, $this->appName, 'unverified-recovery-email', $recoveryEmail); + } + public function getMainDomain() : string { + return $this->config->getSystemValue('main_domain', ''); + } + public function getLegacyDomain() : string { + return $this->config->getSystemValue('legacy_domain', ''); + } + public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool + { + $user = $this->userManager->get($username); + $email = $user->getEMailAddress(); +>>>>>>> Stashed changes $restrictedDomains = [$legacyDomain, $mainDomain]; @@ -148,6 +199,7 @@ class RecoveryEmailService { } +<<<<<<< Updated upstream public function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) { $conn = $this->LDAPConnectionService->getLDAPConnection(); $userDn = $this->LDAPConnectionService->username2dn($username); @@ -277,4 +329,92 @@ class RecoveryEmailService { $this->manageEmailRestriction($email, 'DELETE', $url); } +======= + private function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) + { + $conn = $this->LDAPConnectionService->getLDAPConnection(); + $userDn = $this->LDAPConnectionService->username2dn($username); + $entry = [ + 'recoveryMailAddress' => $recoveryEmail + ]; + if (!ldap_modify($conn, $userDn, $entry)) { + throw new Exception('Could not modify user entry'); + } + $this->LDAPConnectionService->closeLDAPConnection($conn); + }/** + * Validates the recovery email address. + * + * @param string $recoveryEmail The recovery email address to be validated. + * @throws Exception If the recovery email address has an incorrect format, is already taken, or if the domain is disallowed. + * @return void + */ + public function validateRecoveryEmailAddress(string $recoveryEmail): void { + if (!$this->isValidEmailFormat($recoveryEmail)) { + throw new RecoveryEmailValidationException('Recovery email address has an incorrect format.'); + } + if ($this->checkRecoveryEmailAvailable($recoveryEmail)) { + throw new RecoveryEmailValidationException('Recovery email address is already taken.'); + } + if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { + throw new RecoveryEmailValidationException('You cannot set an email address with a Murena domain as recovery email address.'); + } + if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { + throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); + } + } + /** + * Check if a recovery email address is available (not already taken by another user). + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is available, false otherwise. + */ + public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { + $recoveryEmail = strtolower($recoveryEmail); + $users = $this->config->getUsersForUserValue('email-recovery', 'recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + $users = $this->config->getUsersForUserValue('email-recovery', 'unverified-recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + return false; + } + + /** + * Check if a recovery email address domain is restricted for some domains + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is disallowed, false otherwise. + */ + public function isRecoveryEmailDomainDisallowed(string $recoveryEmail): bool { + + $recoveryEmail = strtolower($recoveryEmail); + + $emailParts = explode('@', $recoveryEmail); + $domain = $emailParts[1] ?? ''; + + $legacyDomain = $this->getLegacyDomain(); + $mainDomain = $this->getMainDomain(); + + $restrictedDomains = [ $legacyDomain, $mainDomain ]; + + return in_array($domain, $restrictedDomains); + } + + /** + * Check if a recovery email address is in valid format + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is valid, false otherwise. + */ + public function isValidEmailFormat(string $recoveryEmail): bool { + return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; + } + + +>>>>>>> Stashed changes } -- GitLab From bf86fa099a41a6abc06bd7a80d8c84a40cb52e70 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 19:57:22 +0530 Subject: [PATCH 02/53] exception --- lib/Exception/BlacklistedEmailException.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Exception/BlacklistedEmailException.php b/lib/Exception/BlacklistedEmailException.php index cfa1580..a6d2235 100644 --- a/lib/Exception/BlacklistedEmailException.php +++ b/lib/Exception/BlacklistedEmailException.php @@ -2,13 +2,9 @@ namespace OCA\EmailRecovery\Exception; -<<<<<<< Updated upstream use Exception; class BlacklistedEmailException extends Exception { -======= -class BlacklistedEmailException extends \Exception { ->>>>>>> Stashed changes public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } -- GitLab From 01f18602c878fd7e6a632c8a9b6b14af19f83fb8 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 20:01:58 +0530 Subject: [PATCH 03/53] exception --- lib/Exception/BlacklistedEmailException.php | 6 +- .../RecoveryEmailValidationException.php | 2 +- lib/Service/RecoveryEmailService.php | 292 ++---------------- 3 files changed, 21 insertions(+), 279 deletions(-) diff --git a/lib/Exception/BlacklistedEmailException.php b/lib/Exception/BlacklistedEmailException.php index a6d2235..2c3ca12 100644 --- a/lib/Exception/BlacklistedEmailException.php +++ b/lib/Exception/BlacklistedEmailException.php @@ -2,10 +2,8 @@ namespace OCA\EmailRecovery\Exception; -use Exception; - -class BlacklistedEmailException extends Exception { +class BlacklistedEmailException extends \Exception { public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } -} +} \ No newline at end of file diff --git a/lib/Exception/RecoveryEmailValidationException.php b/lib/Exception/RecoveryEmailValidationException.php index dd73eed..f70b0ca 100644 --- a/lib/Exception/RecoveryEmailValidationException.php +++ b/lib/Exception/RecoveryEmailValidationException.php @@ -6,4 +6,4 @@ class RecoveryEmailValidationException extends \Exception { public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } -} +} \ No newline at end of file diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 6ae860d..3b5f13a 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -5,117 +5,6 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Service; use Exception; -<<<<<<< Updated upstream -use OCA\EcloudAccounts\Service\LDAPConnectionService; -use OCA\EmailRecovery\Exception\BlacklistedEmailException; -use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; -use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException; -use OCA\EmailRecovery\Exception\RecoveryEmailAlreadyFoundException; -use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException; -use OCP\Defaults; -use OCP\IConfig; -use OCP\ILogger; -use OCP\IURLGenerator; -use OCP\IUser; -use OCP\IUserManager; -use OCP\L10N\IFactory; -use OCP\Mail\IEMailTemplate; -use OCP\Mail\IMailer; -use OCP\Security\VerificationToken\IVerificationToken; -use OCP\Util; -use OCA\EcloudAccounts\Service\BlackListService; - -class RecoveryEmailService { - private ILogger $logger; - private IConfig $config; - private string $appName; - private LDAPConnectionService $LDAPConnectionService; - private IUserManager $userManager; - private IMailer $mailer; - private IFactory $l10nFactory; - private IURLGenerator $urlGenerator; - private Defaults $themingDefaults; - private IVerificationToken $verificationToken; - private CurlService $curl; - private array $apiConfig; - protected const TOKEN_LIFETIME = 60 * 30; // 30 minutes - private BlackListService $blackListService; - - public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService) { - $this->logger = $logger; - $this->config = $config; - $this->appName = $appName; - $this->LDAPConnectionService = $LDAPConnectionService; - $this->userManager = $userManager; - $this->mailer = $mailer; - $this->l10nFactory = $l10nFactory; - $this->urlGenerator = $urlGenerator; - $this->themingDefaults = $themingDefaults; - $this->verificationToken = $verificationToken; - $this->curl = $curlService; - $this->blackListService = $blackListService; - $commonServiceURL = $this->config->getSystemValue('common_services_url', ''); - - if (!empty($commonServiceURL)) { - $commonServiceURL = rtrim($commonServiceURL, '/') . '/'; - } - $this->apiConfig = [ - 'commonServicesURL' => $commonServiceURL, - 'commonServicesToken' => $this->config->getSystemValue('common_services_token', ''), - 'commonApiVersion' => $this->config->getSystemValue('common_api_version', '') - ]; - } - public function setRecoveryEmail(string $username, string $value = '') : void { - $this->config->setUserValue($username, $this->appName, 'recovery-email', $value); - } - public function getRecoveryEmail(string $username) : string { - return $this->config->getUserValue($username, $this->appName, 'recovery-email', ''); - } - public function setUnverifiedRecoveryEmail(string $username, string $value = '') : void { - $this->config->setUserValue($username, $this->appName, 'unverified-recovery-email', $value); - } - public function getUnverifiedRecoveryEmail(string $username) : string { - return $this->config->getUserValue($username, $this->appName, 'unverified-recovery-email', ''); - } - public function deleteUnverifiedRecoveryEmail(string $username) : void { - $this->config->deleteUserValue($username, $this->appName, 'unverified-recovery-email'); - } - public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool { - $user = $this->userManager->get($username); - $email = $user->getEMailAddress(); - if (!empty($recoveryEmail)) { - if (!filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL)) { - $this->logger->info("User $username's requested recovery email does not match email format"); - throw new InvalidRecoveryEmailException(); - } - if (strcmp($recoveryEmail, $email) === 0) { - $this->logger->info("User ID $username's requested recovery email is the same as email"); - throw new SameRecoveryEmailAsEmailException(); - } - if ($this->isRecoveryEmailTaken($username, $recoveryEmail)) { - $this->logger->info("User ID $username's requested recovery email address is already taken"); - throw new RecoveryEmailAlreadyFoundException(); - } - if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { - $this->logger->info("User ID $username's requested recovery email address is disallowed."); - throw new MurenaDomainDisallowedException(); - } - if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { - $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); - throw new BlacklistedEmailException(); - } - } - return true; - } - public function isRecoveryEmailDomainDisallowed(string $recoveryEmail): bool { - $recoveryEmail = strtolower($recoveryEmail); - $emailParts = explode('@', $recoveryEmail); - $domain = $emailParts[1] ?? ''; - - $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); - - $mainDomain = $this->config->getSystemValue('main_domain', ''); -======= use OCP\ILogger; use OCP\IConfig; use OCP\IUserManager; @@ -164,172 +53,28 @@ class RecoveryEmailService { $user = $this->userManager->get($username); $email = $user->getEMailAddress(); ->>>>>>> Stashed changes - - $restrictedDomains = [$legacyDomain, $mainDomain]; - - return in_array($domain, $restrictedDomains); - } - public function isRecoveryEmailTaken(string $username, string $recoveryEmail): bool { - $recoveryEmail = strtolower($recoveryEmail); - - $currentRecoveryEmail = $this->getRecoveryEmail($username); - $currentUnverifiedRecoveryEmail = $this->getUnverifiedRecoveryEmail($username); - - if ($currentRecoveryEmail === $recoveryEmail || $currentUnverifiedRecoveryEmail === $recoveryEmail) { - return false; - } - - $usersWithEmailRecovery = $this->config->getUsersForUserValue('email-recovery', 'recovery-email', $recoveryEmail); - if (count($usersWithEmailRecovery)) { - return true; - } - - $usersWithUnverifiedRecovery = $this->config->getUsersForUserValue('email-recovery', 'unverified-recovery-email', $recoveryEmail); - if (count($usersWithUnverifiedRecovery)) { - return true; - } - - return false; - } - - public function updateRecoveryEmail(string $username, string $recoveryEmail) : void { - $this->setUnverifiedRecoveryEmail($username, $recoveryEmail); - $this->setRecoveryEmail($username, ''); - } - - -<<<<<<< Updated upstream - public function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) { - $conn = $this->LDAPConnectionService->getLDAPConnection(); - $userDn = $this->LDAPConnectionService->username2dn($username); - $entry = [ - 'recoveryMailAddress' => $recoveryEmail - ]; - if (!ldap_modify($conn, $userDn, $entry)) { - throw new Exception('Could not modify user entry'); - } - $this->LDAPConnectionService->closeLDAPConnection($conn); - } - public function sendVerificationEmail(string $uid, string $recoveryEmailAddress) : void { - try { - $user = $this->userManager->get($uid); - $emailTemplate = $this->generateVerificationEmailTemplate($user, $recoveryEmailAddress); - $email = $this->mailer->createMessage(); - $email->useTemplate($emailTemplate); - $email->setTo([$recoveryEmailAddress]); - $email->setFrom([Util::getDefaultEmailAddress('no-reply') => $this->themingDefaults->getName()]); - $this->mailer->send($email); - } catch (\Exception $e) { - $this->logger->error('Error sending notification email to user ' . $uid, ['exception' => $e]); - } - } - /** - * @param IUser $user - * @param string $recoveryEmailAddress - * @return IEMailTemplate - */ - public function generateVerificationEmailTemplate(IUser $user, string $recoveryEmailAddress) { - $userId = $user->getUID(); - - $lang = $this->config->getUserValue($userId, 'core', 'lang', null); - $l10n = $this->l10nFactory->get('settings', $lang); - - $token = $this->createToken($user, $recoveryEmailAddress); - $link = $this->urlGenerator->linkToRouteAbsolute($this->appName .'.email_recovery.verify_recovery_email', ['token' => $token,'userId' => $user->getUID()]); - $this->logger->error('EMAIL URL LINK: ' . $link); - $displayName = $user->getDisplayName(); + if (!filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL)) { + $this->logger->info("User $username's requested recovery email does not match email format"); + throw new InvalidRecoveryEmailException(); + } + if (strcmp($recoveryEmail, $email) === 0) { + $this->logger->info("User ID $username's requested recovery email is the same as email"); + throw new SameRecoveryEmailAsEmailException(); + } + return true; + } - $emailTemplate = $this->mailer->createEMailTemplate('recovery-email.confirmation', [ - 'link' => $link, - 'displayname' => $displayName, - 'userid' => $userId, - 'instancename' => $this->themingDefaults->getName(), - 'resetTokenGenerated' => true, - ]); + public function updateRecoveryEmail(string $username, string $recoveryEmail) : void + { + $user = $this->userManager->get($username); + if ($this->LDAPConnectionService->isUserOnLDAPBackend($user) && $this->LDAPConnectionService->isLDAPEnabled()) { + $this->updateRecoveryEmailAtLDAPServer($username, $recoveryEmail); + } + $this->config->setUserValue($username, $this->appName, 'recovery-email', $recoveryEmail); + } - $emailTemplate->setSubject($l10n->t('Recovery Email Update in Your %s Account', [$this->themingDefaults->getName()])); - $emailTemplate->addHeader(); - $emailTemplate->addHeading($l10n->t('Hello %s', [$displayName])); - $emailTemplate->addBodyText($l10n->t('This is to inform you that the recovery email for your %s account has been successfully updated.', [$this->themingDefaults->getName()])); - $emailTemplate->addBodyText($l10n->t('To verify your new recovery email, please click on the following button.')); - $leftButtonText = $l10n->t('Verify recovery email'); - $emailTemplate->addBodyButton( - $leftButtonText, - $link - ); - $emailTemplate->addBodyText($l10n->t('Please note that this link will be valid for the next 30 minutes.')); - $emailTemplate->addBodyText($l10n->t('If you did not initiate this change, please contact our support team immediately.')); - $emailTemplate->addBodyText($l10n->t('Thank you for choosing %s.', [$this->themingDefaults->getName()])); - $emailTemplate->addFooter('', $lang); - return $emailTemplate; - } - private function createToken(IUser $user, string $recoveryEmail = ''): string { - $ref = \substr(hash('sha256', $recoveryEmail), 0, 8); - return $this->verificationToken->create($user, 'verifyRecoveryMail' . $ref, $recoveryEmail, self::TOKEN_LIFETIME); - } - public function verifyToken(string $token, IUser $user, string $verificationKey, string $email): void { - $this->verificationToken->check($token, $user, $verificationKey, $email); - } - public function deleteVerificationToken(string $token, IUser $user, string $verificationKey): void { - $this->verificationToken->delete($token, $user, $verificationKey); - } - public function makeRecoveryEmailVerified(string $userId): void { - $newRecoveryEmailAddress = $this->getUnverifiedRecoveryEmail($userId); - if ($newRecoveryEmailAddress !== '') { - $this->setRecoveryEmail($userId, $newRecoveryEmailAddress); - $this->deleteUnverifiedRecoveryEmail($userId); - } - } - private function manageEmailRestriction(string $email, string $method, string $url) : void { - $params = []; - - $token = $this->apiConfig['commonServicesToken']; - $headers = [ - "Authorization: Bearer $token" - ]; - - if ($method === 'POST') { - $this->curl->post($url, $params, $headers); - } elseif ($method === 'DELETE') { - $this->curl->delete($url, $params, $headers); - } - - if ($this->curl->getLastStatusCode() !== 200) { - throw new Exception('Error ' . strtolower($method) . 'ing email ' . $email . ' in restricted list. Status Code: ' . $this->curl->getLastStatusCode()); - } - } - - public function restrictEmail(string $email) : void { - $commonServicesURL = $this->apiConfig['commonServicesURL']; - $commonApiVersion = $this->apiConfig['commonApiVersion']; - - if (!isset($commonServicesURL) || empty($commonServicesURL)) { - return; - } - - $endpoint = $commonApiVersion . '/emails/restricted/' . $email; - $url = $commonServicesURL . $endpoint; // POST /v2/emails/restricted/@email - - $this->manageEmailRestriction($email, 'POST', $url); - } - - public function unrestrictEmail(string $email) : void { - $commonServicesURL = $this->apiConfig['commonServicesURL']; - $commonApiVersion = $this->apiConfig['commonApiVersion']; - - if (!isset($commonServicesURL) || empty($commonServicesURL)) { - return; - } - - $endpoint = $commonApiVersion . '/emails/restricted/' . $email; - $url = $commonServicesURL . $endpoint; // DELETE /v2/emails/restricted/@email - - $this->manageEmailRestriction($email, 'DELETE', $url); - } -======= private function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) { $conn = $this->LDAPConnectionService->getLDAPConnection(); @@ -416,5 +161,4 @@ class RecoveryEmailService } ->>>>>>> Stashed changes } -- GitLab From 55b56063e685aada40ff3984660bff9b79ccaafe Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 20:07:46 +0530 Subject: [PATCH 04/53] exception --- lib/Service/RecoveryEmailService.php | 388 +++++++++++++++++---------- 1 file changed, 252 insertions(+), 136 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 3b5f13a..455ea00 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -5,160 +5,276 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Service; use Exception; -use OCP\ILogger; -use OCP\IConfig; -use OCP\IUserManager; +use OCA\EcloudAccounts\Service\LDAPConnectionService; +use OCA\EmailRecovery\Exception\BlacklistedEmailException; use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; +use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException; +use OCA\EmailRecovery\Exception\RecoveryEmailAlreadyFoundException; use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException; -use OCA\EmailRecovery\Service\LDAPConnectionService; -use OCA\EmailRecovery\Service\BlackListService; -use OCA\EmailRecovery\Exception\BlacklistedEmailException; -use OCA\EmailRecovery\Exception\RecoveryEmailValidationException; - -class RecoveryEmailService -{ - private $LDAPConnectionService; - private $config; - private $appName; - private $userManager; - private $blackListService; - private $logger; - - public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, BlackListService $blackListService) - { - $this->logger = $logger; - $this->config = $config; - $this->appName = $appName; - $this->LDAPConnectionService = $LDAPConnectionService; - $this->userManager = $userManager; - $this->blackListService = $blackListService; - } - public function getRecoveryEmail(string $username) : string - { - return $this->config->getUserValue($username, $this->appName, 'recovery-email', ''); - } - public function setRecoveryEmail(string $uid, string $recoveryEmail): void { - $this->config->setUserValue($uid, $this->appName, 'recovery-email', $recoveryEmail); - } - public function setUnverifiedRecoveryEmail(string $uid, string $recoveryEmail): void { - $this->config->setUserValue($uid, $this->appName, 'unverified-recovery-email', $recoveryEmail); - } - public function getMainDomain() : string { - return $this->config->getSystemValue('main_domain', ''); - } - public function getLegacyDomain() : string { - return $this->config->getSystemValue('legacy_domain', ''); - } - public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool - { - $user = $this->userManager->get($username); - $email = $user->getEMailAddress(); - - if (!filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL)) { - $this->logger->info("User $username's requested recovery email does not match email format"); - throw new InvalidRecoveryEmailException(); - } - if (strcmp($recoveryEmail, $email) === 0) { - $this->logger->info("User ID $username's requested recovery email is the same as email"); - throw new SameRecoveryEmailAsEmailException(); - } - return true; - } - - public function updateRecoveryEmail(string $username, string $recoveryEmail) : void - { - $user = $this->userManager->get($username); - if ($this->LDAPConnectionService->isUserOnLDAPBackend($user) && $this->LDAPConnectionService->isLDAPEnabled()) { - $this->updateRecoveryEmailAtLDAPServer($username, $recoveryEmail); - } - $this->config->setUserValue($username, $this->appName, 'recovery-email', $recoveryEmail); - } - - - private function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) - { - $conn = $this->LDAPConnectionService->getLDAPConnection(); - $userDn = $this->LDAPConnectionService->username2dn($username); - $entry = [ - 'recoveryMailAddress' => $recoveryEmail - ]; - if (!ldap_modify($conn, $userDn, $entry)) { - throw new Exception('Could not modify user entry'); - } - $this->LDAPConnectionService->closeLDAPConnection($conn); - }/** - * Validates the recovery email address. - * - * @param string $recoveryEmail The recovery email address to be validated. - * @throws Exception If the recovery email address has an incorrect format, is already taken, or if the domain is disallowed. - * @return void - */ - public function validateRecoveryEmailAddress(string $recoveryEmail): void { - if (!$this->isValidEmailFormat($recoveryEmail)) { - throw new RecoveryEmailValidationException('Recovery email address has an incorrect format.'); - } - if ($this->checkRecoveryEmailAvailable($recoveryEmail)) { - throw new RecoveryEmailValidationException('Recovery email address is already taken.'); - } - if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { - throw new RecoveryEmailValidationException('You cannot set an email address with a Murena domain as recovery email address.'); +use OCP\Defaults; +use OCP\IConfig; +use OCP\ILogger; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; +use OCP\L10N\IFactory; +use OCP\Mail\IEMailTemplate; +use OCP\Mail\IMailer; +use OCP\Security\VerificationToken\IVerificationToken; +use OCP\Util; +use OCA\EcloudAccounts\Service\BlackListService; + +class RecoveryEmailService { + private ILogger $logger; + private IConfig $config; + private string $appName; + private LDAPConnectionService $LDAPConnectionService; + private IUserManager $userManager; + private IMailer $mailer; + private IFactory $l10nFactory; + private IURLGenerator $urlGenerator; + private Defaults $themingDefaults; + private IVerificationToken $verificationToken; + private CurlService $curl; + private array $apiConfig; + protected const TOKEN_LIFETIME = 60 * 30; // 30 minutes + private BlackListService $blackListService; + + public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService) { + $this->logger = $logger; + $this->config = $config; + $this->appName = $appName; + $this->LDAPConnectionService = $LDAPConnectionService; + $this->userManager = $userManager; + $this->mailer = $mailer; + $this->l10nFactory = $l10nFactory; + $this->urlGenerator = $urlGenerator; + $this->themingDefaults = $themingDefaults; + $this->verificationToken = $verificationToken; + $this->curl = $curlService; + $this->blackListService = $blackListService; + $commonServiceURL = $this->config->getSystemValue('common_services_url', ''); + + if (!empty($commonServiceURL)) { + $commonServiceURL = rtrim($commonServiceURL, '/') . '/'; } - if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { - throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); + $this->apiConfig = [ + 'commonServicesURL' => $commonServiceURL, + 'commonServicesToken' => $this->config->getSystemValue('common_services_token', ''), + 'commonApiVersion' => $this->config->getSystemValue('common_api_version', '') + ]; + } + public function setRecoveryEmail(string $username, string $value = '') : void { + $this->config->setUserValue($username, $this->appName, 'recovery-email', $value); + } + public function getRecoveryEmail(string $username) : string { + return $this->config->getUserValue($username, $this->appName, 'recovery-email', ''); + } + public function setUnverifiedRecoveryEmail(string $username, string $value = '') : void { + $this->config->setUserValue($username, $this->appName, 'unverified-recovery-email', $value); + } + public function getUnverifiedRecoveryEmail(string $username) : string { + return $this->config->getUserValue($username, $this->appName, 'unverified-recovery-email', ''); + } + public function deleteUnverifiedRecoveryEmail(string $username) : void { + $this->config->deleteUserValue($username, $this->appName, 'unverified-recovery-email'); + } + public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool { + $user = $this->userManager->get($username); + $email = $user->getEMailAddress(); + if (!empty($recoveryEmail)) { + if (!filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL)) { + $this->logger->info("User $username's requested recovery email does not match email format"); + throw new InvalidRecoveryEmailException(); + } + if (strcmp($recoveryEmail, $email) === 0) { + $this->logger->info("User ID $username's requested recovery email is the same as email"); + throw new SameRecoveryEmailAsEmailException(); + } + if ($this->isRecoveryEmailTaken($username, $recoveryEmail)) { + $this->logger->info("User ID $username's requested recovery email address is already taken"); + throw new RecoveryEmailAlreadyFoundException(); + } + if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { + $this->logger->info("User ID $username's requested recovery email address is disallowed."); + throw new MurenaDomainDisallowedException(); + } + if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { + $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); + throw new BlacklistedEmailException(); + } } + return true; } - /** - * Check if a recovery email address is available (not already taken by another user). - * - * @param string $recoveryEmail The recovery email address to check. - * - * @return bool True if the recovery email address is available, false otherwise. - */ - public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { + public function isRecoveryEmailDomainDisallowed(string $recoveryEmail): bool { $recoveryEmail = strtolower($recoveryEmail); - $users = $this->config->getUsersForUserValue('email-recovery', 'recovery-email', $recoveryEmail); - if(count($users)) { + $emailParts = explode('@', $recoveryEmail); + $domain = $emailParts[1] ?? ''; + + $legacyDomain = $this->config->getSystemValue('legacy_domain', ''); + + $mainDomain = $this->config->getSystemValue('main_domain', ''); + + $restrictedDomains = [$legacyDomain, $mainDomain]; + + return in_array($domain, $restrictedDomains); + } + public function isRecoveryEmailTaken(string $username, string $recoveryEmail): bool { + $recoveryEmail = strtolower($recoveryEmail); + + $currentRecoveryEmail = $this->getRecoveryEmail($username); + $currentUnverifiedRecoveryEmail = $this->getUnverifiedRecoveryEmail($username); + + if ($currentRecoveryEmail === $recoveryEmail || $currentUnverifiedRecoveryEmail === $recoveryEmail) { + return false; + } + + $usersWithEmailRecovery = $this->config->getUsersForUserValue('email-recovery', 'recovery-email', $recoveryEmail); + if (count($usersWithEmailRecovery)) { return true; } - $users = $this->config->getUsersForUserValue('email-recovery', 'unverified-recovery-email', $recoveryEmail); - if(count($users)) { + + $usersWithUnverifiedRecovery = $this->config->getUsersForUserValue('email-recovery', 'unverified-recovery-email', $recoveryEmail); + if (count($usersWithUnverifiedRecovery)) { return true; } + return false; } - /** - * Check if a recovery email address domain is restricted for some domains - * - * @param string $recoveryEmail The recovery email address to check. - * - * @return bool True if the recovery email address is disallowed, false otherwise. - */ - public function isRecoveryEmailDomainDisallowed(string $recoveryEmail): bool { - - $recoveryEmail = strtolower($recoveryEmail); - - $emailParts = explode('@', $recoveryEmail); - $domain = $emailParts[1] ?? ''; - - $legacyDomain = $this->getLegacyDomain(); - $mainDomain = $this->getMainDomain(); - - $restrictedDomains = [ $legacyDomain, $mainDomain ]; + public function updateRecoveryEmail(string $username, string $recoveryEmail) : void { + $this->setUnverifiedRecoveryEmail($username, $recoveryEmail); + $this->setRecoveryEmail($username, ''); + } - return in_array($domain, $restrictedDomains); + + public function updateRecoveryEmailAtLDAPServer(string $username, $recoveryEmail) { + $conn = $this->LDAPConnectionService->getLDAPConnection(); + $userDn = $this->LDAPConnectionService->username2dn($username); + $entry = [ + 'recoveryMailAddress' => $recoveryEmail + ]; + if (!ldap_modify($conn, $userDn, $entry)) { + throw new Exception('Could not modify user entry'); + } + $this->LDAPConnectionService->closeLDAPConnection($conn); } + public function sendVerificationEmail(string $uid, string $recoveryEmailAddress) : void { + try { + $user = $this->userManager->get($uid); + $emailTemplate = $this->generateVerificationEmailTemplate($user, $recoveryEmailAddress); + $email = $this->mailer->createMessage(); + $email->useTemplate($emailTemplate); + $email->setTo([$recoveryEmailAddress]); + $email->setFrom([Util::getDefaultEmailAddress('no-reply') => $this->themingDefaults->getName()]); + $this->mailer->send($email); + } catch (\Exception $e) { + $this->logger->error('Error sending notification email to user ' . $uid, ['exception' => $e]); + } + } /** - * Check if a recovery email address is in valid format - * - * @param string $recoveryEmail The recovery email address to check. - * - * @return bool True if the recovery email address is valid, false otherwise. + * @param IUser $user + * @param string $recoveryEmailAddress + * @return IEMailTemplate */ - public function isValidEmailFormat(string $recoveryEmail): bool { - return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; - } + public function generateVerificationEmailTemplate(IUser $user, string $recoveryEmailAddress) { + $userId = $user->getUID(); + + $lang = $this->config->getUserValue($userId, 'core', 'lang', null); + $l10n = $this->l10nFactory->get('settings', $lang); + + $token = $this->createToken($user, $recoveryEmailAddress); + $link = $this->urlGenerator->linkToRouteAbsolute($this->appName .'.email_recovery.verify_recovery_email', ['token' => $token,'userId' => $user->getUID()]); + $this->logger->error('EMAIL URL LINK: ' . $link); + $displayName = $user->getDisplayName(); + $emailTemplate = $this->mailer->createEMailTemplate('recovery-email.confirmation', [ + 'link' => $link, + 'displayname' => $displayName, + 'userid' => $userId, + 'instancename' => $this->themingDefaults->getName(), + 'resetTokenGenerated' => true, + ]); + $emailTemplate->setSubject($l10n->t('Recovery Email Update in Your %s Account', [$this->themingDefaults->getName()])); + $emailTemplate->addHeader(); + $emailTemplate->addHeading($l10n->t('Hello %s', [$displayName])); + $emailTemplate->addBodyText($l10n->t('This is to inform you that the recovery email for your %s account has been successfully updated.', [$this->themingDefaults->getName()])); + $emailTemplate->addBodyText($l10n->t('To verify your new recovery email, please click on the following button.')); + $leftButtonText = $l10n->t('Verify recovery email'); + $emailTemplate->addBodyButton( + $leftButtonText, + $link + ); + $emailTemplate->addBodyText($l10n->t('Please note that this link will be valid for the next 30 minutes.')); + $emailTemplate->addBodyText($l10n->t('If you did not initiate this change, please contact our support team immediately.')); + $emailTemplate->addBodyText($l10n->t('Thank you for choosing %s.', [$this->themingDefaults->getName()])); + $emailTemplate->addFooter('', $lang); + + return $emailTemplate; + } + private function createToken(IUser $user, string $recoveryEmail = ''): string { + $ref = \substr(hash('sha256', $recoveryEmail), 0, 8); + return $this->verificationToken->create($user, 'verifyRecoveryMail' . $ref, $recoveryEmail, self::TOKEN_LIFETIME); + } + public function verifyToken(string $token, IUser $user, string $verificationKey, string $email): void { + $this->verificationToken->check($token, $user, $verificationKey, $email); + } + public function deleteVerificationToken(string $token, IUser $user, string $verificationKey): void { + $this->verificationToken->delete($token, $user, $verificationKey); + } + public function makeRecoveryEmailVerified(string $userId): void { + $newRecoveryEmailAddress = $this->getUnverifiedRecoveryEmail($userId); + if ($newRecoveryEmailAddress !== '') { + $this->setRecoveryEmail($userId, $newRecoveryEmailAddress); + $this->deleteUnverifiedRecoveryEmail($userId); + } + } + private function manageEmailRestriction(string $email, string $method, string $url) : void { + $params = []; + + $token = $this->apiConfig['commonServicesToken']; + $headers = [ + "Authorization: Bearer $token" + ]; + + if ($method === 'POST') { + $this->curl->post($url, $params, $headers); + } elseif ($method === 'DELETE') { + $this->curl->delete($url, $params, $headers); + } + + if ($this->curl->getLastStatusCode() !== 200) { + throw new Exception('Error ' . strtolower($method) . 'ing email ' . $email . ' in restricted list. Status Code: ' . $this->curl->getLastStatusCode()); + } + } + + public function restrictEmail(string $email) : void { + $commonServicesURL = $this->apiConfig['commonServicesURL']; + $commonApiVersion = $this->apiConfig['commonApiVersion']; + + if (!isset($commonServicesURL) || empty($commonServicesURL)) { + return; + } + + $endpoint = $commonApiVersion . '/emails/restricted/' . $email; + $url = $commonServicesURL . $endpoint; // POST /v2/emails/restricted/@email + + $this->manageEmailRestriction($email, 'POST', $url); + } + + public function unrestrictEmail(string $email) : void { + $commonServicesURL = $this->apiConfig['commonServicesURL']; + $commonApiVersion = $this->apiConfig['commonApiVersion']; + + if (!isset($commonServicesURL) || empty($commonServicesURL)) { + return; + } + + $endpoint = $commonApiVersion . '/emails/restricted/' . $email; + $url = $commonServicesURL . $endpoint; // DELETE /v2/emails/restricted/@email + + $this->manageEmailRestriction($email, 'DELETE', $url); + } } -- GitLab From e64e45f1f4bac979a2b248019d2634340add0024 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 20:23:05 +0530 Subject: [PATCH 05/53] added validations --- lib/Service/RecoveryEmailService.php | 62 +++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 455ea00..e6a0f86 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -11,6 +11,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\RecoveryEmailValidationException; use OCP\Defaults; use OCP\IConfig; use OCP\ILogger; @@ -22,7 +23,7 @@ use OCP\Mail\IEMailTemplate; use OCP\Mail\IMailer; use OCP\Security\VerificationToken\IVerificationToken; use OCP\Util; -use OCA\EcloudAccounts\Service\BlackListService; +use OCA\EmailRecovery\Service\BlackListService; class RecoveryEmailService { private ILogger $logger; @@ -101,7 +102,7 @@ class RecoveryEmailService { } if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); - throw new BlacklistedEmailException(); + throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); } } return true; @@ -277,4 +278,61 @@ class RecoveryEmailService { $this->manageEmailRestriction($email, 'DELETE', $url); } + /** + * Validates the recovery email address. + * + * @param string $recoveryEmail The recovery email address to be validated. + * @throws Exception If the recovery email address has an incorrect format, is already taken, or if the domain is disallowed. + * @return void + */ + public function validateRecoveryEmailAddress(string $recoveryEmail): void { + if (!$this->isValidEmailFormat($recoveryEmail)) { + throw new RecoveryEmailValidationException('Recovery email address has an incorrect format.'); + } + if ($this->checkRecoveryEmailAvailable($recoveryEmail)) { + throw new RecoveryEmailValidationException('Recovery email address is already taken.'); + } + if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { + throw new RecoveryEmailValidationException('You cannot set an email address with a Murena domain as recovery email address.'); + } + if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { + throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); + } + } + /** + * Check if a recovery email address is available (not already taken by another user). + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is available, false otherwise. + */ + public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { + $recoveryEmail = strtolower($recoveryEmail); + $users = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + $users = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + return false; + } + /** + * Check if a recovery email address is in valid format + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is valid, false otherwise. + */ + public function isValidEmailFormat(string $recoveryEmail): bool { + return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; + } + public function getMainDomain() : string { + return $this->config->getSystemValue('main_domain', ''); + } + public function getLegacyDomain() : string { + return $this->config->getSystemValue('legacy_domain', ''); + } + } -- GitLab From 24c0b065c800220ab4cb715a87ac73f3feb79728 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 1 Jul 2024 20:24:12 +0530 Subject: [PATCH 06/53] added validations --- lib/Service/RecoveryEmailService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index e6a0f86..1c9f613 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -84,7 +84,7 @@ class RecoveryEmailService { $user = $this->userManager->get($username); $email = $user->getEMailAddress(); if (!empty($recoveryEmail)) { - if (!filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL)) { + if (!$this->isValidEmailFormat($recoveryEmail)) { $this->logger->info("User $username's requested recovery email does not match email format"); throw new InvalidRecoveryEmailException(); } -- GitLab From e2fa737b85c6835ea1811afdec4bda68679f7437 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 09:41:02 +0530 Subject: [PATCH 07/53] changes by php cs fixer --- lib/AppInfo/Application.php | 3 + lib/Exception/BlacklistedEmailException.php | 6 +- .../RecoveryEmailValidationException.php | 2 +- lib/Service/BlackListService.php | 277 +++++++++--------- lib/Service/RecoveryEmailService.php | 8 +- 5 files changed, 144 insertions(+), 152 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 332e94a..7e0dab1 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -28,6 +28,7 @@ namespace OCA\EmailRecovery\AppInfo; use OCA\EmailRecovery\Listeners\BeforeTemplateRenderedListener; use OCA\EmailRecovery\Listeners\UserConfigChangedListener; +use OCA\EmailRecovery\Listeners\UserChangedListener; use OCA\EmailRecovery\Notification\Notifier; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -36,6 +37,7 @@ use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Notification\IManager as INotificationManager; use OCP\User\Events\UserConfigChangedEvent; +use OCP\User\Events\UserChangedEvent; class Application extends App implements IBootstrap { public const APP_ID = 'email-recovery'; @@ -47,6 +49,7 @@ class Application extends App implements IBootstrap { public function register(IRegistrationContext $context): void { $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); + $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerNotifier']); diff --git a/lib/Exception/BlacklistedEmailException.php b/lib/Exception/BlacklistedEmailException.php index 2c3ca12..a6d2235 100644 --- a/lib/Exception/BlacklistedEmailException.php +++ b/lib/Exception/BlacklistedEmailException.php @@ -2,8 +2,10 @@ namespace OCA\EmailRecovery\Exception; -class BlacklistedEmailException extends \Exception { +use Exception; + +class BlacklistedEmailException extends Exception { public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } -} \ No newline at end of file +} diff --git a/lib/Exception/RecoveryEmailValidationException.php b/lib/Exception/RecoveryEmailValidationException.php index f70b0ca..dd73eed 100644 --- a/lib/Exception/RecoveryEmailValidationException.php +++ b/lib/Exception/RecoveryEmailValidationException.php @@ -6,4 +6,4 @@ class RecoveryEmailValidationException extends \Exception { public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } -} \ No newline at end of file +} diff --git a/lib/Service/BlackListService.php b/lib/Service/BlackListService.php index 97a07e5..93a3c5f 100644 --- a/lib/Service/BlackListService.php +++ b/lib/Service/BlackListService.php @@ -11,158 +11,147 @@ use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; -class BlackListService -{ - private ILogger $logger; - protected IFactory $l10nFactory; - private LDAPConnectionService $LDAPConnectionService; - private IAppData $appData; - private $appName; - private const BLACKLISTED_DOMAINS_FILE_NAME = 'blacklisted_domains.json'; - private const BLACKLISTED_DOMAINS_URL = 'https://raw.githubusercontent.com/disposable/disposable-email-domains/master/domains.json'; +class BlackListService { + private ILogger $logger; + protected IFactory $l10nFactory; + private LDAPConnectionService $LDAPConnectionService; + private IAppData $appData; + private $appName; + private const BLACKLISTED_DOMAINS_FILE_NAME = 'blacklisted_domains.json'; + private const BLACKLISTED_DOMAINS_URL = 'https://raw.githubusercontent.com/disposable/disposable-email-domains/master/domains.json'; - public function __construct(string $appName, ILogger $logger, IFactory $l10nFactory, LDAPConnectionService $LDAPConnectionService, IAppData $appData) - { - $this->logger = $logger; - $this->l10nFactory = $l10nFactory; - $this->LDAPConnectionService = $LDAPConnectionService; - $this->appData = $appData; - $this->appName = $appName; - } + public function __construct(string $appName, ILogger $logger, IFactory $l10nFactory, LDAPConnectionService $LDAPConnectionService, IAppData $appData) { + $this->logger = $logger; + $this->l10nFactory = $l10nFactory; + $this->LDAPConnectionService = $LDAPConnectionService; + $this->appData = $appData; + $this->appName = $appName; + } - public function mapActiveAttributesInLDAP(string $username, bool $isEnabled): void - { - $userActiveAttributes = $this->getActiveAttributes($isEnabled); - $this->updateAttributesInLDAP($username, $userActiveAttributes); - } + public function mapActiveAttributesInLDAP(string $username, bool $isEnabled): void { + $userActiveAttributes = $this->getActiveAttributes($isEnabled); + $this->updateAttributesInLDAP($username, $userActiveAttributes); + } - private function getActiveAttributes(bool $isEnabled): array - { - return [ - 'active' => $isEnabled ? 'TRUE' : 'FALSE', - 'mailActive' => $isEnabled ? 'TRUE' : 'FALSE', - ]; - } + private function getActiveAttributes(bool $isEnabled): array { + return [ + 'active' => $isEnabled ? 'TRUE' : 'FALSE', + 'mailActive' => $isEnabled ? 'TRUE' : 'FALSE', + ]; + } - public function updateAttributesInLDAP(string $username, array $attributes): void - { - if (!$this->LDAPConnectionService->isLDAPEnabled()) { - return; - } + public function updateAttributesInLDAP(string $username, array $attributes): void { + if (!$this->LDAPConnectionService->isLDAPEnabled()) { + return; + } - $conn = $this->LDAPConnectionService->getLDAPConnection(); - $userDn = $this->LDAPConnectionService->username2dn($username); + $conn = $this->LDAPConnectionService->getLDAPConnection(); + $userDn = $this->LDAPConnectionService->username2dn($username); - if ($userDn === false) { - throw new Exception('Could not find DN for username: ' . $username); - } + if ($userDn === false) { + throw new Exception('Could not find DN for username: ' . $username); + } - if (!ldap_modify($conn, $userDn, $attributes)) { - throw new Exception('Could not modify user ' . $username . ' entry at LDAP server. Attributes: ' . print_r($attributes, true)); - } + if (!ldap_modify($conn, $userDn, $attributes)) { + throw new Exception('Could not modify user ' . $username . ' entry at LDAP server. Attributes: ' . print_r($attributes, true)); + } - $this->LDAPConnectionService->closeLDAPConnection($conn); - } - /** - * Check if an email domain is blacklisted against a JSON list of disposable email domains. - * - * @param string $email The email address to check. - * @return bool True if the email domain is blacklisted, false otherwise. - */ - public function isBlacklistedEmail(string $email): bool - { - if (!$this->ensureDocumentsFolder()) { - return false; - } - $blacklistedDomains = $this->getBlacklistedDomainData(); - if (empty($blacklistedDomains)) { - return false; - } - $emailParts = explode('@', $email); - $emailDomain = strtolower(end($emailParts)); - return in_array($emailDomain, $blacklistedDomains); - } - /** - * Update the blacklisted domains data by fetching it from a URL and saving it locally. - * - * @return void - */ - public function updateBlacklistedDomains(): void - { - $blacklisted_domain_url = self::BLACKLISTED_DOMAINS_URL; - $json_data = file_get_contents($blacklisted_domain_url); - $this->setBlacklistedDomainsData($json_data); - } - /** - * Store blacklisted domain data in a file within AppData. - * - * @param string $data The data to be stored in the file. - * @return void - */ - private function setBlacklistedDomainsData(string $data): void - { - $file = $this->getBlacklistedDomainsFile(); - $file->putContent($data); - } - /** - * Retrieve the blacklisted domain file path - * - * @return ISimpleFile - */ - private function getBlacklistedDomainsFile(): ISimpleFile - { - try { - $currentFolder = $this->appData->getFolder('/'); - } catch (NotFoundException $e) { - $currentFolder = $this->appData->newFolder('/'); - } - $filename = self::BLACKLISTED_DOMAINS_FILE_NAME; - if ($currentFolder->fileExists($filename)) { - return $currentFolder->getFile($filename); - } - return $currentFolder->newFile($filename); - } - /** - * Retrieve the blacklisted domain data. - * - * @return array The array of blacklisted domains. - */ - public function getBlacklistedDomainData(): array - { - $document = self::BLACKLISTED_DOMAINS_FILE_NAME; - $file = $this->getBlacklistedDomainsFile(); - try { - $blacklistedDomainsInJson = $file->getContent(); - if (empty($blacklistedDomainsInJson)) { - return []; - } - return json_decode($blacklistedDomainsInJson, true, 512, JSON_THROW_ON_ERROR); - } catch (NotFoundException $e) { - $this->logger->warning('Blacklisted domains file ' . $document . ' not found!'); - return []; - } catch (\Throwable $e) { - $this->logger->warning('Error decoding blacklisted domains file ' . $document . ': ' . $e->getMessage()); - return []; - } - } + $this->LDAPConnectionService->closeLDAPConnection($conn); + } + /** + * Check if an email domain is blacklisted against a JSON list of disposable email domains. + * + * @param string $email The email address to check. + * @return bool True if the email domain is blacklisted, false otherwise. + */ + public function isBlacklistedEmail(string $email): bool { + if (!$this->ensureDocumentsFolder()) { + return false; + } + $blacklistedDomains = $this->getBlacklistedDomainData(); + if (empty($blacklistedDomains)) { + return false; + } + $emailParts = explode('@', $email); + $emailDomain = strtolower(end($emailParts)); + return in_array($emailDomain, $blacklistedDomains); + } + /** + * Update the blacklisted domains data by fetching it from a URL and saving it locally. + * + * @return void + */ + public function updateBlacklistedDomains(): void { + $blacklisted_domain_url = self::BLACKLISTED_DOMAINS_URL; + $json_data = file_get_contents($blacklisted_domain_url); + $this->setBlacklistedDomainsData($json_data); + } + /** + * Store blacklisted domain data in a file within AppData. + * + * @param string $data The data to be stored in the file. + * @return void + */ + private function setBlacklistedDomainsData(string $data): void { + $file = $this->getBlacklistedDomainsFile(); + $file->putContent($data); + } + /** + * Retrieve the blacklisted domain file path + * + * @return ISimpleFile + */ + private function getBlacklistedDomainsFile(): ISimpleFile { + try { + $currentFolder = $this->appData->getFolder('/'); + } catch (NotFoundException $e) { + $currentFolder = $this->appData->newFolder('/'); + } + $filename = self::BLACKLISTED_DOMAINS_FILE_NAME; + if ($currentFolder->fileExists($filename)) { + return $currentFolder->getFile($filename); + } + return $currentFolder->newFile($filename); + } + /** + * Retrieve the blacklisted domain data. + * + * @return array The array of blacklisted domains. + */ + public function getBlacklistedDomainData(): array { + $document = self::BLACKLISTED_DOMAINS_FILE_NAME; + $file = $this->getBlacklistedDomainsFile(); + try { + $blacklistedDomainsInJson = $file->getContent(); + if (empty($blacklistedDomainsInJson)) { + return []; + } + return json_decode($blacklistedDomainsInJson, true, 512, JSON_THROW_ON_ERROR); + } catch (NotFoundException $e) { + $this->logger->warning('Blacklisted domains file ' . $document . ' not found!'); + return []; + } catch (\Throwable $e) { + $this->logger->warning('Error decoding blacklisted domains file ' . $document . ': ' . $e->getMessage()); + return []; + } + } - /** - * Ensure the specified folder exists within AppData. - * - * @return bool - */ - private function ensureDocumentsFolder(): bool - { - try { - $this->appData->getFolder('/'); - } catch (NotFoundException $e) { - $this->logger->error($this->appName . ' AppData folder not found!'); - return false; - } catch (\RuntimeException $e) { - $this->logger->error($this->appName . ' AppData folder not found! Runtime Error: ' . $e->getMessage()); - return false; - } - return true; - } + /** + * Ensure the specified folder exists within AppData. + * + * @return bool + */ + private function ensureDocumentsFolder(): bool { + try { + $this->appData->getFolder('/'); + } catch (NotFoundException $e) { + $this->logger->error($this->appName . ' AppData folder not found!'); + return false; + } catch (\RuntimeException $e) { + $this->logger->error($this->appName . ' AppData folder not found! Runtime Error: ' . $e->getMessage()); + return false; + } + return true; + } } diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 1c9f613..1766f37 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -23,7 +23,6 @@ use OCP\Mail\IEMailTemplate; use OCP\Mail\IMailer; use OCP\Security\VerificationToken\IVerificationToken; use OCP\Util; -use OCA\EmailRecovery\Service\BlackListService; class RecoveryEmailService { private ILogger $logger; @@ -299,7 +298,7 @@ class RecoveryEmailService { throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); } } - /** + /** * Check if a recovery email address is available (not already taken by another user). * * @param string $recoveryEmail The recovery email address to check. @@ -309,11 +308,11 @@ class RecoveryEmailService { public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { $recoveryEmail = strtolower($recoveryEmail); $users = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); - if(count($users)) { + if (count($users)) { return true; } $users = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); - if(count($users)) { + if (count($users)) { return true; } return false; @@ -334,5 +333,4 @@ class RecoveryEmailService { public function getLegacyDomain() : string { return $this->config->getSystemValue('legacy_domain', ''); } - } -- GitLab From 82429c0af4a2bfadc2c9b51b34d553ca70c3fb8f Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 09:43:10 +0530 Subject: [PATCH 08/53] used appname --- lib/Service/RecoveryEmailService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 1766f37..8513c55 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -129,12 +129,12 @@ class RecoveryEmailService { return false; } - $usersWithEmailRecovery = $this->config->getUsersForUserValue('email-recovery', 'recovery-email', $recoveryEmail); + $usersWithEmailRecovery = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); if (count($usersWithEmailRecovery)) { return true; } - $usersWithUnverifiedRecovery = $this->config->getUsersForUserValue('email-recovery', 'unverified-recovery-email', $recoveryEmail); + $usersWithUnverifiedRecovery = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); if (count($usersWithUnverifiedRecovery)) { return true; } -- GitLab From 43b12a16ebb2ab46ccad11536b6afc473a7e1133 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 10:03:44 +0530 Subject: [PATCH 09/53] removed duplication --- lib/Service/RecoveryEmailService.php | 33 ++++++---------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 8513c55..e059358 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -11,7 +11,6 @@ use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException; use OCA\EmailRecovery\Exception\RecoveryEmailAlreadyFoundException; use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException; -use OCA\EmailRecovery\Exception\RecoveryEmailValidationException; use OCP\Defaults; use OCP\IConfig; use OCP\ILogger; @@ -79,15 +78,18 @@ class RecoveryEmailService { public function deleteUnverifiedRecoveryEmail(string $username) : void { $this->config->deleteUserValue($username, $this->appName, 'unverified-recovery-email'); } - public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool { - $user = $this->userManager->get($username); - $email = $user->getEMailAddress(); + public function validateRecoveryEmail(string $username = '', string $recoveryEmail) : bool { + $email = ''; + if (!$username) { + $user = $this->userManager->get($username); + $email = $user->getEMailAddress(); + } if (!empty($recoveryEmail)) { if (!$this->isValidEmailFormat($recoveryEmail)) { $this->logger->info("User $username's requested recovery email does not match email format"); throw new InvalidRecoveryEmailException(); } - if (strcmp($recoveryEmail, $email) === 0) { + if ($email != '' && strcmp($recoveryEmail, $email) === 0) { $this->logger->info("User ID $username's requested recovery email is the same as email"); throw new SameRecoveryEmailAsEmailException(); } @@ -277,27 +279,6 @@ class RecoveryEmailService { $this->manageEmailRestriction($email, 'DELETE', $url); } - /** - * Validates the recovery email address. - * - * @param string $recoveryEmail The recovery email address to be validated. - * @throws Exception If the recovery email address has an incorrect format, is already taken, or if the domain is disallowed. - * @return void - */ - public function validateRecoveryEmailAddress(string $recoveryEmail): void { - if (!$this->isValidEmailFormat($recoveryEmail)) { - throw new RecoveryEmailValidationException('Recovery email address has an incorrect format.'); - } - if ($this->checkRecoveryEmailAvailable($recoveryEmail)) { - throw new RecoveryEmailValidationException('Recovery email address is already taken.'); - } - if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { - throw new RecoveryEmailValidationException('You cannot set an email address with a Murena domain as recovery email address.'); - } - if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { - throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); - } - } /** * Check if a recovery email address is available (not already taken by another user). * -- GitLab From 681d6bb6a765ffc6ac91043a3c89c77968e0116d Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 10:05:21 +0530 Subject: [PATCH 10/53] removed duplication --- lib/Service/RecoveryEmailService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index e059358..ad71bf1 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -80,7 +80,7 @@ class RecoveryEmailService { } public function validateRecoveryEmail(string $username = '', string $recoveryEmail) : bool { $email = ''; - if (!$username) { + if ($username != '') { $user = $this->userManager->get($username); $email = $user->getEMailAddress(); } -- GitLab From 29bc25befcca91dc5af8afe81916d36559cacd7b Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 10:10:14 +0530 Subject: [PATCH 11/53] removed unncessary --- lib/Service/RecoveryEmailService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index ad71bf1..f013255 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -103,7 +103,7 @@ class RecoveryEmailService { } if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); - throw new BlacklistedEmailException('The domain of this email address is blacklisted. Please provide another recovery address.'); + throw new BlacklistedEmailException(); } } return true; -- GitLab From 5d282ed8b065006b0e08710f0950b2d35f7d3e36 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 10:15:18 +0530 Subject: [PATCH 12/53] added appName --- lib/Controller/EmailRecoveryController.php | 2 ++ lib/Service/RecoveryEmailService.php | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index 776fd43..a73245e 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -53,6 +53,7 @@ class EmailRecoveryController extends Controller { private IUserManager $userManager; private IVerificationToken $verificationToken; private ICrypto $crypto; + private string $appName; public function __construct( string $appName, @@ -75,6 +76,7 @@ class EmailRecoveryController extends Controller { $this->userManager = $userManager; $this->verificationToken = $verificationToken; $this->crypto = $crypto; + $this->appName = $appName; } /** diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index f013255..3e8fc62 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Service; use Exception; -use OCA\EcloudAccounts\Service\LDAPConnectionService; use OCA\EmailRecovery\Exception\BlacklistedEmailException; use OCA\EmailRecovery\Exception\InvalidRecoveryEmailException; use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException; -- GitLab From 6911fa0521144014b9a758c0a823b7eb2f0d3211 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 2 Jul 2024 10:17:40 +0530 Subject: [PATCH 13/53] RecoveryEmailValidationException removed --- lib/Exception/RecoveryEmailValidationException.php | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 lib/Exception/RecoveryEmailValidationException.php diff --git a/lib/Exception/RecoveryEmailValidationException.php b/lib/Exception/RecoveryEmailValidationException.php deleted file mode 100644 index dd73eed..0000000 --- a/lib/Exception/RecoveryEmailValidationException.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Tue, 2 Jul 2024 10:19:33 +0530 Subject: [PATCH 14/53] remoevd unncesary code --- lib/Service/RecoveryEmailService.php | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 3e8fc62..d5f8ef6 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -278,25 +278,6 @@ class RecoveryEmailService { $this->manageEmailRestriction($email, 'DELETE', $url); } - /** - * Check if a recovery email address is available (not already taken by another user). - * - * @param string $recoveryEmail The recovery email address to check. - * - * @return bool True if the recovery email address is available, false otherwise. - */ - public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { - $recoveryEmail = strtolower($recoveryEmail); - $users = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); - if (count($users)) { - return true; - } - $users = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); - if (count($users)) { - return true; - } - return false; - } /** * Check if a recovery email address is in valid format * @@ -307,10 +288,4 @@ class RecoveryEmailService { public function isValidEmailFormat(string $recoveryEmail): bool { return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; } - public function getMainDomain() : string { - return $this->config->getSystemValue('main_domain', ''); - } - public function getLegacyDomain() : string { - return $this->config->getSystemValue('legacy_domain', ''); - } } -- GitLab From 24d1b5a86234553f782f224deb6467f90f63d1fb Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 8 Jul 2024 20:27:23 +0530 Subject: [PATCH 15/53] added function --- lib/Service/RecoveryEmailService.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index d5f8ef6..643979b 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -288,4 +288,23 @@ class RecoveryEmailService { public function isValidEmailFormat(string $recoveryEmail): bool { return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; } + /** + * Check if a recovery email address is available (not already taken by another user). + * + * @param string $recoveryEmail The recovery email address to check. + * + * @return bool True if the recovery email address is available, false otherwise. + */ + public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { + $recoveryEmail = strtolower($recoveryEmail); + $users = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + $users = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); + if(count($users)) { + return true; + } + return false; + } } -- GitLab From 597ba4a37d2df03d8bc25d086cd54af24ec6f7ba Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Mon, 8 Jul 2024 20:31:35 +0530 Subject: [PATCH 16/53] added function --- lib/Service/RecoveryEmailService.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 643979b..d5f8ef6 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -288,23 +288,4 @@ class RecoveryEmailService { public function isValidEmailFormat(string $recoveryEmail): bool { return filter_var($recoveryEmail, FILTER_VALIDATE_EMAIL) !== false; } - /** - * Check if a recovery email address is available (not already taken by another user). - * - * @param string $recoveryEmail The recovery email address to check. - * - * @return bool True if the recovery email address is available, false otherwise. - */ - public function checkRecoveryEmailAvailable(string $recoveryEmail): bool { - $recoveryEmail = strtolower($recoveryEmail); - $users = $this->config->getUsersForUserValue($this->appName, 'recovery-email', $recoveryEmail); - if(count($users)) { - return true; - } - $users = $this->config->getUsersForUserValue($this->appName, 'unverified-recovery-email', $recoveryEmail); - if(count($users)) { - return true; - } - return false; - } } -- GitLab From abcd0e584b62ebec4bd905dc5df95ebf594abe7f Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 08:52:00 +0530 Subject: [PATCH 17/53] removed unncessary --- lib/Listeners/UserChangedListener.php | 53 +-------------------------- 1 file changed, 1 insertion(+), 52 deletions(-) diff --git a/lib/Listeners/UserChangedListener.php b/lib/Listeners/UserChangedListener.php index e657be6..d702f2c 100644 --- a/lib/Listeners/UserChangedListener.php +++ b/lib/Listeners/UserChangedListener.php @@ -4,34 +4,16 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Listeners; -use Exception; -use OCA\EmailRecovery\Db\MailboxMapper; use OCA\EmailRecovery\Service\BlackListService; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\ILogger; use OCP\User\Events\UserChangedEvent; -use OCP\Util; class UserChangedListener implements IEventListener { - private const QUOTA_FEATURE = 'quota'; - private const RECOVERY_EMAIL_FEATURE = 'recovery-email'; - - private const ENABLED_FEATURE = 'enabled'; - - private $util; - - private $logger; - - private $mailboxMapper; - private $blackListService; - public function __construct(Util $util, ILogger $logger, MailboxMapper $mailboxMapper, BlackListService $blackListService) { - $this->util = $util; - $this->mailboxMapper = $mailboxMapper; - $this->logger = $logger; + public function __construct(BlackListService $blackListService) { $this->blackListService = $blackListService; } @@ -43,16 +25,7 @@ class UserChangedListener implements IEventListener { $feature = $event->getFeature(); $user = $event->getUser(); $username = $user->getUID(); - $newValue = $event->getValue(); - if ($feature === self::QUOTA_FEATURE) { - $updatedQuota = $event->getValue(); - $quotaInBytes = (int) $this->util->computerFileSize($updatedQuota); - $backend = $user->getBackend()->getBackendName(); - - $this->updateQuota($username, $backend, $quotaInBytes); - } - if ($feature === self::RECOVERY_EMAIL_FEATURE) { $recoveryEmail = $event->getValue(); $recoveryEmailAttribute = [ @@ -61,29 +34,5 @@ class UserChangedListener implements IEventListener { $this->blackListService->updateAttributesInLDAP($username, $recoveryEmailAttribute); } - - if ($feature === self::ENABLED_FEATURE) { - try { - $this->blackListService->mapActiveAttributesInLDAP($username, $newValue); - } catch (Exception $e) { - $this->logger->logException('Failed to update LDAP attributes for user: ' . $username, ['exception' => $e]); - } - } - } - - private function updateQuota(string $username, string $backend, int $quotaInBytes) { - try { - if ($backend === 'SQL raw') { - $this->mailboxMapper->updateMailboxQuota($username, $quotaInBytes); - } - if ($backend === 'LDAP') { - $quotaAttribute = [ - 'quota' => $quotaInBytes - ]; - $this->blackListService->updateAttributesInLDAP($username, $quotaAttribute); - } - } catch (Exception $e) { - $this->logger->error("Error setting quota for user $username " . $e->getMessage()); - } } } -- GitLab From d06cf1a877737793568f3ea50924c8331b784317 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 09:35:08 +0530 Subject: [PATCH 18/53] added exceptions --- lib/Controller/EmailRecoveryController.php | 25 ++++++---------------- lib/Service/RecoveryEmailService.php | 16 ++++++++------ 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index a73245e..27a4e46 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -170,25 +170,14 @@ class EmailRecoveryController extends Controller { } } catch (Exception $e) { $response->setStatus(500); - if ($e instanceof InvalidRecoveryEmailException) { + if ($e instanceof InvalidRecoveryEmailException || + $e instanceof SameRecoveryEmailAsEmailException || + $e instanceof RecoveryEmailAlreadyFoundException || + $e instanceof MurenaDomainDisallowedException || + $e instanceof BlacklistedEmailException + ) { $response->setStatus(400); - $response->setData(['message' => $this->l->t('Invalid Recovery Email')]); - } - if ($e instanceof SameRecoveryEmailAsEmailException) { - $response->setStatus(400); - $response->setData(['message' => $this->l->t('Error! User email address cannot be saved as recovery email address!')]); - } - if ($e instanceof RecoveryEmailAlreadyFoundException) { - $response->setStatus(400); - $response->setData(['message' => $this->l->t('Recovery email address is already taken.')]); - } - if ($e instanceof MurenaDomainDisallowedException) { - $response->setStatus(400); - $response->setData(['message' => $this->l->t('You cannot set an email address with a Murena domain as recovery email address.')]); - } - if ($e instanceof BlacklistedEmailException) { - $response->setStatus(400); - $response->setData(['message' => $this->l->t('The domain of this email address is blacklisted. Please provide another recovery address.')]); + $response->setData(['message' => $e->getMessage()]); } } } diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index d5f8ef6..b4d9dcc 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -21,6 +21,7 @@ use OCP\Mail\IEMailTemplate; use OCP\Mail\IMailer; use OCP\Security\VerificationToken\IVerificationToken; use OCP\Util; +use OCP\IL10N; class RecoveryEmailService { private ILogger $logger; @@ -37,8 +38,10 @@ class RecoveryEmailService { private array $apiConfig; protected const TOKEN_LIFETIME = 60 * 30; // 30 minutes private BlackListService $blackListService; + private IL10N $l; - public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService) { + + public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService, IL10N $l) { $this->logger = $logger; $this->config = $config; $this->appName = $appName; @@ -51,6 +54,7 @@ class RecoveryEmailService { $this->verificationToken = $verificationToken; $this->curl = $curlService; $this->blackListService = $blackListService; + $this->l = $l; $commonServiceURL = $this->config->getSystemValue('common_services_url', ''); if (!empty($commonServiceURL)) { @@ -86,23 +90,23 @@ class RecoveryEmailService { if (!empty($recoveryEmail)) { if (!$this->isValidEmailFormat($recoveryEmail)) { $this->logger->info("User $username's requested recovery email does not match email format"); - throw new InvalidRecoveryEmailException(); + throw new InvalidRecoveryEmailException($this->l->t('Invalid Recovery Email')); } if ($email != '' && strcmp($recoveryEmail, $email) === 0) { $this->logger->info("User ID $username's requested recovery email is the same as email"); - throw new SameRecoveryEmailAsEmailException(); + throw new SameRecoveryEmailAsEmailException($this->l->t('Error! User email address cannot be saved as recovery email address!')); } if ($this->isRecoveryEmailTaken($username, $recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address is already taken"); - throw new RecoveryEmailAlreadyFoundException(); + throw new RecoveryEmailAlreadyFoundException($this->l->t('Recovery email address is already taken.')); } if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address is disallowed."); - throw new MurenaDomainDisallowedException(); + throw new MurenaDomainDisallowedException($this->l->t('You cannot set an email address with a Murena domain as recovery email address.')); } if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); - throw new BlacklistedEmailException(); + throw new BlacklistedEmailException($this->l->t('The domain of this email address is blacklisted. Please provide another recovery address.')); } } return true; -- GitLab From a3b243d9d4bf96a5ff7a2a74f09ab9871181db6b Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 11:08:41 +0530 Subject: [PATCH 19/53] removed commands --- appinfo/info.xml | 3 ++ lib/Command/UpdateBlacklistedDomains.php | 39 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 lib/Command/UpdateBlacklistedDomains.php diff --git a/appinfo/info.xml b/appinfo/info.xml index bf39775..318e406 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -20,4 +20,7 @@ OCA\EmailRecovery\BackgroundJob\WeeklyRecoveryNotificationJob + + OCA\EmailRecovery\Command\UpdateBlacklistedDomains + diff --git a/lib/Command/UpdateBlacklistedDomains.php b/lib/Command/UpdateBlacklistedDomains.php new file mode 100644 index 0000000..5e4d9cf --- /dev/null +++ b/lib/Command/UpdateBlacklistedDomains.php @@ -0,0 +1,39 @@ +blackListService = $blackListService; + $this->logger = $logger; + } + + protected function configure() { + $this->setName(Application::APP_ID.':update-blacklisted-domains')->setDescription('Update blacklisted domains'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + try { + $this->blackListService->updateBlacklistedDomains(); + $output->writeln('Updated blacklisted domains for creation.'); + } catch (\Throwable $th) { + $this->logger->error('Error while updating blacklisted domains. ' . $th->getMessage()); + $output->writeln('Error while updating blacklisted domains. '. $th->getMessage()); + } + return 1; + } +} -- GitLab From c9070cbd78d8c2111e837d3fed877657930b2cda Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 11:11:14 +0530 Subject: [PATCH 20/53] removed commands --- lib/Command/UpdateBlacklistedDomains.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Command/UpdateBlacklistedDomains.php b/lib/Command/UpdateBlacklistedDomains.php index 5e4d9cf..b0bbed8 100644 --- a/lib/Command/UpdateBlacklistedDomains.php +++ b/lib/Command/UpdateBlacklistedDomains.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace OCA\EcloudAccounts\Command; +namespace OCA\EmailRecovery\Command; -use OCA\EcloudAccounts\AppInfo\Application; +use OCA\EmailRecovery\AppInfo\Application; use OCA\EmailRecovery\Service\BlackListService; use OCP\ILogger; use Symfony\Component\Console\Command\Command; -- GitLab From f684a8d5adccce844703738dc9ef1e257965b426 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 11:23:22 +0530 Subject: [PATCH 21/53] removed commands --- lib/Controller/EmailRecoveryController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index 27a4e46..2d073f6 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -53,7 +53,7 @@ class EmailRecoveryController extends Controller { private IUserManager $userManager; private IVerificationToken $verificationToken; private ICrypto $crypto; - private string $appName; + protected string $appName; public function __construct( string $appName, -- GitLab From e517b71a572d24a1305443dae7c3a258b10d6f75 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 11:28:59 +0530 Subject: [PATCH 22/53] change in email recovery --- lib/Controller/EmailRecoveryController.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index 2d073f6..681ba97 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -40,9 +40,8 @@ use OCP\ILogger; use OCP\IRequest; use OCP\IUserManager; use OCP\IUserSession; -use OCP\Security\ICrypto; use OCP\Security\VerificationToken\InvalidTokenException; -use OCP\Security\VerificationToken\IVerificationToken; +use OCA\EmailRecovery\AppInfo\Application; class EmailRecoveryController extends Controller { private IConfig $config; @@ -51,12 +50,8 @@ class EmailRecoveryController extends Controller { private IUserSession $userSession; private RecoveryEmailService $recoveryEmailService; private IUserManager $userManager; - private IVerificationToken $verificationToken; - private ICrypto $crypto; - protected string $appName; public function __construct( - string $appName, IRequest $request, IConfig $config, ILogger $logger, @@ -64,19 +59,14 @@ class EmailRecoveryController extends Controller { IUserSession $userSession, RecoveryEmailService $recoveryEmailService, IUserManager $userManager, - IVerificationToken $verificationToken, - ICrypto $crypto ) { - parent::__construct($appName, $request); + parent::__construct($request); $this->config = $config; $this->logger = $logger; $this->l = $l; $this->userSession = $userSession; $this->recoveryEmailService = $recoveryEmailService; $this->userManager = $userManager; - $this->verificationToken = $verificationToken; - $this->crypto = $crypto; - $this->appName = $appName; } /** @@ -86,8 +76,8 @@ class EmailRecoveryController extends Controller { public function getRecoveryEmail() { $response = new JSONResponse(); $userId = $this->userSession->getUser()->getUID(); - $recoveryEmail = $this->config->getUserValue($userId, $this->appName, 'recovery-email'); - $unverifiedRecoveryEmail = $this->config->getUserValue($userId, $this->appName, 'unverified-recovery-email'); + $recoveryEmail = $this->config->getUserValue($userId, Application::APP_ID, 'recovery-email'); + $unverifiedRecoveryEmail = $this->config->getUserValue($userId, Application::APP_ID, 'unverified-recovery-email'); $data = ["recoveryEmail" => $recoveryEmail, "unverifiedRecoveryEmail" => $unverifiedRecoveryEmail]; $response->setData($data); return $response; -- GitLab From 81b6d538295587c4d0257916a43968ca57d09c89 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Tue, 9 Jul 2024 11:32:10 +0530 Subject: [PATCH 23/53] change in email recovery --- lib/Controller/EmailRecoveryController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Controller/EmailRecoveryController.php b/lib/Controller/EmailRecoveryController.php index 681ba97..09157f0 100644 --- a/lib/Controller/EmailRecoveryController.php +++ b/lib/Controller/EmailRecoveryController.php @@ -52,6 +52,7 @@ class EmailRecoveryController extends Controller { private IUserManager $userManager; public function __construct( + string $appName, IRequest $request, IConfig $config, ILogger $logger, @@ -60,7 +61,7 @@ class EmailRecoveryController extends Controller { RecoveryEmailService $recoveryEmailService, IUserManager $userManager, ) { - parent::__construct($request); + parent::__construct($appName, $request); $this->config = $config; $this->logger = $logger; $this->l = $l; -- GitLab From 18138d5a800cd056564c71ed13ea773c530f06de Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 14:06:30 +0530 Subject: [PATCH 24/53] added listeners --- lib/AppInfo/Application.php | 13 +++++++ lib/Listeners/BeforeUserCreatedListener.php | 42 +++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 lib/Listeners/BeforeUserCreatedListener.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 7e0dab1..99c5666 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -29,6 +29,7 @@ namespace OCA\EmailRecovery\AppInfo; use OCA\EmailRecovery\Listeners\BeforeTemplateRenderedListener; use OCA\EmailRecovery\Listeners\UserConfigChangedListener; use OCA\EmailRecovery\Listeners\UserChangedListener; +use OCA\EmailRecovery\Listeners\BeforeUserCreatedListener; use OCA\EmailRecovery\Notification\Notifier; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -38,6 +39,9 @@ use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Notification\IManager as INotificationManager; use OCP\User\Events\UserConfigChangedEvent; use OCP\User\Events\UserChangedEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\User\Events\CreateUserEvent; +use OCP\User\Events\BeforeUserCreatedEvent; class Application extends App implements IBootstrap { public const APP_ID = 'email-recovery'; @@ -57,4 +61,13 @@ class Application extends App implements IBootstrap { public function registerNotifier(INotificationManager $manager): void { $manager->registerNotifierService(Notifier::class); } + /** + * + */ + protected function registerSystemHooks(): void { + /* @var IEventDispatcher $eventDispatcher */ + $dispatcher = $this->getContainer()->get(IEventDispatcher::class); + $dispatcher->addServiceListener(CreateUserEvent::class, BeforeUserCreatedListener::class); + $dispatcher->addServiceListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); + } } diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php new file mode 100644 index 0000000..ae1d61d --- /dev/null +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -0,0 +1,42 @@ +logger = $logger; + } + + /** + * @param Event $event + */ + public function handle(Event $event): void { + $this->logger->info('=====> INSIDE BeforeUserCreatedListener'); + if ($event instanceof BeforeUserCreatedEvent || $event instanceof CreateUserEvent) { + $this->preventRegistrationsIfRecoveryEmailInvalid($event->getUid()); + } + } + + /** + * @param string $userId + */ + protected function preventRegistrationsIfRecoveryEmailInvalid(string $userId): void { + $this->logger->info('=====> INSIDE preventRegistrationsIfRecoveryEmailInvalid'); + // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); + } +} -- GitLab From 1041c68be24d3836bb4979e2f4d6fa11bcdb18c8 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 14:10:15 +0530 Subject: [PATCH 25/53] listener added --- lib/AppInfo/Application.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 99c5666..fa278a3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -54,6 +54,7 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); + $this->registerSystemHooks(); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerNotifier']); -- GitLab From 842a7e7c9d30709b579e2bfadc3c4d28ed0a4cf5 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 14:47:10 +0530 Subject: [PATCH 26/53] added BeforeUserRegisteredEvent --- lib/Listeners/BeforeUserCreatedListener.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index ae1d61d..5be43c7 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -9,6 +9,7 @@ use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; use OCP\User\Events\BeforeUserCreatedEvent; +use OCP\User\Events\BeforeUserRegisteredEvent; use OCP\User\Events\CreateUserEvent; /** @@ -26,8 +27,8 @@ class BeforeUserCreatedListener implements IEventListener { * @param Event $event */ public function handle(Event $event): void { - $this->logger->info('=====> INSIDE BeforeUserCreatedListener'); - if ($event instanceof BeforeUserCreatedEvent || $event instanceof CreateUserEvent) { + $this->logger->info('=====> INSIDE BeforeUserRegisteredEvent'); + if ($event instanceof BeforeUserCreatedEvent || $event instanceof CreateUserEvent || $event instanceof BeforeUserRegisteredEvent) { $this->preventRegistrationsIfRecoveryEmailInvalid($event->getUid()); } } -- GitLab From e5a428854de4f0249490a9bfe96d6a0820fe62de Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 15:04:48 +0530 Subject: [PATCH 27/53] eventdispatcher added --- lib/Listeners/BeforeUserCreatedListener.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 5be43c7..2448dd0 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -11,6 +11,7 @@ use OCP\ILogger; use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\BeforeUserRegisteredEvent; use OCP\User\Events\CreateUserEvent; +use OCP\EventDispatcher\IEventDispatcher; /** * Class BeforeUserCreatedListener @@ -21,6 +22,9 @@ class BeforeUserCreatedListener implements IEventListener { private $logger; public function __construct(ILogger $logger) { $this->logger = $logger; + $container = $this->getContainer(); + $dispatcher = $container->query(IEventDispatcher::class); + $dispatcher->addListener('OCP\IUser::beforeUserCreated', [$this, 'handleBeforeUserCreated']); } /** @@ -40,4 +44,14 @@ class BeforeUserCreatedListener implements IEventListener { $this->logger->info('=====> INSIDE preventRegistrationsIfRecoveryEmailInvalid'); // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } + public function handleBeforeUserCreated($event) { + $this->logger->info('=====> INSIDE handleBeforeUserCreated'); + $username = $event->getUsername(); + // Add custom logic or validation + + // Example: prevent user creation if username is 'test' + if ($username === 'test') { + throw new \Exception('Username "test" is not allowed.'); + } + } } -- GitLab From 3101381f609603da20252bb9a9e0c69e538e47e4 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 15:10:59 +0530 Subject: [PATCH 28/53] resolved conflicts --- lib/Service/RecoveryEmailService.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 28a9a20..fbb88c0 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -108,9 +108,12 @@ class RecoveryEmailService { return true; } - public function validateRecoveryEmail(string $username, string $recoveryEmail) : bool { - $user = $this->userManager->get($username); - $email = $user->getEMailAddress(); + public function validateRecoveryEmail(string $username = '', string $recoveryEmail) : bool { + $email = ''; + if ($username != '') { + $user = $this->userManager->get($username); + $email = $user->getEMailAddress(); + } if (!empty($recoveryEmail)) { if (!$this->isValidEmailFormat($recoveryEmail)) { $this->logger->info("User $username's requested recovery email does not match email format"); -- GitLab From 2c07c66bde3620e4196bab147208e4b1a2c1279b Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 15:14:07 +0530 Subject: [PATCH 29/53] removed in usercreatedlistener --- lib/Listeners/BeforeUserCreatedListener.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 2448dd0..5be43c7 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -11,7 +11,6 @@ use OCP\ILogger; use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\BeforeUserRegisteredEvent; use OCP\User\Events\CreateUserEvent; -use OCP\EventDispatcher\IEventDispatcher; /** * Class BeforeUserCreatedListener @@ -22,9 +21,6 @@ class BeforeUserCreatedListener implements IEventListener { private $logger; public function __construct(ILogger $logger) { $this->logger = $logger; - $container = $this->getContainer(); - $dispatcher = $container->query(IEventDispatcher::class); - $dispatcher->addListener('OCP\IUser::beforeUserCreated', [$this, 'handleBeforeUserCreated']); } /** @@ -44,14 +40,4 @@ class BeforeUserCreatedListener implements IEventListener { $this->logger->info('=====> INSIDE preventRegistrationsIfRecoveryEmailInvalid'); // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } - public function handleBeforeUserCreated($event) { - $this->logger->info('=====> INSIDE handleBeforeUserCreated'); - $username = $event->getUsername(); - // Add custom logic or validation - - // Example: prevent user creation if username is 'test' - if ($username === 'test') { - throw new \Exception('Username "test" is not allowed.'); - } - } } -- GitLab From eb98f021fda2adc051c8d43ea874b8e33cfafcbf Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 15:17:08 +0530 Subject: [PATCH 30/53] new exception added --- lib/AppInfo/Application.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index fa278a3..3093e32 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -48,6 +48,9 @@ class Application extends App implements IBootstrap { public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); + $container = $this->getContainer(); + $dispatcher = $container->query(IEventDispatcher::class); + $dispatcher->addListener('OCP\IUser::beforeUserCreated', [$this, 'handleBeforeUserCreated']); } public function register(IRegistrationContext $context): void { @@ -71,4 +74,13 @@ class Application extends App implements IBootstrap { $dispatcher->addServiceListener(CreateUserEvent::class, BeforeUserCreatedListener::class); $dispatcher->addServiceListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); } + public function handleBeforeUserCreated($event) { + $username = $event->getUsername(); + // Add custom logic or validation + + // Example: prevent user creation if username is 'test' + // if ($username === 'test') { + throw new \Exception('Username "test" is not allowed.'); + // } + } } -- GitLab From 40605f4340fba83fdac1ada5d6729fa99d0cc427 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 15:22:09 +0530 Subject: [PATCH 31/53] new exception added --- lib/Service/RecoveryEmailService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index fbb88c0..51bef55 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -43,7 +43,7 @@ class RecoveryEmailService { private BlackListService $blackListService; private IL10N $l; - public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, ISession $session, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService) { + public function __construct(string $appName, ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService, ISession $session, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, BlackListService $blackListService, IL10N $l) { $this->logger = $logger; $this->config = $config; $this->appName = $appName; -- GitLab From 119d85e7fa04bdd145b95f0730e4f6dbe4f38c27 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 21:16:03 +0530 Subject: [PATCH 32/53] changes --- lib/AppInfo/Application.php | 1 + lib/Listeners/BeforeUserCreatedListener.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 3093e32..81e9309 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -57,6 +57,7 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); + $context->registerEventListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); $this->registerSystemHooks(); } public function boot(IBootContext $context): void { diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 5be43c7..9c32d18 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -21,6 +21,8 @@ class BeforeUserCreatedListener implements IEventListener { private $logger; public function __construct(ILogger $logger) { $this->logger = $logger; + echo 'tst'; + die; } /** -- GitLab From bcb7dfa4e862f21f80f1f100b3d801693f4e8224 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 21:28:59 +0530 Subject: [PATCH 33/53] changes --- lib/AppInfo/Application.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 81e9309..c50343f 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -42,6 +42,7 @@ use OCP\User\Events\UserChangedEvent; use OCP\EventDispatcher\IEventDispatcher; use OCP\User\Events\CreateUserEvent; use OCP\User\Events\BeforeUserCreatedEvent; +use OCP\User\Events\BeforeUserRegisteredEvent; class Application extends App implements IBootstrap { public const APP_ID = 'email-recovery'; @@ -58,6 +59,7 @@ class Application extends App implements IBootstrap { $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); $context->registerEventListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); + $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); $this->registerSystemHooks(); } public function boot(IBootContext $context): void { @@ -74,6 +76,7 @@ class Application extends App implements IBootstrap { $dispatcher = $this->getContainer()->get(IEventDispatcher::class); $dispatcher->addServiceListener(CreateUserEvent::class, BeforeUserCreatedListener::class); $dispatcher->addServiceListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); + $dispatcher->addServiceListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); } public function handleBeforeUserCreated($event) { $username = $event->getUsername(); -- GitLab From 360b1d2c4c934baa817d66071746528958babf73 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 21:32:41 +0530 Subject: [PATCH 34/53] changes --- lib/AppInfo/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index c50343f..e046a03 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -60,7 +60,7 @@ class Application extends App implements IBootstrap { $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); $context->registerEventListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); - $this->registerSystemHooks(); + // $this->registerSystemHooks(); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerNotifier']); -- GitLab From d948c5432b02e8a3e90e1bba6a70a6078f5fb38e Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 21:36:01 +0530 Subject: [PATCH 35/53] testing new listener --- lib/AppInfo/Application.php | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index e046a03..e406a26 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -39,8 +39,6 @@ use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Notification\IManager as INotificationManager; use OCP\User\Events\UserConfigChangedEvent; use OCP\User\Events\UserChangedEvent; -use OCP\EventDispatcher\IEventDispatcher; -use OCP\User\Events\CreateUserEvent; use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\BeforeUserRegisteredEvent; @@ -49,9 +47,6 @@ class Application extends App implements IBootstrap { public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); - $container = $this->getContainer(); - $dispatcher = $container->query(IEventDispatcher::class); - $dispatcher->addListener('OCP\IUser::beforeUserCreated', [$this, 'handleBeforeUserCreated']); } public function register(IRegistrationContext $context): void { @@ -60,7 +55,6 @@ class Application extends App implements IBootstrap { $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); $context->registerEventListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); - // $this->registerSystemHooks(); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerNotifier']); @@ -68,23 +62,4 @@ class Application extends App implements IBootstrap { public function registerNotifier(INotificationManager $manager): void { $manager->registerNotifierService(Notifier::class); } - /** - * - */ - protected function registerSystemHooks(): void { - /* @var IEventDispatcher $eventDispatcher */ - $dispatcher = $this->getContainer()->get(IEventDispatcher::class); - $dispatcher->addServiceListener(CreateUserEvent::class, BeforeUserCreatedListener::class); - $dispatcher->addServiceListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); - $dispatcher->addServiceListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); - } - public function handleBeforeUserCreated($event) { - $username = $event->getUsername(); - // Add custom logic or validation - - // Example: prevent user creation if username is 'test' - // if ($username === 'test') { - throw new \Exception('Username "test" is not allowed.'); - // } - } } -- GitLab From 87e14d373ec20b4f28de223ac100ef1c48880d28 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 21:55:18 +0530 Subject: [PATCH 36/53] BeforeUserRegisteredEvent event --- lib/AppInfo/Application.php | 2 -- lib/Listeners/BeforeUserCreatedListener.php | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index e406a26..e0365a8 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -39,7 +39,6 @@ use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Notification\IManager as INotificationManager; use OCP\User\Events\UserConfigChangedEvent; use OCP\User\Events\UserChangedEvent; -use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\BeforeUserRegisteredEvent; class Application extends App implements IBootstrap { @@ -53,7 +52,6 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); - $context->registerEventListener(BeforeUserCreatedEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); } public function boot(IBootContext $context): void { diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 9c32d18..b18099f 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -8,9 +8,7 @@ use InvalidArgumentException; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; -use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\BeforeUserRegisteredEvent; -use OCP\User\Events\CreateUserEvent; /** * Class BeforeUserCreatedListener @@ -21,16 +19,13 @@ class BeforeUserCreatedListener implements IEventListener { private $logger; public function __construct(ILogger $logger) { $this->logger = $logger; - echo 'tst'; - die; } /** * @param Event $event */ public function handle(Event $event): void { - $this->logger->info('=====> INSIDE BeforeUserRegisteredEvent'); - if ($event instanceof BeforeUserCreatedEvent || $event instanceof CreateUserEvent || $event instanceof BeforeUserRegisteredEvent) { + if ($event instanceof BeforeUserRegisteredEvent) { $this->preventRegistrationsIfRecoveryEmailInvalid($event->getUid()); } } @@ -39,7 +34,8 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $userId */ protected function preventRegistrationsIfRecoveryEmailInvalid(string $userId): void { - $this->logger->info('=====> INSIDE preventRegistrationsIfRecoveryEmailInvalid'); + print_r($userId); + die; // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } } -- GitLab From d08784db19cd3bbf8b059700e594158214c28660 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 10 Jul 2024 22:28:51 +0530 Subject: [PATCH 37/53] BeforeUserRegisteredEvent event --- lib/Listeners/BeforeUserCreatedListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index b18099f..4b99da8 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -26,7 +26,7 @@ class BeforeUserCreatedListener implements IEventListener { */ public function handle(Event $event): void { if ($event instanceof BeforeUserRegisteredEvent) { - $this->preventRegistrationsIfRecoveryEmailInvalid($event->getUid()); + $this->preventRegistrationsIfRecoveryEmailInvalid($event->getRecoveryEmail()); } } -- GitLab From 531037c59fbb2bbfc9977adb9a3c5aec6f3f5181 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 10:26:16 +0530 Subject: [PATCH 38/53] added BeforeUserCreatedEvent --- lib/Listeners/BeforeUserCreatedListener.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 4b99da8..9ae638d 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -8,7 +8,7 @@ use InvalidArgumentException; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; -use OCP\User\Events\BeforeUserRegisteredEvent; +use OCP\User\Events\BeforeUserCreatedEvent; /** * Class BeforeUserCreatedListener @@ -25,7 +25,9 @@ class BeforeUserCreatedListener implements IEventListener { * @param Event $event */ public function handle(Event $event): void { - if ($event instanceof BeforeUserRegisteredEvent) { + print_r($event); + die; + if ($event instanceof BeforeUserCreatedEvent) { $this->preventRegistrationsIfRecoveryEmailInvalid($event->getRecoveryEmail()); } } -- GitLab From 7019f9961966ed7acf4a8638334039f2bb2b1668 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 10:48:59 +0530 Subject: [PATCH 39/53] added BeforeUserCreatedEvent --- lib/Listeners/BeforeUserCreatedListener.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 9ae638d..caf10ba 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -25,8 +25,6 @@ class BeforeUserCreatedListener implements IEventListener { * @param Event $event */ public function handle(Event $event): void { - print_r($event); - die; if ($event instanceof BeforeUserCreatedEvent) { $this->preventRegistrationsIfRecoveryEmailInvalid($event->getRecoveryEmail()); } @@ -36,8 +34,6 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $userId */ protected function preventRegistrationsIfRecoveryEmailInvalid(string $userId): void { - print_r($userId); - die; // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } } -- GitLab From 06e116c57f42a51c5a2d4a154ec4808da4d2366a Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 11:17:26 +0530 Subject: [PATCH 40/53] test --- lib/AppInfo/Application.php | 2 +- lib/Listeners/BeforeUserCreatedListener.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index e0365a8..747813b 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -49,10 +49,10 @@ class Application extends App implements IBootstrap { } public function register(IRegistrationContext $context): void { + $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); - $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerNotifier']); diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index caf10ba..4b99da8 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -8,7 +8,7 @@ use InvalidArgumentException; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; -use OCP\User\Events\BeforeUserCreatedEvent; +use OCP\User\Events\BeforeUserRegisteredEvent; /** * Class BeforeUserCreatedListener @@ -25,7 +25,7 @@ class BeforeUserCreatedListener implements IEventListener { * @param Event $event */ public function handle(Event $event): void { - if ($event instanceof BeforeUserCreatedEvent) { + if ($event instanceof BeforeUserRegisteredEvent) { $this->preventRegistrationsIfRecoveryEmailInvalid($event->getRecoveryEmail()); } } @@ -34,6 +34,8 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $userId */ protected function preventRegistrationsIfRecoveryEmailInvalid(string $userId): void { + print_r($userId); + die; // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } } -- GitLab From 455d32d5b11e0750841fd03ea16799e2b4efa030 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 11:28:31 +0530 Subject: [PATCH 41/53] added lang --- lib/Service/RecoveryEmailService.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 51bef55..73fb1b2 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -108,32 +108,33 @@ class RecoveryEmailService { return true; } - public function validateRecoveryEmail(string $username = '', string $recoveryEmail) : bool { + public function validateRecoveryEmail(string $username = '', string $recoveryEmail, string $language = 'en') : bool { $email = ''; if ($username != '') { $user = $this->userManager->get($username); $email = $user->getEMailAddress(); } + $l = $this->l10nFactory->get($this->appName, $language); if (!empty($recoveryEmail)) { if (!$this->isValidEmailFormat($recoveryEmail)) { $this->logger->info("User $username's requested recovery email does not match email format"); - throw new InvalidRecoveryEmailException($this->l->t('Invalid Recovery Email')); + throw new InvalidRecoveryEmailException($l->t('Invalid Recovery Email')); } if ($email != '' && strcmp($recoveryEmail, $email) === 0) { $this->logger->info("User ID $username's requested recovery email is the same as email"); - throw new SameRecoveryEmailAsEmailException($this->l->t('Error! User email address cannot be saved as recovery email address!')); + throw new SameRecoveryEmailAsEmailException($l->t('Error! User email address cannot be saved as recovery email address!')); } if ($this->isRecoveryEmailTaken($username, $recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address is already taken"); - throw new RecoveryEmailAlreadyFoundException($this->l->t('Recovery email address is already taken.')); + throw new RecoveryEmailAlreadyFoundException($l->t('Recovery email address is already taken.')); } if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address is disallowed."); - throw new MurenaDomainDisallowedException($this->l->t('You cannot set an email address with a Murena domain as recovery email address.')); + throw new MurenaDomainDisallowedException($l->t('You cannot set an email address with a Murena domain as recovery email address.')); } if ($this->blackListService->isBlacklistedEmail($recoveryEmail)) { $this->logger->info("User ID $username's requested recovery email address domain is blacklisted. Please provide another recovery address."); - throw new BlacklistedEmailException($this->l->t('The domain of this email address is blacklisted. Please provide another recovery address.')); + throw new BlacklistedEmailException($l->t('The domain of this email address is blacklisted. Please provide another recovery address.')); } } return true; -- GitLab From 7566718b064137d3dca65d5d3cfbc9845bbf5f6d Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 11:30:16 +0530 Subject: [PATCH 42/53] changes --- lib/AppInfo/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 747813b..5ee01dd 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -49,7 +49,7 @@ class Application extends App implements IBootstrap { } public function register(IRegistrationContext $context): void { - $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); + // $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); -- GitLab From a29712846914617107b9ebee107f794b6c9e0fea Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 13:29:44 +0530 Subject: [PATCH 43/53] reverted BeforeUserRegisteredEvent --- lib/AppInfo/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 5ee01dd..747813b 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -49,7 +49,7 @@ class Application extends App implements IBootstrap { } public function register(IRegistrationContext $context): void { - // $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); + $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); -- GitLab From 2081f8a70e55ef13325dd0f500f9275cee5b54bc Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 13:58:52 +0530 Subject: [PATCH 44/53] called listner --- lib/Listeners/BeforeUserCreatedListener.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 4b99da8..f063402 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -8,7 +8,7 @@ use InvalidArgumentException; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; -use OCP\User\Events\BeforeUserRegisteredEvent; +use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; /** * Class BeforeUserCreatedListener @@ -31,10 +31,10 @@ class BeforeUserCreatedListener implements IEventListener { } /** - * @param string $userId + * @param string $recoveryEmail */ - protected function preventRegistrationsIfRecoveryEmailInvalid(string $userId): void { - print_r($userId); + protected function preventRegistrationsIfRecoveryEmailInvalid(string $recoveryEmail): void { + print_r($recoveryEmail); die; // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); } -- GitLab From 6b9bfb3697fcd2642a0583dc487dc1dbfab88ee8 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 14:13:30 +0530 Subject: [PATCH 45/53] no new register die --- lib/AppInfo/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 747813b..4a171c3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -39,7 +39,7 @@ use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Notification\IManager as INotificationManager; use OCP\User\Events\UserConfigChangedEvent; use OCP\User\Events\UserChangedEvent; -use OCP\User\Events\BeforeUserRegisteredEvent; +use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; class Application extends App implements IBootstrap { public const APP_ID = 'email-recovery'; -- GitLab From 850cf5dee3119f2fdcac1d97200f1e9a34707037 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 15:03:31 +0530 Subject: [PATCH 46/53] BeforeUserCreatedListner added --- lib/Listeners/BeforeUserCreatedListener.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index f063402..00d8455 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -4,11 +4,12 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Listeners; -use InvalidArgumentException; +use Exception; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; +use OCA\EmailRecovery\Service\RecoveryEmailService; /** * Class BeforeUserCreatedListener @@ -17,8 +18,10 @@ use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; */ class BeforeUserCreatedListener implements IEventListener { private $logger; - public function __construct(ILogger $logger) { + private RecoveryEmailService $recoveryEmailService; + public function __construct(ILogger $logger, RecoveryEmailService $recoveryEmailService) { $this->logger = $logger; + $this->recoveryEmailService = $recoveryEmailService; } /** @@ -34,8 +37,10 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $recoveryEmail */ protected function preventRegistrationsIfRecoveryEmailInvalid(string $recoveryEmail): void { - print_r($recoveryEmail); - die; - // throw new InvalidArgumentException("The username {$userId} is queued for deletion"); + try { + $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail); + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } } } -- GitLab From fb8a1d8ce32ab127462f39dff03c2ac3b8380198 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 15:21:13 +0530 Subject: [PATCH 47/53] throwin exception --- lib/Listeners/BeforeUserCreatedListener.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 00d8455..c642ed1 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Listeners; -use Exception; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ILogger; @@ -37,10 +36,6 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $recoveryEmail */ protected function preventRegistrationsIfRecoveryEmailInvalid(string $recoveryEmail): void { - try { - $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail); - } catch (Exception $e) { - throw new Exception($e->getMessage()); - } + $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail); } } -- GitLab From 91b8965d26d4d23d1a39aa9b2d8a838227bc4944 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 15:32:24 +0530 Subject: [PATCH 48/53] throwin exception --- lib/Listeners/BeforeUserCreatedListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index c642ed1..35e4bea 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -28,14 +28,14 @@ class BeforeUserCreatedListener implements IEventListener { */ public function handle(Event $event): void { if ($event instanceof BeforeUserRegisteredEvent) { - $this->preventRegistrationsIfRecoveryEmailInvalid($event->getRecoveryEmail()); + $this->preventRegistrationIfRecoveryEmailInvalid($event->getRecoveryEmail()); } } /** * @param string $recoveryEmail */ - protected function preventRegistrationsIfRecoveryEmailInvalid(string $recoveryEmail): void { + protected function preventRegistrationIfRecoveryEmailInvalid(string $recoveryEmail): void { $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail); } } -- GitLab From 30155b8e8a27c275df46fa44a126e1a4912f0420 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 18:17:52 +0530 Subject: [PATCH 49/53] Added language --- lib/Listeners/BeforeUserCreatedListener.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 35e4bea..7f4bb0d 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -9,6 +9,7 @@ use OCP\EventDispatcher\IEventListener; use OCP\ILogger; use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; use OCA\EmailRecovery\Service\RecoveryEmailService; +use OCA\EcloudAccounts\Exception\RecoveryEmailValidationException; /** * Class BeforeUserCreatedListener @@ -28,14 +29,19 @@ class BeforeUserCreatedListener implements IEventListener { */ public function handle(Event $event): void { if ($event instanceof BeforeUserRegisteredEvent) { - $this->preventRegistrationIfRecoveryEmailInvalid($event->getRecoveryEmail()); + $this->preventRegistrationIfRecoveryEmailInvalid($event->getRecoveryEmail(), $event->getLanguage()); } } /** * @param string $recoveryEmail + * @param string $language */ - protected function preventRegistrationIfRecoveryEmailInvalid(string $recoveryEmail): void { - $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail); + protected function preventRegistrationIfRecoveryEmailInvalid(string $recoveryEmail, string $language): void { + try { + $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail, $language); + } catch (\Throwable $th) { + new RecoveryEmailValidationException($th->getMessage()); + } } } -- GitLab From d696c4e9fbf077f07894545331106182e3a3bf3e Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 18:34:23 +0530 Subject: [PATCH 50/53] changes in throwable --- lib/Listeners/BeforeUserCreatedListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 7f4bb0d..679a9de 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -41,7 +41,7 @@ class BeforeUserCreatedListener implements IEventListener { try { $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail, $language); } catch (\Throwable $th) { - new RecoveryEmailValidationException($th->getMessage()); + throw new RecoveryEmailValidationException($th->getMessage()); } } } -- GitLab From c2460786e411f25f96c9d98ee0b2390a48061438 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Thu, 11 Jul 2024 18:40:20 +0530 Subject: [PATCH 51/53] removed unncessary logger call --- lib/Listeners/BeforeUserCreatedListener.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserCreatedListener.php index 679a9de..0241853 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserCreatedListener.php @@ -6,7 +6,6 @@ namespace OCA\EmailRecovery\Listeners; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\ILogger; use OCA\EcloudAccounts\Event\BeforeUserRegisteredEvent; use OCA\EmailRecovery\Service\RecoveryEmailService; use OCA\EcloudAccounts\Exception\RecoveryEmailValidationException; @@ -17,10 +16,8 @@ use OCA\EcloudAccounts\Exception\RecoveryEmailValidationException; * @package OCA\EmailRecovery\EventListener\User */ class BeforeUserCreatedListener implements IEventListener { - private $logger; private RecoveryEmailService $recoveryEmailService; - public function __construct(ILogger $logger, RecoveryEmailService $recoveryEmailService) { - $this->logger = $logger; + public function __construct(RecoveryEmailService $recoveryEmailService) { $this->recoveryEmailService = $recoveryEmailService; } -- GitLab From 6caf9cdafb57297d1ca75a3d0e07a14dae7f2f05 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Fri, 12 Jul 2024 13:43:32 +0530 Subject: [PATCH 52/53] Used Ldap service from ecloud-account --- lib/AppInfo/Application.php | 4 +- ...r.php => BeforeUserRegisteredListener.php} | 8 +- lib/Listeners/UserChangedListener.php | 10 +- lib/Service/BlackListService.php | 23 +--- lib/Service/LDAPConnectionService.php | 107 ------------------ lib/Service/RecoveryEmailService.php | 1 + 6 files changed, 14 insertions(+), 139 deletions(-) rename lib/Listeners/{BeforeUserCreatedListener.php => BeforeUserRegisteredListener.php} (75%) delete mode 100644 lib/Service/LDAPConnectionService.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 4a171c3..277036d 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -29,7 +29,7 @@ namespace OCA\EmailRecovery\AppInfo; use OCA\EmailRecovery\Listeners\BeforeTemplateRenderedListener; use OCA\EmailRecovery\Listeners\UserConfigChangedListener; use OCA\EmailRecovery\Listeners\UserChangedListener; -use OCA\EmailRecovery\Listeners\BeforeUserCreatedListener; +use OCA\EmailRecovery\Listeners\BeforeUserRegisteredListener; use OCA\EmailRecovery\Notification\Notifier; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -49,7 +49,7 @@ class Application extends App implements IBootstrap { } public function register(IRegistrationContext $context): void { - $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserCreatedListener::class); + $context->registerEventListener(BeforeUserRegisteredEvent::class, BeforeUserRegisteredListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(UserConfigChangedEvent::class, UserConfigChangedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); diff --git a/lib/Listeners/BeforeUserCreatedListener.php b/lib/Listeners/BeforeUserRegisteredListener.php similarity index 75% rename from lib/Listeners/BeforeUserCreatedListener.php rename to lib/Listeners/BeforeUserRegisteredListener.php index 0241853..1f28620 100644 --- a/lib/Listeners/BeforeUserCreatedListener.php +++ b/lib/Listeners/BeforeUserRegisteredListener.php @@ -11,11 +11,11 @@ use OCA\EmailRecovery\Service\RecoveryEmailService; use OCA\EcloudAccounts\Exception\RecoveryEmailValidationException; /** - * Class BeforeUserCreatedListener + * Class BeforeUserRegisteredListener * * @package OCA\EmailRecovery\EventListener\User */ -class BeforeUserCreatedListener implements IEventListener { +class BeforeUserRegisteredListener implements IEventListener { private RecoveryEmailService $recoveryEmailService; public function __construct(RecoveryEmailService $recoveryEmailService) { $this->recoveryEmailService = $recoveryEmailService; @@ -26,7 +26,7 @@ class BeforeUserCreatedListener implements IEventListener { */ public function handle(Event $event): void { if ($event instanceof BeforeUserRegisteredEvent) { - $this->preventRegistrationIfRecoveryEmailInvalid($event->getRecoveryEmail(), $event->getLanguage()); + $this->validateRecoveryEmail($event->getRecoveryEmail(), $event->getLanguage()); } } @@ -34,7 +34,7 @@ class BeforeUserCreatedListener implements IEventListener { * @param string $recoveryEmail * @param string $language */ - protected function preventRegistrationIfRecoveryEmailInvalid(string $recoveryEmail, string $language): void { + protected function validateRecoveryEmail(string $recoveryEmail, string $language): void { try { $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail, $language); } catch (\Throwable $th) { diff --git a/lib/Listeners/UserChangedListener.php b/lib/Listeners/UserChangedListener.php index d702f2c..afc0558 100644 --- a/lib/Listeners/UserChangedListener.php +++ b/lib/Listeners/UserChangedListener.php @@ -4,17 +4,17 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Listeners; -use OCA\EmailRecovery\Service\BlackListService; +use OCA\EcloudAccounts\Service\LDAPConnectionService; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\User\Events\UserChangedEvent; class UserChangedListener implements IEventListener { private const RECOVERY_EMAIL_FEATURE = 'recovery-email'; - private $blackListService; + private $LDAPConnectionService; - public function __construct(BlackListService $blackListService) { - $this->blackListService = $blackListService; + public function __construct(LDAPConnectionService $LDAPConnectionService) { + $this->LDAPConnectionService = $LDAPConnectionService; } public function handle(Event $event): void { @@ -32,7 +32,7 @@ class UserChangedListener implements IEventListener { 'recoveryMailAddress' => $recoveryEmail ]; - $this->blackListService->updateAttributesInLDAP($username, $recoveryEmailAttribute); + $this->LDAPConnectionService->updateAttributesInLDAP($username, $recoveryEmailAttribute); } } } diff --git a/lib/Service/BlackListService.php b/lib/Service/BlackListService.php index 93a3c5f..891cf62 100644 --- a/lib/Service/BlackListService.php +++ b/lib/Service/BlackListService.php @@ -4,12 +4,12 @@ declare(strict_types=1); namespace OCA\EmailRecovery\Service; -use Exception; use OCP\ILogger; use OCP\L10N\IFactory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; +use OCA\EcloudAccounts\Service\LDAPConnectionService; class BlackListService { private ILogger $logger; @@ -31,7 +31,7 @@ class BlackListService { public function mapActiveAttributesInLDAP(string $username, bool $isEnabled): void { $userActiveAttributes = $this->getActiveAttributes($isEnabled); - $this->updateAttributesInLDAP($username, $userActiveAttributes); + $this->LDAPConnectionService->updateAttributesInLDAP($username, $userActiveAttributes); } private function getActiveAttributes(bool $isEnabled): array { @@ -40,25 +40,6 @@ class BlackListService { 'mailActive' => $isEnabled ? 'TRUE' : 'FALSE', ]; } - - public function updateAttributesInLDAP(string $username, array $attributes): void { - if (!$this->LDAPConnectionService->isLDAPEnabled()) { - return; - } - - $conn = $this->LDAPConnectionService->getLDAPConnection(); - $userDn = $this->LDAPConnectionService->username2dn($username); - - if ($userDn === false) { - throw new Exception('Could not find DN for username: ' . $username); - } - - if (!ldap_modify($conn, $userDn, $attributes)) { - throw new Exception('Could not modify user ' . $username . ' entry at LDAP server. Attributes: ' . print_r($attributes, true)); - } - - $this->LDAPConnectionService->closeLDAPConnection($conn); - } /** * Check if an email domain is blacklisted against a JSON list of disposable email domains. * diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php deleted file mode 100644 index 58c3be6..0000000 --- a/lib/Service/LDAPConnectionService.php +++ /dev/null @@ -1,107 +0,0 @@ -userManager = $userManager; - $this->getConfigurationFromBackend(); - $ldapConfigPrefixes = $ldapBackendHelper->getServerConfigurationPrefixes(true); - $prefix = array_shift($ldapConfigPrefixes); - $this->ldapConfig = new Configuration($prefix); - $this->config = $config; - } - - - private function getConfigurationFromBackend() { - // We don't actually need user id to get access from backend - $uid = ''; - $backends = $this->userManager->getBackends(); - foreach ($backends as $backend) { - if ($backend->getBackendName() === 'LDAP') { - $this->access = $backend->getLDAPAccess($uid); - $connection = $this->access->getConnection(); - $configuration = $connection->getConfiguration(); - - if ($configuration['ldap_configuration_active']) { - $this->ldapEnabled = true; - $this->configuration = $configuration; - break; - } - } - } - } - - public function isUserOnLDAPBackend($user) { - $backend = $user->getBackend(); - return $backend->getBackendName() === 'LDAP'; - } - - public function isLDAPEnabled(): bool { - return $this->ldapEnabled; - } - - public function username2dn(string $username) { - return $this->access->username2dn($username); - } - public function getLDAPConnection() { - if (!$this->ldapEnabled) { - throw new Exception('LDAP backend is not enabled'); - } - - $adminDn = $this->configuration['ldap_dn']; - $adminPassword = $this->configuration['ldap_agent_password']; - $host = $this->configuration['ldap_host']; - $port = intval($this->configuration['ldap_port']); - - $conn = ldap_connect($host, $port); - ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3); - ldap_bind($conn, $adminDn, $adminPassword); - - if (!$conn) { - throw new Exception('Could not connect to LDAP server!'); - } - return $conn; - } - - public function closeLDAPConnection($conn): void { - ldap_close($conn); - } - - public function getLDAPAccess() { - if (!$this->access) { - throw new Exception('Access not defined!'); - } - return $this->access; - } - - public function getLDAPBaseUsers(): array { - $bases = $this->ldapConfig->ldapBaseUsers; - if (empty($bases)) { - $bases = $this->ldapConfig->ldapBase; - } - return $bases; - } - public function getDisplayNameAttribute(): string { - return $this->ldapConfig->ldapUserDisplayName; - } - public function getLdapQuota() { - return $this->config->getSystemValue('default_quota', '1024'); - } -} diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php index 73fb1b2..d6892c8 100644 --- a/lib/Service/RecoveryEmailService.php +++ b/lib/Service/RecoveryEmailService.php @@ -24,6 +24,7 @@ use OCP\Mail\IMailer; use OCP\Security\VerificationToken\IVerificationToken; use OCP\Util; use OCP\IL10N; +use OCA\EcloudAccounts\Service\LDAPConnectionService; class RecoveryEmailService { private ILogger $logger; -- GitLab From 3b21133b76bfa0057ae9e9b61437567f04f72059 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Fri, 12 Jul 2024 23:26:21 +0530 Subject: [PATCH 53/53] used Exception instead --- lib/Listeners/BeforeUserRegisteredListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Listeners/BeforeUserRegisteredListener.php b/lib/Listeners/BeforeUserRegisteredListener.php index 1f28620..5e598bf 100644 --- a/lib/Listeners/BeforeUserRegisteredListener.php +++ b/lib/Listeners/BeforeUserRegisteredListener.php @@ -37,8 +37,8 @@ class BeforeUserRegisteredListener implements IEventListener { protected function validateRecoveryEmail(string $recoveryEmail, string $language): void { try { $this->recoveryEmailService->validateRecoveryEmail('', $recoveryEmail, $language); - } catch (\Throwable $th) { - throw new RecoveryEmailValidationException($th->getMessage()); + } catch (\Exception $e) { + throw new RecoveryEmailValidationException($e->getMessage()); } } } -- GitLab