Router bugfix, save and update route frontend
This commit is contained in:
@@ -9,6 +9,7 @@ namespace Core\API {
|
||||
|
||||
public function __construct(Context $context, bool $externalCall = false, array $params = array()) {
|
||||
parent::__construct($context, $externalCall, $params);
|
||||
$this->loginRequired = true;
|
||||
}
|
||||
|
||||
protected function fetchAPIKey(int $apiKeyId): ApiKey|bool {
|
||||
@@ -41,7 +42,6 @@ namespace Core\API\ApiKey {
|
||||
public function __construct(Context $context, $externalCall = false) {
|
||||
parent::__construct($context, $externalCall, array());
|
||||
$this->apiKeyAllowed = false;
|
||||
$this->loginRequired = true;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
@@ -73,9 +73,7 @@ namespace Core\API\ApiKey {
|
||||
public function __construct(Context $context, $externalCall = false) {
|
||||
$params = $this->getPaginationParameters(["token", "validUntil", "active"]);
|
||||
$params["showActiveOnly"] = new Parameter("showActiveOnly", Parameter::TYPE_BOOLEAN, true, true);
|
||||
|
||||
parent::__construct($context, $externalCall, $params);
|
||||
$this->loginRequired = true;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
@@ -119,7 +117,7 @@ namespace Core\API\ApiKey {
|
||||
parent::__construct($context, $externalCall, array(
|
||||
"id" => new Parameter("id", Parameter::TYPE_INT),
|
||||
));
|
||||
$this->loginRequired = true;
|
||||
$this->apiKeyAllowed = false;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
@@ -147,7 +145,6 @@ namespace Core\API\ApiKey {
|
||||
parent::__construct($user, $externalCall, array(
|
||||
"id" => new Parameter("id", Parameter::TYPE_INT),
|
||||
));
|
||||
$this->loginRequired = true;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace Core\API\Routes {
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use Core\Objects\Router\ApiRoute;
|
||||
use Core\Objects\Router\Router;
|
||||
use Core\Objects\Router\StaticRoute;
|
||||
|
||||
class Fetch extends RoutesAPI {
|
||||
|
||||
@@ -102,108 +103,40 @@ namespace Core\API\Routes {
|
||||
}
|
||||
}
|
||||
|
||||
class Save extends RoutesAPI {
|
||||
|
||||
private array $routes;
|
||||
class Get extends RoutesAPI {
|
||||
|
||||
public function __construct(Context $context, $externalCall = false) {
|
||||
parent::__construct($context, $externalCall, array(
|
||||
'routes' => new Parameter('routes', Parameter::TYPE_ARRAY, false)
|
||||
));
|
||||
parent::__construct($context, $externalCall, [
|
||||
"id" => new Parameter("id", Parameter::TYPE_INT)
|
||||
]);
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
if (!$this->validateRoutes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = $this->context->getSQL();
|
||||
$sql->startTransaction();
|
||||
$routeId = $this->getParam("id");
|
||||
|
||||
// DELETE old rules;
|
||||
$this->success = ($sql->truncate("Route")->execute() !== FALSE);
|
||||
$route = Route::find($sql, $routeId);
|
||||
$this->lastError = $sql->getLastError();
|
||||
|
||||
// INSERT new routes
|
||||
if ($this->success) {
|
||||
$insertStatement = Route::getHandler($sql)->getInsertQuery($this->routes);
|
||||
$this->success = ($insertStatement->execute() !== FALSE);
|
||||
$this->lastError = $sql->getLastError();
|
||||
}
|
||||
$this->success = ($route !== FALSE);
|
||||
|
||||
if ($this->success) {
|
||||
$sql->commit();
|
||||
return $this->regenerateCache();
|
||||
} else {
|
||||
$sql->rollback();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function validateRoutes(): bool {
|
||||
|
||||
$this->routes = array();
|
||||
$keys = array(
|
||||
"id" => Parameter::TYPE_INT,
|
||||
"pattern" => [Parameter::TYPE_STRING, Parameter::TYPE_INT],
|
||||
"type" => Parameter::TYPE_STRING,
|
||||
"target" => Parameter::TYPE_STRING,
|
||||
"extra" => Parameter::TYPE_STRING,
|
||||
"active" => Parameter::TYPE_BOOLEAN,
|
||||
"exact" => Parameter::TYPE_BOOLEAN,
|
||||
);
|
||||
|
||||
foreach ($this->getParam("routes") as $index => $route) {
|
||||
foreach ($keys as $key => $expectedType) {
|
||||
if (!array_key_exists($key, $route)) {
|
||||
if ($key !== "id") { // id is optional
|
||||
return $this->createError("Route $index missing key: $key");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$value = $route[$key];
|
||||
$type = Parameter::parseType($value);
|
||||
if (!is_array($expectedType)) {
|
||||
$expectedType = [$expectedType];
|
||||
}
|
||||
|
||||
if (!in_array($type, $expectedType)) {
|
||||
if (count($expectedType) > 0) {
|
||||
$expectedTypeName = "expected: " . Parameter::names[$expectedType];
|
||||
} else {
|
||||
$expectedTypeName = "expected one of: " . implode(",", array_map(
|
||||
function ($type) {
|
||||
return Parameter::names[$type];
|
||||
}, $expectedType));
|
||||
}
|
||||
$gotTypeName = Parameter::names[$type];
|
||||
return $this->createError("Route $index has invalid value for key: $key, $expectedTypeName, got: $gotTypeName");
|
||||
}
|
||||
if ($route === null) {
|
||||
return $this->createError("Route not found");
|
||||
} else {
|
||||
$this->result["route"] = $route;
|
||||
}
|
||||
|
||||
$type = $route["type"];
|
||||
if (!isset(Route::ROUTE_TYPES[$type])) {
|
||||
return $this->createError("Invalid type: $type");
|
||||
}
|
||||
|
||||
if (empty($route["pattern"])) {
|
||||
return $this->createError("Pattern cannot be empty.");
|
||||
}
|
||||
|
||||
if (empty($route["target"])) {
|
||||
return $this->createError("Target cannot be empty.");
|
||||
}
|
||||
|
||||
$this->routes[] = $route;
|
||||
}
|
||||
|
||||
return true;
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
public static function getDefaultACL(Insert $insert): void {
|
||||
$insert->addRow(self::getEndpoint(), [Group::ADMIN], "Allows users to save the site routing", true);
|
||||
$insert->addRow(
|
||||
self::getEndpoint(),
|
||||
[Group::ADMIN, Group::MODERATOR],
|
||||
"Allows users to fetch a single route",
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +151,6 @@ namespace Core\API\Routes {
|
||||
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN),
|
||||
"active" => new Parameter("active", Parameter::TYPE_BOOLEAN, true, true),
|
||||
));
|
||||
$this->isPublic = false;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
@@ -237,6 +169,11 @@ namespace Core\API\Routes {
|
||||
$sql = $this->context->getSQL();
|
||||
$this->success = $route->save($sql) !== false;
|
||||
$this->lastError = $sql->getLastError();
|
||||
|
||||
if ($this->success) {
|
||||
$this->result["routeId"] = $route->getId();
|
||||
}
|
||||
|
||||
return $this->success && $this->regenerateCache();
|
||||
}
|
||||
|
||||
@@ -256,7 +193,6 @@ namespace Core\API\Routes {
|
||||
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN),
|
||||
"active" => new Parameter("active", Parameter::TYPE_BOOLEAN, true, true),
|
||||
));
|
||||
$this->isPublic = false;
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
@@ -417,24 +353,17 @@ namespace Core\API\Routes {
|
||||
class Check extends RoutesAPI {
|
||||
public function __construct(Context $context, bool $externalCall) {
|
||||
parent::__construct($context, $externalCall, [
|
||||
"id" => new Parameter("id", Parameter::TYPE_INT),
|
||||
"path" => new StringType("path")
|
||||
"pattern" => new StringType("pattern", 128),
|
||||
"path" => new StringType("path"),
|
||||
"exact" => new Parameter("exact", Parameter::TYPE_BOOLEAN, true, true)
|
||||
]);
|
||||
}
|
||||
|
||||
protected function _execute(): bool {
|
||||
$sql = $this->context->getSQL();
|
||||
$routeId = $this->getParam("id");
|
||||
$route = Route::find($sql, $routeId);
|
||||
if ($route === false) {
|
||||
$this->lastError = $sql->getLastError();
|
||||
return false;
|
||||
} else if ($route === null) {
|
||||
return $this->createError("Route not found");
|
||||
}
|
||||
|
||||
$this->success = true;
|
||||
$path = $this->getParam("path");
|
||||
$pattern = $this->getParam("pattern");
|
||||
$exact = $this->getParam("exact");
|
||||
$route = new StaticRoute($pattern, $exact, "");
|
||||
$this->result["match"] = $route->match($path);
|
||||
return $this->success;
|
||||
}
|
||||
@@ -442,7 +371,7 @@ namespace Core\API\Routes {
|
||||
public static function getDefaultACL(Insert $insert): void {
|
||||
$insert->addRow("routes/check",
|
||||
[Group::ADMIN, Group::MODERATOR],
|
||||
"Users with this permission can see, if a route is matched with the given path for debugging purposes",
|
||||
"Users with this permission can see, if a route pattern is matched with the given path for debugging purposes",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ use Core\Objects\DatabaseEntity\Attribute\MaxLength;
|
||||
use Core\Objects\DatabaseEntity\Attribute\Unique;
|
||||
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;
|
||||
use Core\Objects\Router\DocumentRoute;
|
||||
use Core\Objects\Router\RedirectRoute;
|
||||
use Core\Objects\Router\RedirectPermanentlyRoute;
|
||||
use Core\Objects\Router\RedirectTemporaryRoute;
|
||||
use Core\Objects\Router\Router;
|
||||
use Core\Objects\Router\StaticFileRoute;
|
||||
|
||||
@@ -23,8 +24,8 @@ abstract class Route extends DatabaseEntity {
|
||||
const TYPE_REDIRECT_PERMANENTLY = "redirect_permanently";
|
||||
const TYPE_REDIRECT_TEMPORARY = "redirect_temporary";
|
||||
const ROUTE_TYPES = [
|
||||
self::TYPE_REDIRECT_TEMPORARY => RedirectRoute::class,
|
||||
self::TYPE_REDIRECT_PERMANENTLY => RedirectRoute::class,
|
||||
self::TYPE_REDIRECT_TEMPORARY => RedirectTemporaryRoute::class,
|
||||
self::TYPE_REDIRECT_PERMANENTLY => RedirectPermanentlyRoute::class,
|
||||
self::TYPE_STATIC => StaticFileRoute::class,
|
||||
self::TYPE_DYNAMIC => DocumentRoute::class
|
||||
];
|
||||
@@ -60,6 +61,10 @@ abstract class Route extends DatabaseEntity {
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
public function isExact(): bool {
|
||||
return $this->exact;
|
||||
}
|
||||
|
||||
private static function parseParamType(?string $type): ?int {
|
||||
if ($type === null || trim($type) === "") {
|
||||
return null;
|
||||
|
||||
@@ -2,8 +2,18 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
use Core\Driver\SQL\SQL;
|
||||
|
||||
class RedirectPermanentlyRoute extends RedirectRoute {
|
||||
|
||||
const HTTP_STATUS_CODE = 308;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $destination) {
|
||||
parent::__construct("redirect_permanently", $pattern, $exact, $destination, 308);
|
||||
parent::__construct("redirect_permanently", $pattern, $exact, $destination, self::HTTP_STATUS_CODE);
|
||||
}
|
||||
|
||||
public function postFetch(SQL $sql, array $row) {
|
||||
parent::postFetch($sql, $row);
|
||||
$this->code = self::HTTP_STATUS_CODE;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use JetBrains\PhpStorm\Pure;
|
||||
class RedirectRoute extends Route {
|
||||
|
||||
#[Transient]
|
||||
private int $code;
|
||||
protected int $code;
|
||||
|
||||
public function __construct(string $type, string $pattern, bool $exact, string $destination, int $code = 307) {
|
||||
parent::__construct($type, $pattern, $destination, $exact);
|
||||
|
||||
@@ -2,8 +2,18 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
use Core\Driver\SQL\SQL;
|
||||
|
||||
class RedirectTemporaryRoute extends RedirectRoute {
|
||||
|
||||
const HTTP_STATUS_CODE = 307;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $destination) {
|
||||
parent::__construct("redirect_temporary", $pattern, $exact, $destination, 307);
|
||||
parent::__construct("redirect_temporary", $pattern, $exact, $destination, self::HTTP_STATUS_CODE);
|
||||
}
|
||||
|
||||
public function postFetch(SQL $sql, array $row) {
|
||||
parent::postFetch($sql, $row);
|
||||
$this->code = self::HTTP_STATUS_CODE;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ class StaticRoute extends Route {
|
||||
private int $code;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $data, int $code = 200) {
|
||||
parent::__construct("static", $pattern, $exact);
|
||||
parent::__construct("static", $pattern, "", $exact);
|
||||
$this->data = $data;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user