From e7cddfd37e055bb533279a40876b0d56d2ff4666 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sat, 17 Nov 2018 21:37:18 +0100 Subject: [PATCH] Added personal role management. --- assets/less/classes/settings/role.less | 66 +++++++++++++++++++ assets/less/classes/settings/session.less | 2 +- assets/less/main.less | 1 + build.php | 56 +++++++++++----- ...18_11_17_191807_roles_table_extensions.php | 22 +++++++ public/manage/users.php | 8 +-- public/members.php | 2 +- public/settings.php | 32 +++++++-- src/Users/role.php | 26 ++++++++ src/Users/user.php | 4 ++ templates/manage/users/roles_create.twig | 2 +- templates/user/settings.twig | 36 ++++++++++ 12 files changed, 226 insertions(+), 31 deletions(-) create mode 100644 assets/less/classes/settings/role.less create mode 100644 database/2018_11_17_191807_roles_table_extensions.php diff --git a/assets/less/classes/settings/role.less b/assets/less/classes/settings/role.less new file mode 100644 index 00000000..75f92152 --- /dev/null +++ b/assets/less/classes/settings/role.less @@ -0,0 +1,66 @@ +.settings__role { + border: 1px solid var(--accent-colour); + background-color: var(--accent-colour); + border-radius: 2px; + margin: 2px; + overflow: none; + width: 200px; + + &__collection { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: 2px; + } + + &__content { + background-color: var(--background-colour-translucent); + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + } + + &__name { + font-size: 1.2em; + line-height: 1.7em; + border-bottom: 1px solid var(--accent-colour); + padding: 0 5px; + } + + &__description { + font-size: .9em; + line-height: 1.8em; + padding: 0 2px; + margin: 0 2px; + flex: 1 1 auto; + } + + &__options { + flex: 0 0 auto; + display: flex; + font-size: 1.5em; + justify-content: space-evenly; + } + + &__option { + border: 0; + background: transparent; + color: inherit; + font: inherit; + text-shadow: inherit; + transition: color .2s; + flex: 0 0 auto; + width: 40px; + height: 40px; + + &:not(&--disabled):hover { + color: var(--accent-colour); + cursor: pointer; + } + + &--disabled { + opacity: .2; + } + } +} diff --git a/assets/less/classes/settings/session.less b/assets/less/classes/settings/session.less index 9555d315..bb469e93 100644 --- a/assets/less/classes/settings/session.less +++ b/assets/less/classes/settings/session.less @@ -5,7 +5,7 @@ overflow: hidden; &--current { - // todo: make this now bad + // todo: make this not bad background-image: linear-gradient(0deg, #111c, #111c); background-color: var(--accent-colour); } diff --git a/assets/less/main.less b/assets/less/main.less index 553b3ba3..d74240df 100644 --- a/assets/less/main.less +++ b/assets/less/main.less @@ -133,6 +133,7 @@ body { @import "classes/settings/login-history"; @import "classes/settings/session"; @import "classes/settings/sessions"; +@import "classes/settings/role"; // News @import "classes/news/container"; diff --git a/build.php b/build.php index 828859dc..2f24177a 100644 --- a/build.php +++ b/build.php @@ -141,23 +141,35 @@ function recursiveConcat(string $source, string $existing = ''): string return $existing; } +$doAll = empty($argv[1]) || $argv[1] === 'all'; +$doCss = $doAll || $argv[1] === 'css'; +$doJs = $doAll || $argv[1] === 'js'; + // Make sure we're running from the misuzu root directory. chdir(__DIR__); misuzu_log('Cleanup'); -createDirIfNotExist(CSS_DIR); -createDirIfNotExist(JS_DIR); -deleteAllFilesInDir(CSS_DIR, '*.css'); -deleteAllFilesInDir(JS_DIR, '*.js'); -deleteAllFilesInDir(TS_DIR, '*.d.ts'); -misuzu_log(); -misuzu_log('Compiling LESS'); +if ($doCss) { + createDirIfNotExist(CSS_DIR); + deleteAllFilesInDir(CSS_DIR, '*.css'); +} -if (!is_file(LESS_DIR . LESS_ENTRY_POINT)) { - misuzu_log('==> ERR: Entry point for this style does not exist (' . basename(LESS_ENTRY_POINT) . ')'); -} else { - system(sprintf(LESS_CMD, escapeshellarg(LESS_DIR . LESS_ENTRY_POINT), LESS_DEST)); +if ($doJs) { + createDirIfNotExist(JS_DIR); + deleteAllFilesInDir(JS_DIR, '*.js'); + deleteAllFilesInDir(TS_DIR, '*.d.ts'); +} + +if ($doCss) { + misuzu_log(); + misuzu_log('Compiling LESS'); + + if (!is_file(LESS_DIR . LESS_ENTRY_POINT)) { + misuzu_log('==> ERR: Entry point for this style does not exist (' . basename(LESS_ENTRY_POINT) . ')'); + } else { + system(sprintf(LESS_CMD, escapeshellarg(LESS_DIR . LESS_ENTRY_POINT), LESS_DEST)); + } } misuzu_log(); @@ -169,16 +181,22 @@ define('IMPORT_SEQ', [ 'files' => NODE_IMPORT_CSS, 'destination' => NODE_DEST_CSS, 'insert-semicolon' => false, + 'do' => $doCss, ], [ 'name' => 'JavaScript', 'files' => NODE_IMPORT_JS, 'destination' => NODE_DEST_JS, 'insert-semicolon' => true, + 'do' => $doJs, ], ]); foreach (IMPORT_SEQ as $sequence) { + if (!$sequence['do']) { + continue; + } + misuzu_log("=> {$sequence['name']}"); $contents = ''; @@ -203,12 +221,14 @@ foreach (IMPORT_SEQ as $sequence) { file_put_contents($sequence['destination'], $contents); } -misuzu_log(); -misuzu_log('Compiling TypeScript'); -misuzu_log(shell_exec('tsc --extendedDiagnostics -p tsconfig.json')); -file_put_contents(TS_DEST, recursiveConcat(TS_SRC)); -deleteAllFilesInDir(TS_SRC, '*.js'); -rmdir(TS_SRC); +if ($doJs) { + misuzu_log(); + misuzu_log('Compiling TypeScript'); + misuzu_log(shell_exec('tsc --extendedDiagnostics -p tsconfig.json')); + file_put_contents(TS_DEST, recursiveConcat(TS_SRC)); + deleteAllFilesInDir(TS_SRC, '*.js'); + rmdir(TS_SRC); +} misuzu_log(); misuzu_log('Copying data...'); @@ -222,7 +242,7 @@ foreach (NODE_COPY_DIRECTORY as $source => $dest) { } // no need to do this in debug mode, auto reload is enabled and cache is disabled -if (!file_exists(__DIR__ . '/.debug')) { +if ($doAll && !file_exists(__DIR__ . '/.debug')) { // Clear Twig cache misuzu_log(); misuzu_log('Deleting template cache'); diff --git a/database/2018_11_17_191807_roles_table_extensions.php b/database/2018_11_17_191807_roles_table_extensions.php new file mode 100644 index 00000000..b1eee64c --- /dev/null +++ b/database/2018_11_17_191807_roles_table_extensions.php @@ -0,0 +1,22 @@ +exec(" + ALTER TABLE `msz_roles` + CHANGE COLUMN `role_secret` `role_hidden` TINYINT(1) NOT NULL DEFAULT '0' AFTER `role_description`, + ADD COLUMN `role_can_leave` TINYINT(1) NOT NULL DEFAULT '0' AFTER `role_hidden`; + "); +} + +function migrate_down(PDO $conn): void +{ + $conn->exec(" + ALTER TABLE `msz_roles` + CHANGE COLUMN `role_hidden` `role_secret` TINYINT(1) NOT NULL DEFAULT '0' AFTER `role_description`, + DROP COLUMN `role_can_leave`; + "); +} diff --git a/public/manage/users.php b/public/manage/users.php index 50b1c192..4007b609 100644 --- a/public/manage/users.php +++ b/public/manage/users.php @@ -375,12 +375,12 @@ switch ($_GET['v'] ?? null) { $updateRole = db_prepare(' INSERT INTO `msz_roles` ( - `role_name`, `role_hierarchy`, `role_secret`, `role_colour`, + `role_name`, `role_hierarchy`, `role_hidden`, `role_colour`, `role_description`, `role_title` ) VALUES ( - :role_name, :role_hierarchy, :role_secret, :role_colour, + :role_name, :role_hierarchy, :role_hidden, :role_colour, :role_description, :role_title ) '); @@ -389,7 +389,7 @@ switch ($_GET['v'] ?? null) { UPDATE `msz_roles` SET `role_name` = :role_name, `role_hierarchy` = :role_hierarchy, - `role_secret` = :role_secret, + `role_hidden` = :role_hidden, `role_colour` = :role_colour, `role_description` = :role_description, `role_title` = :role_title @@ -400,7 +400,7 @@ switch ($_GET['v'] ?? null) { $updateRole->bindValue('role_name', $roleName); $updateRole->bindValue('role_hierarchy', $roleHierarchy); - $updateRole->bindValue('role_secret', $roleSecret ? 1 : 0); + $updateRole->bindValue('role_hidden', $roleSecret ? 1 : 0); $updateRole->bindValue('role_colour', $roleColour); $updateRole->bindValue('role_description', $roleDescription); $updateRole->bindValue('role_title', $roleTitle); diff --git a/public/members.php b/public/members.php index 2f0def16..404aaa22 100644 --- a/public/members.php +++ b/public/members.php @@ -78,7 +78,7 @@ if (!$role) { $roles = db_query(' SELECT `role_id`, `role_name`, `role_colour` FROM `msz_roles` - WHERE `role_secret` = 0 + WHERE `role_hidden` = 0 ORDER BY `role_id` ')->fetchAll(PDO::FETCH_ASSOC); diff --git a/public/settings.php b/public/settings.php index 54e0af2c..e11ea6be 100644 --- a/public/settings.php +++ b/public/settings.php @@ -51,9 +51,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - if (!$disableAccountOptions) { - $currentPasswordValid = !empty($_POST['current_password']); + if (!empty($_POST['role'])) { + $roleId = (int)($_POST['role']['id'] ?? 0); + if ($roleId > 0 && user_role_has(user_session_current('user_id'), $roleId)) { + switch ($_POST['role']['mode'] ?? '') { + case 'display': + user_role_set_display(user_session_current('user_id'), $roleId); + break; + + case 'leave': + if (user_role_can_leave($roleId)) { + user_role_remove(user_session_current('user_id'), $roleId); + } else { + $errors[] = "You're not allow to leave this role, an administrator has to remove it for you."; + } + break; + } + } else { + $errors[] = "You're trying to modify a role that hasn't been assigned to you."; + } + } + + if (!$disableAccountOptions && !empty($_POST['current_password'])) { if (!user_password_verify_db(user_session_current('user_id'), $_POST['current_password'] ?? '')) { $errors[] = 'Your password was incorrect.'; } else { @@ -158,17 +178,16 @@ $logins['list'] = user_login_attempts_list($sessions['offset'], $sessions['take' $logs['list'] = audit_log_list($logs['offset'], $logs['take'], user_session_current('user_id')); $getUserRoles = db_prepare(' - SELECT r.`role_id`, r.`role_name` + SELECT r.`role_id`, r.`role_name`, r.`role_description`, r.`role_colour`, r.`role_can_leave` FROM `msz_user_roles` as ur LEFT JOIN `msz_roles` as r ON r.`role_id` = ur.`role_id` WHERE ur.`user_id` = :user_id + ORDER BY r.`role_hierarchy` DESC '); $getUserRoles->bindValue('user_id', user_session_current('user_id')); $userRoles = $getUserRoles->execute() ? $getUserRoles->fetchAll(PDO::FETCH_ASSOC) : []; -var_dump($userRoles); - if (empty($errors)) { // delete this in 2019 $errors[] = 'A few of the elements on this page have been moved to the on-profile editor. To find them, go to your profile and hit the "Edit Profile" button below your avatar.'; } @@ -180,5 +199,6 @@ echo tpl_render('user.settings', [ 'sessions' => $sessions, 'logins' => $logins, 'logs' => $logs, - 'roles' => $userRoles, + 'user_roles' => $userRoles, + 'user_display_role' => user_role_get_display(user_session_current('user_id')), ]); diff --git a/src/Users/role.php b/src/Users/role.php index 8f48d296..b4d95651 100644 --- a/src/Users/role.php +++ b/src/Users/role.php @@ -26,6 +26,17 @@ function user_role_remove(int $userId, int $roleId): bool return $removeRole->execute(); } +function user_role_can_leave(int $roleId): bool +{ + $canLeaveRole = db_prepare(' + SELECT `role_can_leave` != 0 + FROM `msz_roles` + WHERE `role_id` = :role_id + '); + $canLeaveRole->bindValue('role_id', $roleId); + return $canLeaveRole->execute() ? (bool)$canLeaveRole->fetchColumn() : false; +} + function user_role_has(int $userId, int $roleId): bool { $hasRole = db_prepare(' @@ -55,3 +66,18 @@ function user_role_set_display(int $userId, int $roleId): bool return $setDisplay->execute(); } + +function user_role_get_display(int $userId): int +{ + if ($userId < 1) { + return MSZ_ROLE_MAIN; + } + + $fetchRole = db_prepare(' + SELECT `display_role` + FROM `msz_users` + WHERE `user_id` = :user_id + '); + $fetchRole->bindValue('user_id', $userId); + return $fetchRole->execute() ? (int)$fetchRole->fetchColumn() : MSZ_ROLE_MAIN; +} diff --git a/src/Users/user.php b/src/Users/user.php index 0a11915f..6f7ecea8 100644 --- a/src/Users/user.php +++ b/src/Users/user.php @@ -1,4 +1,8 @@
Hide Rank
- {{ input_checkbox('role[secret]', '', edit_role is defined and edit_role.role_secret) }} + {{ input_checkbox('role[secret]', '', edit_role is defined and edit_role.role_hidden) }}
diff --git a/templates/user/settings.twig b/templates/user/settings.twig index e328d423..239b01e7 100644 --- a/templates/user/settings.twig +++ b/templates/user/settings.twig @@ -92,6 +92,42 @@

This is a listing of the user roles you're a part of, you can select which you want to leave or which one you want to boast as your main role which will change your username colour accordingly.

+ +
+ {% for role in user_roles %} + {% set is_display_role = user_display_role == role.role_id %} + +
+
+
+ {{ role.role_name }} +
+ +
+ {{ role.role_description }} +
+ +
+ {{ input_csrf('settings') }} + {{ input_hidden('role[id]', role.role_id) }} + + + + +
+
+
+ {% endfor %} +