From b5a8f93b87720d5d5f033a4b3a131ce0fb621dbc Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 31 Oct 2024 08:29:56 +0100 Subject: [PATCH] Merge commit from fork --- includes/services/UserManager.php | 94 +++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/includes/services/UserManager.php b/includes/services/UserManager.php index 5e70b33f2..652e82db3 100644 --- a/includes/services/UserManager.php +++ b/includes/services/UserManager.php @@ -23,6 +23,10 @@ use YesWiki\Security\Controller\SecurityController; use YesWiki\Wiki; +if (!function_exists('send_mail')) { + require_once 'includes/email.inc.php'; +} + class UserManager implements UserProviderInterface, PasswordUpgraderInterface { protected $wiki; @@ -33,6 +37,7 @@ class UserManager implements UserProviderInterface, PasswordUpgraderInterface private $getOneByNameCacheResults; + public const KEY_VOCABULARY = 'http://outils-reseaux.org/_vocabulary/key'; public function __construct( Wiki $wiki, @@ -47,6 +52,7 @@ public function __construct( $this->securityController = $securityController; $this->params = $params; $this->getOneByNameCacheResults = []; + $this->userlink = ''; } private function arrayToUser(?array $userAsArray = null, bool $fillEmpty = false): ?User @@ -176,6 +182,94 @@ public function create($wikiNameOrUser, string $email = "", string $plainPasswor ); } + /* + * Password recovery process (AKA reset password) + * 1. A key is generated using name, email alongside with other stuff. + * 2. The triple (user's name, specific key "vocabulary",key) is stored in triples table. + * 3. In order to update h·er·is password, the user must provided that key. + * 4. The new password is accepted only if the key matches with the value in triples table. + * 5. The corresponding row is removed from triples table. + */ + + protected function generateUserLink($user) + { + // Generate the password recovery key + $passwordHasher = $this->passwordHasherFactory->getPasswordHasher($user); + $plainKey = $user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s'); + $hashedKey = $passwordHasher->hash($plainKey); + $tripleStore = $this->wiki->services->get(TripleStore::class); + // Erase the previous triples in the trible table + $tripleStore->delete($user['name'], self::KEY_VOCABULARY, null, '', ''); + // Store the (name, vocabulary, key) triple in triples table + $tripleStore->create($user['name'], self::KEY_VOCABULARY, $hashedKey, '', ''); + + // Generate the recovery email + $this->userlink = $this->wiki->Href('', 'MotDePassePerdu', [ + 'a' => 'recover', + 'email' => $hashedKey, + 'u' => base64_encode($user['name']), + ], false); + } + + /** + * Part of the Password recovery process: Handles the password recovery email process. + * + * Generates the password recovery key + * Stores the (name, vocabulary, key) triple in triples table + * Generates the recovery email + * Sends it + * + * @return bool True if OK or false if any problems + */ + public function sendPasswordRecoveryEmail(User $user, string $title): bool + { + $this->generateUserLink($user); + $pieces = parse_url($this->params->get('base_url')); + $domain = isset($pieces['host']) ? $pieces['host'] : ''; + + $message = _t('LOGIN_DEAR') . ' ' . $user['name'] . ",\n"; + $message .= _t('LOGIN_CLICK_FOLLOWING_LINK') . ' :' . "\n"; + $message .= '-----------------------' . "\n"; + $message .= $this->userlink . "\n"; + $message .= '-----------------------' . "\n"; + $message .= _t('LOGIN_THE_TEAM') . ' ' . $domain . "\n"; + + $subject = $title . ' ' . $domain; + // Send the email + return send_mail($this->params->get('BAZ_ADRESSE_MAIL_ADMIN'), $this->params->get('BAZ_ADRESSE_MAIL_ADMIN'), $user['email'], $subject, $message); + } + + /** + * Assessor for userlink field. + */ + public function getUserLink(): string + { + return $this->userlink; + } + + /** + * Assessor for userlink field. + */ + public function getLastUserLink(User $user): string + { + $passwordHasher = $this->passwordHasherFactory->getPasswordHasher($user); + $plainKey = $user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s'); + $hashedKey = $passwordHasher->hash($plainKey); + $tripleStore = $this->wiki->services->get(TripleStore::class); + $key = $tripleStore->getOne($user['name'], self::KEY_VOCABULARY, '', ''); + if ($key != null) { + $this->userlink = $this->wiki->Href('', 'MotDePassePerdu', [ + 'a' => 'recover', + 'email' => $key, + 'u' => base64_encode($user['name']), + ], false); + } else { + $this->generateUserLink($user); + } + + return $this->userlink; + } + /** * update user params * for e-mail check is existing e-mail