668 lines
27 KiB
PHP
668 lines
27 KiB
PHP
<?php
|
|
|
|
namespace com\fwdekker\deathnotifier;
|
|
|
|
use com\fwdekker\deathnotifier\mailer\ChangedEmailEmail;
|
|
use com\fwdekker\deathnotifier\mailer\ChangedPasswordEmail;
|
|
use com\fwdekker\deathnotifier\mailer\Mailer;
|
|
use com\fwdekker\deathnotifier\mailer\RegisterEmail;
|
|
use com\fwdekker\deathnotifier\mailer\ResetPasswordEmail;
|
|
use com\fwdekker\deathnotifier\mailer\VerifyEmailEmail;
|
|
use PDO;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
|
|
/**
|
|
* Unit tests for `UserManager`.
|
|
*/
|
|
class UserManagerTest extends DatabaseTestCase
|
|
{
|
|
private UserManager $user_manager;
|
|
private Mailer&MockObject $mailer;
|
|
|
|
|
|
public function get_user_manager(): UserManager
|
|
{
|
|
return new UserManager($this->logger, $this->database->conn, $this->mailer);
|
|
}
|
|
|
|
public function setUp(): void
|
|
{
|
|
$this->mailer = $this->createMock(Mailer::class);
|
|
$this->mailer->method("queue_email")->willReturn(Response::satisfied());
|
|
|
|
parent::setUp();
|
|
|
|
$this->user_manager = $this->get_user_manager();
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the UUID of the given email address.
|
|
*
|
|
* @param string $email the email address to return the email verification token of
|
|
* @return string|null the email verification token of the given email address
|
|
*/
|
|
private function get_uuid(string $email): ?string
|
|
{
|
|
$stmt = $this->database->conn->prepare("SELECT uuid FROM users WHERE email=:email;");
|
|
$stmt->bindValue(":email", $email);
|
|
$stmt->execute();
|
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
return empty($results) ? null : $results[0]["uuid"];
|
|
}
|
|
|
|
/**
|
|
* Returns the email verification token of the given email address.
|
|
*
|
|
* @param string $email the email address to return the email verification token of
|
|
* @return string|null the email verification token of the given email address, or `null` if there is no user with
|
|
* the given email address
|
|
*/
|
|
private function get_email_token(string $email): ?string
|
|
{
|
|
$stmt = $this->database->conn->prepare("SELECT email_verification_token FROM users WHERE email=:email;");
|
|
$stmt->bindValue(":email", $email);
|
|
$stmt->execute();
|
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
return empty($results) ? null : $results[0]["email_verification_token"];
|
|
}
|
|
|
|
/**
|
|
* Changes the timestamp of the email verification token of the given email address, if a user with that email
|
|
* address exists.
|
|
*
|
|
* @param string $email the email address to set the timestamp of
|
|
* @param int $timestamp the timestamp to set
|
|
*/
|
|
private function set_email_token_timestamp(string $email, int $timestamp): void
|
|
{
|
|
$stmt = $this->database->conn->prepare("UPDATE users
|
|
SET email_verification_token_timestamp=:timestamp
|
|
WHERE email=:email;");
|
|
$stmt->bindValue(":email", $email);
|
|
$stmt->bindValue(":timestamp", $timestamp);
|
|
$stmt->execute();
|
|
}
|
|
|
|
/**
|
|
* Returns the password verification token of the given email address.
|
|
*
|
|
* @param string $email the email address to return the password verification token of
|
|
* @return string|null the password verification token of the given email address, or `null` if there is no user
|
|
* with the given email address
|
|
*/
|
|
private function get_password_token(string $email): ?string
|
|
{
|
|
$stmt = $this->database->conn->prepare("SELECT password_reset_token FROM users WHERE email=:email;");
|
|
$stmt->bindValue(":email", $email);
|
|
$stmt->execute();
|
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
return empty($results) ? null : $results[0]["password_reset_token"];
|
|
}
|
|
|
|
/**
|
|
* Changes the timestamp of the password verification token of the given email address, if a user with that email
|
|
* address exists.
|
|
*
|
|
* @param string $email the email address to set the timestamp of
|
|
* @param int $timestamp the timestamp to set
|
|
*/
|
|
private function set_password_token_timestamp(string $email, int $timestamp): void
|
|
{
|
|
$stmt = $this->database->conn->prepare("UPDATE users
|
|
SET password_reset_token_timestamp=:timestamp
|
|
WHERE email=:email;");
|
|
$stmt->bindValue(":email", $email);
|
|
$stmt->bindValue(":timestamp", $timestamp);
|
|
$stmt->execute();
|
|
}
|
|
|
|
|
|
public function test_register_user_returns_an_unsatisfied_response_if_the_email_is_used(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->register_user("john@example.com", "password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_register_user_registers_the_user_and_returns_a_satisfied_response_if_the_email_is_unused(): void
|
|
{
|
|
$response = $this->user_manager->register_user("john@example.com", "password");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertNotNull($this->get_uuid("john@example.com"));
|
|
}
|
|
|
|
public function test_register_user_sends_an_email_with_the_verification_token(): void
|
|
{
|
|
$this->mailer
|
|
->expects($this->once())
|
|
->method("queue_email")
|
|
->with($this->callback(
|
|
fn($email) => $email instanceof RegisterEmail && $email->recipient === "john@example.com")
|
|
);
|
|
|
|
$response = $this->user_manager->register_user("john@example.com", "password");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
}
|
|
|
|
|
|
public function test_check_login_returns_an_unsatisfied_response_if_the_email_does_not_exist(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->check_login("lydia@other.example.com", "password");
|
|
|
|
self::assertFalse($response[0]->satisfied);
|
|
self::assertNull($response[1]);
|
|
}
|
|
|
|
public function test_check_login_returns_an_unsatisfied_response_if_the_email_is_incorrect(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->check_login("lydia@other.example.com", "password");
|
|
|
|
self::assertFalse($response[0]->satisfied);
|
|
self::assertNull($response[1]);
|
|
}
|
|
|
|
public function test_check_login_returns_a_satisfied_response_if_the_email_and_password_are_correct(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->check_login("john@example.com", "password");
|
|
|
|
self::assertTrue($response[0]->satisfied);
|
|
self::assertNotNull($response[1]);
|
|
}
|
|
|
|
|
|
public function test_user_exists_returns_false_if_the_user_does_not_exist(): void
|
|
{
|
|
self::assertFalse($this->user_manager->user_exists("invalid-uuid"));
|
|
}
|
|
|
|
public function test_user_exists_returns_true_if_the_user_exists(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
self::assertTrue($this->user_manager->user_exists($uuid));
|
|
}
|
|
|
|
|
|
public function test_get_user_returns_a_satisfied_response_with_the_user_data_if_the_uuid_exists(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->get_user($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertArrayHasKey("email", $response->payload);
|
|
}
|
|
|
|
public function test_get_user_returns_an_unsatisfied_response_if_the_uuid_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->get_user("invalid-uuid");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
|
|
public function test_delete_user_deletes_the_user_and_returns_a_satisfied_response_if_the_uuid_is_used(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->delete_user($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertFalse($this->user_manager->user_exists($uuid));
|
|
}
|
|
|
|
public function test_delete_user_returns_a_satisfied_response_even_if_the_user_was_already_deleted(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$this->user_manager->delete_user($uuid);
|
|
|
|
$response = $this->user_manager->delete_user($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
}
|
|
|
|
public function test_delete_user_returns_a_satisfied_response_even_if_the_uuid_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->delete_user("invalid-uuid");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
}
|
|
|
|
|
|
public function test_set_email_returns_an_unsatisfied_response_if_the_email_is_not_different(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->set_email($uuid, "john@example.com");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_set_email_returns_an_unsatisfied_response_if_the_email_is_already_used(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->user_manager->register_user("lydia@other.example.com", "another-password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->set_email($uuid, "lydia@other.example.com");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_set_email_returns_a_satisfied_response_and_sends_an_email_if_the_email_is_unused(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->mailer
|
|
->expects($this->once())
|
|
->method("queue_email")
|
|
->with($this->callback(
|
|
fn($email) => $email instanceof ChangedEmailEmail && $email->recipient === "lydia@other.example.com")
|
|
);
|
|
$response = $this->user_manager->set_email($uuid, "lydia@other.example.com");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertNull($this->get_email_token("john@example.com"));
|
|
self::assertNotNull($this->get_email_token("lydia@other.example.com"));
|
|
}
|
|
|
|
public function test_set_email_retains_the_uuid_of_the_user(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$old_uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->user_manager->set_email($old_uuid, "lydia@other.example.com");
|
|
$new_uuid = $this->get_uuid("lydia@other.example.com");
|
|
|
|
self::assertEquals($old_uuid, $new_uuid);
|
|
}
|
|
|
|
public function test_set_email_disallows_logging_in_with_the_old_email_address(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->user_manager->set_email($uuid, "lydia@other.example.com");
|
|
|
|
self::assertFalse($this->user_manager->check_login("john@example.com", "password")[0]->satisfied);
|
|
}
|
|
|
|
|
|
public function test_verify_email_returns_an_unsatisfied_response_if_the_email_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->verify_email("does-not-exist@example.com", "token");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_verify_email_returns_an_unsatisfied_response_if_the_wrong_token_is_given(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->verify_email("john@example.com", "incorrect-token");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_verify_email_returns_an_unsatisfied_response_if_an_email_is_already_verified(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$token = $this->get_email_token("john@example.com");
|
|
|
|
$this->user_manager->verify_email("john@example.com", $token);
|
|
$response = $this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_verify_email_returns_an_unsatisfied_response_if_the_token_is_expired(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_email_token_timestamp("john@example.com", "1640995200");
|
|
$token = $this->get_email_token("john@example.com");
|
|
|
|
$response = $this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_verify_email_verifies_the_email_and_returns_a_satisfied_response_if_the_verification_token_is_valid(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$token = $this->get_email_token("john@example.com");
|
|
|
|
$response = $this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertNull($this->get_email_token("john@example.com"));
|
|
self::assertTrue($this->user_manager->get_user($uuid)->payload["email_verified"] === 1);
|
|
}
|
|
|
|
|
|
public function test_resend_verify_email_returns_an_unsatisfied_response_if_the_uuid_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->resend_verify_email("invalid-uuid");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_resend_verify_email_does_not_send_an_email_and_returns_an_unsatisfied_response_if_the_email_is_already_verified(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$token = $this->get_email_token("john@example.com");
|
|
$this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
$this->mailer->expects($this->never())->method("queue_email");
|
|
$response = $this->user_manager->resend_verify_email($uuid);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_resend_verify_email_does_not_send_an_email_and_returns_an_unsatisfied_response_if_the_user_recently_registered(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->mailer->expects($this->never())->method("queue_email");
|
|
$response = $this->user_manager->resend_verify_email($uuid);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_resend_verify_email_does_not_send_an_email_and_returns_an_unsatisfied_response_if_an_email_was_recently_sent(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_email_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_VERIFICATION_EMAILS + 1)
|
|
);
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$this->user_manager->resend_verify_email($uuid);
|
|
|
|
$this->mailer->expects($this->never())->method("queue_email");
|
|
$response = $this->user_manager->resend_verify_email($uuid);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_resend_verify_email_sends_an_email_and_returns_a_satisfied_response_if_no_email_was_recently_sent(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_email_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_VERIFICATION_EMAILS + 1)
|
|
);
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->mailer
|
|
->expects($this->once())
|
|
->method("queue_email")
|
|
->with($this->callback(
|
|
fn($email) => $email instanceof VerifyEmailEmail && $email->recipient === "john@example.com")
|
|
);
|
|
$response = $this->user_manager->resend_verify_email($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
}
|
|
|
|
public function test_resend_verify_email_disallows_verifying_the_email_with_the_old_token(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$old_token = $this->get_email_token("john@example.com");
|
|
$this->set_email_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_VERIFICATION_EMAILS + 1)
|
|
);
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$this->user_manager->resend_verify_email($uuid);
|
|
|
|
$response = $this->user_manager->verify_email("john@example.com", $old_token);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
|
|
public function test_toggle_notifications_returns_an_unsatisfied_response_if_the_uuid_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->toggle_notifications("invalid-uuid");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_toggle_notifications_does_not_toggle_notifications_and_returns_an_unsatisfied_response_if_the_email_is_not_verified(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->toggle_notifications($uuid);
|
|
|
|
self::assertFalse($response->satisfied);
|
|
self::assertTrue($this->user_manager->get_user($uuid)->payload["email_notifications_enabled"] === 1);
|
|
}
|
|
|
|
public function test_toggle_notifications_enables_notifications_and_returns_a_satisfied_response_if_they_are_disabled(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$token = $this->get_email_token("john@example.com");
|
|
$this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
$this->user_manager->toggle_notifications($uuid);
|
|
$response = $this->user_manager->toggle_notifications($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertTrue($this->user_manager->get_user($uuid)->payload["email_notifications_enabled"] === 1);
|
|
}
|
|
|
|
public function test_toggle_notifications_disables_notifications_and_returns_a_satisfied_response_if_they_are_enabled(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$token = $this->get_email_token("john@example.com");
|
|
$this->user_manager->verify_email("john@example.com", $token);
|
|
|
|
$response = $this->user_manager->toggle_notifications($uuid);
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertFalse($this->user_manager->get_user($uuid)->payload["email_notifications_enabled"] === 1);
|
|
}
|
|
|
|
|
|
public function test_set_password_returns_an_unsatisfied_response_if_the_uuid_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->set_password("invalid_uuid", "old-password", "new-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_set_password_returns_an_unsatisfied_response_if_the_old_password_is_incorrect(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$response = $this->user_manager->set_password($uuid, "wrong-password", "new-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
self::assertFalse($this->user_manager->check_login("john@example.com", "new-password")[0]->satisfied);
|
|
}
|
|
|
|
public function test_set_password_sends_an_email_and_returns_a_satisfied_response_if_the_old_password_is_correct(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
|
|
$this->mailer
|
|
->expects($this->once())
|
|
->method("queue_email")
|
|
->with($this->callback(
|
|
fn($email) => $email instanceof ChangedPasswordEmail && $email->recipient === "john@example.com")
|
|
);
|
|
$response = $this->user_manager->set_password($uuid, "password", "new-password");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertTrue($this->user_manager->check_login("john@example.com", "new-password")[0]->satisfied);
|
|
}
|
|
|
|
public function test_set_password_disallows_resetting_the_password_with_an_old_token(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
$uuid = $this->get_uuid("john@example.com");
|
|
$token = $this->get_password_token("john@example.com");
|
|
|
|
$this->user_manager->set_password($uuid, "password", "new-password");
|
|
$response = $this->user_manager->reset_password("john@example.com", $token, "newer-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
self::assertFalse($this->user_manager->check_login("john@example.com", "newer-password")[0]->satisfied);
|
|
}
|
|
|
|
|
|
public function test_send_password_reset_returns_an_unsatisfied_response_if_the_email_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->send_password_reset("invalid@example.com");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_send_password_reset_does_not_send_an_email_and_returns_an_unsatisfied_response_if_the_user_recently_registered(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$this->mailer->expects($this->never())->method("queue_email");
|
|
$response = $this->user_manager->send_password_reset("john@example.com");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_send_password_reset_does_not_send_an_email_and_returns_an_unsatisfied_response_if_an_email_was_recently_sent(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
|
|
$this->mailer->expects($this->never())->method("queue_email");
|
|
$response = $this->user_manager->send_password_reset("john@example.com");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_send_password_reset_sends_an_email_and_returns_a_satisfied_response_if_no_email_was_recently_sent(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
|
|
$this->mailer
|
|
->expects($this->once())
|
|
->method("queue_email")
|
|
->with($this->callback(
|
|
fn($email) => $email instanceof ResetPasswordEmail && $email->recipient === "john@example.com")
|
|
);
|
|
$response = $this->user_manager->send_password_reset("john@example.com");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
}
|
|
|
|
public function test_send_password_reset_disallows_resetting_the_password_with_the_old_token(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
$old_token = $this->get_password_token("john@example.com");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
|
|
$response = $this->user_manager->reset_password("john@example.com", $old_token, "password-new");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
|
|
public function test_reset_password_returns_an_unsatisfied_response_if_the_email_does_not_exist(): void
|
|
{
|
|
$response = $this->user_manager->reset_password("does-not-exist@example.com", "token", "new-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
}
|
|
|
|
public function test_reset_password_does_not_change_the_password_and_returns_an_unsatisfied_response_if_the_wrong_token_is_given(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
|
|
$response = $this->user_manager->reset_password("john@example.com", "incorrect-token", "new-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
self::assertFalse($this->user_manager->check_login("john@example.com", "new-password")[0]->satisfied);
|
|
}
|
|
|
|
public function test_reset_password_does_not_change_the_password_and_returns_an_unsatisfied_response_if_the_token_is_expired(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
$this->set_password_token_timestamp("john@example.com", "1640995200");
|
|
$token = $this->get_password_token("john@example.com");
|
|
|
|
$response = $this->user_manager->reset_password("john@example.com", $token, "new-password");
|
|
|
|
self::assertFalse($response->satisfied);
|
|
self::assertFalse($this->user_manager->check_login("john@example.com", "new-password")[0]->satisfied);
|
|
}
|
|
|
|
public function test_reset_password_changes_the_password_if_the_verification_token_is_valid(): void
|
|
{
|
|
$this->user_manager->register_user("john@example.com", "password");
|
|
$this->set_password_token_timestamp(
|
|
"john@example.com",
|
|
time() - 60 * (UserManager::MINUTES_BETWEEN_PASSWORD_RESETS + 1)
|
|
);
|
|
$this->user_manager->send_password_reset("john@example.com");
|
|
$token = $this->get_password_token("john@example.com");
|
|
|
|
$response = $this->user_manager->reset_password("john@example.com", $token, "new-password");
|
|
|
|
self::assertTrue($response->satisfied);
|
|
self::assertNull($this->get_password_token("john@example.com"));
|
|
self::assertTrue($this->user_manager->check_login("john@example.com", "new-password")[0]->satisfied);
|
|
}
|
|
}
|