2022-12-01 18:24:08 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace com\fwdekker\deathnotifier\user;
|
|
|
|
|
|
|
|
use com\fwdekker\deathnotifier\Action;
|
2022-12-03 14:59:53 +01:00
|
|
|
use com\fwdekker\deathnotifier\Config;
|
|
|
|
use com\fwdekker\deathnotifier\mailer\Email;
|
2022-12-04 23:56:49 +01:00
|
|
|
use com\fwdekker\deathnotifier\mailer\EmailQueue;
|
2022-12-08 18:37:26 +01:00
|
|
|
use com\fwdekker\deathnotifier\validation\HasStringLengthRule;
|
|
|
|
use com\fwdekker\deathnotifier\validation\InvalidTypeException;
|
|
|
|
use com\fwdekker\deathnotifier\validation\InvalidValueException;
|
|
|
|
use com\fwdekker\deathnotifier\validation\IsEmailRule;
|
|
|
|
use com\fwdekker\deathnotifier\validation\IsValidCsrfTokenRule;
|
|
|
|
use com\fwdekker\deathnotifier\validation\RuleSet;
|
|
|
|
use com\fwdekker\deathnotifier\validation\LoginValidator;
|
2022-12-01 18:24:08 +01:00
|
|
|
|
|
|
|
|
2022-12-03 14:59:53 +01:00
|
|
|
/**
|
|
|
|
* Registers a new user.
|
2022-12-04 23:56:49 +01:00
|
|
|
*
|
|
|
|
* @see RegisterEmail
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
2022-12-01 18:24:08 +01:00
|
|
|
class RegisterAction extends Action
|
|
|
|
{
|
2022-12-03 14:59:53 +01:00
|
|
|
/**
|
2022-12-04 23:56:49 +01:00
|
|
|
* @var UserList the list to register the user in
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
2022-12-04 23:56:49 +01:00
|
|
|
private readonly UserList $user_list;
|
2022-12-03 14:59:53 +01:00
|
|
|
/**
|
2022-12-04 23:56:49 +01:00
|
|
|
* @var EmailQueue the queue to add a verification email to
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
2022-12-04 23:56:49 +01:00
|
|
|
private readonly EmailQueue $email_queue;
|
2022-12-01 18:24:08 +01:00
|
|
|
|
|
|
|
|
2022-12-03 14:59:53 +01:00
|
|
|
/**
|
|
|
|
* Constructs a new `RegisterAction`.
|
|
|
|
*
|
2022-12-04 23:56:49 +01:00
|
|
|
* @param UserList $user_list the list to register the user in
|
|
|
|
* @param EmailQueue $email_queue the queue to add a verification email to
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
2022-12-04 23:56:49 +01:00
|
|
|
public function __construct(UserList $user_list, EmailQueue $email_queue)
|
2022-12-01 18:24:08 +01:00
|
|
|
{
|
2022-12-04 23:56:49 +01:00
|
|
|
$this->user_list = $user_list;
|
|
|
|
$this->email_queue = $email_queue;
|
2022-12-01 18:24:08 +01:00
|
|
|
}
|
|
|
|
|
2022-12-03 14:59:53 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a new user.
|
|
|
|
*
|
2022-12-04 23:56:49 +01:00
|
|
|
* Requires that the user is logged out and that a valid CSRF token is present.
|
|
|
|
*
|
|
|
|
* @param array<int|string, mixed> $inputs `"token": string`: a valid CSRF token, `"email": string`: the email
|
|
|
|
* address to register the account under, `"password": string`: the password to use for the new account
|
2022-12-03 14:59:53 +01:00
|
|
|
* @return null
|
2022-12-08 18:37:26 +01:00
|
|
|
* @throws InvalidTypeException if any of the inputs has the incorrect type
|
|
|
|
* @throws InvalidValueException if the user is logged in, if no valid CSRF token is present, if the email address
|
2022-12-04 23:56:49 +01:00
|
|
|
* is invalid, if the email address is already in use, or if the password is too short or too long
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
2022-12-04 23:56:49 +01:00
|
|
|
public function handle(array $inputs): mixed
|
2022-12-01 18:24:08 +01:00
|
|
|
{
|
2022-12-08 18:37:26 +01:00
|
|
|
(new LoginValidator(validate_logged_out: true))->check($_SESSION);
|
2022-12-04 23:56:49 +01:00
|
|
|
(new RuleSet([
|
|
|
|
"token" => [new IsValidCsrfTokenRule()],
|
|
|
|
"email" => [new IsEmailRule()],
|
|
|
|
"password" => [new HasStringLengthRule(UserList::MIN_PASSWORD_LENGTH, UserList::MAX_PASSWORD_LENGTH)],
|
|
|
|
]))->check($inputs);
|
|
|
|
|
|
|
|
$this->user_list->transaction(function () use ($inputs) {
|
|
|
|
if ($this->user_list->has_user_with_email($inputs["email"]))
|
2022-12-08 18:37:26 +01:00
|
|
|
throw new InvalidValueException("That email address already in use.", "email");
|
2022-12-04 23:56:49 +01:00
|
|
|
|
|
|
|
$token = $this->user_list->add_user($inputs["email"], $inputs["password"]);
|
2022-12-12 17:37:07 +01:00
|
|
|
$this->email_queue->queue_emails([new RegisterEmail($inputs["email"], $token)]);
|
2022-12-03 14:59:53 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An email to be sent to a recently registered user, including instructions for email verification.
|
2022-12-04 23:56:49 +01:00
|
|
|
*
|
|
|
|
* @see RegisterAction
|
2022-12-03 14:59:53 +01:00
|
|
|
*/
|
|
|
|
class RegisterEmail extends Email
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* A string identifying the type of email.
|
|
|
|
*/
|
|
|
|
public const TYPE = "register";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string the token to verify the email address with
|
|
|
|
*/
|
|
|
|
public string $token;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs a new `RegisterEmail`.
|
|
|
|
*
|
|
|
|
* @param string $recipient the intended recipient of the email
|
|
|
|
* @param string $token the token to verify the email address with
|
|
|
|
*/
|
|
|
|
public function __construct(string $recipient, string $token)
|
|
|
|
{
|
|
|
|
parent::__construct($this::TYPE, $recipient);
|
|
|
|
|
|
|
|
$this->token = $token;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function get_subject(): string
|
|
|
|
{
|
|
|
|
return "Welcome to Death Notifier";
|
|
|
|
}
|
|
|
|
|
|
|
|
public function get_body(): string
|
|
|
|
{
|
2022-12-07 23:12:33 +01:00
|
|
|
$base_path = Config::get("server.base_path");
|
2022-12-03 14:59:53 +01:00
|
|
|
$verify_path = "$base_path?action=verify-email&email=" . rawurlencode($this->recipient) . "&token=$this->token";
|
2022-12-01 18:24:08 +01:00
|
|
|
|
2022-12-03 14:59:53 +01:00
|
|
|
return
|
|
|
|
"You have successfully created an account with Death Notifier. " .
|
|
|
|
"Welcome!" .
|
|
|
|
"\n\n" .
|
|
|
|
"Until you verify your email address, you will not receive any notifications. " .
|
|
|
|
"You can verify your email address by clicking the link below. " .
|
2022-12-04 23:56:49 +01:00
|
|
|
"This link will expire after " . UserList::MINUTES_VALID_VERIFICATION . " minutes." .
|
2022-12-03 14:59:53 +01:00
|
|
|
"\n" .
|
|
|
|
"Verify: $verify_path" .
|
|
|
|
"\n\n" .
|
|
|
|
"If you did not create this account, you can delete the account. " .
|
|
|
|
"Go to the Death Notifier website, reset your password, log in, and delete the account." .
|
|
|
|
"\n\n" .
|
|
|
|
$base_path;
|
2022-12-01 18:24:08 +01:00
|
|
|
}
|
|
|
|
}
|