2022-08-12 20:46:43 +02:00
|
|
|
<?php
|
|
|
|
|
2022-08-14 16:49:52 +02:00
|
|
|
namespace php;
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-14 18:31:55 +02:00
|
|
|
use PDO;
|
2022-08-12 20:46:43 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Manages interaction with the database in the context of users.
|
|
|
|
*/
|
2022-08-14 15:52:47 +02:00
|
|
|
// TODO: Remove duplication in this class
|
2022-08-12 20:46:43 +02:00
|
|
|
class UserManager
|
|
|
|
{
|
2022-08-14 17:54:55 +02:00
|
|
|
/**
|
|
|
|
* The maximum length of an email address.
|
|
|
|
*/
|
|
|
|
private const MAX_EMAIL_LENGTH = 254;
|
|
|
|
/**
|
|
|
|
* The minimum length of a password;
|
|
|
|
*/
|
|
|
|
private const MIN_PASSWORD_LENGTH = 8;
|
|
|
|
/**
|
|
|
|
* The maximum length of a password.
|
|
|
|
*/
|
2022-08-21 14:20:43 +02:00
|
|
|
private const MAX_PASSWORD_LENGTH = 64;
|
2022-08-14 17:54:55 +02:00
|
|
|
|
2022-08-12 20:46:43 +02:00
|
|
|
/**
|
2022-08-23 12:22:57 +02:00
|
|
|
* @var PDO The database connection to interact with.
|
2022-08-12 20:46:43 +02:00
|
|
|
*/
|
2022-08-23 12:22:57 +02:00
|
|
|
private PDO $conn;
|
2022-08-12 20:46:43 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs a new user manager.
|
|
|
|
*
|
2022-08-23 12:22:57 +02:00
|
|
|
* @param PDO $conn the database connection to interact with
|
2022-08-12 20:46:43 +02:00
|
|
|
*/
|
2022-08-23 21:58:27 +02:00
|
|
|
public function __construct(PDO $conn)
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn = $conn;
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-14 12:31:47 +02:00
|
|
|
/**
|
|
|
|
* Populates the database with the necessary structures for users.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function install(): void
|
|
|
|
{
|
2022-08-23 15:53:52 +02:00
|
|
|
$this->conn->exec("CREATE TABLE users(uuid text not null unique primary key default(lower(hex(randomblob(16)))),
|
|
|
|
email text not null unique,
|
2022-08-23 12:22:57 +02:00
|
|
|
email_verification_token text,
|
|
|
|
password text not null,
|
2022-08-23 15:53:52 +02:00
|
|
|
password_update_time int not null);");
|
2022-08-14 12:31:47 +02:00
|
|
|
}
|
|
|
|
|
2022-08-12 20:46:43 +02:00
|
|
|
/**
|
|
|
|
* Registers a new user.
|
|
|
|
*
|
2022-08-23 15:53:52 +02:00
|
|
|
* @param Mailer $mailer the mailer to notify the user with
|
2022-08-21 14:20:43 +02:00
|
|
|
* @param string $email the user-submitted email address
|
|
|
|
* @param string $password the user-submitted password
|
|
|
|
* @param string $password_confirm the user-submitted password confirmation
|
2022-08-12 20:46:43 +02:00
|
|
|
* @return Response a response with message `null` if the user was registered, or a response with a message
|
|
|
|
* explaining what went wrong otherwise
|
|
|
|
*/
|
2022-08-23 15:53:52 +02:00
|
|
|
public function register(Mailer $mailer, string $email, string $password, string $password_confirm): Response
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
|
|
|
// Validate
|
2022-08-14 17:54:55 +02:00
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > self::MAX_EMAIL_LENGTH)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Invalid email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 17:54:55 +02:00
|
|
|
if (strlen($password) < self::MIN_PASSWORD_LENGTH || strlen($password) > self::MAX_PASSWORD_LENGTH)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: [
|
|
|
|
"target" => "password",
|
2022-08-21 14:20:43 +02:00
|
|
|
"message" => "Your password should be at least 8 and at most 64 characters long."
|
2022-08-19 01:39:23 +02:00
|
|
|
],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 14:14:25 +02:00
|
|
|
if ($password !== $password_confirm)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "passwordConfirm", "message" => "Passwords do not match."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
// Begin transaction
|
|
|
|
$this->conn->beginTransaction();
|
2022-08-12 20:46:43 +02:00
|
|
|
|
|
|
|
// Check if email address is already in use
|
2022-08-23 17:57:43 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT COUNT(*) AS count
|
2022-08-23 12:22:57 +02:00
|
|
|
FROM users
|
|
|
|
WHERE email=:email;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
|
|
|
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($result["count"] > 0) {
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->rollBack();
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Email address already in use."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Register user
|
2022-08-23 15:53:52 +02:00
|
|
|
$stmt = $this->conn->prepare("INSERT INTO users (email, email_verification_token,
|
2022-08-23 12:22:57 +02:00
|
|
|
password, password_update_time)
|
2022-08-23 21:58:27 +02:00
|
|
|
VALUES (:email, lower(hex(randomblob(16))),
|
2022-08-23 15:53:52 +02:00
|
|
|
:password, unixepoch())
|
2022-08-23 21:58:27 +02:00
|
|
|
RETURNING email_verification_token;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
|
|
|
$stmt->bindValue(":password", password_hash($password, PASSWORD_DEFAULT));
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
2022-08-23 21:58:27 +02:00
|
|
|
$email_verification_token = $stmt->fetchAll(PDO::FETCH_ASSOC)[0]["email_verification_token"];
|
2022-08-12 20:46:43 +02:00
|
|
|
|
|
|
|
// Respond
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->commit();
|
2022-08-23 21:58:27 +02:00
|
|
|
$mailer->queue_registration($email, $email_verification_token);
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes the user with the given UUID.
|
|
|
|
*
|
|
|
|
* @param string $uuid the UUID of the user to delete
|
|
|
|
* @return Response a response with message `null` if the user was deleted, or a response with a message explaining
|
|
|
|
* what went wrong otherwise
|
|
|
|
*/
|
|
|
|
public function delete(string $uuid): Response
|
|
|
|
{
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("DELETE FROM users WHERE uuid=:uuid;");
|
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
|
|
|
$stmt->execute();
|
2022-08-14 18:31:55 +02:00
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("DELETE FROM trackings WHERE user_uuid=:uuid");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validates a login attempt with the given email address and password.
|
|
|
|
*
|
|
|
|
* @param string $email the email address of the user whose password should be checked
|
|
|
|
* @param string $password the password to check against the specified user
|
2022-08-19 19:07:39 +02:00
|
|
|
* @return Response a response with user data if the login was successful, or a response with a message explaining
|
|
|
|
* what went wrong otherwise
|
2022-08-12 20:46:43 +02:00
|
|
|
*/
|
2022-08-19 19:07:39 +02:00
|
|
|
public function check_login(string $email, string $password): Response
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
2022-08-19 17:23:24 +02:00
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > self::MAX_EMAIL_LENGTH)
|
2022-08-19 19:07:39 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Invalid email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-19 17:23:24 +02:00
|
|
|
if (strlen($password) > self::MAX_PASSWORD_LENGTH)
|
2022-08-19 19:07:39 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "password", "message" => "Incorrect combination of email and password."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 17:54:55 +02:00
|
|
|
|
2022-08-23 15:53:52 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT uuid, email, email_verification_token IS NULL AS email_is_verified,
|
|
|
|
password, password_update_time
|
2022-08-23 12:22:57 +02:00
|
|
|
FROM users
|
|
|
|
WHERE email=:email;");
|
2022-08-14 12:31:47 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
|
|
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-19 19:07:39 +02:00
|
|
|
if (sizeof($results) === 0 || !password_verify($password, $results[0]["password"])) {
|
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "password", "message" => "Incorrect combination of email and password."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$user = $results[0];
|
|
|
|
unset($user["password"]);
|
|
|
|
return new Response(payload: $user, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the user with the given UUID.
|
|
|
|
*
|
|
|
|
* @param string $uuid the UUID of the user to return
|
2022-08-14 12:31:47 +02:00
|
|
|
* @return Response the user with the given UUID, or a response with an explanation what went wrong otherwise
|
2022-08-12 20:46:43 +02:00
|
|
|
*/
|
2022-08-14 12:31:47 +02:00
|
|
|
public function get_user_data(string $uuid): Response
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
2022-08-23 15:53:52 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT uuid, email, email_verification_token IS NULL AS email_is_verified,
|
|
|
|
password_update_time
|
2022-08-23 12:22:57 +02:00
|
|
|
FROM users
|
|
|
|
WHERE uuid=:uuid;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
|
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
2022-08-18 16:25:23 +02:00
|
|
|
if ($user === false)
|
2022-08-19 19:07:39 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "uuid", "message" => "Something went wrong. Please try logging in again."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(payload: $user, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the indicated user's email address.
|
|
|
|
*
|
|
|
|
* @param string $uuid the UUID of the user whose email address should be updated
|
|
|
|
* @param string $email the new email address
|
2022-08-21 14:20:43 +02:00
|
|
|
* @param Mailer $mailer the mailer to send a notification with to the user
|
2022-08-12 20:46:43 +02:00
|
|
|
* @return Response a response with message `null` if the email address was updated, or a response with a message
|
|
|
|
* explaining what went wrong otherwise
|
|
|
|
*/
|
2022-08-21 14:20:43 +02:00
|
|
|
public function set_email(string $uuid, string $email, Mailer $mailer): Response
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
|
|
|
// Validate
|
2022-08-14 17:54:55 +02:00
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > self::MAX_EMAIL_LENGTH)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Invalid email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
// Begin transaction
|
|
|
|
$this->conn->beginTransaction();
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-21 14:20:43 +02:00
|
|
|
// Check if email address is different
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT email FROM users WHERE uuid=:uuid;");
|
2022-08-21 14:20:43 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
|
|
|
$stmt->execute();
|
|
|
|
$email_old = $stmt->fetch(PDO::FETCH_ASSOC)["email"];
|
2022-08-23 15:53:52 +02:00
|
|
|
if (hash_equals($email_old, $email))
|
2022-08-21 14:20:43 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "That is already your email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
|
|
|
|
2022-08-12 20:46:43 +02:00
|
|
|
// Check if email address is already in use
|
2022-08-23 17:57:43 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT COUNT(*) AS count
|
2022-08-23 12:22:57 +02:00
|
|
|
FROM users
|
|
|
|
WHERE email=:email;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
|
|
|
if ($stmt->fetch(PDO::FETCH_ASSOC)["count"] > 0) {
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->rollBack();
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Email address already in use."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update email address
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("UPDATE users
|
2022-08-23 21:58:27 +02:00
|
|
|
SET email=:email, email_verification_token=lower(hex(randomblob(16)))
|
|
|
|
WHERE uuid=:uuid
|
|
|
|
RETURNING email_verification_token;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
|
|
|
$stmt->bindValue(":email", $email);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
2022-08-23 21:58:27 +02:00
|
|
|
$email_verification_token = $stmt->fetchAll(PDO::FETCH_ASSOC)[0]["email_verification_token"];
|
2022-08-12 20:46:43 +02:00
|
|
|
|
|
|
|
// Respond
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->commit();
|
2022-08-23 21:58:27 +02:00
|
|
|
$mailer->queue_verification($email, $email_verification_token);
|
2022-08-21 14:20:43 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Verifies an email address with a token.
|
|
|
|
*
|
|
|
|
* @param string $email the email address to verify
|
|
|
|
* @param string $email_verification_token the token to verify the email address with
|
|
|
|
* @return Response the server's response to the request
|
|
|
|
*/
|
|
|
|
public function verify_email(string $email, string $email_verification_token): Response
|
|
|
|
{
|
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > self::MAX_EMAIL_LENGTH)
|
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Invalid email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->beginTransaction();
|
2022-08-21 14:20:43 +02:00
|
|
|
|
2022-08-23 15:53:52 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT email_verification_token
|
2022-08-23 12:22:57 +02:00
|
|
|
FROM users
|
|
|
|
WHERE email=:email;");
|
2022-08-21 14:20:43 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
|
|
|
$stmt->execute();
|
|
|
|
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
|
2022-08-23 15:53:52 +02:00
|
|
|
if ($result === false ||
|
|
|
|
($result["email_verification_token"] !== null
|
|
|
|
&& !hash_equals($result["email_verification_token"], $email_verification_token))) {
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->rollBack();
|
2022-08-21 14:20:43 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "email", "message" => "Failed to verify email address."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-08-23 15:53:52 +02:00
|
|
|
if ($result["email_verification_token"] === null) {
|
|
|
|
// Email already verified, returning
|
|
|
|
$this->conn->rollBack();
|
2022-08-21 14:20:43 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
|
|
|
}
|
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("UPDATE users
|
2022-08-23 15:53:52 +02:00
|
|
|
SET email_verification_token=null
|
2022-08-23 12:22:57 +02:00
|
|
|
WHERE email=:email;");
|
2022-08-21 14:20:43 +02:00
|
|
|
$stmt->bindValue(":email", $email);
|
|
|
|
$stmt->execute();
|
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->commit();
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the indicated user's password.
|
|
|
|
*
|
|
|
|
* @param string $uuid the UUID of the user whose password should be updated
|
2022-08-14 12:31:47 +02:00
|
|
|
* @param string $password_old the old password
|
|
|
|
* @param string $password_new the new password
|
2022-08-12 20:46:43 +02:00
|
|
|
* @param string $password_confirm the confirmation of the new password
|
|
|
|
* @return Response a response with message `null` if the password was updated, or a response with a message
|
|
|
|
* explaining what went wrong otherwise
|
|
|
|
*/
|
2022-08-14 12:31:47 +02:00
|
|
|
public function set_password(string $uuid, string $password_old, string $password_new,
|
|
|
|
string $password_confirm): Response
|
2022-08-12 20:46:43 +02:00
|
|
|
{
|
|
|
|
// Validate
|
2022-08-19 01:39:23 +02:00
|
|
|
if (strlen($password_old) > self::MAX_PASSWORD_LENGTH)
|
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "passwordOld", "message" => "Incorrect old password."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 17:54:55 +02:00
|
|
|
if (strlen($password_new) < self::MIN_PASSWORD_LENGTH || strlen($password_new) > self::MAX_PASSWORD_LENGTH)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: [
|
|
|
|
"target" => "passwordNew",
|
2022-08-21 14:20:43 +02:00
|
|
|
"message" => "Your password should be at least 8 and at most 64 characters long."
|
2022-08-19 01:39:23 +02:00
|
|
|
],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 14:14:25 +02:00
|
|
|
if ($password_new !== $password_confirm)
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "passwordConfirm", "message" => "New passwords do not match."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-23 12:22:57 +02:00
|
|
|
// Begin transaction
|
|
|
|
$this->conn->beginTransaction();
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-14 12:31:47 +02:00
|
|
|
// Validate old password
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("SELECT password FROM users WHERE uuid=:uuid;");
|
2022-08-14 12:31:47 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
|
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
2022-08-14 12:31:47 +02:00
|
|
|
if (!password_verify($password_old, $user["password"])) {
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->rollBack();
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(
|
|
|
|
payload: ["target" => "passwordOld", "message" => "Incorrect old password."],
|
|
|
|
satisfied: false
|
|
|
|
);
|
2022-08-14 12:31:47 +02:00
|
|
|
}
|
|
|
|
|
2022-08-12 20:46:43 +02:00
|
|
|
// Update password
|
2022-08-23 12:22:57 +02:00
|
|
|
$stmt = $this->conn->prepare("UPDATE users
|
|
|
|
SET password=:password, password_update_time=unixepoch()
|
|
|
|
WHERE uuid=:uuid;");
|
2022-08-12 20:46:43 +02:00
|
|
|
$stmt->bindValue(":uuid", $uuid);
|
2022-08-14 12:31:47 +02:00
|
|
|
$stmt->bindValue(":password", password_hash($password_new, PASSWORD_DEFAULT));
|
2022-08-14 18:31:55 +02:00
|
|
|
$stmt->execute();
|
2022-08-12 20:46:43 +02:00
|
|
|
|
2022-08-14 18:31:55 +02:00
|
|
|
// Respond
|
2022-08-23 12:22:57 +02:00
|
|
|
$this->conn->commit();
|
2022-08-19 01:39:23 +02:00
|
|
|
return new Response(payload: null, satisfied: true);
|
2022-08-12 20:46:43 +02:00
|
|
|
}
|
|
|
|
}
|