Initial permission stuffs.

This commit is contained in:
flash 2018-07-08 01:24:34 +02:00
parent fa368c396c
commit ffc23c11fd
12 changed files with 343 additions and 172 deletions

View file

@ -6,6 +6,8 @@ date_default_timezone_set('UTC');
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/src/changelog.php';
require_once __DIR__ . '/src/colour.php';
require_once __DIR__ . '/src/manage.php';
require_once __DIR__ . '/src/perms.php';
require_once __DIR__ . '/src/zalgo.php';
require_once __DIR__ . '/src/Forum/forum.php';
require_once __DIR__ . '/src/Forum/post.php';
@ -36,16 +38,17 @@ if (PHP_SAPI !== 'cli') {
ob_start('ob_gzhandler');
}
$app->startTemplating();
$tpl = $app->getTemplating();
if ($app->getConfig()->get('Auth', 'lockdown', 'bool', false)) {
http_response_code(503);
$app->startTemplating();
$app->getTemplating()->addPath('auth', __DIR__ . '/views/auth');
echo $app->getTemplating()->render('lockdown');
$tpl->addPath('auth', __DIR__ . '/views/auth');
echo $tpl->render('lockdown');
exit;
}
$app->startTemplating();
$app->getTemplating()->addPath('mio', __DIR__ . '/views/mio');
$tpl->addPath('mio', __DIR__ . '/views/mio');
if (isset($_COOKIE['msz_uid'], $_COOKIE['msz_sid'])) {
$app->startSession((int)$_COOKIE['msz_uid'], $_COOKIE['msz_sid']);
@ -74,18 +77,22 @@ if (PHP_SAPI !== 'cli') {
');
$getUserDisplayInfo->bindValue('user_id', $app->getUserId());
$userDisplayInfo = $getUserDisplayInfo->execute() ? $getUserDisplayInfo->fetch() : [];
$app->getTemplating()->var('current_user', $userDisplayInfo);
$tpl->var('current_user', $userDisplayInfo);
}
}
$manage_mode = 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);
$tpl->var('has_manage_access', $hasManageAccess);
if ($manage_mode) {
if ($app->getUserId() !== 1) {
if ($inManageMode) {
if (!$hasManageAccess) {
echo render_error(403);
exit;
}
$app->getTemplating()->addPath('manage', __DIR__ . '/views/manage');
$tpl = $app->getTemplating();
$tpl->var('manage_menu', manage_get_menu($app->getUserId()));
$tpl->addPath('manage', __DIR__ . '/views/manage');
}
}

View file

@ -6,12 +6,18 @@ require_once __DIR__ . '/../../misuzu.php';
$db = Database::connection();
$tpl = $app->getTemplating();
$changelogPerms = perms_get_user(MSZ_PERMS_CHANGELOG, $app->getUserId());
$queryOffset = (int)($_GET['o'] ?? 0);
switch ($_GET['v'] ?? null) {
case 'changes':
$changesTake = 20;
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES)) {
echo render_error(403);
break;
}
$changesTake = 20;
$changesCount = (int)$db->query('
SELECT COUNT(`change_id`)
FROM `msz_changelog_changes`
@ -61,6 +67,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'change':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES)) {
echo render_error(403);
break;
}
$changeId = (int)($_GET['c'] ?? 0);
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
@ -180,6 +191,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'tags':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS)) {
echo render_error(403);
break;
}
$tagsTake = 32;
$tagsCount = (int)$db->query('
@ -212,6 +228,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'tag':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS)) {
echo render_error(403);
break;
}
$tagId = (int)($_GET['t'] ?? 0);
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
@ -268,6 +289,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'actions':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS)) {
echo render_error(403);
break;
}
$actionTake = 32;
$actionCount = (int)$db->query('
@ -300,6 +326,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'action':
if (!perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS)) {
echo render_error(403);
break;
}
$actionId = (int)($_GET['a'] ?? 0);
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
@ -363,8 +394,4 @@ switch ($_GET['v'] ?? null) {
echo $tpl->render('@manage.changelog.action_edit');
break;
default:
header('Location: ?v=changes');
break;
}

