From d9a20ae62efdb3047783b0745b20693e9d7d092b Mon Sep 17 00:00:00 2001 From: Roman Hergenreder Date: Fri, 3 Apr 2020 18:09:01 +0200 Subject: [PATCH] Groups & Stuff --- core/Api/Request.class.php | 22 +++++---- core/Api/User/Fetch.class.php | 53 +++++++++++++++++++++ core/Configuration/CreateDatabase.class.php | 4 +- core/Documents/Install.class.php | 1 + core/Driver/SQL/MySQL.class.php | 3 +- core/Driver/SQL/PostgreSQL.class.php | 7 +-- core/Objects/User.class.php | 12 ++++- core/constants.php | 11 +++++ index.php | 15 +++--- 9 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 core/Api/User/Fetch.class.php diff --git a/core/Api/Request.class.php b/core/Api/Request.class.php index 6fb0656..bc04cd6 100644 --- a/core/Api/Request.class.php +++ b/core/Api/Request.class.php @@ -16,24 +16,27 @@ class Request { protected bool $variableParamCount; protected bool $isDisabled; protected bool $apiKeyAllowed; + protected int $requiredGroup; private array $aDefaultParams; private array $allowedMethods; - private bool $externCall; + private bool $externalCall; public function __construct(User $user, bool $externalCall = false, array $params = array()) { $this->user = $user; $this->aDefaultParams = $params; - $this->lastError = ''; + $this->success = false; $this->result = array(); - $this->externCall = $externalCall; + $this->externalCall = $externalCall; $this->isPublic = true; $this->isDisabled = false; $this->loginRequired = false; $this->variableParamCount = false; $this->apiKeyAllowed = true; $this->allowedMethods = array("GET", "POST"); + $this->requiredGroup = 0; + $this->lastError = ""; } protected function forbidMethod($method) { @@ -82,7 +85,7 @@ class Request { $this->result['logoutIn'] = $this->user->getSession()->getExpiresSeconds(); } - if($this->externCall) { + if($this->externalCall) { $values = $_REQUEST; if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER["CONTENT_TYPE"]) && in_array("application/json", explode(";", $_SERVER["CONTENT_TYPE"]))) { $jsonData = json_decode(file_get_contents('php://input'), true); @@ -95,7 +98,7 @@ class Request { return false; } - if($this->externCall && !$this->isPublic) { + if($this->externalCall && !$this->isPublic) { $this->lastError = 'This function is private.'; header('HTTP 1.1 403 Forbidden'); return false; @@ -107,8 +110,7 @@ class Request { return false; } - - if($this->loginRequired) { + if($this->loginRequired || $this->requiredGroup > 0) { $authorized = false; if(isset($values['api_key']) && $this->apiKeyAllowed) { $apiKey = $values['api_key']; @@ -119,6 +121,10 @@ class Request { $this->lastError = 'You are not logged in.'; header('HTTP 1.1 401 Unauthorized'); return false; + } else if($this->requiredGroup > 0 && !$this->user->hasGroup($this->requiredGroup)) { + $this->lastError = "Insufficient permissions. Required group: ". GroupName($this->requiredGroup); + header('HTTP 1.1 401 Unauthorized'); + return false; } } @@ -151,7 +157,7 @@ class Request { public function getResult() { return $this->result; } public function success() { return $this->success; } public function loginRequired() { return $this->loginRequired; } - public function isExternalCall() { return $this->externCall; } + public function isExternalCall() { return $this->externalCall; } public function getJsonResult() { $this->result['success'] = $this->success; diff --git a/core/Api/User/Fetch.class.php b/core/Api/User/Fetch.class.php new file mode 100644 index 0000000..8802ccb --- /dev/null +++ b/core/Api/User/Fetch.class.php @@ -0,0 +1,53 @@ +loginRequired = true; + // $this->requiredGroup = USER_GROUP_ADMIN; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $sql = $this->user->getSQL(); + $res = $sql->select("User.uid as userId", "User.name", "User.email", "Group.uid as groupId", "Group.name as groupName") + ->from("User") + ->leftJoin("UserGroup", "User.uid", "UserGroup.user_id") + ->leftJoin("Group", "Group.uid", "UserGroup.group_id") + ->execute(); + + $this->success = ($res !== FALSE); + $this->lastError = $sql->getLastError(); + + if($this->success) { + $this->result["users"] = array(); + foreach($res as $row) { + $userId = $row["userId"]; + $groupId = $row["groupId"]; + $groupName = $row["groupName"]; + if (!isset($this->result["users"][$userId])) { + $this->result["users"][$userId] = array( + "uid" => $userId, + "name" => $row["name"], + "email" => $row["email"], + "groups" => array(), + ); + } + + if(!is_null($groupId)) { + $this->result["users"][$userId]["groups"][$groupId] = $groupName; + } + } + } + + return $this->success; + } +} \ No newline at end of file diff --git a/core/Configuration/CreateDatabase.class.php b/core/Configuration/CreateDatabase.class.php index 78dea38..d3c66b7 100755 --- a/core/Configuration/CreateDatabase.class.php +++ b/core/Configuration/CreateDatabase.class.php @@ -63,8 +63,8 @@ class CreateDatabase { ->unique("name"); $queries[] = $sql->insert("Group", array("uid", "name")) - ->addRow(USER_GROUP_DEFAULT, "Default") - ->addRow(USER_GROUP_ADMIN, "Administrator"); + ->addRow(USER_GROUP_DEFAULT, USER_GROUP_DEFAULT_NAME) + ->addRow(USER_GROUP_ADMIN, USER_GROUP_ADMIN_NAME); $queries[] = $sql->createTable("UserGroup") ->addInt("user_id") diff --git a/core/Documents/Install.class.php b/core/Documents/Install.class.php index 9857263..4521341 100644 --- a/core/Documents/Install.class.php +++ b/core/Documents/Install.class.php @@ -331,6 +331,7 @@ namespace Documents\Install { ->returning("uid") ->execute() && $sql->insert("UserGroup", array("group_id", "user_id")) + ->addRow(USER_GROUP_DEFAULT, $sql->getLastInsertId()) ->addRow(USER_GROUP_ADMIN, $sql->getLastInsertId()) ->execute(); diff --git a/core/Driver/SQL/MySQL.class.php b/core/Driver/SQL/MySQL.class.php index a05c4d9..98b0f78 100644 --- a/core/Driver/SQL/MySQL.class.php +++ b/core/Driver/SQL/MySQL.class.php @@ -13,7 +13,6 @@ use \Driver\SQL\Column\DateTimeColumn; use Driver\SQL\Column\BoolColumn; use Driver\SQL\Column\JsonColumn; -use Driver\SQL\Query\Insert; use Driver\SQL\Strategy\Strategy; use \Driver\SQL\Strategy\UpdateStrategy; @@ -31,7 +30,7 @@ class MySQL extends SQL { return 'mysqli'; } - // Connection Managment + // Connection Management public function connect() { if(!is_null($this->connection)) { diff --git a/core/Driver/SQL/PostgreSQL.class.php b/core/Driver/SQL/PostgreSQL.class.php index bb807e8..a97aa69 100644 --- a/core/Driver/SQL/PostgreSQL.class.php +++ b/core/Driver/SQL/PostgreSQL.class.php @@ -4,7 +4,6 @@ namespace Driver\SQL; use \Api\Parameter\Parameter; -use \Driver\SQL\Column\Column; use \Driver\SQL\Column\IntColumn; use \Driver\SQL\Column\SerialColumn; use \Driver\SQL\Column\StringColumn; @@ -13,11 +12,7 @@ use \Driver\SQL\Column\DateTimeColumn; use Driver\SQL\Column\BoolColumn; use Driver\SQL\Column\JsonColumn; -use \Driver\SQL\Strategy\CascadeStrategy; -use \Driver\SQL\Strategy\SetDefaultStrategy; -use \Driver\SQL\Strategy\SetNullStrategy; use Driver\SQL\Strategy\Strategy; -use \Driver\SQL\Strategy\UpdateStrategy; class PostgreSQL extends SQL { @@ -33,7 +28,7 @@ class PostgreSQL extends SQL { return 'pgsql'; } - // Connection Managment + // Connection Management public function connect() { if(!is_null($this->connection)) { return true; diff --git a/core/Objects/User.class.php b/core/Objects/User.class.php index ac2c76b..28d6f56 100644 --- a/core/Objects/User.class.php +++ b/core/Objects/User.class.php @@ -19,6 +19,7 @@ class User extends ApiObject { private int $uid; private string $username; private Language $language; + private array $groups; public function __construct($configuration) { session_start(); @@ -52,6 +53,8 @@ class User extends ApiObject { public function setLanguage(Language $language) { $this->language = $language; $language->load(); } public function getSession() { return $this->session; } public function getConfiguration() { return $this->configuration; } + public function getGroups() { return $this->groups; } + public function hasGroup(int $group) { return isset($this->groups[$group]); } public function __debugInfo() { $debugInfo = array( @@ -113,10 +116,12 @@ class User extends ApiObject { public function readData($userId, $sessionId, $sessionUpdate = true) { $res = $this->sql->select("User.name", "Language.uid as langId", "Language.code as langCode", "Language.name as langName", - "Session.data", "Session.stay_logged_in") + "Session.data", "Session.stay_logged_in", "Group.uid as groupId", "Group.name as groupName") ->from("User") ->innerJoin("Session", "Session.user_id", "User.uid") ->leftJoin("Language", "User.language_id", "Language.uid") + ->leftJoin("UserGroup", "UserGroup.user_id", "User.uid") + ->leftJoin("Group", "UserGroup.group_id", "Group.uid") ->where(new Compare("User.uid", $userId)) ->where(new Compare("Session.uid", $sessionId)) ->where(new Compare("Session.active", true)) @@ -136,9 +141,14 @@ class User extends ApiObject { $this->session->stayLoggedIn($row["stay_logged_in"]); if($sessionUpdate) $this->session->update(); $this->loggedIn = true; + if(!is_null($row['langId'])) { $this->setLanguage(Language::newInstance($row['langId'], $row['langCode'], $row['langName'])); } + + foreach($res as $row) { + $this->groups[$row["groupId"]] = $row["groupName"]; + } } } diff --git a/core/constants.php b/core/constants.php index a89eec7..7d4d2f7 100644 --- a/core/constants.php +++ b/core/constants.php @@ -1,4 +1,15 @@ USER_GROUP_DEFAULT_NAME, + USER_GROUP_ADMIN => USER_GROUP_ADMIN_NAME, + ); + + return ($groupNames[$index] ?? "Unknown Group"); +} \ No newline at end of file diff --git a/index.php b/index.php index 7eed76c..b7fe087 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,9 @@ execute(); @@ -69,8 +73,8 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) { $documentName = str_replace("/", "\\", $documentName); $class = "\\Documents\\$documentName"; $file = getClassPath($class); - if(!file_exists($file) || !is_subclass_of($class, \Elements\Document::class)) { - $document = new \Documents\Document404($user); + if(!file_exists($file) || !is_subclass_of($class, Document::class)) { + $document = new Document404($user); } else { $document = new $class($user); } @@ -80,5 +84,4 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) { } $user->sendCookies(); -die($response); -?> +die($response); \ No newline at end of file