From f8aaa71260ae2c57b91c626a2981a2b31f1ca71c Mon Sep 17 00:00:00 2001 From: flashwave Date: Mon, 16 Sep 2024 21:44:37 +0000 Subject: [PATCH] Added optional string role IDs for the API. --- .../2024_09_16_205613_add_role_id_string.php | 13 ++++ public-legacy/manage/users/role.php | 36 ++++++++- src/Users/RoleInfo.php | 26 +++++-- src/Users/Roles.php | 73 ++++++++++++------- src/Users/UsersRpcActions.php | 8 ++ templates/manage/users/role.twig | 8 +- 6 files changed, 125 insertions(+), 39 deletions(-) create mode 100644 database/2024_09_16_205613_add_role_id_string.php diff --git a/database/2024_09_16_205613_add_role_id_string.php b/database/2024_09_16_205613_add_role_id_string.php new file mode 100644 index 0000000..9353f70 --- /dev/null +++ b/database/2024_09_16_205613_add_role_id_string.php @@ -0,0 +1,13 @@ +execute(<< $roleString, 'role_ur_name' => $roleName, 'role_ur_hidden' => $roleHide, 'role_ur_leavable' => $roleLeavable, @@ -96,11 +98,31 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { break; } + if(strlen($roleString) > 20) { + echo 'Role string may not be longer than 20 characters.'; + break; + } + if(strlen($roleString) > 1 && !ctype_alpha($roleString[0])) { + echo 'Role string most start with an alphabetical character.'; + break; + } + if($isNew) { - $roleInfo = $roles->createRole($roleName, $roleRank, $roleColour, $roleTitle, $roleDesc, $roleHide, $roleLeavable); + $roleInfo = $roles->createRole( + $roleName, + $roleRank, + $roleColour, + string: $roleString, + title: $roleTitle, + description: $roleDesc, + hidden: $roleHide, + leavable: $roleLeavable + ); } else { if($roleName === $roleInfo->getName()) $roleName = null; + if($roleString === $roleInfo->getString()) + $roleString = null; if($roleHide === $roleInfo->isHidden()) $roleHide = null; if($roleLeavable === $roleInfo->isLeavable()) @@ -115,7 +137,17 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { if((string)$roleColour === (string)$roleInfo->getColour()) $roleColour = null; - $roles->updateRole($roleInfo, $roleName, $roleRank, $roleColour, $roleTitle, $roleDesc, $roleHide, $roleLeavable); + $roles->updateRole( + $roleInfo, + string: $roleString, + name: $roleName, + rank: $roleRank, + colour: $roleColour, + title: $roleTitle, + description: $roleDesc, + hidden: $roleHide, + leavable: $roleLeavable + ); } $msz->createAuditLog( diff --git a/src/Users/RoleInfo.php b/src/Users/RoleInfo.php index db479a6..906295d 100644 --- a/src/Users/RoleInfo.php +++ b/src/Users/RoleInfo.php @@ -9,6 +9,7 @@ use Index\Data\IDbResult; class RoleInfo implements Stringable { public function __construct( private string $id, + private ?string $string, private int $rank, private string $name, private ?string $title, @@ -22,14 +23,15 @@ class RoleInfo implements Stringable { public static function fromResult(IDbResult $result): RoleInfo { return new RoleInfo( id: $result->getString(0), - rank: $result->getInteger(1), - name: $result->getString(2), - title: $result->getStringOrNull(3), - description: $result->getStringOrNull(4), - hidden: $result->getBoolean(5), - leavable: $result->getBoolean(6), - colour: $result->getIntegerOrNull(7), - created: $result->getInteger(8), + string: $result->getStringOrNull(1), + rank: $result->getInteger(2), + name: $result->getString(3), + title: $result->getStringOrNull(4), + description: $result->getStringOrNull(5), + hidden: $result->getBoolean(6), + leavable: $result->getBoolean(7), + colour: $result->getIntegerOrNull(8), + created: $result->getInteger(9), ); } @@ -41,6 +43,14 @@ class RoleInfo implements Stringable { return $this->id === Roles::DEFAULT_ROLE; } + public function hasString(): bool { + return $this->string !== null && $this->string !== ''; + } + + public function getString(): ?string { + return $this->string; + } + public function getRank(): int { return $this->rank; } diff --git a/src/Users/Roles.php b/src/Users/Roles.php index a0d9421..1ec61b6 100644 --- a/src/Users/Roles.php +++ b/src/Users/Roles.php @@ -57,6 +57,8 @@ class Roles { public function getRoles( UserInfo|string|null $userInfo = null, ?bool $hidden = null, + ?bool $hasString = null, + bool $orderByRank = false, ?Pagination $pagination = null ): iterable { if($userInfo instanceof UserInfo) @@ -67,23 +69,26 @@ class Roles { $hasPagination = $pagination !== null; $args = 0; - $query = 'SELECT role_id, role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour, UNIX_TIMESTAMP(role_created) FROM msz_roles'; + $query = 'SELECT role_id, role_string, role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour, UNIX_TIMESTAMP(role_created) FROM msz_roles'; if($hasUserInfo) { ++$args; $query .= ' WHERE role_id IN (SELECT role_id FROM msz_users_roles WHERE user_id = ?)'; } if($hasHidden) $query .= sprintf(' %s role_hidden %s 0', ++$args > 1 ? 'AND' : 'WHERE', $hidden ? '<>' : '='); + if($hasString) + $query .= sprintf(' %s role_string %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $hasString ? 'IS NOT' : 'IS'); + if($orderByRank) + $query .= ' ORDER BY role_hierarchy DESC'; if($hasPagination) $query .= ' LIMIT ? OFFSET ?'; - $args = 0; $stmt = $this->cache->get($query); if($hasUserInfo) - $stmt->addParameter(++$args, $userInfo); + $stmt->nextParameter($userInfo); if($hasPagination) { - $stmt->addParameter(++$args, $pagination->getRange()); - $stmt->addParameter(++$args, $pagination->getOffset()); + $stmt->nextParameter($pagination->getRange()); + $stmt->nextParameter($pagination->getOffset()); } $stmt->execute(); @@ -91,7 +96,7 @@ class Roles { } public function getRole(string $roleId): RoleInfo { - $stmt = $this->cache->get('SELECT role_id, role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour, UNIX_TIMESTAMP(role_created) FROM msz_roles WHERE role_id = ?'); + $stmt = $this->cache->get('SELECT role_id, role_string, role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour, UNIX_TIMESTAMP(role_created) FROM msz_roles WHERE role_id = ?'); $stmt->addParameter(1, $roleId); $stmt->execute(); @@ -106,6 +111,7 @@ class Roles { string $name, int $rank, Colour $colour, + string $string = '', string $title = '', string $description = '', bool $hidden = false, @@ -113,18 +119,22 @@ class Roles { ): RoleInfo { $colour = $colour->shouldInherit() ? null : Colour::toMisuzu($colour); + if($string === '') + $string = null; + // should these continue to accept NULL? if($title === '') $title = null; if($description === '') $description = null; - $stmt = $this->cache->get('INSERT INTO msz_roles (role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour) VALUES (?, ?, ?, ?, ?, ?, ?)'); - $stmt->addParameter(1, $rank); - $stmt->addParameter(2, $name); - $stmt->addParameter(3, $title); - $stmt->addParameter(4, $description); - $stmt->addParameter(5, $hidden ? 1 : 0); - $stmt->addParameter(6, $leavable ? 1 : 0); - $stmt->addParameter(7, $colour); + $stmt = $this->cache->get('INSERT INTO msz_roles (role_string, role_hierarchy, role_name, role_title, role_description, role_hidden, role_can_leave, role_colour) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'); + $stmt->nextParameter($string); + $stmt->nextParameter($rank); + $stmt->nextParameter($name); + $stmt->nextParameter($title); + $stmt->nextParameter($description); + $stmt->nextParameter($hidden ? 1 : 0); + $stmt->nextParameter($leavable ? 1 : 0); + $stmt->nextParameter($colour); $stmt->execute(); return $this->getRole((string)$this->dbConn->getLastInsertId()); @@ -156,6 +166,7 @@ class Roles { public function updateRole( RoleInfo|string $roleInfo, + ?string $string = null, ?string $name = null, ?int $rank = null, ?Colour $colour = null, @@ -167,6 +178,7 @@ class Roles { if($roleInfo instanceof RoleInfo) $roleInfo = $roleInfo->getId(); + $applyString = $string !== null; $applyTitle = $title !== null; $applyDescription = $description !== null; $applyColour = $colour !== null; @@ -176,24 +188,29 @@ class Roles { if($applyColour) $colour = $colour->shouldInherit() ? null : Colour::toMisuzu($colour); + if($string === '') + $string = null; + // should these continue to accept NULL? if($title === '') $title = null; if($description === '') $description = null; - $stmt = $this->cache->get('UPDATE msz_roles SET role_hierarchy = COALESCE(?, role_hierarchy), role_name = COALESCE(?, role_name), role_title = IF(?, ?, role_title), role_description = IF(?, ?, role_description), role_hidden = IF(?, ?, role_hidden), role_can_leave = IF(?, ?, role_can_leave), role_colour = IF(?, ?, role_colour) WHERE role_id = ?'); - $stmt->addParameter(1, $rank); - $stmt->addParameter(2, $name); - $stmt->addParameter(3, $applyTitle ? 1 : 0); - $stmt->addParameter(4, $title); - $stmt->addParameter(5, $applyDescription ? 1 : 0); - $stmt->addParameter(6, $description); - $stmt->addParameter(7, $applyHidden ? 1 : 0); - $stmt->addParameter(8, $hidden ? 1 : 0); - $stmt->addParameter(9, $applyLeavable ? 1 : 0); - $stmt->addParameter(10, $leavable ? 1 : 0); - $stmt->addParameter(11, $applyColour ? 1 : 0); - $stmt->addParameter(12, $colour); - $stmt->addParameter(13, $roleInfo); + $stmt = $this->cache->get('UPDATE msz_roles SET role_string = IF(?, ?, role_string), role_hierarchy = COALESCE(?, role_hierarchy), role_name = COALESCE(?, role_name), role_title = IF(?, ?, role_title), role_description = IF(?, ?, role_description), role_hidden = IF(?, ?, role_hidden), role_can_leave = IF(?, ?, role_can_leave), role_colour = IF(?, ?, role_colour) WHERE role_id = ?'); + $stmt->nextParameter($applyString ? 1 : 0); + $stmt->nextParameter($string); + $stmt->nextParameter($rank); + $stmt->nextParameter($name); + $stmt->nextParameter($applyTitle ? 1 : 0); + $stmt->nextParameter($title); + $stmt->nextParameter($applyDescription ? 1 : 0); + $stmt->nextParameter($description); + $stmt->nextParameter($applyHidden ? 1 : 0); + $stmt->nextParameter($hidden ? 1 : 0); + $stmt->nextParameter($applyLeavable ? 1 : 0); + $stmt->nextParameter($leavable ? 1 : 0); + $stmt->nextParameter($applyColour ? 1 : 0); + $stmt->nextParameter($colour); + $stmt->nextParameter($roleInfo); $stmt->execute(); } diff --git a/src/Users/UsersRpcActions.php b/src/Users/UsersRpcActions.php index a514e95..5abe05c 100644 --- a/src/Users/UsersRpcActions.php +++ b/src/Users/UsersRpcActions.php @@ -6,6 +6,7 @@ use Misuzu\SiteInfo; use Misuzu\URLs\URLRegistry; use Misuzu\Users\Assets\UserAvatarAsset; use Aiwass\Server\{RpcActionHandler,RpcQuery}; +use Index\XArray; use Index\Colour\{Colour,ColourRGB}; final class UsersRpcActions extends RpcActionHandler { @@ -65,6 +66,13 @@ final class UsersRpcActions extends RpcActionHandler { if($userInfo->hasLastActive()) $output['last_active_at'] = $userInfo->getLastActiveAt()->toIso8601ZuluString(); + $roles = XArray::select( + $this->usersCtx->getRoles()->getRoles(userInfo: $userInfo, hasString: true, orderByRank: true), + fn($roleInfo) => $roleInfo->getString(), + ); + if(!empty($roles)) + $output['roles'] = $roles; + if($userInfo->hasTitle()) $output['title'] = $userInfo->getTitle(); diff --git a/templates/manage/users/role.twig b/templates/manage/users/role.twig index 3ee317c..c2a7c8d 100644 --- a/templates/manage/users/role.twig +++ b/templates/manage/users/role.twig @@ -17,6 +17,13 @@ + + -