View file

@ -6,13 +6,19 @@ require_once __DIR__ . '/../../misuzu.php';
$db = Database::connection();
$templating = $app->getTemplating();
$userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId());
$isPostRequest = $_SERVER['REQUEST_METHOD'] === 'POST';
$queryQffset = (int)($_GET['o'] ?? 0);
switch ($_GET['v'] ?? null) {
case 'listing':
$usersTake = 32;
if (!perms_check($userPerms, MSZ_PERM_MANAGE_USERS)) {
echo render_error(403);
break;
}
$usersTake = 32;
$manageUsersCount = $db->query('
SELECT COUNT(`user_id`)
FROM `msz_users`
@ -25,6 +31,7 @@ switch ($_GET['v'] ?? null) {
FROM `msz_users` as u
LEFT JOIN `msz_roles` as r
ON u.`display_role` = r.`role_id`
ORDER BY `user_id`
LIMIT :offset, :take
');
$getManageUsers->bindValue('offset', $queryQffset);
@ -41,6 +48,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'view':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_USERS)) {
echo render_error(403);
break;
}
$userId = $_GET['u'] ?? null;
if ($userId === null || ($userId = (int)$userId) < 1) {
@ -141,6 +153,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'roles':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_ROLES)) {
echo render_error(403);
break;
}
$rolesTake = 10;
$manageRolesCount = $db->query('
@ -173,6 +190,11 @@ switch ($_GET['v'] ?? null) {
break;
case 'role':
if (!perms_check($userPerms, MSZ_PERM_MANAGE_ROLES)) {
echo render_error(403);
break;
}
$roleId = $_GET['r'] ?? null;
if ($isPostRequest) {

View file

@ -5,16 +5,52 @@ use Misuzu\IO\File;
require_once __DIR__ . '/../misuzu.php';
$db = Database::connection();
$templating = $app->getTemplating();
$tpl = $app->getTemplating();
$queryOffset = (int)($_GET['o'] ?? 0);
$queryTake = 15;
if (!$app->hasActiveSession()) {
$userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId());
$settingsModes = [
'account' => [
'title' => 'Account',
'allow' => perms_check($userPerms, MSZ_PERM_EDIT_PROFILE),
],
'avatar' => [
'title' => 'Avatar',
'allow' => perms_check($userPerms, MSZ_PERM_CHANGE_AVATAR),
],
'sessions' => [
'title' => 'Sessions',
'allow' => true,
],
'login-history' => [
'title' => 'Login History',
'allow' => true,
],
];
$settingsMode = $_GET['m'] ?? null;
$settingsNavigation = [];
foreach ($settingsModes as $key => $value) {
if ($value['allow']) {
$settingsNavigation[$value['title']] = $key;
if ($settingsMode === null) {
$settingsMode = $key;
}
}
}
if (!$app->hasActiveSession() || !$settingsModes[$settingsMode]['allow']) {
echo render_error(403);
return;
}
$tpl->var('settings_navigation', $settingsNavigation);
$csrfErrorString = "Couldn't verify you, please refresh the page and retry.";
$avatarErrorStrings = [
@ -41,23 +77,15 @@ $avatarErrorStrings = [
],
];
$settingsModes = [
'account' => 'Account',
'avatar' => 'Avatar',
'sessions' => 'Sessions',
'login-history' => 'Login History',
];
$settingsMode = $_GET['m'] ?? key($settingsModes);
$templating->vars([
$tpl->vars([
'settings_mode' => $settingsMode,
'settings_modes' => $settingsModes,
]);
if (!array_key_exists($settingsMode, $settingsModes)) {
http_response_code(404);
$templating->var('settings_title', 'Not Found');
echo $templating->render('settings.notfound');
$tpl->var('settings_title', 'Not Found');
echo $tpl->render('settings.notfound');
return;
}
@ -293,8 +321,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
}
$templating->var('settings_title', $settingsModes[$settingsMode]);
$templating->var('settings_errors', $settingsErrors);
$tpl->var('settings_title', $settingsModes[$settingsMode]['title']);
$tpl->var('settings_errors', $settingsErrors);
switch ($settingsMode) {
case 'account':
@ -307,7 +335,7 @@ switch ($settingsMode) {
$getUserFields->bindValue('user_id', $app->getUserId());
$userFields = $getUserFields->execute() ? $getUserFields->fetch() : [];
$templating->vars([
$tpl->vars([
'settings_profile_fields' => $profileFields,
'settings_profile_values' => $userFields,
'settings_disable_account_options' => $disableAccountOptions,
@ -316,7 +344,7 @@ switch ($settingsMode) {
case 'avatar':
$userHasAvatar = File::exists($app->getStore('avatars/original')->filename($avatarFileName));
$templating->vars([
$tpl->vars([
'avatar_user_id' => $app->getUserId(),
'avatar_max_width' => $avatarWidthMax,
'avatar_max_height' => $avatarHeightMax,
@ -348,7 +376,7 @@ switch ($settingsMode) {
$getSessions->bindValue('user_id', $app->getUserId());
$sessions = $getSessions->execute() ? $getSessions->fetchAll() : [];
$templating->vars([
$tpl->vars([
'active_session_id' => $app->getSessionId(),
'user_sessions' => $sessions,
'sessions_offset' => $queryOffset,
@ -380,7 +408,7 @@ switch ($settingsMode) {
$getLoginAttempts->bindValue('user_id', $app->getUserId());
$loginAttempts = $getLoginAttempts->execute() ? $getLoginAttempts->fetchAll() : [];
$templating->vars([
$tpl->vars([
'user_login_attempts' => $loginAttempts,
'login_attempts_offset' => $queryOffset,
'login_attempts_take' => $queryTake,
@ -389,4 +417,4 @@ switch ($settingsMode) {
break;
}
echo $templating->render("settings.{$settingsMode}");
echo $tpl->render("settings.{$settingsMode}");

View file

@ -73,7 +73,9 @@ class Application extends ApplicationBase
public function getConfig(): ConfigManager
{
if (is_null($this->configInstance)) {
throw new UnexpectedValueException('Internal ConfigManager instance is null, how did you even manage to do this?');
throw new UnexpectedValueException(
'Internal ConfigManager instance is null, how did you even manage to do this?'
);
}
return $this->configInstance;
@ -242,7 +244,6 @@ class Application extends ApplicationBase
$this->templatingInstance->addFilter('html_colour');
$this->templatingInstance->addFilter('url_construct');
$this->templatingInstance->addFilter('country_name', 'get_country_name');
$this->templatingInstance->addFilter('flip', 'array_flip');
$this->templatingInstance->addFilter('first_paragraph');
$this->templatingInstance->addFilter('colour_get_css');
$this->templatingInstance->addFilter('colour_get_css_contrast');
@ -256,6 +257,7 @@ class Application extends ApplicationBase
$this->templatingInstance->addFunction('git_hash', [Application::class, 'gitCommitHash']);
$this->templatingInstance->addFunction('git_branch', [Application::class, 'gitBranch']);
$this->templatingInstance->addFunction('csrf_token', 'tmp_csrf_token');
$this->templatingInstance->addFunction('perms_check');
$this->templatingInstance->var('app', $this);
}

View file

@ -3,6 +3,17 @@ use Misuzu\Application;
use Misuzu\Database;
use Misuzu\IO\File;
define('MSZ_PERM_EDIT_PROFILE', 1);
define('MSZ_PERM_CHANGE_AVATAR', 1 << 1);
define('MSZ_PERM_MANAGE', 1 << 20);
define('MSZ_PERM_MANAGE_USERS', 1 << 21);
define('MSZ_PERM_MANAGE_ROLES', 1 << 22);
define('MSZ_PERM_MANAGE_PERMS', 1 << 23);
define('MSZ_PERM_MANAGE_REPORTS', 1 << 24);
define('MSZ_PERM_MANAGE_RESTRICTIONS', 1 << 25);
define('MSZ_PERM_MANAGE_BLACKLISTS', 1 << 26);
define('MSZ_USERS_PASSWORD_HASH_ALGO', PASSWORD_ARGON2I);
function user_create(

View file

@ -1,6 +1,10 @@
<?php
use Misuzu\Database;
define('MSZ_CHANGELOG_MANAGE_CHANGES', 1);
define('MSZ_CHANGELOG_MANAGE_TAGS', 1 << 1);
define('MSZ_CHANGELOG_MANAGE_ACTIONS', 1 << 2);
function changelog_action_add(string $name, ?int $colour = null, ?string $class = null): int
{
$dbc = Database::connection();
@ -42,7 +46,7 @@ function changelog_entry_create(int $userId, int $actionId, string $log, string
return $createChange->execute() ? (int)$dbc->lastInsertId() : 0;
}
define('CHANGELOG_GET_QUERY', '
define('MSZ_CHANGELOG_GET_QUERY', '
SELECT
c.`change_id`, c.`change_log`,
a.`action_name`, a.`action_colour`, a.`action_class`,
@ -70,7 +74,7 @@ function changelog_get_changes(string $date, int $user, int $offset, int $take):
$hasUser = $user > 0;
$query = sprintf(
CHANGELOG_GET_QUERY,
MSZ_CHANGELOG_GET_QUERY,
$hasDate ? 'DATE(c.`change_created`) = :date' : '1',
$hasUser ? 'c.`user_id` = :user' : '1',
!$hasDate ? 'LIMIT :offset, :take' : ''

93
src/manage.php Normal file
View file

@ -0,0 +1,93 @@
<?php
function manage_get_menu(int $userId): array
{
$userPerms = perms_get_user(MSZ_PERMS_USER, $userId);
if (!perms_check($userPerms, MSZ_PERM_MANAGE)) {
return [];
}
$changelogPerms = perms_get_user(MSZ_PERMS_CHANGELOG, $userId);
$menu = [];
$menu['General'] = [
'Overview' => '/manage/index.php?v=overview',
'Logs' => '/manage/index.php?v=logs',
'_',
'Emoticons' => '/manage/index.php?v=emoticons',
'Settings' => '/manage/index.php?v=settings',
];
$canUsers = perms_check($userPerms, MSZ_PERM_MANAGE_USERS);
$canRoles = perms_check($userPerms, MSZ_PERM_MANAGE_ROLES);
$canPerms = perms_check($userPerms, MSZ_PERM_MANAGE_PERMS);
$canReports = perms_check($userPerms, MSZ_PERM_MANAGE_REPORTS);
$canRestricts = perms_check($userPerms, MSZ_PERM_MANAGE_RESTRICTIONS);
$canBlacklists = perms_check($userPerms, MSZ_PERM_MANAGE_BLACKLISTS);
if ($canUsers || $canRoles || $canPerms
|| $canReports || $canRestricts || $canBlacklists) {
$menu['Users'] = [];
if ($canUsers) {
$menu['Users']['Listing'] = '/manage/users.php?v=listing';
}
if ($canRoles || $canPerms) {
$menu['Users'][] = '_';
if ($canRoles) {
$menu['Users']['Roles'] = '/manage/users.php?v=roles';
}
if ($canPerms) {
$menu['Users']['Permissions'] = '/manage/users.php?v=permissions';
}
}
if ($canReports || $canRestricts || $canBlacklists) {
$menu['Users'][] = '_';
if ($canReports) {
$menu['Users']['Reports'] = '/manage/users.php?v=reports';
}
if ($canRestricts) {
$menu['Users']['Restrictions'] = '/manage/users.php?v=restrictions';
}
if ($canBlacklists) {
$menu['Users']['Blacklisting'] = '/manage/users.php?v=blacklisting';
}
}
}
/*$menu['Forum'] = [
'Listing' => '/manage/forums.php?v=listing',
'Permisisons' => '/manage/forums.php?v=permissions',
'Settings' => '/manage/forums.php?v=settings',
];*/
$canChanges = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_CHANGES);
$canChangeTags = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_TAGS);
$canChangeActions = perms_check($changelogPerms, MSZ_CHANGELOG_MANAGE_ACTIONS);
if ($canChanges || $canChangeTags || $canChangeActions) {
$menu['Changelog'] = [];
if ($canChanges) {
$menu['Changelog']['Changes'] = '/manage/changelog.php?v=changes';
}
if ($canChangeTags) {
$menu['Changelog']['Tags'] = '/manage/changelog.php?v=tags';
}
if ($canChangeActions) {
$menu['Changelog']['Actions'] = '/manage/changelog.php?v=actions';
}
}
return $menu;
}

95
src/perms.php Normal file
View file

@ -0,0 +1,95 @@
<?php
use Misuzu\Database;
define('MSZ_PERMS_USER', 'user');
define('MSZ_PERMS_CHANGELOG', 'changelog');
$_msz_perms_cache = [];
function perms_construct_cache_key(string $prefix, string $mode, int $pid): string
{
return $prefix . '_' . $mode . '_' . $pid;
}
function perms_get_cache(string $prefix, string $mode, int $pid): int
{
global $_msz_perms_cache;
return $_msz_perms_cache[perms_construct_cache_key($prefix, $mode, $pid)];
}
function perms_set_cache(string $prefix, string $mode, int $pid, int $perms): int
{
global $_msz_perms_cache;
return $_msz_perms_cache[perms_construct_cache_key($prefix, $mode, $pid)] = $perms;
}
function perms_is_cached(string $prefix, string $mode, int $pid): bool
{
global $_msz_perms_cache;
return array_key_exists(perms_construct_cache_key($prefix, $mode, $pid), $_msz_perms_cache);
}
function perms_get_user(string $prefix, int $user): int
{
if ($user < 1) {
return 0;
} elseif ($user === 1) {
return 0x7FFFFFFF;
}
if (perms_is_cached($prefix, 'user', $user)) {
return perms_get_cache($prefix, 'user', $user);
}
$permsAllow = 0;
$permsDeny = 0;
$getPerms = Database::connection()->prepare("
SELECT `{$prefix}_perms_allow` as `allow`, `{$prefix}_perms_deny` as `deny`
FROM `msz_permissions`
WHERE (`user_id` = :user_id_1 AND `role_id` IS NULL)
OR (
`user_id` IS NULL
AND `role_id` IN (
SELECT `role_id`
FROM `msz_user_roles`
WHERE `user_id` = :user_id_2
)
)
");
$getPerms->bindValue('user_id_1', $user);
$getPerms->bindValue('user_id_2', $user);
$perms = $getPerms->execute() ? $getPerms->fetchAll(PDO::FETCH_ASSOC) : [];
foreach ($perms as $perm) {
$permsAllow |= $perm['allow'];
$permsDeny |= $perm['deny'];
}
return perms_set_cache($prefix, 'user', $user, $permsAllow &~ $permsDeny);
}
function perms_get_role(string $prefix, int $role): int
{
if ($role < 1) {
return 0;
}
if (perms_is_cached($prefix, 'role', $user)) {
return perms_get_cache($prefix, 'role', $user);
}
$getPerms = Database::connection()->prepare("
SELECT `{$prefix}_perms_allow` &~ `{$prefix}_perms_deny`
FROM `msz_permissions`
WHERE `role_id` = :role_id
AND `user_id` IS NULL
");
$getPerms->bindValue('role_id', $role);
return perms_set_cache($prefix, 'role', $role, $getPerms->execute() ? (int)$getPerms->fetchColumn() : 0);
}
function perms_check(int $perms, int $perm): bool
{
return ($perms & $perm) > 0;
}

View file

@ -1,124 +1,3 @@
{% set menus = [
{
'name': 'general',
'title': 'General',
'sections': [
[
{
'name': 'overview',
'title': 'Overview',
'url': '/manage/index.php?v=overview',
},
{
'name': 'logs',
'title': 'Logs',
'url': '/manage/index.php?v=logs',
},
],
[
{
'name': 'emotes',
'title': 'Emoticons',
'url': '/manage/index.php?v=emoticons',
},
{
'name': 'settings',
'title': 'Settings',
'url': '/manage/index.php?v=settings',
},
],
],
},
{
'name': 'users',
'title': 'Users',
'sections': [
[
{
'name': 'listing',
'title': 'Listing',
'url': '/manage/users.php?v=listing',
},
],
[
{
'name': 'roles',
'title': 'Roles',
'url': '/manage/users.php?v=roles',
},
{
'name': 'perms',
'title': 'Permissions',
'url': '/manage/users.php?v=permissions',
},
],
[
{
'name': 'report',
'title': 'Reports',
'url': '/manage/users.php?v=reports',
},
{
'name': 'restrictions',
'title': 'Restrictions',
'url': '/manage/users.php?v=restrictions',
},
{
'name': 'blacklist',
'title': 'Blacklisting',
'url': '/manage/users.php?v=blacklist',
},
],
],
},
{
'name': 'forum',
'title': 'Forum',
'sections': [
[
{
'name': 'forums',
'title': 'Listing',
'url': '/manage/forums.php?v=listing',
},
{
'name': 'perms',
'title': 'Permissions',
'url': '/manage/forums.php?v=permissions',
},
{
'name': 'settings',
'title': 'Settings',
'url': '/manage/forums.php?v=settings',
},
],
],
},
{
'name': 'changelog',
'title': 'Changelog',
'sections': [
[
{
'name': 'changes',
'title': 'Changes',
'url': '/manage/changelog.php?v=changes',
},
{
'name': 'tags',
'title': 'Tags',
'url': '/manage/changelog.php?v=tags',
},
{
'name': 'actions',
'title': 'Actions',
'url': '/manage/changelog.php?v=actions',
},
],
],
},
] %}
<!DOCTYPE html>
<html>
<head>
@ -138,18 +17,21 @@
</a>
<div class="header__navigation">
{% for menu in menus %}
{% for name, menu in manage_menu %}
<div class="header__menu">
<input type="checkbox" id="menu-{{ menu.name }}-state" class="header__menu__state">
<label for="menu-{{ menu.name }}-state" class="header__menu__toggle">{{ menu.title }}</label>
<input type="checkbox" id="menu-{{ name|lower }}-state" class="header__menu__state">
<label for="menu-{{ name|lower }}-state" class="header__menu__toggle">{{ name }}</label>
<div class="header__menu__options">
{% for section in menu.sections %}
<div class="header__menu__section">
{% for item in section %}
<a class="header__menu__link header__menu__link--{{ menu.name }}-{{ item.name }}" href="{{ item.url }}">{{ item.title }}</a>
{% endfor %}
</div>
<div class="header__menu__section">
{% for title, link in menu %}
{% if link == '_' %}
</div>
<div class="header__menu__section">
{% else %}
<a class="header__menu__link" href="{{ link }}">{{ title }}</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endfor %}

View file

@ -38,7 +38,7 @@
<ul class="header__user__links">
<li class="header__user__option"><a class="header__user__link" href="/profile.php?u={{ current_user.user_id }}">Profile</a></li>
<li class="header__user__option"><a class="header__user__link" href="/settings.php">Settings</a></li>
{% if current_user.user_id == 1 %}
{% if has_manage_access %}
<li class="header__user__option"><a class="header__user__link" href="{{ manage_link|default('/manage/index.php') }}">Manage</a></li>
{% endif %}
<li class="header__user__option"><a class="header__user__link" href="/auth.php?m=logout&amp;s={{ csrf_token() }}">Logout</a></li>

View file

@ -4,7 +4,7 @@
{% set title = 'Settings » ' ~ settings_title %}
{% block content %}
{{ navigation(settings_modes|flip, settings_mode, true, '?m=%s') }}
{{ navigation(settings_navigation, settings_mode, true, '?m=%s') }}
{% block settings_container %}
{% if settings_errors is defined and settings_errors|length > 0 %}