diff options
Diffstat (limited to 'src/application/actions/pwreset')
| -rw-r--r-- | src/application/actions/pwreset/_common.php | 6 | ||||
| -rw-r--r-- | src/application/actions/pwreset/get.php | 29 | ||||
| -rw-r--r-- | src/application/actions/pwreset/post.php | 107 | 
3 files changed, 142 insertions, 0 deletions
| diff --git a/src/application/actions/pwreset/_common.php b/src/application/actions/pwreset/_common.php new file mode 100644 index 0000000..4dc0cf0 --- /dev/null +++ b/src/application/actions/pwreset/_common.php @@ -0,0 +1,6 @@ +<?php + +if ($currentUser) { +    header("Location: ."); +    exit; +} diff --git a/src/application/actions/pwreset/get.php b/src/application/actions/pwreset/get.php new file mode 100644 index 0000000..c66b28d --- /dev/null +++ b/src/application/actions/pwreset/get.php @@ -0,0 +1,29 @@ +<?php + +$token = $_GET["token"] ?? null; +$signature = $_GET["sig"] ?? null; + +if ($token !== null && $signature !== null) { +    $resetUser = decodePasswordResetLink($db, $token, $signature); +    if ($resetUser === null) { +        http_response_code(400); +        msg_error(__("The password reset link is either invalid or it expired"), true); +        exit; +    } + +    _view("template_start", [ "_title" => __("Reset password") ]); +    _view("template_navigation_start"); +    _view("template_navigation_end"); +    _view("form_new_password", [ +        "token" => $token, +        "signature" => $signature, +    ]); +    _view("template_end", [...getThemeAndLangInfo()]); +} else { +    _view("template_start", [ "_title" => __("Reset password") ]); +    _view("template_navigation_start"); +    _view("template_navigation", ["user" => null]); +    _view("template_navigation_end"); +    _view("form_password_reset"); +    _view("template_end", [...getThemeAndLangInfo()]); +} diff --git a/src/application/actions/pwreset/post.php b/src/application/actions/pwreset/post.php new file mode 100644 index 0000000..772b09c --- /dev/null +++ b/src/application/actions/pwreset/post.php @@ -0,0 +1,107 @@ +<?php + +use mystic\forum\orm\User; +use mystic\forum\utils\RequestUtils; +use Symfony\Component\Mailer\Exception\TransportException; +use Symfony\Component\Mailer\Transport; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; + +$token = $_GET["token"] ?? null; +$signature = $_GET["sig"] ?? null; + +if ($token !== null && $signature !== null) { +    RequestUtils::setFormErrorDestination("?_action=pwreset&token=" . urlencode($token) . "&sig=" . urlencode($signature)); +    $formId = "pwnew"; +    $newPassword = RequestUtils::getRequiredField("new_password", $formId); +    $retypePassword = RequestUtils::getRequiredField("retype_password", $formId); +    $resetUser = decodePasswordResetLink($db, $token, $signature); + +    if ($resetUser === null) { +        http_response_code(400); +        msg_error(__("The password reset link is either invalid or it expired"), true); +        exit; +    } + +    if ($newPassword !== $retypePassword) { +        RequestUtils::triggerFormError(__("New passwords don't match"), $formId); +    } + +    if (strlen($newPassword) < 8) { +        RequestUtils::triggerFormError(__("Password too short! Your password must consist of 8 or more characters"), $formId); +    } + +    $resetUser->passwordHash = password_hash($newPassword, PASSWORD_DEFAULT); +    $resetUser->passwordResetToken = null; +    $resetUser->passwordResetTokenCreated = null; +     +    if (!$db->update($resetUser)) { +        RequestUtils::triggerFormError(__("Failed to update password"), $formId); +    } + +    Transport::fromDsn(env("MAILER_DSN"))->send( +        (new Email()) +            ->from(env("MAILER_FROM")) +            ->to(new Address($resetUser->email, $resetUser->displayName)) +            ->text(__( +                "Hello, %user_display_name%!\n" . +                "\n" . +                "We are sending this email to let you know your passwort has been reset successfully!\n" . +                "\n" . +                "Kind regards,\n" . +                "%forum_copyright%", +                params: [ +                    "forum_title" => (env("MYSTIC_FORUM_TITLE") ?? "Forum"), +                    "user_display_name" => $resetUser->displayName, +                    "forum_copyright" => (env("MYSTIC_FORUM_COPYRIGHT") ?? env("MYSTIC_FORUM_TITLE") ?? "Forum") +                ] +            )) +            ->subject(__("Password reset successfully!")) +    ); + +    msg_info(__("Password reset successfully!"), true); +} else { +    $formId = "pwreset"; +    $email = RequestUtils::getRequiredField("email", $formId); + +    $user = new User(); +    $user->email = $email; + +    if ($db->fetchWhere($user, "email")) { +        try { +            Transport::fromDsn(env("MAILER_DSN"))->send( +                (new Email()) +                    ->from(env("MAILER_FROM")) +                    ->to(new Address($user->email, $user->displayName)) +                    ->text(__( +                        "Hello, %user_display_name%!\n" . +                        "\n" . +                        "A password reset has been requested successfully! Please click the link below to set a new password:\n" . +                        "%reset_link%\n" . +                        "\n" . +                        "If this wasn't you, you can safely ignore this email. The link will only be valid for one hour.\n" . +                        "\n" . +                        "Kind regards,\n" . +                        "%forum_copyright%", +                        params: [ +                            "forum_title" => (env("MYSTIC_FORUM_TITLE") ?? "Forum"), +                            "user_display_name" => $user->displayName, +                            "reset_link" => generatePasswordResetLink($db, $user), +                            "forum_copyright" => (env("MYSTIC_FORUM_COPYRIGHT") ?? env("MYSTIC_FORUM_TITLE") ?? "Forum") +                        ] +                    )) +                    ->subject(__("Forgot your password? No problem!")) +        ); +        } catch (TransportException $_) { +            // fail silently +        } +    } else { +        // don't make the delay difference too obvious +        usleep(random_int(900, 4500) * 1000); + +        // ideally, at some point we would just want to queue up the email +        // and send it asynchronously, but this'll have to do for now +    } + +    msg_info(__("If an account exists with the given email address, we will have sent a password reset link to that email address."), true); +} |