web-base/core/Api/RoutesAPI.class.php

399 lines
11 KiB
PHP
Raw Normal View History

2020-06-20 20:13:51 +02:00
<?php
namespace Api {
2021-04-07 12:57:00 +02:00
use Driver\SQL\Condition\Compare;
2020-06-20 20:13:51 +02:00
abstract class RoutesAPI extends Request {
2020-06-21 22:36:50 +02:00
2021-04-07 12:57:00 +02:00
const ACTIONS = array("redirect_temporary", "redirect_permanently", "static", "dynamic");
2020-06-21 22:36:50 +02:00
protected function formatRegex(string $input, bool $append) : string {
$start = startsWith($input, "^");
$end = endsWith($input, "$");
if ($append) {
if (!$start) $input = "^$input";
if (!$end) $input = "$input$";
} else {
if ($start) $input = substr($input, 1);
if ($end) $input = substr($input, 0, strlen($input)-1);
}
return $input;
}
2021-04-07 12:57:00 +02:00
protected function routeExists($uid): bool {
$sql = $this->user->getSQL();
$res = $sql->select($sql->count())
->from("Route")
->where(new Compare("uid", $uid))
->execute();
$this->success = ($res !== false);
$this->lastError = $sql->getLastError();
if ($this->success) {
if ($res[0]["count"] === 0) {
return $this->createError("Route not found");
}
}
return $this->success;
}
protected function toggleRoute($uid, $active): bool {
if (!$this->routeExists($uid)) {
return false;
}
$sql = $this->user->getSQL();
$this->success = $sql->update("Route")
->set("active", $active)
->where(new Compare("uid", $uid))
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}
2020-06-20 20:13:51 +02:00
}
}
namespace Api\Routes {
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
use Api\RoutesAPI;
use Driver\SQL\Column\Column;
2021-04-07 12:57:00 +02:00
use Driver\SQL\Condition\Compare;
2020-06-20 20:13:51 +02:00
use Driver\SQL\Condition\CondBool;
2020-06-24 16:09:04 +02:00
use Driver\SQL\Condition\CondRegex;
2021-04-07 12:57:00 +02:00
use Objects\User;
2020-06-20 20:13:51 +02:00
class Fetch extends RoutesAPI {
public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array());
}
2021-04-02 21:58:06 +02:00
public function execute($values = array()): bool {
2020-06-20 20:13:51 +02:00
if(!parent::execute($values)) {
return false;
}
$sql = $this->user->getSQL();
$res = $sql
->select("uid", "request", "action", "target", "extra", "active")
->from("Route")
->orderBy("uid")
->ascending()
->execute();
$this->lastError = $sql->getLastError();
$this->success = ($res !== FALSE);
if ($this->success) {
$routes = array();
foreach($res as $row) {
$routes[] = array(
"uid" => intval($row["uid"]),
2020-06-21 22:36:50 +02:00
"request" => $this->formatRegex($row["request"], false),
2020-06-20 20:13:51 +02:00
"action" => $row["action"],
"target" => $row["target"],
"extra" => $row["extra"] ?? "",
2020-06-25 16:54:58 +02:00
"active" => intval($sql->parseBool($row["active"])),
2020-06-20 20:13:51 +02:00
);
}
$this->result["routes"] = $routes;
}
return $this->success;
}
}
class Find extends RoutesAPI {
public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array(
'request' => new StringType('request', 128, true, '/')
));
$this->isPublic = false;
}
2021-04-02 21:58:06 +02:00
public function execute($values = array()): bool {
2020-06-20 20:13:51 +02:00
if(!parent::execute($values)) {
return false;
}
$request = $this->getParam('request');
if (!startsWith($request, '/')) {
$request = "/$request";
}
$sql = $this->user->getSQL();
$res = $sql
->select("uid", "request", "action", "target", "extra")
->from("Route")
->where(new CondBool("active"))
2020-06-24 16:09:04 +02:00
->where(new CondRegex($request, new Column("request")))
2021-11-11 14:25:26 +01:00
->orderBy("uid")->ascending()
2020-06-20 20:13:51 +02:00
->limit(1)
->execute();
$this->lastError = $sql->getLastError();
$this->success = ($res !== FALSE);
if ($this->success) {
if (!empty($res)) {
$row = $res[0];
$this->result["route"] = array(
"uid" => intval($row["uid"]),
"request" => $row["request"],
"action" => $row["action"],
"target" => $row["target"],
"extra" => $row["extra"]
);
} else {
$this->result["route"] = NULL;
}
}
return $this->success;
}
}
class Save extends RoutesAPI {
private array $routes;
public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array(
'routes' => new Parameter('routes',Parameter::TYPE_ARRAY, false)
));
}
2021-04-02 21:58:06 +02:00
public function execute($values = array()): bool {
2020-06-20 20:13:51 +02:00
if(!parent::execute($values)) {
return false;
}
if (!$this->validateRoutes()) {
return false;
}
$sql = $this->user->getSQL();
// DELETE old rules
$this->success = ($sql->truncate("Route")->execute() !== FALSE);
$this->lastError = $sql->getLastError();
// INSERT new routes
if ($this->success) {
$stmt = $sql->insert("Route", array("request", "action", "target", "extra", "active"));
2020-06-25 21:53:33 +02:00
2020-06-20 20:13:51 +02:00
foreach($this->routes as $route) {
$stmt->addRow($route["request"], $route["action"], $route["target"], $route["extra"], $route["active"]);
}
$this->success = ($stmt->execute() !== FALSE);
$this->lastError = $sql->getLastError();
}
return $this->success;
}
2021-04-07 12:57:00 +02:00
private function validateRoutes(): bool {
2020-06-20 20:13:51 +02:00
$this->routes = array();
$keys = array(
"request" => Parameter::TYPE_STRING,
"action" => Parameter::TYPE_STRING,
"target" => Parameter::TYPE_STRING,
"extra" => Parameter::TYPE_STRING,
"active" => Parameter::TYPE_BOOLEAN
);
foreach($this->getParam("routes") as $index => $route) {
foreach($keys as $key => $expectedType) {
if (!array_key_exists($key, $route)) {
return $this->createError("Route $index missing key: $key");
}
$value = $route[$key];
$type = Parameter::parseType($value);
2020-06-25 16:54:58 +02:00
if ($type !== $expectedType) {
2020-06-20 20:13:51 +02:00
$expectedTypeName = Parameter::names[$expectedType];
$gotTypeName = Parameter::names[$type];
return $this->createError("Route $index has invalid value for key: $key, expected: $expectedTypeName, got: $gotTypeName");
}
}
$action = $route["action"];
2021-04-07 12:57:00 +02:00
if (!in_array($action, self::ACTIONS)) {
2020-06-20 20:13:51 +02:00
return $this->createError("Invalid action: $action");
}
if(empty($route["request"])) {
return $this->createError("Request cannot be empty.");
}
if(empty($route["target"])) {
return $this->createError("Target cannot be empty.");
}
2020-06-21 22:36:50 +02:00
// add start- and end pattern for database queries
$route["request"] = $this->formatRegex($route["request"], true);
2020-06-20 20:13:51 +02:00
$this->routes[] = $route;
}
return true;
}
}
2021-04-07 12:57:00 +02:00
class Add extends RoutesAPI {
public function __construct(User $user, bool $externalCall = false) {
parent::__construct($user, $externalCall, array(
"request" => new StringType("request", 128),
"action" => new StringType("action"),
"target" => new StringType("target", 128),
"extra" => new StringType("extra", 64, true, ""),
));
$this->isPublic = false;
}
public function execute($values = array()): bool {
if (!parent::execute($values)) {
return false;
}
$request = $this->formatRegex($this->getParam("request"), true);
$action = $this->getParam("action");
$target = $this->getParam("target");
$extra = $this->getParam("extra");
if (!in_array($action, self::ACTIONS)) {
return $this->createError("Invalid action: $action");
}
$sql = $this->user->getSQL();
$this->success = $sql->insert("Route", ["request", "action", "target", "extra"])
->addRow($request, $action, $target, $extra)
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}
}
class Update extends RoutesAPI {
public function __construct(User $user, bool $externalCall = false) {
parent::__construct($user, $externalCall, array(
"uid" => new Parameter("uid", Parameter::TYPE_INT),
"request" => new StringType("request", 128),
"action" => new StringType("action"),
"target" => new StringType("target", 128),
"extra" => new StringType("extra", 64, true, ""),
));
$this->isPublic = false;
}
public function execute($values = array()): bool {
if (!parent::execute($values)) {
return false;
}
$uid = $this->getParam("uid");
if (!$this->routeExists($uid)) {
return false;
}
$request = $this->formatRegex($this->getParam("request"), true);
$action = $this->getParam("action");
$target = $this->getParam("target");
$extra = $this->getParam("extra");
if (!in_array($action, self::ACTIONS)) {
return $this->createError("Invalid action: $action");
}
$sql = $this->user->getSQL();
$this->success = $sql->update("Route")
->set("request", $request)
->set("action", $action)
->set("target", $target)
->set("extra", $extra)
->where(new Compare("uid", $uid))
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}
}
class Remove extends RoutesAPI {
public function __construct(User $user, bool $externalCall = false) {
parent::__construct($user, $externalCall, array(
"uid" => new Parameter("uid", Parameter::TYPE_INT)
));
$this->isPublic = false;
}
public function execute($values = array()): bool {
if (!parent::execute($values)) {
return false;
}
$uid = $this->getParam("uid");
if (!$this->routeExists($uid)) {
return false;
}
$sql = $this->user->getSQL();
$this->success = $sql->delete("Route")
->where(new Compare("uid", $uid))
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}
}
class Enable extends RoutesAPI {
public function __construct(User $user, bool $externalCall = false) {
parent::__construct($user, $externalCall, array(
"uid" => new Parameter("uid", Parameter::TYPE_INT)
));
$this->isPublic = false;
}
public function execute($values = array()): bool {
if (!parent::execute($values)) {
return false;
}
$uid = $this->getParam("uid");
return $this->toggleRoute($uid, true);
}
}
class Disable extends RoutesAPI {
public function __construct(User $user, bool $externalCall = false) {
parent::__construct($user, $externalCall, array(
"uid" => new Parameter("uid", Parameter::TYPE_INT)
));
$this->isPublic = false;
}
public function execute($values = array()): bool {
if (!parent::execute($values)) {
return false;
}
$uid = $this->getParam("uid");
return $this->toggleRoute($uid, false);
}
}
2020-06-20 20:13:51 +02:00
}