web-base/Core/API/RoutesAPI.class.php

404 lines
12 KiB
PHP
Raw Normal View History

2020-06-20 20:13:51 +02:00
<?php
2022-11-18 18:06:46 +01:00
namespace Core\API {
2021-04-07 12:57:00 +02:00
2022-11-18 18:06:46 +01:00
use Core\API\Routes\GenerateCache;
use Core\Objects\Context;
2022-11-27 15:58:44 +01:00
use Core\Objects\DatabaseEntity\Route;
2024-03-28 11:56:17 +01:00
use Core\Objects\Router\ApiRoute;
2021-04-07 12:57:00 +02:00
2020-06-20 20:13:51 +02:00
abstract class RoutesAPI extends Request {
2020-06-21 22:36:50 +02:00
2022-12-04 13:21:40 +01:00
const ROUTER_CACHE_CLASS = "\\Site\\Cache\\RouterCache";
2021-04-07 12:57:00 +02:00
2022-05-31 16:14:49 +02:00
protected string $routerCachePath;
2020-06-21 22:36:50 +02:00
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall, array $params) {
parent::__construct($context, $externalCall, $params);
2023-01-09 15:59:53 +01:00
$this->routerCachePath = WEBROOT . DIRECTORY_SEPARATOR . getClassPath(self::ROUTER_CACHE_CLASS);
2020-06-21 22:36:50 +02:00
}
2021-04-07 12:57:00 +02:00
2022-11-27 15:58:44 +01:00
protected function toggleRoute(int $id, bool $active): bool {
2022-06-20 19:52:31 +02:00
$sql = $this->context->getSQL();
2022-11-27 15:58:44 +01:00
$route = Route::find($sql, $id);
if ($route === false) {
2021-04-07 12:57:00 +02:00
return false;
2022-11-27 15:58:44 +01:00
} else if ($route === null) {
return $this->createError("Route not found");
2024-03-28 11:56:17 +01:00
} else if ($route instanceof ApiRoute) {
return $this->createError("This route cannot be modified");
2021-04-07 12:57:00 +02:00
}
2022-11-27 15:58:44 +01:00
$route->setActive($active);
2022-11-29 14:17:11 +01:00
$this->success = $route->save($sql, ["active"]);
2021-04-07 12:57:00 +02:00
$this->lastError = $sql->getLastError();
2022-11-27 15:58:44 +01:00
return $this->success && $this->regenerateCache();
2022-05-31 16:14:49 +02:00
}
protected function regenerateCache(): bool {
2022-06-20 19:52:31 +02:00
$req = new GenerateCache($this->context);
2022-05-31 16:14:49 +02:00
$this->success = $req->execute();
$this->lastError = $req->getLastError();
2021-04-07 12:57:00 +02:00
return $this->success;
}
2022-11-27 15:58:44 +01:00
protected function createRoute(string $type, string $pattern, string $target,
?string $extra, bool $exact, bool $active = true): ?Route {
$routeClass = Route::ROUTE_TYPES[$type] ?? null;
if (!$routeClass) {
$this->createError("Invalid type: $type");
return null;
}
try {
$routeClass = new \ReflectionClass($routeClass);
$routeObj = $routeClass->newInstance($pattern, $exact, $target);
$routeObj->setExtra($extra);
$routeObj->setActive($active);
return $routeObj;
} catch (\ReflectionException $exception) {
$this->createError("Error instantiating route class: " . $exception->getMessage());
return null;
}
}
2020-06-20 20:13:51 +02:00
}
}
2022-11-18 18:06:46 +01:00
namespace Core\API\Routes {
use Core\API\Parameter\Parameter;
use Core\API\Parameter\StringType;
use Core\API\RoutesAPI;
use Core\Objects\Context;
2023-01-16 21:47:23 +01:00
use Core\Objects\DatabaseEntity\Group;
2022-11-27 12:33:27 +01:00
use Core\Objects\DatabaseEntity\Route;
2024-03-28 11:56:17 +01:00
use Core\Objects\Router\ApiRoute;
2024-04-02 15:33:00 +02:00
use Core\Objects\Router\EmptyRoute;
2022-11-18 18:06:46 +01:00
use Core\Objects\Router\Router;
2020-06-20 20:13:51 +02:00
class Fetch extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall, array());
2020-06-20 20:13:51 +02:00
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2022-06-20 19:52:31 +02:00
$sql = $this->context->getSQL();
2020-06-20 20:13:51 +02:00
2022-11-27 15:58:44 +01:00
$routes = Route::findAll($sql);
2020-06-20 20:13:51 +02:00
$this->lastError = $sql->getLastError();
2022-11-27 15:58:44 +01:00
$this->success = ($routes !== FALSE);
2020-06-20 20:13:51 +02:00
if ($this->success) {
2024-03-28 11:56:17 +01:00
$this->result["routes"] = $routes;
2020-06-20 20:13:51 +02:00
}
return $this->success;
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to fetch site routing.";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2020-06-20 20:13:51 +02:00
}
class Get extends RoutesAPI {
2020-06-20 20:13:51 +02:00
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall, [
"id" => new Parameter("id", Parameter::TYPE_INT)
]);
2020-06-20 20:13:51 +02:00
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2022-06-20 19:52:31 +02:00
$sql = $this->context->getSQL();
$routeId = $this->getParam("id");
2020-06-20 20:13:51 +02:00
$route = Route::find($sql, $routeId);
2020-06-20 20:13:51 +02:00
$this->lastError = $sql->getLastError();
$this->success = ($route !== FALSE);
2020-06-20 20:13:51 +02:00
2022-11-27 15:58:44 +01:00
if ($this->success) {
if ($route === null) {
return $this->createError("Route not found");
} else {
$this->result["route"] = $route;
2020-06-20 20:13:51 +02:00
}
}
return $this->success;
2020-06-20 20:13:51 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to fetch a single route";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN, Group::MODERATOR];
2023-01-16 21:47:23 +01:00
}
2020-06-20 20:13:51 +02:00
}
2021-04-07 12:57:00 +02:00
class Add extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, array(
2022-11-27 15:58:44 +01:00
"pattern" => new StringType("pattern", 128),
"type" => new StringType("type"),
2021-04-07 12:57:00 +02:00
"target" => new StringType("target", 128),
2022-05-31 16:14:49 +02:00
"extra" => new StringType("extra", 64, true, ""),
2022-11-27 15:58:44 +01:00
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN),
"active" => new Parameter("active", Parameter::TYPE_BOOLEAN, true, true),
2021-04-07 12:57:00 +02:00
));
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2021-04-07 12:57:00 +02:00
2022-11-27 15:58:44 +01:00
$pattern = $this->getParam("pattern");
$type = $this->getParam("type");
2021-04-07 12:57:00 +02:00
$target = $this->getParam("target");
$extra = $this->getParam("extra");
2022-11-27 15:58:44 +01:00
$exact = $this->getParam("exact");
$active = $this->getParam("active");
$route = $this->createRoute($type, $pattern, $target, $extra, $exact, $active);
if ($route === null) {
return false;
2021-04-07 12:57:00 +02:00
}
2022-06-20 19:52:31 +02:00
$sql = $this->context->getSQL();
2022-11-27 15:58:44 +01:00
$this->success = $route->save($sql) !== false;
2021-04-07 12:57:00 +02:00
$this->lastError = $sql->getLastError();
if ($this->success) {
$this->result["routeId"] = $route->getId();
}
2022-11-27 15:58:44 +01:00
return $this->success && $this->regenerateCache();
2021-04-07 12:57:00 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to add new routes";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2021-04-07 12:57:00 +02:00
}
class Update extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, array(
"id" => new Parameter("id", Parameter::TYPE_INT),
2022-11-27 15:58:44 +01:00
"pattern" => new StringType("pattern", 128),
"type" => new StringType("type"),
2021-04-07 12:57:00 +02:00
"target" => new StringType("target", 128),
2022-05-31 16:14:49 +02:00
"extra" => new StringType("extra", 64, true, ""),
2022-12-01 11:01:49 +01:00
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN),
"active" => new Parameter("active", Parameter::TYPE_BOOLEAN, true, true),
2021-04-07 12:57:00 +02:00
));
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2021-04-07 12:57:00 +02:00
2022-06-20 19:52:31 +02:00
$id = $this->getParam("id");
2022-11-27 15:58:44 +01:00
$sql = $this->context->getSQL();
$route = Route::find($sql, $id);
if ($route === false) {
return $this->createError("Error fetching route: " . $sql->getLastError());
} else if ($route === null) {
return $this->createError("Route not found");
2021-04-07 12:57:00 +02:00
}
$target = $this->getParam("target");
$extra = $this->getParam("extra");
2022-11-27 15:58:44 +01:00
$type = $this->getParam("type");
$pattern = $this->getParam("pattern");
$exact = $this->getParam("exact");
$active = $this->getParam("active");
if ($route->getType() !== $type) {
2023-01-16 21:47:23 +01:00
if (!$route->delete($sql)) {
2022-11-27 15:58:44 +01:00
return false;
2023-01-16 21:47:23 +01:00
} else {
$route = $this->createRoute($type, $pattern, $target, $extra, $exact, $active);
if ($route === null) {
return false;
}
2022-11-27 15:58:44 +01:00
}
} else {
$route->setPattern($pattern);
$route->setActive($active);
$route->setExtra($extra);
$route->setTarget($target);
$route->setExact($exact);
2021-04-07 12:57:00 +02:00
}
2022-11-27 15:58:44 +01:00
$this->success = $route->save($sql) !== false;
2021-04-07 12:57:00 +02:00
$this->lastError = $sql->getLastError();
2022-11-27 15:58:44 +01:00
return $this->success && $this->regenerateCache();
2021-04-07 12:57:00 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to update existing routes";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2021-04-07 12:57:00 +02:00
}
class Remove extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, array(
"id" => new Parameter("id", Parameter::TYPE_INT)
2021-04-07 12:57:00 +02:00
));
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2021-04-07 12:57:00 +02:00
2022-11-27 15:58:44 +01:00
$sql = $this->context->getSQL();
$id = $this->getParam("id");
2022-11-27 15:58:44 +01:00
$route = Route::find($sql, $id);
if ($route === false) {
return $this->createError("Error fetching route: " . $sql->getLastError());
} else if ($route === null) {
return $this->createError("Route not found");
2024-03-28 11:56:17 +01:00
} else if ($route instanceof ApiRoute) {
return $this->createError("This route cannot be deleted");
2021-04-07 12:57:00 +02:00
}
2022-11-27 15:58:44 +01:00
$this->success = $route->delete($sql) !== false;
2021-04-07 12:57:00 +02:00
$this->lastError = $sql->getLastError();
2022-11-27 15:58:44 +01:00
return $this->success && $this->regenerateCache();
2021-04-07 12:57:00 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to remove routes";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2021-04-07 12:57:00 +02:00
}
class Enable extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, array(
"id" => new Parameter("id", Parameter::TYPE_INT)
2021-04-07 12:57:00 +02:00
));
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2022-11-27 15:58:44 +01:00
$id = $this->getParam("id");
return $this->toggleRoute($id, true);
2021-04-07 12:57:00 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to enable a route";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2021-04-07 12:57:00 +02:00
}
class Disable extends RoutesAPI {
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, array(
"id" => new Parameter("id", Parameter::TYPE_INT)
2021-04-07 12:57:00 +02:00
));
}
2022-02-21 13:01:03 +01:00
public function _execute(): bool {
2022-11-27 15:58:44 +01:00
$id = $this->getParam("id");
return $this->toggleRoute($id, false);
2021-04-07 12:57:00 +02:00
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to disable a route";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN];
2023-01-16 21:47:23 +01:00
}
2021-04-07 12:57:00 +02:00
}
2022-05-31 16:14:49 +02:00
class GenerateCache extends RoutesAPI {
private ?Router $router;
2022-06-20 19:52:31 +02:00
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, []);
2022-05-31 16:14:49 +02:00
$this->router = null;
}
protected function _execute(): bool {
2022-06-20 19:52:31 +02:00
$sql = $this->context->getSQL();
2022-11-27 12:33:27 +01:00
$routes = Route::findBy(Route::createBuilder($sql, false)
->whereTrue("active")
->orderBy("id")
->ascending());
2022-05-31 16:14:49 +02:00
2022-11-27 12:33:27 +01:00
$this->success = $routes !== false;
2022-05-31 16:14:49 +02:00
$this->lastError = $sql->getLastError();
if (!$this->success) {
return false;
}
2022-06-20 19:52:31 +02:00
$this->router = new Router($this->context);
2022-11-27 12:33:27 +01:00
foreach ($routes as $route) {
$this->router->addRoute($route);
2022-05-31 16:14:49 +02:00
}
$this->success = $this->router->writeCache($this->routerCachePath);
if (!$this->success) {
return $this->createError("Error saving router cache file: " . $this->routerCachePath);
}
return $this->success;
}
public function getRouter(): ?Router {
return $this->router;
}
2023-01-16 21:47:23 +01:00
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "Allows users to regenerate the routing cache";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN, Group::SUPPORT];
2023-01-16 21:47:23 +01:00
}
2022-05-31 16:14:49 +02:00
}
2024-03-27 20:50:57 +01:00
class Check extends RoutesAPI {
public function __construct(Context $context, bool $externalCall) {
parent::__construct($context, $externalCall, [
"pattern" => new StringType("pattern", 128),
"path" => new StringType("path"),
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN, true, true)
2024-03-27 20:50:57 +01:00
]);
}
protected function _execute(): bool {
$path = $this->getParam("path");
$pattern = $this->getParam("pattern");
$exact = $this->getParam("exact");
2024-04-02 15:33:00 +02:00
$route = new EmptyRoute($pattern, $exact, "");
2024-03-27 20:50:57 +01:00
$this->result["match"] = $route->match($path);
return $this->success;
}
2024-04-23 12:14:28 +02:00
public static function getDescription(): string {
return "This endpoint grants the ability to check, if a route pattern is matched with the given path for debugging purposes";
}
public static function getDefaultPermittedGroups(): array {
return [Group::ADMIN, Group::MODERATOR];
2024-03-27 20:50:57 +01:00
}
}
2020-06-20 20:13:51 +02:00
}