diff --git a/Core/API/LogsAPI.class.php b/Core/API/LogsAPI.class.php index cd54eb3..ccb5189 100644 --- a/Core/API/LogsAPI.class.php +++ b/Core/API/LogsAPI.class.php @@ -9,7 +9,6 @@ namespace Core\API { parent::__construct($context, $externalCall, $params); } } - } namespace Core\API\Logs { @@ -34,33 +33,35 @@ namespace Core\API\Logs { use Pagination; + protected array $shownLogLevels; + protected ?\DateTime $since; + public function __construct(Context $context, bool $externalCall = false) { $params = self::getPaginationParameters(['id', 'timestamp', "module", "severity"], 'timestamp', 'desc'); $params["since"] = new Parameter("since", Parameter::TYPE_DATE_TIME, true); - $params["severity"] = new StringType("severity", 32, true, "debug"); + $params["severity"] = new StringType("severity", 32, true, "debug", array_values(Logger::LOG_LEVELS)); $params["query"] = new StringType("query", 64, true, null); parent::__construct($context, $externalCall, $params); - $this->csrfTokenRequired = false; + $this->shownLogLevels = Logger::LOG_LEVELS; + $this->since = null; } - protected function _execute(): bool { - $since = $this->getParam("since"); - $sql = $this->context->getSQL(); + protected function getFilter(): CondIn|CondAnd|bool { + $this->since = $this->getParam("since"); $severity = strtolower(trim($this->getParam("severity"))); $query = $this->getParam("query"); - $shownLogLevels = Logger::LOG_LEVELS; $logLevel = array_search($severity, Logger::LOG_LEVELS, true); if ($logLevel === false) { return $this->createError("Invalid severity. Allowed values: " . implode(",", Logger::LOG_LEVELS)); } else if ($logLevel > 0) { - $shownLogLevels = array_slice(Logger::LOG_LEVELS, $logLevel); + $this->shownLogLevels = array_slice(Logger::LOG_LEVELS, $logLevel); } - $condition = new CondIn(new Column("severity"), $shownLogLevels); - if ($since !== null) { - $condition = new CondAnd($condition, new Compare("timestamp", $since, ">=")); + $condition = new CondIn(new Column("severity"), $this->shownLogLevels); + if ($this->since !== null) { + $condition = new CondAnd($condition, new Compare("timestamp", $this->since, ">=")); } if ($query) { @@ -70,6 +71,48 @@ namespace Core\API\Logs { )); } + return $condition; + } + + protected function loadFromFileSystem(array &$logs): void { + // get all log entries from filesystem (if database failed) + $logPath = realpath(implode(DIRECTORY_SEPARATOR, [WEBROOT, "Site", "Logs"])); + if ($logPath) { + $index = 1; + foreach (scandir($logPath) as $fileName) { + $logFile = $logPath . DIRECTORY_SEPARATOR . $fileName; + // {module}_{severity}_{date}_{time}_{ms}.log + if (preg_match("/^(\w+)_(\w+)_((\d+-\d+-\d+_){2}\d+)\.log$/", $fileName, $matches) && is_file($logFile)) { + $content = @file_get_contents($logFile); + $date = \DateTime::createFromFormat(Logger::LOG_FILE_DATE_FORMAT, $matches[3]); + if ($content && $date) { + + // filter log date + if ($this->since !== null && datetimeDiff($date, $this->since) > 0) { + continue; + } + + // filter log level + if (!in_array(trim(strtolower($matches[2])), $this->shownLogLevels)) { + continue; + } + + $logs[] = [ + "id" => "file-" . ($index++), + "module" => $matches[1], + "severity" => $matches[2], + "message" => $content, + "timestamp" => $date->format(Parameter::DATE_TIME_FORMAT) + ]; + } + } + } + } + } + + protected function _execute(): bool { + $sql = $this->context->getSQL(); + $condition = $this->getFilter(); if (!$this->initPagination($sql, SystemLog::class, $condition)) { return false; } @@ -97,40 +140,7 @@ namespace Core\API\Logs { ]; } - // get all log entries from filesystem (if database failed) - $logPath = realpath(implode(DIRECTORY_SEPARATOR, [WEBROOT, "Site", "Logs"])); - if ($logPath) { - $index = 1; - foreach (scandir($logPath) as $fileName) { - $logFile = $logPath . DIRECTORY_SEPARATOR . $fileName; - // {module}_{severity}_{date}_{time}_{ms}.log - if (preg_match("/^(\w+)_(\w+)_((\d+-\d+-\d+_){2}\d+)\.log$/", $fileName, $matches) && is_file($logFile)) { - $content = @file_get_contents($logFile); - $date = \DateTime::createFromFormat(Logger::LOG_FILE_DATE_FORMAT, $matches[3]); - if ($content && $date) { - - // filter log date - if ($since !== null && datetimeDiff($date, $since) > 0) { - continue; - } - - // filter log level - if (!in_array(trim(strtolower($matches[2])), $shownLogLevels)) { - continue; - } - - $this->result["logs"][] = [ - "id" => "file-" . ($index++), - "module" => $matches[1], - "severity" => $matches[2], - "message" => $content, - "timestamp" => $date->format(Parameter::DATE_TIME_FORMAT) - ]; - } - } - } - } - + $this->loadFromFileSystem($this->result["logs"]); return true; } @@ -138,5 +148,4 @@ namespace Core\API\Logs { $insert->addRow(self::getEndpoint(), [Group::ADMIN], "Allows users to fetch system logs", true); } } - } \ No newline at end of file diff --git a/Core/API/PermissionAPI.class.php b/Core/API/PermissionAPI.class.php index 86297d4..cb10e8d 100644 --- a/Core/API/PermissionAPI.class.php +++ b/Core/API/PermissionAPI.class.php @@ -114,7 +114,7 @@ namespace Core\API\Permission { } $sql = $this->context->getSQL(); - $res = $sql->select("method", "groups", "description", "isCore") + $res = $sql->select("method", "groups", "description", "is_core") ->from("ApiPermission") ->execute(); @@ -127,12 +127,12 @@ namespace Core\API\Permission { $method = $row["method"]; $description = $row["description"]; $groups = json_decode($row["groups"]); - $isCore = $row["isCore"]; + $isCore = $row["is_core"]; $permissions[] = [ "method" => $method, "groups" => $groups, "description" => $description, - "isCore" => $isCore + "is_core" => $isCore ]; } $this->result["permissions"] = $permissions; @@ -181,11 +181,11 @@ namespace Core\API\Permission { } if ($description === null) { - $updateQuery = $sql->insert("ApiPermission", ["method", "groups", "isCore"]) + $updateQuery = $sql->insert("ApiPermission", ["method", "groups", "is_core"]) ->onDuplicateKeyStrategy(new UpdateStrategy(["method"], ["groups" => $groupIds])) ->addRow($method, $groupIds, false); } else { - $updateQuery = $sql->insert("ApiPermission", ["method", "groups", "isCore", "description"]) + $updateQuery = $sql->insert("ApiPermission", ["method", "groups", "is_core", "description"]) ->onDuplicateKeyStrategy(new UpdateStrategy(["method"], ["groups" => $groupIds, "description" => $description])) ->addRow($method, $groupIds, false, $description); } diff --git a/Core/API/Request.class.php b/Core/API/Request.class.php index 2f1b0a6..a404567 100644 --- a/Core/API/Request.class.php +++ b/Core/API/Request.class.php @@ -32,17 +32,20 @@ abstract class Request { $this->context = $context; $this->logger = new Logger($this->getAPIName(), $this->context->getSQL()); $this->defaultParams = $params; + $this->externalCall = $externalCall; + $this->variableParamCount = false; + // result + $this->lastError = ""; $this->success = false; $this->result = array(); - $this->externalCall = $externalCall; + + // restrictions $this->isPublic = true; $this->isDisabled = false; $this->loginRequired = false; - $this->variableParamCount = false; $this->apiKeyAllowed = true; $this->allowedMethods = array("GET", "POST"); - $this->lastError = ""; $this->csrfTokenRequired = true; } @@ -267,14 +270,19 @@ abstract class Request { } $this->success = true; - $success = $this->_execute(); - if ($this->success !== $success) { - // _execute returns a different value then it set for $this->success - // this should actually not occur, how to handle this case? - $this->success = $success; + try { + $success = $this->_execute(); + if ($this->success !== $success) { + // _execute might return a different value then it set for $this->success + // this should actually not occur, how to handle this case? + $this->success = $success; + } + } catch (\Error $err) { + $this->createError($err->getMessage()); + $this->logger->error($err->getMessage()); } - $sql->setLastError(''); + $sql->setLastError(""); return $this->success; } diff --git a/Core/Configuration/CreateDatabase.class.php b/Core/Configuration/CreateDatabase.class.php index 0bc5d7e..72e2408 100644 --- a/Core/Configuration/CreateDatabase.class.php +++ b/Core/Configuration/CreateDatabase.class.php @@ -39,7 +39,7 @@ class CreateDatabase extends DatabaseScript { ->addJson("groups", true, '[]') ->addString("description", 128, false, "") ->primaryKey("method") - ->addBool("isCore", false); + ->addBool("is_core", false); self::loadDefaultACL($queries, $sql); self::loadPatches($queries, $sql); @@ -122,7 +122,7 @@ class CreateDatabase extends DatabaseScript { } public static function loadDefaultACL(array &$queries, SQL $sql) { - $query = $sql->insert("ApiPermission", ["method", "groups", "description", "isCore"]); + $query = $sql->insert("ApiPermission", ["method", "groups", "description", "is_core"]); foreach (Request::getApiEndpoints() as $reflectionClass) { $method = $reflectionClass->getName() . "::getDefaultACL"; diff --git a/Core/Driver/SQL/SQL.class.php b/Core/Driver/SQL/SQL.class.php index 7659a52..714c698 100644 --- a/Core/Driver/SQL/SQL.class.php +++ b/Core/Driver/SQL/SQL.class.php @@ -298,7 +298,7 @@ abstract class SQL { } } - public function setLastError($str) { + public function setLastError($str): void { $this->lastError = $str; } @@ -306,7 +306,7 @@ abstract class SQL { return $this->lastInsertId; } - public function close() { + public function close(): void { $this->disconnect(); $this->connection = NULL; }