Added permissions system.

This commit is contained in:
flash 2018-07-08 21:24:59 +02:00
parent ffc23c11fd
commit f924484ac3
16 changed files with 929 additions and 289 deletions

View file

@ -0,0 +1,54 @@
.permissions {
display: flex;
flex-direction: column;
margin-bottom: 4px;
&__line {
display: flex;
font-size: 1.1em;
line-height: 1.4em;
&--header {
font-size: 1.2em;
line-height: 1.5em;
border-bottom: 1px solid #333;
padding-bottom: 1px;
&:not(:first-child) {
margin-top: 4px;
}
}
}
&__title {
flex: 1 1 auto;
padding: 4px;
}
&__input {
cursor: pointer;
}
&__choice {
width: 100px;
text-align: center;
padding: 4px;
&--radio {
cursor: pointer;
border-left: 1px solid #333;
}
&--yes:hover {
background-color: #0a0;
}
&--no:hover {
background-color: #a00;
}
&--never:hover {
background-color: #400;
}
}
}

View file

@ -30,6 +30,7 @@ body {
@import "classes/pagination"; @import "classes/pagination";
@import "classes/user-listing"; @import "classes/user-listing";
@import "classes/permissions";
@import "classes/changelog-change"; @import "classes/changelog-change";
@import "classes/changelog-tags"; @import "classes/changelog-tags";

View file

@ -0,0 +1,39 @@
<?php
namespace Misuzu\DatabaseMigrations\InitialPermissionsTable;
use PDO;
function migrate_up(PDO $conn): void
{
// if you need new permission sets, create a migration that adds a new column to this table.
$conn->exec("
CREATE TABLE `msz_permissions` (
`user_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`role_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`user_perms_allow` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`user_perms_deny` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`changelog_perms_allow` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`changelog_perms_deny` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`news_perms_allow` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`news_perms_deny` INT(10) UNSIGNED NOT NULL DEFAULT '0',
UNIQUE INDEX `user_id` (`user_id`),
UNIQUE INDEX `role_id` (`role_id`),
CONSTRAINT `role_id_foreign`
FOREIGN KEY (`role_id`)
REFERENCES `msz_roles` (`role_id`)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT `user_id_foreign`
FOREIGN KEY (`user_id`)
REFERENCES `msz_users` (`user_id`)
ON UPDATE CASCADE
ON DELETE CASCADE
)
");
}
function migrate_down(PDO $conn): void
{
$conn->exec('DROP TABLE `msz_permissions`');
}

View file

@ -7,6 +7,7 @@ require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/src/changelog.php'; require_once __DIR__ . '/src/changelog.php';
require_once __DIR__ . '/src/colour.php'; require_once __DIR__ . '/src/colour.php';
require_once __DIR__ . '/src/manage.php'; require_once __DIR__ . '/src/manage.php';
require_once __DIR__ . '/src/news.php';
require_once __DIR__ . '/src/perms.php'; require_once __DIR__ . '/src/perms.php';
require_once __DIR__ . '/src/zalgo.php'; require_once __DIR__ . '/src/zalgo.php';
require_once __DIR__ . '/src/Forum/forum.php'; require_once __DIR__ . '/src/Forum/forum.php';
@ -82,7 +83,7 @@ if (PHP_SAPI !== 'cli') {
} }
$inManageMode = starts_with($_SERVER['REQUEST_URI'], '/manage'); $inManageMode = starts_with($_SERVER['REQUEST_URI'], '/manage');
$hasManageAccess = perms_check(perms_get_user(MSZ_PERMS_USER, $app->getUserId()), MSZ_PERM_MANAGE); $hasManageAccess = perms_check(perms_get_user(MSZ_PERMS_USER, $app->getUserId()), MSZ_USER_PERM_CAN_MANAGE);
$tpl->var('has_manage_access', $hasManageAccess); $tpl->var('has_manage_access', $hasManageAccess);
if ($inManageMode) { if ($inManageMode) {

View file

@ -12,7 +12,7 @@ $queryOffset = (int)($_GET['o'] ?? 0);
switch ($_GET['v'] ?? null) { switch ($_GET['v'] ?? null) {
case 'changes': case 'changes':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_CHANGES)) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -67,7 +67,7 @@ switch ($_GET['v'] ?? null) {
break; break;
case 'change': case 'change':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_CHANGES)) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -191,7 +191,7 @@ switch ($_GET['v'] ?? null) {
break; break;
case 'tags': case 'tags':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_TAGS)) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -228,7 +228,7 @@ switch ($_GET['v'] ?? null) {
break; break;
case 'tag': case 'tag':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_TAGS)) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -289,7 +289,7 @@ switch ($_GET['v'] ?? null) {
break; break;
case 'actions': case 'actions':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_ACTIONS)) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -326,7 +326,7 @@ switch ($_GET['v'] ?? null) {
break; break;
case 'action': case 'action':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS)) { if (!perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_ACTIONS)) {
echo render_error(403); echo render_error(403);
break; break;
} }

View file

