Merged account and avatar settings pages.
This commit is contained in:
parent
bd83bc15a0
commit
294380d7bc
9 changed files with 524 additions and 569 deletions
|
@ -33,7 +33,7 @@ switch ($_GET['v'] ?? null) {
|
|||
$getManageUsers = Database::prepare('
|
||||
SELECT
|
||||
u.`user_id`, u.`username`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) as `colour`
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) as `user_colour`
|
||||
FROM `msz_users` as u
|
||||
LEFT JOIN `msz_roles` as r
|
||||
ON u.`display_role` = r.`role_id`
|
||||
|
|
|
@ -10,54 +10,23 @@ $queryOffset = (int)($_GET['o'] ?? 0);
|
|||
$queryTake = 15;
|
||||
|
||||
$userPerms = perms_get_user(MSZ_PERMS_USER, $app->getUserId());
|
||||
|
||||
$settingsModes = [
|
||||
'account' => [
|
||||
'title' => 'Account',
|
||||
'allow' => perms_check($userPerms, MSZ_USER_PERM_EDIT_PROFILE),
|
||||
],
|
||||
'images' => [
|
||||
'title' => 'Avatar',
|
||||
'allow' => perms_check($userPerms, MSZ_USER_PERM_CHANGE_AVATAR),
|
||||
],
|
||||
'sessions' => [
|
||||
'title' => 'Sessions',
|
||||
'allow' => true,
|
||||
],
|
||||
'login-history' => [
|
||||
'title' => 'Login History',
|
||||
'allow' => true,
|
||||
],
|
||||
'log' => [
|
||||
'title' => 'Account Log',
|
||||
'allow' => true,
|
||||
],
|
||||
$perms = [
|
||||
'edit_profile' => perms_check($userPerms, MSZ_USER_PERM_EDIT_PROFILE),
|
||||
'edit_avatar' => perms_check($userPerms, MSZ_USER_PERM_CHANGE_AVATAR),
|
||||
];
|
||||
$settingsMode = $_GET['m'] ?? null;
|
||||
|
||||
if ($settingsMode === 'avatar') {
|
||||
header('Location: ?m=images');
|
||||
return;
|
||||
}
|
||||
|
||||
$settingsNavigation = [];
|
||||
|
||||
foreach ($settingsModes as $key => $value) {
|
||||
if ($value['allow']) {
|
||||
$settingsNavigation[$value['title']] = $key;
|
||||
|
||||
if ($settingsMode === null) {
|
||||
$settingsMode = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$app->hasActiveSession() || !$settingsModes[$settingsMode]['allow']) {
|
||||
if (!$app->hasActiveSession()) {
|
||||
echo render_error(403);
|
||||
return;
|
||||
}
|
||||
|
||||
$tpl->var('settings_navigation', $settingsNavigation);
|
||||
$settingsModes = [
|
||||
'account' => 'Account',
|
||||
'sessions' => 'Sessions',
|
||||
'login-history' => 'Login History',
|
||||
'log' => 'Account Log',
|
||||
];
|
||||
$settingsMode = $_GET['m'] ?? key($settingsModes);
|
||||
|
||||
$csrfErrorString = "Couldn't verify you, please refresh the page and retry.";
|
||||
|
||||
|
@ -86,6 +55,7 @@ $avatarErrorStrings = [
|
|||
];
|
||||
|
||||
$tpl->vars([
|
||||
'settings_perms' => $perms,
|
||||
'settings_mode' => $settingsMode,
|
||||
'settings_modes' => $settingsModes,
|
||||
]);
|
||||
|
@ -106,14 +76,10 @@ $avatarHeightMax = $app->getConfig()->get('Avatar', 'max_height', 'int', 4000);
|
|||
$avatarFileSizeMax = $app->getConfig()->get('Avatar', 'max_filesize', 'int', 1000000);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
switch ($settingsMode) {
|
||||
case 'account':
|
||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
$settingsErrors[] = $csrfErrorString;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($_POST['profile']) && is_array($_POST['profile'])) {
|
||||
} else {
|
||||
if (!empty($_POST['profile']) && is_array($_POST['profile'])) {
|
||||
$setUserFieldErrors = user_profile_fields_set($app->getUserId(), $_POST['profile']);
|
||||
|
||||
if (count($setUserFieldErrors) > 0) {
|
||||
|
@ -142,109 +108,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
}
|
||||
}
|
||||
|
||||
if (!$disableAccountOptions) {
|
||||
if (!empty($_POST['current_password'])
|
||||
|| (
|
||||
(isset($_POST['password']) || isset($_POST['email']))
|
||||
&& (!empty($_POST['password']['new']) || !empty($_POST['email']['new']))
|
||||
)
|
||||
) {
|
||||
$updateAccountFields = [];
|
||||
|
||||
$fetchPassword = Database::prepare('
|
||||
SELECT `password`
|
||||
FROM `msz_users`
|
||||
WHERE `user_id` = :user_id
|
||||
');
|
||||
$fetchPassword->bindValue('user_id', $app->getUserId());
|
||||
$currentPassword = $fetchPassword->execute() ? $fetchPassword->fetchColumn() : null;
|
||||
|
||||
if (empty($currentPassword)) {
|
||||
$settingsErrors[] = 'Something went horribly wrong.';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!password_verify($_POST['current_password'], $currentPassword)) {
|
||||
$settingsErrors[] = 'Your current password was incorrect.';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($_POST['email']['new'])) {
|
||||
if (empty($_POST['email']['confirm'])
|
||||
|| $_POST['email']['new'] !== $_POST['email']['confirm']) {
|
||||
$settingsErrors[] = 'The given e-mail addresses did not match.';
|
||||
break;
|
||||
}
|
||||
|
||||
$email_validate = user_validate_email($_POST['email']['new'], true);
|
||||
|
||||
if ($email_validate !== '') {
|
||||
switch ($email_validate) {
|
||||
case 'dns':
|
||||
$settingsErrors[] = 'No valid MX record exists for this domain.';
|
||||
break;
|
||||
|
||||
case 'format':
|
||||
$settingsErrors[] = 'The given e-mail address was incorrectly formatted.';
|
||||
break;
|
||||
|
||||
case 'in-use':
|
||||
$settingsErrors[] = 'This e-mail address is already in use.';
|
||||
break;
|
||||
|
||||
default:
|
||||
$settingsErrors[] = 'Unknown e-mail validation error.';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$updateAccountFields['email'] = strtolower($_POST['email']['new']);
|
||||
|
||||
audit_log('PERSONAL_EMAIL_CHANGE', $app->getUserId(), [
|
||||
$updateAccountFields['email'],
|
||||
]);
|
||||
}
|
||||
|
||||
if (!empty($_POST['password']['new'])) {
|
||||
if (empty($_POST['password']['confirm'])
|
||||
|| $_POST['password']['new'] !== $_POST['password']['confirm']) {
|
||||
$settingsErrors[] = "The given passwords did not match.";
|
||||
break;
|
||||
}
|
||||
|
||||
$password_validate = user_validate_password($_POST['password']['new']);
|
||||
|
||||
if ($password_validate !== '') {
|
||||
$settingsErrors[] = "The given passwords was too weak.";
|
||||
break;
|
||||
}
|
||||
|
||||
$updateAccountFields['password'] = user_password_hash($_POST['password']['new']);
|
||||
|
||||
audit_log('PERSONAL_PASSWORD_CHANGE', $app->getUserId());
|
||||
}
|
||||
|
||||
if (count($updateAccountFields) > 0) {
|
||||
$updateUser = Database::prepare('
|
||||
UPDATE `msz_users`
|
||||
SET ' . pdo_prepare_array_update($updateAccountFields, true) . '
|
||||
WHERE `user_id` = :user_id
|
||||
');
|
||||
$updateAccountFields['user_id'] = $app->getUserId();
|
||||
$updateUser->execute($updateAccountFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'images':
|
||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
$settingsErrors[] = $csrfErrorString;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($_POST['avatar']) && is_array($_POST['avatar']) && !empty($_POST['avatar']['mode'])) {
|
||||
switch ($_POST['avatar']['mode']) {
|
||||
if (!empty($_POST['avatar']) && is_array($_POST['avatar'])) {
|
||||
switch ($_POST['avatar']['mode'] ?? '') {
|
||||
case 'delete':
|
||||
user_avatar_delete($app->getUserId());
|
||||
break;
|
||||
|
@ -286,21 +151,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'sessions':
|
||||
if (!tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
$settingsErrors[] = $csrfErrorString;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($_POST['session']) && is_numeric($_POST['session'])) {
|
||||
$session_id = (int)($_POST['session'] ?? 0);
|
||||
|
||||
if ($session_id < 1) {
|
||||
$settingsErrors[] = 'Invalid session.';
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
$findSession = Database::prepare('
|
||||
SELECT `session_id`, `user_id`
|
||||
FROM `msz_sessions`
|
||||
|
@ -311,9 +168,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
|
||||
if (!$session || (int)$session['user_id'] !== $app->getUserId()) {
|
||||
$settingsErrors[] = 'You may only end your own sessions.';
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((int)$session['session_id'] === $app->getSessionId()) {
|
||||
header('Location: /auth.php?m=logout&s=' . tmp_csrf_token());
|
||||
return;
|
||||
|
@ -323,11 +178,99 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
audit_log('PERSONAL_SESSION_DESTROY', $app->getUserId(), [
|
||||
$session['session_id'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$disableAccountOptions) {
|
||||
if (!empty($_POST['current_password'])
|
||||
|| (
|
||||
(isset($_POST['password']) || isset($_POST['email']))
|
||||
&& (!empty($_POST['password']['new']) || !empty($_POST['email']['new']))
|
||||
)
|
||||
) {
|
||||
$updateAccountFields = [];
|
||||
|
||||
$fetchPassword = Database::prepare('
|
||||
SELECT `password`
|
||||
FROM `msz_users`
|
||||
WHERE `user_id` = :user_id
|
||||
');
|
||||
$fetchPassword->bindValue('user_id', $app->getUserId());
|
||||
$currentPassword = $fetchPassword->execute() ? $fetchPassword->fetchColumn() : null;
|
||||
|
||||
if (empty($currentPassword)) {
|
||||
$settingsErrors[] = 'Something went horribly wrong.';
|
||||
} else {
|
||||
if (!password_verify($_POST['current_password'], $currentPassword)) {
|
||||
$settingsErrors[] = 'Your current password was incorrect.';
|
||||
} else {
|
||||
if (!empty($_POST['email']['new'])) {
|
||||
if (empty($_POST['email']['confirm'])
|
||||
|| $_POST['email']['new'] !== $_POST['email']['confirm']) {
|
||||
$settingsErrors[] = 'The given e-mail addresses did not match.';
|
||||
} else {
|
||||
$email_validate = user_validate_email($_POST['email']['new'], true);
|
||||
|
||||
if ($email_validate !== '') {
|
||||
switch ($email_validate) {
|
||||
case 'dns':
|
||||
$settingsErrors[] = 'No valid MX record exists for this domain.';
|
||||
break;
|
||||
|
||||
case 'format':
|
||||
$settingsErrors[] = 'The given e-mail address was incorrectly formatted.';
|
||||
break;
|
||||
|
||||
case 'in-use':
|
||||
$settingsErrors[] = 'This e-mail address is already in use.';
|
||||
break;
|
||||
|
||||
default:
|
||||
$settingsErrors[] = 'Unknown e-mail validation error.';
|
||||
}
|
||||
} else {
|
||||
$updateAccountFields['email'] = strtolower($_POST['email']['new']);
|
||||
audit_log('PERSONAL_EMAIL_CHANGE', $app->getUserId(), [
|
||||
$updateAccountFields['email'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['password']['new'])) {
|
||||
if (empty($_POST['password']['confirm'])
|
||||
|| $_POST['password']['new'] !== $_POST['password']['confirm']) {
|
||||
$settingsErrors[] = "The given passwords did not match.";
|
||||
} else {
|
||||
$password_validate = user_validate_password($_POST['password']['new']);
|
||||
|
||||
if ($password_validate !== '') {
|
||||
$settingsErrors[] = "The given passwords was too weak.";
|
||||
} else {
|
||||
$updateAccountFields['password'] = user_password_hash($_POST['password']['new']);
|
||||
audit_log('PERSONAL_PASSWORD_CHANGE', $app->getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($updateAccountFields) > 0) {
|
||||
$updateUser = Database::prepare('
|
||||
UPDATE `msz_users`
|
||||
SET ' . pdo_prepare_array_update($updateAccountFields, true) . '
|
||||
WHERE `user_id` = :user_id
|
||||
');
|
||||
$updateAccountFields['user_id'] = $app->getUserId();
|
||||
$updateUser->execute($updateAccountFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tpl->var('settings_title', $settingsModes[$settingsMode]['title']);
|
||||
$tpl->var('settings_title', $settingsModes[$settingsMode]);
|
||||
$tpl->var('settings_errors', $settingsErrors);
|
||||
|
||||
switch ($settingsMode) {
|
||||
|
@ -348,23 +291,18 @@ switch ($settingsMode) {
|
|||
');
|
||||
$getMail->bindValue('user_id', $app->getUserId());
|
||||
$currentEmail = $getMail->execute() ? $getMail->fetchColumn() : 'Failed to fetch e-mail address.';
|
||||
|
||||
$tpl->vars([
|
||||
'settings_profile_fields' => $profileFields,
|
||||
'settings_profile_values' => $userFields,
|
||||
'settings_disable_account_options' => $disableAccountOptions,
|
||||
'settings_email' => $currentEmail,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'images':
|
||||
$userHasAvatar = File::exists($app->getStore('avatars/original')->filename($avatarFileName));
|
||||
|
||||
$tpl->vars([
|
||||
'avatar_user_id' => $app->getUserId(),
|
||||
'avatar_max_width' => $avatarWidthMax,
|
||||
'avatar_max_height' => $avatarHeightMax,
|
||||
'avatar_max_filesize' => $avatarFileSizeMax,
|
||||
'user_has_avatar' => $userHasAvatar,
|
||||
'settings_profile_fields' => $profileFields,
|
||||
'settings_profile_values' => $userFields,
|
||||
'settings_disable_account_options' => $disableAccountOptions,
|
||||
'settings_email' => $currentEmail,
|
||||
]);
|
||||
break;
|
||||
|
||||
|
|
|
@ -286,6 +286,7 @@ 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');
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
{% extends '@mio/settings/master.twig' %}
|
||||
|
||||
{% block settings_content %}
|
||||
<form method="post" action="?m=account" class="settings__account">
|
||||
<div class="container">
|
||||
<div class="container__title">Account</div>
|
||||
<form action="" method="post" class="settings__account">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
||||
|
||||
<div class="settings__account__row">
|
||||
{% if settings_perms.edit_profile %}
|
||||
<div class="settings__account__column">
|
||||
<div class="settings__account__title">Profile</div>
|
||||
|
||||
|
@ -17,6 +22,7 @@
|
|||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if settings_disable_account_options %}
|
||||
<div class="settings__account__column settings__account__column--no-margin settings__account__column--disabled">
|
||||
|
@ -106,9 +112,84 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if settings_perms.edit_profile or not settings_disable_account_options %}
|
||||
<div class="settings__account__row settings__account__row--buttons">
|
||||
<button class="input__button" name="csrf" value="{{ csrf_token() }}">Update</button>
|
||||
<button class="input__button">Update</button>
|
||||
<button class="input__button" type="reset">Reset</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if settings_perms.edit_avatar %}
|
||||
<div class="container">
|
||||
<div class="container__title">Avatar</div>
|
||||
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="{{ avatar_max_filesize }}">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
|
||||
|
||||
<div class="settings__images__sections">
|
||||
<div class="settings__images__requirements">
|
||||
<ul class="settings__images__requirements__list">
|
||||
<li class="settings__images__requirement settings__images__requirement--header">Guidelines</li>
|
||||
<li class="settings__images__requirement">Keep things sane and suitable for all ages.</li>
|
||||
<li class="settings__images__requirement">Image may not exceed the <strong>{{ avatar_max_filesize|byte_symbol(true) }}</strong> filesize limit.</li>
|
||||
<li class="settings__images__requirement settings__images__requirement--header">Avatar</li>
|
||||
<li class="settings__images__requirement">May not be larger than <strong>{{ avatar_max_width }}x{{ avatar_max_height }}</strong>.</li>
|
||||
<li class="settings__images__requirement">Will be centre cropped to be <strong>200x200</strong>.</li>
|
||||
<li class="settings__images__requirement">Animated gif images are allowed.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings__avatar">
|
||||
<label class="settings__avatar__label">
|
||||
<div
|
||||
class="avatar settings__avatar__preview"
|
||||
id="avatar-preview"
|
||||
style="background-image:url('/profile.php?u={{ avatar_user_id }}&m=avatar')"></div>
|
||||
<input
|
||||
class="settings__avatar__input"
|
||||
accept="image/png,image/jpeg,image/gif"
|
||||
type="file"
|
||||
name="avatar[file]"
|
||||
id="avatar-selection">
|
||||
<div class="settings__avatar__name" id="avatar-name">
|
||||
Click to select a file!
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="settings__avatar__buttons">
|
||||
<button
|
||||
class="settings__avatar__button"
|
||||
name="avatar[mode]"
|
||||
value="upload">
|
||||
Upload
|
||||
</button>
|
||||
<button
|
||||
class="settings__avatar__button settings__avatar__button--delete{{ user_has_avatar ? '' : ' settings__avatar__button--disabled' }}"
|
||||
{{ user_has_avatar ? '' : 'disabled' }}
|
||||
name="avatar[mode]"
|
||||
value="delete">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateAvatarPreview(name, url, previewEl, nameEl) {
|
||||
url = url || "/profile.php?u={{ avatar_user_id }}&m=avatar";
|
||||
previewEl = previewEl || document.getElementById('avatar-preview');
|
||||
nameEl = nameEl || document.getElementById('avatar-name');
|
||||
previewEl.style.backgroundImage = 'url(\'{0}\')'.replace('{0}', url);
|
||||
nameEl.textContent = name;
|
||||
}
|
||||
|
||||
document.getElementById('avatar-selection').addEventListener('change', function (ev) {
|
||||
updateAvatarPreview(ev.target.files[0].name, URL.createObjectURL(ev.target.files[0]));
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
{% extends '@mio/settings/master.twig' %}
|
||||
|
||||
{% block settings_content %}
|
||||
<form
|
||||
class="settings__images"
|
||||
method="post"
|
||||
action="?m=images"
|
||||
enctype="multipart/form-data">
|
||||
<input type="hidden"
|
||||
name="MAX_FILE_SIZE"
|
||||
value="{{ avatar_max_filesize }}">
|
||||
<input type="hidden"
|
||||
name="csrf"
|
||||
value="{{ csrf_token() }}">
|
||||
|
||||
<div class="settings__images__sections">
|
||||
<div class="settings__images__requirements">
|
||||
<ul class="settings__images__requirements__list">
|
||||
<li class="settings__images__requirement settings__images__requirement--header">Guidelines</li>
|
||||
<li class="settings__images__requirement">Keep things sane and suitable for all ages.</li>
|
||||
<li class="settings__images__requirement">Image may not exceed the <strong>{{ avatar_max_filesize|byte_symbol(true) }}</strong> filesize limit.</li>
|
||||
<li class="settings__images__requirement settings__images__requirement--header">Avatar</li>
|
||||
<li class="settings__images__requirement">May not be larger than <strong>{{ avatar_max_width }}x{{ avatar_max_height }}</strong>.</li>
|
||||
<li class="settings__images__requirement">Will be centre cropped to be <strong>200x200</strong>.</li>
|
||||
<li class="settings__images__requirement">Animated gif images are allowed.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings__avatar">
|
||||
<label class="settings__avatar__label">
|
||||
<div
|
||||
class="avatar settings__avatar__preview"
|
||||
id="avatar-preview"
|
||||
style="background-image:url('/profile.php?u={{ avatar_user_id }}&m=avatar')"></div>
|
||||
<input
|
||||
class="settings__avatar__input"
|
||||
accept="image/png,image/jpeg,image/gif"
|
||||
type="file"
|
||||
name="avatar[file]"
|
||||
id="avatar-selection">
|
||||
<div class="settings__avatar__name" id="avatar-name">
|
||||
Click to select a file!
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="settings__avatar__buttons">
|
||||
<button
|
||||
class="settings__avatar__button"
|
||||
name="avatar[mode]"
|
||||
value="upload">
|
||||
Upload
|
||||
</button>
|
||||
<button
|
||||
class="settings__avatar__button settings__avatar__button--delete{{ user_has_avatar ? '' : ' settings__avatar__button--disabled' }}"
|
||||
{{ user_has_avatar ? '' : 'disabled' }}
|
||||
name="avatar[mode]"
|
||||
value="delete">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
function updateAvatarPreview(name, url, previewEl, nameEl) {
|
||||
url = url || "/profile.php?u={{ avatar_user_id }}&m=avatar";
|
||||
previewEl = previewEl || document.getElementById('avatar-preview');
|
||||
nameEl = nameEl || document.getElementById('avatar-name');
|
||||
previewEl.style.backgroundImage = 'url(\'' + url + '\')';
|
||||
nameEl.textContent = name;
|
||||
}
|
||||
|
||||
document.getElementById('avatar-selection').addEventListener('change', function (ev) {
|
||||
updateAvatarPreview(ev.target.files[0].name, URL.createObjectURL(ev.target.files[0]));
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -4,11 +4,14 @@
|
|||
{% set alpagination = pagination(audit_log_count, audit_log_take, audit_log_offset, '?m=log', 'settings__') %}
|
||||
|
||||
{% block settings_content %}
|
||||
<div class="container">
|
||||
<div class="container__title">Account Log</div>
|
||||
|
||||
<div class="settings__log">
|
||||
<div class="settings__description">
|
||||
<p>This is a log of all "important" actions that have been done using your account for your review. If you notice anything strange, please alert the staff.</p>
|
||||
</div>
|
||||
|
||||
<div class="settings__log">
|
||||
{{ alpagination }}
|
||||
|
||||
{% for log in audit_logs %}
|
||||
|
@ -51,4 +54,5 @@
|
|||
|
||||
{{ alpagination }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
{% set lhpagination = pagination(login_attempts_count, login_attempts_take, login_attempts_offset, '?m=login-history', 'settings__') %}
|
||||
|
||||
{% block settings_content %}
|
||||
<div class="container">
|
||||
<div class="container__title">Login History</div>
|
||||
|
||||
<div class="settings__login-history">
|
||||
<div class="settings__description">
|
||||
<p>These are all the login attempts to your account. If any attempt that you don't recognise is marked as successful your account may be compromised, ask a staff member for advice in this case.</p>
|
||||
</div>
|
||||
|
||||
<div class="settings__login-history">
|
||||
{{ lhpagination }}
|
||||
|
||||
{% for attempt in user_login_attempts %}
|
||||
|
@ -58,4 +61,5 @@
|
|||
|
||||
{{ lhpagination }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% set title = 'Settings » ' ~ settings_title %}
|
||||
|
||||
{% block content %}
|
||||
{{ navigation(settings_navigation, settings_mode, true, '?m=%s') }}
|
||||
{{ navigation(settings_modes|flip, settings_mode, true, '?m=%s') }}
|
||||
|
||||
{% block settings_container %}
|
||||
{% if settings_errors is defined and settings_errors|length > 0 %}
|
||||
|
@ -20,15 +20,15 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="container settings settings--{{ settings_mode }}">
|
||||
<div class="container__title settings__title settings__title--{{ settings_mode }}">{{ title }}</div>
|
||||
{% block settings_content %}
|
||||
<div class="container">
|
||||
<div class="container__title">{{ title }}</div>
|
||||
<div class="container__content">
|
||||
This is a blank settings page.
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{{ navigation(mio_navigation) }}
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
{% set spagination = pagination(sessions_count, sessions_take, sessions_offset, '?m=sessions', 'settings__') %}
|
||||
|
||||
{% block settings_content %}
|
||||
<div class="container">
|
||||
<div class="container__title">Login History</div>
|
||||
|
||||
<div class="settings__sessions">
|
||||
<div class="settings__description">
|
||||
<p>These are the active logins to your account, clicking the Kill button will force a logout on that session. Your current login is highlighted with a darker purple so you don't accidentally force yourself to logout.</p>
|
||||
</div>
|
||||
|
||||
<div class="settings__sessions">
|
||||
{{ spagination }}
|
||||
|
||||
{% for session in user_sessions %}
|
||||
|
@ -66,4 +69,5 @@
|
|||
|
||||
{{ spagination }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Add table
Reference in a new issue