death-notifier/src/main/api.php

245 lines
9.8 KiB
PHP

<?php
use php\Database;
use php\EmailRule;
use php\EqualsRule;
use php\IsNotBlankRule;
use php\IsNotSetRule;
use php\IsSetRule;
use php\LengthRule;
use php\Mailer;
use php\Mediawiki;
use php\Response;
use php\TrackingManager;
use php\UserManager;
use php\Util;
use php\Validator;
/** @noinspection PhpIncludeInspection Exists after `npm run deploy` */
require_once __DIR__ . "/.vendor/autoload.php";
// Preamble
$_POST = Util::parse_post();
$config = Util::read_config() ?? Util::http_exit(500);
$logger = Util::create_logger($config["logger"]);
$conn = Database::connect($config["database"]["filename"]);
$mailer = new Mailer($logger->withName("Mailer"), $config, $conn);
$mediawiki = new Mediawiki($logger->withName("Mediawiki"));
$user_manager = new UserManager($conn, $mailer);
$tracking_manager = new TrackingManager($conn, $mailer, $mediawiki);
if (Database::is_empty($conn)) {
$logger->info("Database does not exist. Creating new database at '{$config["database"]["filename"]}'.");
$mailer->install();
$user_manager->install();
$tracking_manager->install();
}
session_start();
$_SESSION["token"] = $_SESSION["token"] ?? Util::generate_csrf_token($logger);
// Process request
$response = null;
if (isset($_POST["action"])) {
// POST requests; alter state
switch ($_POST["action"]) {
case "register":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsNotSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"email" => [new IsSetRule(), new EmailRule()],
"password" => [
new IsSetRule(),
new LengthRule(UserManager::MIN_PASSWORD_LENGTH, UserManager::MAX_PASSWORD_LENGTH)
],
"password_confirm" => [new IsSetRule()],
])
?? $user_manager->register($_POST["email"], $_POST["password"], $_POST["password_confirm"]);
break;
case "login":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsNotSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"email" => [new IsSetRule(), new EmailRule()],
"password" => [
new IsSetRule(),
new LengthRule(UserManager::MIN_PASSWORD_LENGTH, UserManager::MAX_PASSWORD_LENGTH)
],
]);
if ($response !== null) break;
[$response, $uuid] = $user_manager->check_login($_POST["email"], $_POST["password"]);
if ($response->satisfied) $_SESSION["uuid"] = $uuid;
break;
case "logout":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST, ["token" => [new EqualsRule($_SESSION["token"])]]);
if ($response !== null) break;
session_destroy();
session_start();
$_SESSION["token"] = Util::generate_csrf_token($logger) ?? Util::http_exit(500);
$response = new Response(payload: null, satisfied: true);
break;
case "update-email":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"email" => [new IsSetRule(), new EmailRule()],
])
?? $user_manager->set_email($_SESSION["uuid"], $_POST["email"]);
break;
case "verify-email":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new IsSetRule()],
"email" => [new IsSetRule(), new EmailRule()],
])
?? $user_manager->verify_email($_POST["email"], $_POST["token"]);
break;
case "resend-verify-email":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST, ["token" => [new EqualsRule($_SESSION["token"])]])
?? $user_manager->resend_verify_email($_SESSION["uuid"]);
break;
case "update-password":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"password_old" => [
new IsSetRule(),
new LengthRule(UserManager::MIN_PASSWORD_LENGTH, UserManager::MAX_PASSWORD_LENGTH)
],
"password_new" => [
new IsSetRule(),
new LengthRule(UserManager::MIN_PASSWORD_LENGTH, UserManager::MAX_PASSWORD_LENGTH)
],
"password_confirm" => [new IsSetRule()],
])
?? $user_manager->set_password(
$_SESSION["uuid"],
$_POST["password_old"],
$_POST["password_new"],
$_POST["password_confirm"]
);
break;
case "user-delete":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST, ["token" => [new EqualsRule($_SESSION["token"])]])
?? $user_manager->delete($_SESSION["uuid"]);
break;
case "add-tracking":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"person_name" => [
new IsSetRule(),
new LengthRule(TrackingManager::MIN_TITLE_LENGTH, TrackingManager::MAX_TITLE_LENGTH),
new IsNotBlankRule()
],
])
?? $tracking_manager->add_tracking($_SESSION["uuid"], $_POST["person_name"]);
break;
case "remove-tracking":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? Validator::validate_inputs($_POST,
[
"token" => [new EqualsRule($_SESSION["token"])],
"person_name" => [
new IsSetRule(),
new LengthRule(TrackingManager::MIN_TITLE_LENGTH, TrackingManager::MAX_TITLE_LENGTH),
new IsNotBlankRule()
],
])
?? $tracking_manager->remove_tracking($_SESSION["uuid"], $_POST["person_name"]);
break;
default:
$response = new Response(
payload: ["target" => null, "message" => "Unknown POST action '{$_POST["action"]}'."],
satisfied: false
);
break;
}
} elseif (isset($_GET["action"])) {
// GET requests; do not alter state
switch ($_GET["action"]) {
case "start-session":
if (!isset($_SESSION["uuid"])) {
$response = new Response(payload: ["target" => null, "message" => null], satisfied: false);
break;
}
$response = $user_manager->user_exists($_SESSION["uuid"]);
if (!$response->satisfied) {
session_destroy();
session_start();
$_SESSION["token"] = Util::generate_csrf_token($logger) ?? Util::http_exit(500);
}
break;
case "get-user-data":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? $user_manager->get_user_data($_SESSION["uuid"]);
break;
case "list-trackings":
$response =
Validator::validate_inputs($_SESSION, ["uuid" => [new IsSetRule()]])
?? $tracking_manager->list_trackings($_SESSION["uuid"]);
break;
default:
$response = new Response(
payload: ["target" => null, "message" => "Unknown GET action '{$_GET["action"]}'."],
satisfied: false
);
}
} elseif ($argc > 1) {
// CLI
if (hash_equals($config["admin"]["cli_secret"], "REPLACE THIS WITH A SECRET VALUE"))
exit("Default value for 'cli_secret' detected. Feature disabled.");
if (!hash_equals($config["admin"]["cli_secret"], $argv[2]))
exit("Incorrect value for 'cli_secret'.");
switch ($argv[1]) {
case "update-all-trackings":
$logger->info("Updating all trackings.");
$tracking_manager->update_trackings($tracking_manager->list_all_unique_person_names());
exit("Successfully updated all trackings.");
case "process-email-queue":
$logger->info("Processing email queue.");
$mailer->process_queue();
exit("Successfully processed email queue.");
default:
exit("Unknown CLI action '$argv[1]'.");
}
} else {
// No action given, nothing done, so that's a success
$response = new Response(payload: null, satisfied: true);
}
header("Content-type:application/json;charset=utf-8");
exit(json_encode(array(
"payload" => $response->payload,
"satisfied" => $response->satisfied,
"token" => $_SESSION["token"]
)));