Composer update, Groups frontend, API improvements

This commit is contained in:
2024-04-02 12:54:05 +02:00
parent 0125c83bea
commit 1e33c3b8d4
12 changed files with 699 additions and 471 deletions

View File

@@ -4,6 +4,8 @@ namespace Core\API {
use Core\Driver\SQL\Expression\Count;
use Core\Objects\Context;
use Core\Objects\DatabaseEntity\Group;
use Core\Objects\DatabaseEntity\User;
abstract class GroupsAPI extends Request {
@@ -22,6 +24,30 @@ namespace Core\API {
$this->lastError = $sql->getLastError();
return $this->success && $res[0]["count"] > 0;
}
protected function getGroup(int $groupId): Group|false {
$sql = $this->context->getSQL();
$group = Group::find($sql, $groupId);
if ($group === false) {
return $this->createError("Error fetching group: " . $sql->getLastError());
} else if ($group === null) {
return $this->createError("This group does not exist.");
}
return $group;
}
protected function getUser(int $userId): User|false {
$sql = $this->context->getSQL();
$user = User::find($sql, $userId, true);
if ($user === false) {
return $this->createError("Error fetching user: " . $sql->getLastError());
} else if ($user === null) {
return $this->createError("This user does not exist.");
}
return $user;
}
}
}
@@ -33,12 +59,14 @@ namespace Core\API\Groups {
use Core\API\Traits\Pagination;
use Core\Driver\SQL\Column\Column;
use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\CondAnd;
use Core\Driver\SQL\Expression\Alias;
use Core\Driver\SQL\Expression\Count;
use Core\Driver\SQL\Join\InnerJoin;
use Core\Driver\SQL\Query\Insert;
use Core\Objects\Context;
use Core\Objects\DatabaseEntity\Group;
use Core\Objects\DatabaseEntity\Route;
use Core\Objects\DatabaseEntity\User;
class Fetch extends GroupsAPI {
@@ -49,7 +77,7 @@ namespace Core\API\Groups {
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall,
self::getPaginationParameters(['id', 'name', 'member_count'])
self::getPaginationParameters(['id', 'name', 'memberCount'])
);
$this->groupCount = 0;
@@ -97,14 +125,9 @@ namespace Core\API\Groups {
}
protected function _execute(): bool {
$sql = $this->context->getSQL();
$groupId = $this->getParam("id");
$group = Group::find($sql, $groupId);
if ($group === false) {
return $this->createError("Error fetching group: " . $sql->getLastError());
} else if ($group === null) {
return $this->createError("Group not found");
} else {
$group = $this->getGroup($groupId);
if ($group) {
$this->result["group"] = $group->jsonSerialize();
}
@@ -157,10 +180,10 @@ namespace Core\API\Groups {
class Create extends GroupsAPI {
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall, array(
parent::__construct($context, $externalCall, [
'name' => new StringType('name', 32),
'color' => new StringType('color', 10),
));
]);
}
public function _execute(): bool {
@@ -199,6 +222,55 @@ namespace Core\API\Groups {
}
}
class Update extends GroupsAPI {
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall, [
"id" => new Parameter("id", Parameter::TYPE_INT),
'name' => new StringType('name', 32),
'color' => new StringType('color', 10),
]);
}
public function _execute(): bool {
$sql = $this->context->getSQL();
$groupId = $this->getParam("id");
$name = $this->getParam("name");
if (preg_match("/^[a-zA-Z][a-zA-Z0-9_-]*$/", $name) !== 1) {
return $this->createError("Invalid name");
}
$color = $this->getParam("color");
if (preg_match("/^#[a-fA-F0-9]{3,6}$/", $color) !== 1) {
return $this->createError("Invalid color");
}
$group = $this->getGroup($groupId);
if ($group === false) {
return false;
}
$otherGroup = Group::findBy(Group::createBuilder($sql, true)
->whereNeq("id", $groupId)
->whereEq("name", $name)
->first());
if ($otherGroup) {
return $this->createError("This name is already in use");
}
$group->name = $name;
$group->color = $color;
$this->success = ($group->save($sql) !== FALSE);
$this->lastError = $sql->getLastError();
return $this->success;
}
public static function getDefaultACL(Insert $insert): void {
$insert->addRow(self::getEndpoint(), [Group::ADMIN], "Allows users to update existing groups", true);
}
}
class Delete extends GroupsAPI {
public function __construct(Context $context, $externalCall = false) {
parent::__construct($context, $externalCall, array(
@@ -213,16 +285,13 @@ namespace Core\API\Groups {
}
$sql = $this->context->getSQL();
$group = Group::find($sql, $id);
if ($group === false) {
return $this->createError("Error fetching group: " . $sql->getLastError());
} else if ($group === null) {
return $this->createError("This group does not exist.");
} else {
$group = $this->getGroup($id);
if ($group) {
$this->success = ($group->delete($sql) !== FALSE);
$this->lastError = $sql->getLastError();
return $this->success;
}
return $this->success;
}
public static function getDefaultACL(Insert $insert): void {
@@ -233,32 +302,31 @@ namespace Core\API\Groups {
class AddMember extends GroupsAPI {
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, [
new Parameter("id", Parameter::TYPE_INT),
new Parameter("userId", Parameter::TYPE_INT)
"id" => new Parameter("id", Parameter::TYPE_INT),
"userId" => new Parameter("userId", Parameter::TYPE_INT)
]);
}
protected function _execute(): bool {
$sql = $this->context->getSQL();
$groupId = $this->getParam("id");
$userId = $this->getParam("userId");
$group = Group::find($sql, $groupId);
$group = $this->getGroup($groupId);
if ($group === false) {
return $this->createError("Error fetching group: " . $sql->getLastError());
} else if ($group === null) {
return $this->createError("This group does not exist.");
return false;
}
$user = User::find($sql, $userId, true);
$userId = $this->getParam("userId");
$currentUser = $this->context->getUser();
$user = $this->getUser($userId);
if ($user === false) {
return $this->createError("Error fetching user: " . $sql->getLastError());
} else if ($user === null) {
return $this->createError("This user does not exist.");
return false;
} else if (isset($user->getGroups()[$groupId])) {
return $this->createError("This user is already member of this group.");
} else if ($groupId === Group::ADMIN && !$currentUser->hasGroup(Group::ADMIN)) {
return $this->createError("You cannot add the administrator group to other users.");
}
$user->groups[$groupId] = $group;
$sql = $this->context->getSQL();
$this->success = $user->save($sql, ["groups"], true);
if (!$this->success) {
return $this->createError("Error saving user: " . $sql->getLastError());
@@ -275,32 +343,31 @@ namespace Core\API\Groups {
class RemoveMember extends GroupsAPI {
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, [
new Parameter("id", Parameter::TYPE_INT),
new Parameter("userId", Parameter::TYPE_INT)
"id" => new Parameter("id", Parameter::TYPE_INT),
"userId" => new Parameter("userId", Parameter::TYPE_INT)
]);
}
protected function _execute(): bool {
$sql = $this->context->getSQL();
$groupId = $this->getParam("id");
$userId = $this->getParam("userId");
$group = Group::find($sql, $groupId);
$group = $this->getGroup($groupId);
if ($group === false) {
return $this->createError("Error fetching group: " . $sql->getLastError());
} else if ($group === null) {
return $this->createError("This group does not exist.");
return false;
}
$user = User::find($sql, $userId, true);
$userId = $this->getParam("userId");
$currentUser = $this->context->getUser();
$user = $this->getUser($userId);
if ($user === false) {
return $this->createError("Error fetching user: " . $sql->getLastError());
} else if ($user === null) {
return $this->createError("This user does not exist.");
return false;
} else if (!isset($user->getGroups()[$groupId])) {
return $this->createError("This user is not member of this group.");
} else if ($userId === $currentUser->getId() && $groupId === Group::ADMIN) {
return $this->createError("Cannot remove Administrator group from own user.");
}
unset($user->groups[$groupId]);
$sql = $this->context->getSQL();
$this->success = $user->save($sql, ["groups"], true);
if (!$this->success) {
return $this->createError("Error saving user: " . $sql->getLastError());

View File

@@ -88,13 +88,12 @@ namespace Core\API\Language {
return $this->success;
}
private function updateLanguage(): bool {
private function updateLanguage(): void {
$sql = $this->context->getSQL();
$currentUser = $this->context->getUser();
$currentUser->language = $this->language;
$this->success = $currentUser->save($sql, ["language"]);
$this->lastError = $sql->getLastError();
return $this->success;
}
public function _execute(): bool {
@@ -141,12 +140,12 @@ namespace Core\API\Language {
}
$moduleFound = false;
foreach (["Site", "Core"] as $baseDir) {
$filePath = realpath(implode("/", [$baseDir, "Localization", $code, "$module.php"]));
foreach (["Core", "Site"] as $baseDir) {
$filePath = realpath(implode("/", [WEBROOT, $baseDir, "Localization", $code, "$module.php"]));
if ($filePath && is_file($filePath)) {
$moduleFound = true;
$moduleEntries = @include_once $filePath;
$entries[$module] = $moduleEntries;
$entries[$module] = array_merge($entries[$module] ?? [], $moduleEntries);
break;
}
}

View File

@@ -106,8 +106,11 @@ class Swagger extends Request {
"post" => [
"produces" => ["application/json"],
"responses" => [
"200" => ["description" => ""],
"200" => ["description" => "OK!"],
"400" => ["description" => "Parameter validation failed"],
"401" => ["description" => "Login or 2FA Authorization is required"],
"403" => ["description" => "CSRF-Token validation failed or insufficient permissions"],
"503" => ["description" => "Function is disabled"],
]
]
];

View File

@@ -136,6 +136,7 @@ namespace Core\API\User {
use Core\API\UserAPI;
use Core\API\VerifyCaptcha;
use Core\Driver\SQL\Condition\CondBool;
use Core\Driver\SQL\Condition\CondLike;
use Core\Driver\SQL\Condition\CondOr;
use Core\Driver\SQL\Expression\Alias;
use Core\Driver\SQL\Query\Insert;
@@ -320,6 +321,39 @@ namespace Core\API\User {
}
}
class Search extends UserAPI {
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, [
"query" => new StringType("query", 64)
]);
}
protected function _execute(): bool {
$sql = $this->context->getSQL();
$query = $this->getParam("query");
$users = User::findBy(User::createBuilder($sql, false)
->where(new CondOr(
new CondLike(new Column("name"), "%$query%"),
new CondLike(new Column("full_name"), "%$query%"),
new CondLike(new Column("email"), "%$query%"),
))
->whereTrue("active")
);
if ($users === false) {
return $this->createError($sql->getLastError());
}
$this->result["users"] = $users;
return true;
}
public static function getDefaultACL(Insert $insert): void {
$insert->addRow(self::getEndpoint(), "Allows users to search other users", [Group::ADMIN, Group::SUPPORT], true);
}
}
class Info extends UserAPI {
public function __construct(Context $context, $externalCall = false) {