@ -4,16 +4,22 @@ use Misuzu\Database;
require_once __DIR__ . '/../../misuzu.php'; require_once __DIR__ . '/../../misuzu.php';
$db = Database::connection(); $db = Database::connection();
$templating = $app->getTemplating(); $tpl = $app->getTemplating();
$userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId()); $userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId());
$isPostRequest = $_SERVER['REQUEST_METHOD'] === 'POST'; $isPostRequest = $_SERVER['REQUEST_METHOD'] === 'POST';
$queryQffset = (int)($_GET['o'] ?? 0); $queryQffset = (int)($_GET['o'] ?? 0);
$tpl->vars([
'can_manage_users' => $canManageUsers = perms_check($userPerms, MSZ_USER_PERM_MANAGE_USERS),
'can_manage_roles' => $canManageRoles = perms_check($userPerms, MSZ_USER_PERM_MANAGE_ROLES),
'can_manage_perms' => $canManagePerms = perms_check($userPerms, MSZ_USER_PERM_MANAGE_PERMS),
]);
switch ($_GET['v'] ?? null) { switch ($_GET['v'] ?? null) {
case 'listing': case 'listing':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_USERS)) { if (!$canManageUsers && !$canManagePerms) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -38,17 +44,17 @@ switch ($_GET['v'] ?? null) {
$getManageUsers->bindValue('take', $usersTake); $getManageUsers->bindValue('take', $usersTake);
$manageUsers = $getManageUsers->execute() ? $getManageUsers->fetchAll() : []; $manageUsers = $getManageUsers->execute() ? $getManageUsers->fetchAll() : [];
$templating->vars([ $tpl->vars([
'manage_users' => $manageUsers, 'manage_users' => $manageUsers,
'manage_users_count' => $manageUsersCount, 'manage_users_count' => $manageUsersCount,
'manage_users_range' => $usersTake, 'manage_users_range' => $usersTake,
'manage_users_offset' => $queryQffset, 'manage_users_offset' => $queryQffset,
]); ]);
echo $templating->render('@manage.users.listing'); echo $tpl->render('@manage.users.listing');
break; break;
case 'view': case 'view':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_USERS)) { if (!$canManageUsers && !$canManagePerms) {
echo render_error(403); echo render_error(403);
break; break;
} }
@ -104,22 +110,62 @@ switch ($_GET['v'] ?? null) {
$getAvailableRoles->bindValue('user_id', $manageUser['user_id']); $getAvailableRoles->bindValue('user_id', $manageUser['user_id']);
$availableRoles = $getAvailableRoles->execute() ? $getAvailableRoles->fetchAll() : []; $availableRoles = $getAvailableRoles->execute() ? $getAvailableRoles->fetchAll() : [];
if ($canManagePerms) {
$tpl->var('permissions', $permissions = manage_perms_list(perms_get_user_raw($userId)));
}
if ($isPostRequest) { if ($isPostRequest) {
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
echo 'csrf err'; echo 'csrf err';
break; break;
} }
if (isset($_POST['avatar'])) { if (!empty($_POST['user']) && is_array($_POST['user'])
switch ($_POST['avatar']['mode'] ?? '') { && user_validate_username($_POST['user']['username']) === ''
case 'delete': && user_validate_email($_POST['user']['email']) === '') {
user_avatar_delete($manageUser['user_id']); $updateUserDetails = $db->prepare('
break; UPDATE `msz_users`
SET `username` = :username,
`email` = LOWER(:email),
`user_title` = :title
WHERE `user_id` = :user_id
');
$updateUserDetails->bindValue('username', $_POST['user']['username']);
$updateUserDetails->bindValue('email', $_POST['user']['email']);
$updateUserDetails->bindValue(
'title',
strlen($_POST['user']['title'])
? $_POST['user']['title']
: null
);
$updateUserDetails->bindValue('user_id', $userId);
$updateUserDetails->execute();
}
case 'upload': if (!empty($_POST['avatar']) && !empty($_POST['avatar']['delete'])) {
user_avatar_set_from_path($manageUser['user_id'], $_FILES['avatar']['tmp_name']['file']); user_avatar_delete($manageUser['user_id']);
break; } elseif (!empty($_FILES['avatar'])) {
} user_avatar_set_from_path($manageUser['user_id'], $_FILES['avatar']['tmp_name']['file']);
}
if (!empty($_POST['password'])
&& is_array($_POST['password'])
&& !empty($_POST['password']['new'])
&& !empty($_POST['password']['confirm'])
&& user_validate_password($_POST['password']['new']) === ''
&& $_POST['password']['new'] === $_POST['password']['confirm']) {
$updatePassword = $db->prepare('
UPDATE `msz_users`
SET `password` = :password
WHERE `user_id` = :user_id
');
$updatePassword->bindValue('password', user_password_hash($_POST['password']['new']));
$updatePassword->bindValue('user_id', $userId);
$updatePassword->execute();
}
if (!empty($_POST['profile']) && is_array($_POST['profile'])) {
user_profile_fields_set($userId, $_POST['profile']);
} }
if (isset($_POST['add_role'])) { if (isset($_POST['add_role'])) {
@ -140,26 +186,55 @@ switch ($_GET['v'] ?? null) {
} }
} }
if (!empty($permissions) && !empty($_POST['perms']) && is_array($_POST['perms'])) {
$perms = manage_perms_apply($permissions, $_POST['perms']);
if ($perms !== null) {
$permKeys = array_keys($perms);
$setPermissions = $db->prepare('
REPLACE INTO `msz_permissions`
(`role_id`, `user_id`, `' . implode('`, `', $permKeys) . '`)
VALUES
(NULL, :user_id, :' . implode(', :', $permKeys) . ')
');
$setPermissions->bindValue('user_id', $userId);
foreach ($perms as $key => $value) {
$setPermissions->bindValue($key, $value);
}
$setPermissions->execute();
} else {
$deletePermissions = $db->prepare('
DELETE FROM `msz_permissions`
WHERE `role_id` IS NULL
AND `user_id` = :user_id
');
$deletePermissions->bindValue('user_id', $userId);
$deletePermissions->execute();
}
}
header("Location: ?v=view&u={$manageUser['user_id']}"); header("Location: ?v=view&u={$manageUser['user_id']}");
break; break;
} }
$templating->vars([ $tpl->vars([
'available_roles' => $availableRoles, 'available_roles' => $availableRoles,
'has_roles' => $hasRoles, 'has_roles' => $hasRoles,
'view_user' => $manageUser, 'view_user' => $manageUser,
'profile_fields' => user_profile_fields_get(),
]); ]);
echo $templating->render('@manage.users.view'); echo $tpl->render('@manage.users.view');
break; break;
case 'roles': case 'roles':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_ROLES)) { if (!$canManageRoles && !$canManagePerms) {
echo render_error(403); echo render_error(403);
break; break;
} }
$rolesTake = 10; $rolesTake = 10;
$manageRolesCount = $db->query(' $manageRolesCount = $db->query('
SELECT COUNT(`role_id`) SELECT COUNT(`role_id`)
FROM `msz_roles` FROM `msz_roles`
@ -180,23 +255,27 @@ switch ($_GET['v'] ?? null) {
$getManageRoles->bindValue('take', $rolesTake); $getManageRoles->bindValue('take', $rolesTake);
$manageRoles = $getManageRoles->execute() ? $getManageRoles->fetchAll() : []; $manageRoles = $getManageRoles->execute() ? $getManageRoles->fetchAll() : [];
$templating->vars([ $tpl->vars([
'manage_roles' => $manageRoles, 'manage_roles' => $manageRoles,
'manage_roles_count' => $manageRolesCount, 'manage_roles_count' => $manageRolesCount,
'manage_roles_range' => $rolesTake, 'manage_roles_range' => $rolesTake,
'manage_roles_offset' => $queryQffset, 'manage_roles_offset' => $queryQffset,
]); ]);
echo $templating->render('@manage.users.roles'); echo $tpl->render('@manage.users.roles');
break; break;
case 'role': case 'role':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_ROLES)) { if (!$canManageRoles && !$canManagePerms) {
echo render_error(403); echo render_error(403);
break; break;
} }
$roleId = $_GET['r'] ?? null; $roleId = $_GET['r'] ?? null;
if ($canManagePerms) {
$tpl->var('permissions', $permissions = manage_perms_list(perms_get_role_raw($roleId)));
}
if ($isPostRequest) { if ($isPostRequest) {
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
echo 'csrf err'; echo 'csrf err';
@ -243,28 +322,53 @@ switch ($_GET['v'] ?? null) {
} }
} }
$roleDescription = $_POST['role']['description'] ?? ''; $roleDescription = $_POST['role']['description'] ?? null;
$roleTitle = $_POST['role']['title'] ?? null;
if (strlen($roleDescription) > 1000) { if ($roleDescription !== null) {
echo 'description is too long'; $rdLength = strlen($roleDescription);
break;
if ($rdLength < 1) {
$roleDescription = null;
} elseif ($rdLength > 1000) {
echo 'description is too long';
break;
}
}
if ($roleTitle !== null) {
$rtLength = strlen($roleTitle);
if ($rtLength < 1) {
$roleTitle = null;
} elseif ($rtLength > 64) {
echo 'title is too long';
break;
}
} }
if ($roleId < 1) { if ($roleId < 1) {
$updateRole = $db->prepare(' $updateRole = $db->prepare('
INSERT INTO `msz_roles` INSERT INTO `msz_roles`
(`role_name`, `role_hierarchy`, `role_secret`, `role_colour`, `role_description`, `created_at`) (
`role_name`, `role_hierarchy`, `role_secret`, `role_colour`,
`role_description`, `created_at`, `role_title`
)
VALUES VALUES
(:role_name, :role_hierarchy, :role_secret, :role_colour, :role_description, NOW()) (
:role_name, :role_hierarchy, :role_secret, :role_colour,
:role_description, NOW(), :role_title
)
'); ');
} else { } else {
$updateRole = $db->prepare(' $updateRole = $db->prepare('
UPDATE `msz_roles` SET UPDATE `msz_roles`
`role_name` = :role_name, SET `role_name` = :role_name,
`role_hierarchy` = :role_hierarchy, `role_hierarchy` = :role_hierarchy,
`role_secret` = :role_secret, `role_secret` = :role_secret,
`role_colour` = :role_colour, `role_colour` = :role_colour,
`role_description` = :role_description `role_description` = :role_description,
`role_title` = :role_title
WHERE `role_id` = :role_id WHERE `role_id` = :role_id
'); ');
$updateRole->bindValue('role_id', $roleId); $updateRole->bindValue('role_id', $roleId);
@ -275,12 +379,42 @@ switch ($_GET['v'] ?? null) {
$updateRole->bindValue('role_secret', $roleSecret ? 1 : 0); $updateRole->bindValue('role_secret', $roleSecret ? 1 : 0);
$updateRole->bindValue('role_colour', $roleColour); $updateRole->bindValue('role_colour', $roleColour);
$updateRole->bindValue('role_description', $roleDescription); $updateRole->bindValue('role_description', $roleDescription);
$updateRole->bindValue('role_title', $roleTitle);
$updateRole->execute(); $updateRole->execute();
if ($roleId < 1) { if ($roleId < 1) {
$roleId = (int)$db->lastInsertId(); $roleId = (int)$db->lastInsertId();
} }
if (!empty($permissions) && !empty($_POST['perms']) && is_array($_POST['perms'])) {
$perms = manage_perms_apply($permissions, $_POST['perms']);
if ($perms !== null) {
$permKeys = array_keys($perms);
$setPermissions = $db->prepare('
REPLACE INTO `msz_permissions`
(`role_id`, `user_id`, `' . implode('`, `', $permKeys) . '`)
VALUES
(:role_id, NULL, :' . implode(', :', $permKeys) . ')
');
$setPermissions->bindValue('role_id', $roleId);
foreach ($perms as $key => $value) {
$setPermissions->bindValue($key, $value);
}
$setPermissions->execute();
} else {
$deletePermissions = $db->prepare('
DELETE FROM `msz_permissions`
WHERE `role_id` = :role_id
AND `user_id` IS NULL
');
$deletePermissions->bindValue('role_id', $roleId);
$deletePermissions->execute();
}
}
header("Location: ?v=role&r={$roleId}"); header("Location: ?v=role&r={$roleId}");
break; break;
} }
@ -304,9 +438,9 @@ switch ($_GET['v'] ?? null) {
break; break;
} }
$templating->vars(['edit_role' => $editRole]); $tpl->vars(['edit_role' => $editRole]);
} }
echo $templating->render('@manage.users.roles_create'); echo $tpl->render('@manage.users.roles_create');
break; break;
} }

