Added optional string role IDs for the API.
This commit is contained in:
parent
37a3bc1ee6
commit
f8aaa71260
6 changed files with 125 additions and 39 deletions
13
database/2024_09_16_205613_add_role_id_string.php
Normal file
13
database/2024_09_16_205613_add_role_id_string.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
use Index\Data\IDbConnection;
|
||||
use Index\Data\Migration\IDbMigration;
|
||||
|
||||
final class AddRoleIdString_20240916_205613 implements IDbMigration {
|
||||
public function migrate(IDbConnection $conn): void {
|
||||
$conn->execute(<<<SQL
|
||||
ALTER TABLE msz_roles
|
||||
ADD COLUMN role_string VARCHAR(20) NULL DEFAULT NULL COLLATE 'ascii_general_ci' AFTER role_id,
|
||||
ADD UNIQUE INDEX roles_string_unique (role_string);
|
||||
SQL);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
|||
break;
|
||||
}
|
||||
|
||||
$roleString = (string)filter_input(INPUT_POST, 'ur_string');
|
||||
$roleName = (string)filter_input(INPUT_POST, 'ur_name');
|
||||
$roleHide = !empty($_POST['ur_hidden']);
|
||||
$roleLeavable = !empty($_POST['ur_leavable']);
|
||||
|
@ -54,6 +55,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
|||
$colourBlue = (int)filter_input(INPUT_POST, 'ur_col_blue', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
Template::set([
|
||||
'role_ur_string' => $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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Role String (used in API)</div>
|
||||
<div class="form__label__input">
|
||||
{{ input_text('ur_string', '', role_ur_string|default(role_info.string|default()), 'text', '', false, {'maxlength':20}) }}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Hide Role</div>
|
||||
<div class="form__label__input">
|
||||
|
@ -44,7 +51,6 @@
|
|||
{{ input_text('ur_title', '', role_ur_title|default(role_info.title|default()), 'text', '', false, {'maxlength':64}) }}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
|
Loading…
Reference in a new issue