219 lines
7.4 KiB
PHP
219 lines
7.4 KiB
PHP
<?php
|
|
|
|
use Monolog\ErrorHandler;
|
|
use Monolog\Handler\StreamHandler;
|
|
use Monolog\Logger;
|
|
use php\Mailer;
|
|
use php\Mediawiki;
|
|
use php\Response;
|
|
use php\TrackingManager;
|
|
use php\UserManager;
|
|
|
|
/** @noinspection PhpIncludeInspection Exists after `npm run deploy` */
|
|
require_once __DIR__ . "/vendor/autoload.php";
|
|
|
|
|
|
/// Preparations
|
|
// Load config
|
|
$config = parse_ini_file("config.default.ini.php", process_sections: true, scanner_mode: INI_SCANNER_TYPED) or exit(1);
|
|
if (file_exists("config.ini.php")) {
|
|
$config_custom =
|
|
parse_ini_file("config.ini.php", process_sections: true, scanner_mode: INI_SCANNER_TYPED) or exit(1);
|
|
$config = array_merge($config, $config_custom);
|
|
}
|
|
|
|
// Create logger
|
|
$logger = new Logger("main");
|
|
$logger->pushHandler(new StreamHandler($config["logger"]["file"], $config["logger"]["level"]));
|
|
ErrorHandler::register($logger);
|
|
|
|
// Instantiate utility classes
|
|
$user_manager = new UserManager($logger->withName("UserManager"), $config["database"]["filename"]);
|
|
$tracking_manager = new TrackingManager($logger->withName("TrackingManager"), $config["database"]["filename"]);
|
|
$mailer = new Mailer($logger->withName("Mailer"), $config["mail"]);
|
|
$mediawiki = new Mediawiki($logger->withName("Mediawiki"));
|
|
|
|
// Create db if it does not exist
|
|
if (!file_exists($config["database"]["filename"])) {
|
|
$logger->warning("Database does not exist. Creating new database.");
|
|
|
|
// Create database
|
|
(new SQLite3($config["database"]["filename"]))->close();
|
|
|
|
// Populate database
|
|
$user_manager->install();
|
|
$tracking_manager->install();
|
|
}
|
|
|
|
// Start session
|
|
/**
|
|
* Generates a CSRF token.
|
|
*
|
|
* @return string the generated CSRF token
|
|
*/
|
|
function generate_csrf_token(Logger $logger): string
|
|
{
|
|
try {
|
|
return bin2hex(random_bytes(32));
|
|
} catch (Exception $exception) {
|
|
$logger->emergency("Failed to generate token.", [$exception]);
|
|
http_response_code(500);
|
|
exit();
|
|
}
|
|
}
|
|
|
|
session_start();
|
|
if (!isset($_SESSION["token"]))
|
|
$_SESSION["token"] = generate_csrf_token($logger);
|
|
|
|
// Read JSON from POST
|
|
$post_input = file_get_contents("php://input");
|
|
if ($post_input !== false) $_POST = json_decode($post_input, associative: true);
|
|
|
|
|
|
/// Define validation helpers
|
|
/**
|
|
* Validates the user's CSRF token by comparing `$_POST["token"]` against `$_SESSION["token"]`.
|
|
*
|
|
* @return Response|null `null` if the user's CSRF token is valid, or an error response if either value is not set or if
|
|
* the two are not equal
|
|
*/
|
|
function validate_csrf(): ?Response
|
|
{
|
|
if (!(isset($_POST["token"]) && isset($_SESSION["token"]) && hash_equals($_POST["token"], $_SESSION["token"])))
|
|
return new Response("Invalid CSRF token. Try refreshing the page.", false);
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Validates that the user is logged out by checking that `$_SESSION["uuid"]` is not set.
|
|
*
|
|
* @return Response|null `null` if the user is logged out, or an error response otherwise
|
|
*/
|
|
function validate_logged_out(): ?Response
|
|
{
|
|
if (isset($_SESSION["uuid"]))
|
|
return new Response("Used is already logged in.", false);
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Validates that the user is logged in by checking that `$_SESSION["uuid"]` is set.
|
|
*
|
|
* @return Response|null `null` if the user is logged in, or an error response otherwise
|
|
*/
|
|
function validate_logged_in(): ?Response
|
|
{
|
|
if (!isset($_SESSION["uuid"]))
|
|
return new Response("Used is not logged in.", false);
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Validates that each of `arguments` is set.
|
|
*
|
|
* @param mixed ...$arguments the arguments to check
|
|
* @return Response|null `null` if all `arguments` are set, or an error response otherwise
|
|
*/
|
|
function validate_has_arguments(mixed ...$arguments): ?Response
|
|
{
|
|
foreach (func_get_args() as $argument)
|
|
if (!isset($argument))
|
|
return new Response("Missing argument.", false);
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/// Process request
|
|
$response = null;
|
|
|
|
if (isset($_POST["action"])) {
|
|
// Process POST
|
|
switch ($_POST["action"]) {
|
|
case "register":
|
|
$response = validate_csrf()
|
|
?? validate_logged_out()
|
|
?? validate_has_arguments($_POST["email"], $_POST["password"], $_POST["password_confirm"])
|
|
?? $user_manager->register($_POST["email"], $_POST["password"], $_POST["password_confirm"]);
|
|
break;
|
|
case "login":
|
|
$response = validate_csrf()
|
|
?? validate_logged_out()
|
|
?? validate_has_arguments($_POST["email"], $_POST["password"]);
|
|
if ($response !== null) break;
|
|
|
|
[$response, $uuid] = $user_manager->check_login($_POST["email"], $_POST["password"]);
|
|
if ($uuid !== null) $_SESSION["uuid"] = $uuid;
|
|
break;
|
|
case "logout":
|
|
$response = validate_csrf() ?? validate_logged_in();
|
|
if ($response !== null) break;
|
|
|
|
session_destroy();
|
|
session_start();
|
|
$_SESSION["token"] = generate_csrf_token($logger);
|
|
$response = new Response(null, true);
|
|
break;
|
|
case "update-email":
|
|
$response = validate_csrf()
|
|
?? validate_logged_in()
|
|
?? validate_has_arguments($_POST["email"])
|
|
?? $user_manager->set_email($_SESSION["uuid"], $_POST["email"]);
|
|
break;
|
|
case "update-password":
|
|
$response = validate_csrf()
|
|
?? validate_logged_in()
|
|
?? validate_has_arguments($_POST["password_old"], $_POST["password_new"], $_POST["password_confirm"])
|
|
?? $user_manager->set_password(
|
|
$_SESSION["uuid"],
|
|
$_POST["password_old"],
|
|
$_POST["password_new"],
|
|
$_POST["password_confirm"]
|
|
);
|
|
break;
|
|
case "user-delete":
|
|
$response = validate_csrf()
|
|
?? validate_logged_in()
|
|
?? $user_manager->delete($_SESSION["uuid"]);
|
|
break;
|
|
case "add-tracking":
|
|
$response = validate_csrf()
|
|
?? validate_logged_in()
|
|
?? validate_has_arguments($_POST["person_name"])
|
|
?? $tracking_manager->add_tracking($_SESSION["uuid"], $_POST["person_name"]);
|
|
break;
|
|
case "remove-tracking":
|
|
$response = validate_csrf()
|
|
?? validate_logged_in()
|
|
?? validate_has_arguments($_POST["person_name"])
|
|
?? $tracking_manager->remove_tracking($_SESSION["uuid"], $_POST["person_name"]);
|
|
break;
|
|
case "send-test-email":
|
|
$response = validate_csrf() ?? $mailer->send_test_mail();
|
|
break;
|
|
default:
|
|
$response = new Response("Unknown POST action '" . $_POST["action"] . "'.", false);
|
|
break;
|
|
}
|
|
} else if (isset($_GET["action"])) {
|
|
$response = match ($_GET["action"]) {
|
|
"get-user-data" => validate_logged_in() ?? $user_manager->get_user_data($_SESSION["uuid"]),
|
|
"list-trackings" => validate_logged_in() ?? $tracking_manager->list_trackings($_SESSION["uuid"]),
|
|
"is-alive" => $mediawiki->people_are_alive(array("John Cusack", "Cameron Diaz", "John Malkovich")),
|
|
default => new Response("Unknown GET action '" . $_GET["action"] . "'.", false),
|
|
};
|
|
} else {
|
|
$response = new Response("Unknown method.", false);
|
|
}
|
|
|
|
header("Content-type:application/json;charset=utf-8");
|
|
exit(json_encode(array(
|
|
"message" => $response->message,
|
|
"satisfied" => $response->satisfied,
|
|
"token" => $_SESSION["token"]
|
|
)));
|