View file

@ -15,11 +15,11 @@ $userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId());
$settingsModes = [ $settingsModes = [
'account' => [ 'account' => [
'title' => 'Account', 'title' => 'Account',
'allow' => perms_check($userPerms, MSZ_PERM_EDIT_PROFILE), 'allow' => perms_check($userPerms, MSZ_USER_PERM_EDIT_PROFILE),
], ],
'avatar' => [ 'avatar' => [
'title' => 'Avatar', 'title' => 'Avatar',
'allow' => perms_check($userPerms, MSZ_PERM_CHANGE_AVATAR), 'allow' => perms_check($userPerms, MSZ_USER_PERM_CHANGE_AVATAR),
], ],
'sessions' => [ 'sessions' => [
'title' => 'Sessions', 'title' => 'Sessions',

View file

@ -3,16 +3,16 @@ use Misuzu\Application;
use Misuzu\Database; use Misuzu\Database;
use Misuzu\IO\File; use Misuzu\IO\File;
define('MSZ_PERM_EDIT_PROFILE', 1); define('MSZ_USER_PERM_EDIT_PROFILE', 1);
define('MSZ_PERM_CHANGE_AVATAR', 1 << 1); define('MSZ_USER_PERM_CHANGE_AVATAR', 1 << 1);
define('MSZ_PERM_MANAGE', 1 << 20); define('MSZ_USER_PERM_CAN_MANAGE', 1 << 19);
define('MSZ_PERM_MANAGE_USERS', 1 << 21); define('MSZ_USER_PERM_MANAGE_USERS', 1 << 20);
define('MSZ_PERM_MANAGE_ROLES', 1 << 22); define('MSZ_USER_PERM_MANAGE_ROLES', 1 << 21);
define('MSZ_PERM_MANAGE_PERMS', 1 << 23); define('MSZ_USER_PERM_MANAGE_PERMS', 1 << 22);
define('MSZ_PERM_MANAGE_REPORTS', 1 << 24); define('MSZ_USER_PERM_MANAGE_REPORTS', 1 << 23);
define('MSZ_PERM_MANAGE_RESTRICTIONS', 1 << 25); define('MSZ_USER_PERM_MANAGE_RESTRICTIONS', 1 << 24);
define('MSZ_PERM_MANAGE_BLACKLISTS', 1 << 26); define('MSZ_USER_PERM_MANAGE_BLACKLISTS', 1 << 25);
define('MSZ_USERS_PASSWORD_HASH_ALGO', PASSWORD_ARGON2I); define('MSZ_USERS_PASSWORD_HASH_ALGO', PASSWORD_ARGON2I);

View file

@ -1,9 +1,12 @@
<?php <?php
use Misuzu\Database; use Misuzu\Database;
define('MSZ_CHANGELOG_MANAGE_CHANGES', 1); define('MSZ_CHANGELOG_PERM_MANAGE_CHANGES', 1);
define('MSZ_CHANGELOG_MANAGE_TAGS', 1 << 1); define('MSZ_CHANGELOG_PERM_MANAGE_TAGS', 1 << 1);
define('MSZ_CHANGELOG_MANAGE_ACTIONS', 1 << 2); define('MSZ_CHANGELOG_PERM_MANAGE_ACTIONS', 1 << 2);
define('MSZ_CHANGELOG_PERM_DELETE_COMMENTS', 1 << 3);
define('MSZ_CHANGELOG_PERM_EDIT_COMMENTS', 1 << 4);
define('MSZ_CHANGELOG_PERM_PIN_COMMENTS', 1 << 5);
function changelog_action_add(string $name, ?int $colour = null, ?string $class = null): int function changelog_action_add(string $name, ?int $colour = null, ?string $class = null): int
{ {

View file

@ -3,7 +3,7 @@ function manage_get_menu(int $userId): array
{ {
$userPerms = perms_get_user(MSZ_PERMS_USER, $userId); $userPerms = perms_get_user(MSZ_PERMS_USER, $userId);
if (!perms_check($userPerms, MSZ_PERM_MANAGE)) { if (!perms_check($userPerms, MSZ_USER_PERM_CAN_MANAGE)) {
return []; return [];
} }
@ -19,31 +19,23 @@ function manage_get_menu(int $userId): array
'Settings' => '/manage/index.php?v=settings', 'Settings' => '/manage/index.php?v=settings',
]; ];
$canUsers = perms_check($userPerms, MSZ_PERM_MANAGE_USERS); $canUsers = perms_check($userPerms, MSZ_USER_PERM_MANAGE_USERS);
$canRoles = perms_check($userPerms, MSZ_PERM_MANAGE_ROLES); $canRoles = perms_check($userPerms, MSZ_USER_PERM_MANAGE_ROLES);
$canPerms = perms_check($userPerms, MSZ_PERM_MANAGE_PERMS); $canPerms = perms_check($userPerms, MSZ_USER_PERM_MANAGE_PERMS);
$canReports = perms_check($userPerms, MSZ_PERM_MANAGE_REPORTS); $canReports = perms_check($userPerms, MSZ_USER_PERM_MANAGE_REPORTS);
$canRestricts = perms_check($userPerms, MSZ_PERM_MANAGE_RESTRICTIONS); $canRestricts = perms_check($userPerms, MSZ_USER_PERM_MANAGE_RESTRICTIONS);
$canBlacklists = perms_check($userPerms, MSZ_PERM_MANAGE_BLACKLISTS); $canBlacklists = perms_check($userPerms, MSZ_USER_PERM_MANAGE_BLACKLISTS);
if ($canUsers || $canRoles || $canPerms if ($canUsers || $canRoles || $canPerms
|| $canReports || $canRestricts || $canBlacklists) { || $canReports || $canRestricts || $canBlacklists) {
$menu['Users'] = []; $menu['Users'] = [];
if ($canUsers) { if ($canUsers || $canPerms) {
$menu['Users']['Listing'] = '/manage/users.php?v=listing'; $menu['Users']['Listing'] = '/manage/users.php?v=listing';
} }
if ($canRoles || $canPerms) { if ($canRoles || $canPerms) {
$menu['Users'][] = '_'; $menu['Users']['Roles'] = '/manage/users.php?v=roles';
if ($canRoles) {
$menu['Users']['Roles'] = '/manage/users.php?v=roles';
}
if ($canPerms) {
$menu['Users']['Permissions'] = '/manage/users.php?v=permissions';
}
} }
if ($canReports || $canRestricts || $canBlacklists) { if ($canReports || $canRestricts || $canBlacklists) {
@ -69,9 +61,9 @@ function manage_get_menu(int $userId): array
'Settings' => '/manage/forums.php?v=settings', 'Settings' => '/manage/forums.php?v=settings',
];*/ ];*/
$canChanges = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES); $canChanges = perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_CHANGES);
$canChangeTags = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS); $canChangeTags = perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_TAGS);
$canChangeActions = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS); $canChangeActions = perms_check($changelogPerms, MSZ_CHANGELOG_PERM_MANAGE_ACTIONS);
if ($canChanges || $canChangeTags || $canChangeActions) { if ($canChanges || $canChangeTags || $canChangeActions) {
$menu['Changelog'] = []; $menu['Changelog'] = [];
@ -91,3 +83,291 @@ function manage_get_menu(int $userId): array
return $menu; return $menu;
} }
function manage_perms_value(int $perm, int $allow, int $deny): string
{
if (perms_check($deny, $perm)) {
return 'never';
}
if (perms_check($allow, $perm)) {
return 'yes';
}
return 'no';
}
function manage_perms_apply(array $list, array $post): ?array
{
$perms = perms_create();
foreach ($list as $section) {
if (empty($post[$section['section']])
|| !is_array($post[$section['section']])) {
continue;
}
$allowKey = perms_get_key($section['section'], 'allow');
$denyKey = perms_get_key($section['section'], 'deny');
foreach ($section['perms'] as $perm) {
if (empty($post[$section['section']][$perm['section']])) {
continue;
}
switch ($post[$section['section']][$perm['section']]) {
case 'yes':
$perms[$allowKey] |= $perm['perm'];
$perms[$denyKey] &= ~$perm['perm'];
break;
case 'never':
$perms[$allowKey] &= ~$perm['perm'];
$perms[$denyKey] |= $perm['perm'];
break;
case 'no':
default:
$perms[$allowKey] &= ~$perm['perm'];
$perms[$denyKey] &= ~$perm['perm'];
break;
}
}
}
$returnNothing = 0;
foreach ($perms as $perm) {
$returnNothing |= $perm;
}
if ($returnNothing === 0) {
return null;
}
return $perms;
}
function manage_perms_list(array $rawPerms): array
{
return [
[
'section' => 'user',
'title' => 'User',
'perms' => [
[
'section' => 'edit-profile',
'title' => 'Can edit own profile.',
'perm' => MSZ_USER_PERM_EDIT_PROFILE,
'value' => manage_perms_value(
MSZ_USER_PERM_EDIT_PROFILE,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'change-avatar',
'title' => 'Can change own avatar.',
'perm' => MSZ_USER_PERM_CHANGE_AVATAR,
'value' => manage_perms_value(
MSZ_USER_PERM_CHANGE_AVATAR,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'can-manage',
'title' => 'Can access the management panel.',
'perm' => MSZ_USER_PERM_CAN_MANAGE,
'value' => manage_perms_value(
MSZ_USER_PERM_CAN_MANAGE,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-users',
'title' => 'Can manage other users.',
'perm' => MSZ_USER_PERM_MANAGE_USERS,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_USERS,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-roles',
'title' => 'Can manage roles.',
'perm' => MSZ_USER_PERM_MANAGE_ROLES,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_ROLES,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-perms',
'title' => 'Can manage permissions.',
'perm' => MSZ_USER_PERM_MANAGE_PERMS,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_PERMS,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-reports',
'title' => 'Can handle reports.',
'perm' => MSZ_USER_PERM_MANAGE_REPORTS,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_REPORTS,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-restrictions',
'title' => 'Can manage restrictions.',
'perm' => MSZ_USER_PERM_MANAGE_RESTRICTIONS,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_RESTRICTIONS,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
[
'section' => 'manage-blacklistings',
'title' => 'Can manage blacklistings.',
'perm' => MSZ_USER_PERM_MANAGE_BLACKLISTS,
'value' => manage_perms_value(
MSZ_USER_PERM_MANAGE_BLACKLISTS,
$rawPerms['user_perms_allow'],
$rawPerms['user_perms_deny']
),
],
],
],
[
'section' => 'news',
'title' => 'News',
'perms' => [
[
'section' => 'manage-posts',
'title' => 'Can manage posts.',
'perm' => MSZ_NEWS_PERM_MANAGE_POSTS,
'value' => manage_perms_value(
MSZ_NEWS_PERM_MANAGE_POSTS,
$rawPerms['news_perms_allow'],
$rawPerms['news_perms_deny']
),
],
[
'section' => 'manage-cats',
'title' => 'Can manage catagories.',
'perm' => MSZ_NEWS_PERM_MANAGE_CATEGORIES,
'value' => manage_perms_value(
MSZ_NEWS_PERM_MANAGE_CATEGORIES,
$rawPerms['news_perms_allow'],
$rawPerms['news_perms_deny']
),
],
[
'section' => 'comments-delete',
'title' => 'Can delete comments from others.',
'perm' => MSZ_NEWS_PERM_DELETE_COMMENTS,
'value' => manage_perms_value(
MSZ_NEWS_PERM_DELETE_COMMENTS,
$rawPerms['news_perms_allow'],
$rawPerms['news_perms_deny']
),
],
[
'section' => 'comments-edit',
'title' => 'Can edit comments from others.',
'perm' => MSZ_NEWS_PERM_EDIT_COMMENTS,
'value' => manage_perms_value(
MSZ_NEWS_PERM_EDIT_COMMENTS,
$rawPerms['news_perms_allow'],
$rawPerms['news_perms_deny']
),
],
[
'section' => 'comments-pin',
'title' => 'Can pin comments.',
'perm' => MSZ_NEWS_PERM_PIN_COMMENTS,
'value' => manage_perms_value(
MSZ_NEWS_PERM_PIN_COMMENTS,
$rawPerms['news_perms_allow'],
$rawPerms['news_perms_deny']
),
],
],
],
[
'section' => 'changelog',
'title' => 'Changelog',
'perms' => [
[
'section' => 'manage-changes',
'title' => 'Can manage changes.',
'perm' => MSZ_CHANGELOG_PERM_MANAGE_CHANGES,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_MANAGE_CHANGES,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
[
'section' => 'manage-tags',
'title' => 'Can manage tags.',
'perm' => MSZ_CHANGELOG_PERM_MANAGE_TAGS,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_MANAGE_TAGS,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
[
'section' => 'manage-actions',
'title' => 'Can manage action types.',
'perm' => MSZ_CHANGELOG_PERM_MANAGE_ACTIONS,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_MANAGE_ACTIONS,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
[
'section' => 'comments-delete',
'title' => 'Can delete comments from others.',
'perm' => MSZ_CHANGELOG_PERM_DELETE_COMMENTS,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_DELETE_COMMENTS,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
[
'section' => 'comments-edit',
'title' => 'Can edit comments from others.',
'perm' => MSZ_CHANGELOG_PERM_EDIT_COMMENTS,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_EDIT_COMMENTS,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
[
'section' => 'comments-pin',
'title' => 'Can pin comments.',
'perm' => MSZ_CHANGELOG_PERM_PIN_COMMENTS,
'value' => manage_perms_value(
MSZ_CHANGELOG_PERM_PIN_COMMENTS,
$rawPerms['changelog_perms_allow'],
$rawPerms['changelog_perms_deny']
),
],
],
],
];
}

6
src/news.php Normal file
View file

@ -0,0 +1,6 @@
<?php
define('MSZ_NEWS_PERM_MANAGE_POSTS', 1);
define('MSZ_NEWS_PERM_MANAGE_CATEGORIES', 1 << 1);
define('MSZ_NEWS_PERM_DELETE_COMMENTS', 1 << 2);
define('MSZ_NEWS_PERM_EDIT_COMMENTS', 1 << 3);
define('MSZ_NEWS_PERM_PIN_COMMENTS', 1 << 4);

View file

@ -3,6 +3,18 @@ use Misuzu\Database;
define('MSZ_PERMS_USER', 'user'); define('MSZ_PERMS_USER', 'user');
define('MSZ_PERMS_CHANGELOG', 'changelog'); define('MSZ_PERMS_CHANGELOG', 'changelog');
define('MSZ_PERMS_NEWS', 'news');
define('MSZ_PERM_MODES', [
MSZ_PERMS_USER, MSZ_PERMS_CHANGELOG, MSZ_PERMS_NEWS
]);
define('MSZ_PERMS_ALLOW', 'allow');
define('MSZ_PERMS_DENY', 'deny');
define('MSZ_PERM_SETS', [
MSZ_PERMS_ALLOW, MSZ_PERMS_DENY
]);
$_msz_perms_cache = []; $_msz_perms_cache = [];
@ -29,9 +41,38 @@ function perms_is_cached(string $prefix, string $mode, int $pid): bool
return array_key_exists(perms_construct_cache_key($prefix, $mode, $pid), $_msz_perms_cache); return array_key_exists(perms_construct_cache_key($prefix, $mode, $pid), $_msz_perms_cache);
} }
function perms_get_keys(): array
{
$perms = [];
foreach (MSZ_PERM_MODES as $mode) {
foreach (MSZ_PERM_SETS as $set) {
$perms[] = perms_get_key($mode, $set);
}
}
return $perms;
}
function perms_create(): array
{
$perms = [];
foreach (perms_get_keys() as $key) {
$perms[$key] = 0;
}
return $perms;
}
function perms_get_key(string $prefix, string $suffix): string
{
return $prefix . '_perms_' . $suffix;
}
function perms_get_user(string $prefix, int $user): int function perms_get_user(string $prefix, int $user): int
{ {
if ($user < 1) { if (!in_array($prefix, MSZ_PERM_MODES) || $user < 1) {
return 0; return 0;
} elseif ($user === 1) { } elseif ($user === 1) {
return 0x7FFFFFFF; return 0x7FFFFFFF;
@ -71,7 +112,7 @@ function perms_get_user(string $prefix, int $user): int
function perms_get_role(string $prefix, int $role): int function perms_get_role(string $prefix, int $role): int
{ {
if ($role < 1) { if (!in_array($prefix, MSZ_PERM_MODES) || $role < 1) {
return 0; return 0;
} }
@ -89,6 +130,66 @@ function perms_get_role(string $prefix, int $role): int
return perms_set_cache($prefix, 'role', $role, $getPerms->execute() ? (int)$getPerms->fetchColumn() : 0); return perms_set_cache($prefix, 'role', $role, $getPerms->execute() ? (int)$getPerms->fetchColumn() : 0);
} }
function perms_get_user_raw(int $user): array
{
$emptyPerms = perms_create();
if ($user < 1) {
return $emptyPerms;
}
$getPerms = Database::connection()->prepare('
SELECT
`' . implode('`, `', perms_get_keys()) . '`
FROM `msz_permissions`
WHERE `user_id` = :user_id
AND `role_id` IS NULL
');
$getPerms->bindValue('user_id', $user);
if (!$getPerms->execute()) {
return $emptyPerms;
}
$perms = $getPerms->fetch(PDO::FETCH_ASSOC);
if (!$perms) {
return $emptyPerms;
}
return $perms;
}
function perms_get_role_raw(int $role): array
{
$emptyPerms = perms_create();
if ($role < 1) {
return $emptyPerms;
}
$getPerms = Database::connection()->prepare("
SELECT
`' . implode('`, `', perms_get_keys()) . '`
FROM `msz_permissions`
WHERE `user_id` IS NULL
AND `role_id` = :role_id
");
$getPerms->bindValue('role_id', $role);
if (!$getPerms->execute()) {
return $emptyPerms;
}
$perms = $getPerms->fetch(PDO::FETCH_ASSOC);
if (!$perms) {
return $emptyPerms;
}
return $perms;
}
function perms_check(int $perms, int $perm): bool function perms_check(int $perms, int $perm): bool
{ {
return ($perms & $perm) > 0; return ($perms & $perm) > 0;

View file

@ -91,3 +91,53 @@
</ul> </ul>
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro permissions_table(permissions) %}
<div class="permissions">
{% for perms in permissions %}
<div class="permissions__line permissions__line--header">
<div class="permissions__title">
{{ perms.title }}
</div>
<div class="permissions__choice">
Yes
</div>
<div class="permissions__choice">
No
</div>
<div class="permissions__choice">
Never
</div>
</div>
{% for perm in perms.perms %}
<div class="permissions__line">
<div class="permissions__title">
{{ perm.title }}
</div>
<label class="permissions__choice permissions__choice--radio permissions__choice--yes">
<input {% if perm.value == 'yes' %}checked{% endif %}
class="permissions__input"
type="radio"
name="perms[{{ perms.section }}][{{ perm.section }}]"
value="yes">
</label>
<label class="permissions__choice permissions__choice--radio permissions__choice--no">
<input {% if perm.value == 'no' %}checked{% endif %}
class="permissions__input"
type="radio"
name="perms[{{ perms.section }}][{{ perm.section }}]"
value="no">
</label>
<label class="permissions__choice permissions__choice--radio permissions__choice--never">
<input {% if perm.value == 'never' %}checked{% endif %}
class="permissions__input"
type="radio"
name="perms[{{ perms.section }}][{{ perm.section }}]"
value="never">
</label>
</div>
{% endfor %}
{% endfor %}
</div>
{% endmacro %}

View file

@ -2,9 +2,11 @@
{% from '@manage/macros.twig' import pagination %} {% from '@manage/macros.twig' import pagination %}
{% block content %} {% block content %}
<div class="container"> {% if can_manage_roles %}
<a href="?v=role" class="button">Create new Role</a> <div class="container">
</div> <a href="?v=role" class="button">Create new Role</a>
</div>
{% endif %}
<div class="container listing role-listing"> <div class="container listing role-listing">
{% for role in manage_roles %} {% for role in manage_roles %}

View file

@ -1,4 +1,5 @@
{% extends '@manage/users/master.twig' %} {% extends '@manage/users/master.twig' %}
{% from '@manage/macros.twig' import permissions_table %}
{% block content %} {% block content %}
<form action="?v=role{{ edit_role is defined ? '&r=' ~ edit_role.role_id : '' }}" method="post"> <form action="?v=role{{ edit_role is defined ? '&r=' ~ edit_role.role_id : '' }}" method="post">
@ -32,6 +33,13 @@
</div> </div>
</label> </label>
<label class="form__label">
<div class="form__label__text">Title</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ edit_role is defined ? edit_role.role_title : '' }}" name="role[title]" maxlength="64">
</div>
</label>
<h2 class="container__subtitle">Colour</h2> <h2 class="container__subtitle">Colour</h2>
<label class="form__label"> <label class="form__label">
@ -70,10 +78,17 @@
<textarea class="input input--textarea" name="role[description]" maxlength="1000">{{ edit_role is defined ? edit_role.role_description : '' }}</textarea> <textarea class="input input--textarea" name="role[description]" maxlength="1000">{{ edit_role is defined ? edit_role.role_description : '' }}</textarea>
</div> </div>
</label> </label>
</div>
<div> {% if can_manage_perms %}
<button class="button" name="csrf" value="{{ csrf_token() }}">{{ edit_role is defined ? 'Update role' : 'Create role' }}</button> <div class="container">
<h2 class="container__subtitle">Permissions</h2>
{{ permissions_table(permissions) }}
</div> </div>
{% endif %}
<div class="container">
<button class="button" name="csrf" value="{{ csrf_token() }}">{{ edit_role is defined ? 'Update role' : 'Create role' }}</button>
</div> </div>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -1,229 +1,183 @@
{% extends '@manage/users/master.twig' %} {% extends '@manage/users/master.twig' %}
{% from '@manage/macros.twig' import permissions_table %}
{% block content %} {% block content %}
<div class="container"> {% if can_manage_users %}
<h1 class="container__title"> <form method="post" enctype="multipart/form-data" action="">
Viewing <span style="{{ view_user.colour|html_colour }}">{{ view_user.username }}</span> ({{ view_user.user_id }}) <div class="container">
</h1> <h1 class="container__title">
Viewing <span style="{{ view_user.colour|html_colour }}">{{ view_user.username }}</span> ({{ view_user.user_id }})
</h1>
<label class="form__label"> <label class="form__label">
<div class="form__label__text">Username</div> <div class="form__label__text">Username</div>
<div class="form__label__input"> <div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.username }}" name="user[username]" maxlength="16"> <input class="input input--text" type="text" value="{{ view_user.username }}" name="user[username]" maxlength="16">
</div>
</label>
<label class="form__label">
<div class="form__label__text">E-mail address</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.email }}" name="user[email]" maxlength="255">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Title</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_title }}" name="user[title]" maxlength="64">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Joined</div>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.created_at }}">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Last online</div>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.last_seen }}">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Register IP</div>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.register_ip_decoded }}">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Last IP</div>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.last_ip_decoded }}">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Country</div>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.user_country }}">
</div>
</label>
</div> </div>
</label>
<label class="form__label"> <div class="container">
<div class="form__label__text">E-mail address</div> <h2 class="container__subtitle">Avatar</h2>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.email }}" name="user[email]" maxlength="255"> <label class="form__label">
<div class="form__label__text">New Avatar</div>
<div class="form__label__input">
<input class="input input--text" type="file" name="avatar[file]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Delete Avatar</div>
<div class="form__label__input">
<input class="input" type="checkbox" name="avatar[delete]">
</div>
</label>
</div> </div>
</label>
<label class="form__label"> <div class="container">
<div class="form__label__text">Register IP</div> <h2 class="container__subtitle">Password</h2>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.register_ip_decoded }}"> <label class="form__label">
<div class="form__label__text">New Password</div>
<div class="form__label__input">
<input class="input input--text" type="password" name="password[new]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Confirm Password</div>
<div class="form__label__input">
<input class="input input--text" type="password" name="password[confirm]">
</div>
</label>
</div> </div>
</label>
<label class="form__label"> <div class="container">
<div class="form__label__text">Last IP</div> <h2 class="container__subtitle">Profile fields</h2>
<div class="form__label__input">
<input class="input input--text" readonly type="text" value="{{ view_user.last_ip_decoded }}"> {% for name, props in profile_fields %}
<label class="form__label">
<div class="form__label__text">{{ props.name }}</div>
<div class="form__label__input">
<input class="input input--text" type="{{ props.type|default('text') }}" value="{{ view_user['user_' ~ name] }}" name="profile[{{ name }}]">
</div>
</label>
{% endfor %}
</div> </div>
</label>
<label class="form__label"> {% if can_manage_perms %}
<div class="form__label__text">Country</div> <div class="container">
<div class="form__label__input"> <h2 class="container__subtitle">Permissions</h2>
<input class="input input--text" readonly type="text" value="{{ view_user.user_country }}"> {{ permissions_table(permissions) }}
</div>
</label>
<div>
<button class="button" name="csrf" value="{{ csrf_token() }}">Update</button>
</div>
</div>
<form class="container" method="post" enctype="multipart/form-data" action="">
<h1 class="container__title">
Avatar
</h1>
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
<label class="form__label">
<div class="form__label__text">New Avatar</div>
<div class="form__label__input">
<input class="input input--text" type="file" name="avatar[file]">
</div>
</label>
<div>
<button class="button" name="avatar[mode]" value="upload">Upload</button>
<button class="button" name="avatar[mode]" value="delete">Delete</button>
</div>
</form>
<div class="container">
<h1 class="container__title">
Password
</h1>
<label class="form__label">
<div class="form__label__text">New Password</div>
<div class="form__label__input">
<input class="input input--text" type="password" name="user[password]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Confirm Password</div>
<div class="form__label__input">
<input class="input input--text" type="password" name="user[password_confirm]">
</div>
</label>
<div>
<button class="button" name="csrf" value="{{ csrf_token() }}">Update</button>
</div>
</div>
<div class="container">
<h1 class="container__title">
Profile fields
</h1>
<label class="form__label">
<div class="form__label__text">Twitter</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_twitter }}" name="user[twitter]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">osu!</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_osu }}" name="user[osu]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Website</div>
<div class="form__label__input">
<input class="input input--text" type="url" value="{{ view_user.user_website }}" name="user[website]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Youtube</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_youtube }}" name="user[youtube]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Steam</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_steam }}" name="user[steam]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Twitch.tv</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_twitchtv }}" name="user[twitchtv]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Last.fm</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_twitchtv }}" name="user[twitchtv]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Github</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_github }}" name="user[github]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Skype</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_skype }}" name="user[skype]">
</div>
</label>
<label class="form__label">
<div class="form__label__text">Discord</div>
<div class="form__label__input">
<input class="input input--text" type="text" value="{{ view_user.user_discord }}" name="user[discord]">
</div>
</label>
<div>
<button class="button" name="csrf" value="{{ csrf_token() }}">Update</button>
</div>
</div>
{% if available_roles|length > 0 %}
<form class="container" method="post" action="">
<h1 class="container__title">Add Role</h1>
<label class="form__label">
<div class="form__label__text">Available Roles</div>
<div class="form__label__input">
<select name="add_role[role]" class="input input--select">
{% for role in available_roles %}
<option value="{{ role.role_id }}">
{{ role.role_name }}
</option>
{% endfor %}
</select>
</div> </div>
</label> {% endif %}
<div> <div class="container">
<button class="button" name="csrf" value="{{ csrf_token() }}">Add</button> <button class="button" name="csrf" value="{{ csrf_token() }}">Update</button>
</div> </div>
</form> </form>
{% endif %} {% endif %}
{% if has_roles|length > 0 %} {% if can_manage_users %}
<form class="container" method="post" action=""> <div class="container">
<h1 class="container__title">Manage Roles</h1> {% if has_roles|length > 0 %}
<form method="post" action="" style="display:inline-block">
<h2 class="container__subtitle">Manage Roles</h2>
<input type="hidden" name="csrf" value="{{ csrf_token() }}"> <input type="hidden" name="csrf" value="{{ csrf_token() }}">
<label class="form__label"> <label class="form__label">
<div class="form__label__text">Has Roles</div> <div class="form__label__text">Has Roles</div>
<div class="form__label__input"> <div class="form__label__input">
<select name="manage_roles[role]" class="input input--select"> <select name="manage_roles[role]" class="input input--select">
{% for role in has_roles %} {% for role in has_roles %}
<option value="{{ role.role_id }}"{% if role.role_id == view_user.display_role %} selected{% endif %}> <option value="{{ role.role_id }}"{% if role.role_id == view_user.display_role %} selected{% endif %}>
{{ role.role_name }} {{ role.role_name }}
</option> </option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
</label> </label>
<div> <div>
<button class="button" name="manage_roles[mode]" value="display">Set Display</button> <button class="button" name="manage_roles[mode]" value="display">Set Display</button>
<button class="button" name="manage_roles[mode]" value="remove">Remove</button> <button class="button" name="manage_roles[mode]" value="remove">Remove</button>
</div> </div>
</form> </form>
{% endif %}
{% if available_roles|length > 0 %}
<form method="post" action="" style="display:inline-block">
<h2 class="container__subtitle">Add Role</h2>
<label class="form__label">
<div class="form__label__text">Available Roles</div>
<div class="form__label__input">
<select name="add_role[role]" class="input input--select">
{% for role in available_roles %}
<option value="{{ role.role_id }}">
{{ role.role_name }}
</option>
{% endfor %}
</select>
</div>
</label>
<div>
<button class="button" name="csrf" value="{{ csrf_token() }}">Add</button>
</div>
</form>
{% endif %}
</div>
{% endif %} {% endif %}
<div class="container">
<h1 class="container__title">Permissions</h1>
</div>
<div class="container">
<h1 class="container__title">Sessions</h1>
</div>
{% endblock %} {% endblock %}