[new IsEmailRule()]], ); $this->conn = $conn; $this->user_manager = $user_manager; $this->mail_manager = $mail_manager; } /** * Sends a password reset email. * * @return null * @throws ValidationException if another password reset email was sent too recently */ function handle(): mixed { Database::transaction($this->conn, function () { $user_data = $this->user_manager->get_user_by_email($_POST["email"]); $minutes_left = Util::minutes_until_interval_elapsed( $user_data["password_reset_token_timestamp"], UserManager::MINUTES_BETWEEN_PASSWORD_RESETS ); if ($minutes_left > 0) { throw new ValidationException( "A password reset email was sent recently. " . "Please wait $minutes_left more minute(s) before requesting a new email." ); } $token = $this->user_manager->register_password_reset($_POST["email"]); $this->mail_manager->queue_email(new SendPasswordResetEmail($_POST["email"], $token)); }); return null; } } /** * An email to help a user reset their password. */ class SendPasswordResetEmail extends Email { /** * A string identifying the type of email. */ public const TYPE = "reset-password"; /** * @var string the token to reset the password with */ public string $token; /** * Constructs a new `ResetPasswordEmail`. * * @param string $recipient the intended recipient of the email * @param string $token the token to reset the password with */ public function __construct(string $recipient, string $token) { parent::__construct($this::TYPE, $recipient); $this->token = $token; } public function get_subject(): string { return "Reset your password"; } public function get_body(): string { $base_path = Config::get()["server"]["base_path"]; $verify_path = "$base_path?action=reset-password&email=" . rawurlencode($this->recipient) . "&token=$this->token"; return "You requested a password reset link for your Death Notifier account. " . "You can choose a new password by clicking the link below. " . "This link expires after " . UserManager::MINUTES_VALID_PASSWORD_RESET . " minutes." . "\n" . "Reset password: $verify_path" . "\n\n" . "If you did not request a new password, you can safely ignore this message." . "\n\n" . $base_path; } }