diff --git a/src/Auth.php b/src/Auth.php index 8aaa6f4..b551082 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -624,6 +624,55 @@ class Auth { $stmt->execute(); } + /** + * Initiates a password reset request for the user with the specified email address + * + * The callback function must have the following signature: + * + * `function ($selector, $token)` + * + * Both pieces of information must be sent to the user, usually embedded in a link + * + * When the user wants to proceed to the second step of the password reset, both pieces will be required again + * + * @param string $email the email address of the user who wants to request the password reset + * @param callable $callback the function that sends the password reset information to the user + * @param int|null $requestExpiresAfter (optional) the interval in seconds after which the request should expire + * @param int|null $maxOpenRequests (optional) the maximum number of unexpired and unused requests per user + * @throws InvalidEmailException if the email address was invalid or could not be found + * @throws TooManyRequestsException if the number of allowed attempts/requests has been exceeded + * @throws AuthError if an internal problem occurred (do *not* catch) + */ + public function forgotPassword($email, callable $callback, $requestExpiresAfter = null, $maxOpenRequests = null) { + $email = self::validateEmailAddress($email); + + if ($requestExpiresAfter === null) { + // use six hours as the default + $requestExpiresAfter = 60 * 60 * 6; + } + else { + $requestExpiresAfter = (int) $requestExpiresAfter; + } + + if ($maxOpenRequests === null) { + // use two requests per user as the default + $maxOpenRequests = 2; + } + else { + $maxOpenRequests = (int) $maxOpenRequests; + } + + $userId = $this->getUserIdByEmailAddress($email); + $openRequests = (int) $this->getOpenPasswordResetRequests($userId); + + if ($openRequests < $maxOpenRequests) { + $this->createPasswordResetRequest($userId, $requestExpiresAfter, $callback); + } + else { + self::onTooManyRequests($requestExpiresAfter); + } + } + /** * Returns the user ID for the account with the specified email address (if any) * diff --git a/tests/index.php b/tests/index.php index 27583cd..6283c53 100644 --- a/tests/index.php +++ b/tests/index.php @@ -109,6 +109,31 @@ function processRequestData(\Delight\Auth\Auth $auth) { return 'too many requests'; } } + else if ($_POST['action'] === 'forgotPassword') { + try { + $auth->forgotPassword($_POST['email'], function ($selector, $token) { + echo '
';
+						echo 'Password reset';
+						echo "\n";
+						echo '  >  Selector';
+						echo "\t\t\t\t";
+						echo htmlspecialchars($selector);
+						echo "\n";
+						echo '  >  Token';
+						echo "\t\t\t\t";
+						echo htmlspecialchars($token);
+						echo '
'; + }); + + return 'ok'; + } + catch (\Delight\Auth\InvalidEmailException $e) { + return 'invalid email address'; + } + catch (\Delight\Auth\TooManyRequestsException $e) { + return 'too many requests'; + } + } else if ($_POST['action'] === 'changePassword') { try { $auth->changePassword($_POST['oldPassword'], $_POST['newPassword']); @@ -229,4 +254,10 @@ function showGuestUserForm() { echo ' '; echo ''; echo ''; + + echo '
'; + echo ''; + echo ' '; + echo ''; + echo '
'; }