Updated session manager styling.

This commit is contained in:
flash 2018-10-29 18:55:10 +01:00
parent 8786ed10dc
commit 1430b2e692
8 changed files with 355 additions and 379 deletions

View file

@ -1,4 +1,5 @@
.settings__container { .settings__container {
overflow: auto;
&:not(:last-child) { &:not(:last-child) {
margin-bottom: 2px; margin-bottom: 2px;

View file

@ -1,83 +1,74 @@
@mio-settings-sessions-mobile: 1000px;
.settings__session { .settings__session {
margin: 1px; margin: 4px;
border: 1px solid var(--accent-colour);
border-radius: 2px;
overflow: hidden;
&__country { &--current {
vertical-align: middle; // todo: make this now bad
background-image: linear-gradient(0deg, #111c, #111c);
background-color: var(--accent-colour);
} }
@media (max-width: @mio-settings-sessions-mobile) { &__important {
&__button { display: flex;
width: 100%; align-items: center;
text-align: center; font-size: 1.4em;
z-index: 2;
} }
&__flag {
flex: 0 0 auto;
margin: 10px;
margin-right: 0;
}
&__description {
flex: 1 1 auto;
margin: 10px;
} }
&__actions { &__actions {
flex: 0 0 auto;
display: flex; display: flex;
justify-content: center;
padding: 6px;
border-bottom: 1px solid var(--accent-colour);
margin-bottom: 1px;
} }
&__entry { &__action {
border: 0;
background: transparent;
color: inherit;
font: inherit;
text-shadow: inherit;
padding: 10px;
cursor: pointer;
transition: color .2s;
&:hover {
color: var(--accent-colour);
}
}
&__details {
z-index: 1;
margin: 10px;
margin-top: -5px;
display: flex; display: flex;
border: 1px solid var(--accent-colour);
justify-content: space-between;
padding: 1px;
flex-wrap: wrap; flex-wrap: wrap;
&:not(:last-child) {
margin-bottom: 1px;
} }
&--current { &__detail {
background-color: #c2affe; display: inline-block;
} margin-right: 2px;
}
&__column {
flex-grow: 1;
&:not(:last-child) {
margin-left: 5px;
margin-right: 1px;
}
&--ip,
&--created,
&--expires,
&--options {
flex-grow: 0;
flex-shrink: 0;
}
@media (max-width: @mio-settings-sessions-mobile) {
&--options {
text-align: center;
flex-grow: 1;
width: 100%;
}
}
&--user-agent {
flex-shrink: 1;
flex-grow: 1;
}
&--ip {
min-width: 200px;
}
&--created,
&--expires {
min-width: 120px; min-width: 120px;
&__title {
border-bottom: 1px solid var(--accent-colour);
font-weight: 700;
padding: 1px 5px;
} }
&__name { &__value {
font-weight: 700; padding: 1px 5px;
} }
} }
} }

View file

@ -0,0 +1,12 @@
.settings__sessions {
&__all {
display: flex;
justify-content: center;
margin: 10px;
}
&__pagination {
margin: 4px;
}
}

View file

@ -127,6 +127,7 @@ body {
@import "classes/settings/log"; @import "classes/settings/log";
@import "classes/settings/login-history"; @import "classes/settings/login-history";
@import "classes/settings/session"; @import "classes/settings/session";
@import "classes/settings/sessions";
// News // News
@import "classes/news/container"; @import "classes/news/container";

View file

@ -29,32 +29,36 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!csrf_verify('settings', $_POST['csrf'] ?? '')) { if (!csrf_verify('settings', $_POST['csrf'] ?? '')) {
$settingsErrors[] = MSZ_TMP_USER_ERROR_STRINGS['csrf']; $settingsErrors[] = MSZ_TMP_USER_ERROR_STRINGS['csrf'];
} else { } else {
if (!empty($_POST['session_action'])) { if (!empty($_POST['session'])) {
switch ($_POST['session_action']) { $currentSessionKilled = false;
case 'kill-all':
user_session_purge_all($settingsUserId);
audit_log('PERSONAL_SESSION_DESTROY_ALL', $settingsUserId);
header('Location: /');
return;
}
}
if (!empty($_POST['session']) && is_numeric($_POST['session'])) { if (is_array($_POST['session'])) {
$session = user_session_find((int)($_POST['session'] ?? 0)); foreach ($_POST['session'] as $sessionId) {
$sessionId = intval($sessionId);
$session = user_session_find($sessionId);
if (!$session) { if (!$session || (int)$session['user_id'] !== $settingsUserId) {
$settingsErrors[] = 'Invalid session.'; $settingsErrors[] = "Session #{$sessionId} does not exist.";
} elseif ((int)$session['user_id'] !== $settingsUserId) { break;
$settingsErrors[] = 'You may only end your own sessions.';
} elseif ((int)$session['session_id'] === user_session_current('session_id')) { } elseif ((int)$session['session_id'] === user_session_current('session_id')) {
header('Location: /auth.php?m=logout&s=' . csrf_token('logout')); $currentSessionKilled = true;
return; }
} else {
user_session_delete($session['session_id']); user_session_delete($session['session_id']);
audit_log('PERSONAL_SESSION_DESTROY', $settingsUserId, [ audit_log('PERSONAL_SESSION_DESTROY', $settingsUserId, [
$session['session_id'], $session['session_id'],
]); ]);
} }
} elseif ($_POST['session'] === 'all') {
$currentSessionKilled = true;
user_session_purge_all($settingsUserId);
audit_log('PERSONAL_SESSION_DESTROY_ALL', $settingsUserId);
}
if ($currentSessionKilled) {
header('Location: /');
return;
}
} }
if (!$disableAccountOptions) { if (!$disableAccountOptions) {

View file

@ -4,8 +4,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
{% include '_layout/meta.twig' %} {% include '_layout/meta.twig' %}
<link href="{{ '/css/style.css'|asset_url }}" rel="stylesheet">
<link href="{{ '/css/libraries.css'|asset_url }}" rel="stylesheet"> <link href="{{ '/css/libraries.css'|asset_url }}" rel="stylesheet">
<link href="{{ '/css/style.css'|asset_url }}" rel="stylesheet">
{% if site_background is defined %} {% if site_background is defined %}
<style> <style>
:root { :root {

View file

@ -45,53 +45,67 @@
{% endmacro %} {% endmacro %}
{% macro user_session(session, is_current_session) %} {% macro user_session(session, is_current_session) %}
{% from '_layout/input.twig' import input_hidden, input_csrf, input_checkbox_raw %}
{% set browser = get_browser(session.user_agent) %} {% set browser = get_browser(session.user_agent) %}
<div class="settings__session{% if is_current_session %} settings__session--current{% endif %}" id="session-{{ session.session_id }}"> <div class="settings__session{% if is_current_session %} settings__session--current{% endif %}" id="session-{{ session.session_id }}">
<div class="settings__session__icon settings__session__icon--browser" title="{{ browser.browser }}"> <div class="settings__session__important">
{% if browser.browser[:7]|lower == 'firefox' %} <div class="flag flag--{{ session.session_country|lower }} settings__session__flag"></div>
<i class="fab fa-firefox"></i>
{% elseif browser.browser[:6]|lower == 'chrome' %}
<i class="fab fa-chrome"></i>
{% elseif browser.browser[:4]|lower == 'edge' %}
<i class="fab fa-edge"></i>
{% elseif browser.browser[:2]|lower == 'ie' %}
<i class="fab fa-internet-explorer"></i>
{% elseif browser.browser[:6]|lower == 'safari' %}
<i class="fab fa-safari"></i>
{% elseif browser.browser[:6]|lower == 'opera' %}
<i class="fab fa-opera"></i>
{% else %}
<i class="fas fa-globe"></i>
{% endif %}
</div>
<div class="settings__session__icon settings__session__icon--device" title="{{ browser.device_type }}">
{% if browser.device_type[:7]|lower == 'desktop' %}
<i class="fas fa-desktop"></i>
{% elseif browser.device_type[:6]|lower == 'mobile' %}
<i class="fas fa-mobile-alt"></i>
{% elseif browser.device_type[:6]|lower == 'tablet' %}
<i class="fas fa-tablet-alt"></i>
{% else %}
<i class="fas fa-blender-phone"></i>
{% endif %}
</div>
<div class="settings__session__icon settings__session__icon--system" title="{{ browser.platform }}">
{% if browser.platform[:3]|lower == 'win' %}
<i class="fab fa-windows"></i>
{% elseif browser.platform[:3]|lower == 'ios' or browser.platform[:3]|lower == 'mac' %}
<i class="fab fa-apple"></i>
{% elseif browser.platform[:7]|lower == 'android' %}
<i class="fab fa-android"></i>
{% else %}
<i class="fab fa-linux"></i>
{% endif %}
</div>
<div class="settings__session__description"> <div class="settings__session__description">
{{ browser.browser }} on {{ browser.platform }} {{ browser.browser }} on {{ browser.platform }}
</div> </div>
<form class="settings__session__actions" method="post" action="/settings.php">
{{ input_csrf('settings') }}
{{ input_hidden('session[]', session.session_id) }}
<button class="settings__session__action" title="{{ is_current_session ? 'Logout' : 'End Session' }}">
{% if is_current_session %}
<i class="fas fa-sign-out-alt"></i>
{% else %}
<i class="fas fa-times-circle"></i>
{% endif %}
</button>
</form>
</div>
<div class="settings__session__details">
<div class="settings__session__detail">
<div class="settings__session__detail__title">
IP Address
</div>
<div class="settings__session__detail__value">
{{ session.session_ip_decoded }}
</div>
</div>
<div class="settings__session__detail" title="{{ session.created_at|date('r') }}">
<div class="settings__session__detail__title">
Created
</div>
<time class="settings__session__detail__value" datetime="{{ session.created_at|date('c') }}">
{{ session.created_at|time_diff }}
</time>
</div>
<div class="settings__session__detail" title="{{ session.expires_on|date('r') }}">
<div class="settings__session__detail__title">
Expires
</div>
<time class="settings__session__detail__value" datetime="{{ session.expires_on|date('c') }}">
{{ session.expires_on|time_diff }}
</time>
</div>
<div class="settings__session__detail">
<div class="settings__session__detail__title">
User Agent
</div>
<div class="settings__session__detail__value">
{{ session.user_agent|length > 0 ? session.user_agent : 'None' }}
</div>
</div>
</div>
</div> </div>
{% endmacro %} {% endmacro %}

View file

@ -6,9 +6,6 @@
{% set title = 'Settings' %} {% set title = 'Settings' %}
{% block content %} {% block content %}
<form action="" method="post">
{{ input_csrf('settings') }}
{% if settings_errors is defined and settings_errors|length > 0 %} {% if settings_errors is defined and settings_errors|length > 0 %}
<div class="warning"> <div class="warning">
<div class="warning__content"> <div class="warning__content">
@ -25,8 +22,9 @@
</div> </div>
{% endif %} {% endif %}
<div class="container settings__container" id="account"> <form action="" method="post" class="container settings__container" id="account">
{{ container_title('<i class="fas fa-user fa-fw"></i> Account', '', true) }} {{ container_title('<i class="fas fa-user fa-fw"></i> Account', '', true) }}
{{ input_csrf('settings') }}
<div class="settings__description"> <div class="settings__description">
<p>Here you can change your e-mail address and/or your password, please make sure your e-mail is accurate and your password is strong in order to protect your account. For convenience your current e-mail address is displayed. You are required to verify yourself by entering your current password to change either value.</p> <p>Here you can change your e-mail address and/or your password, please make sure your e-mail is accurate and your password is strong in order to protect your account. For convenience your current e-mail address is displayed. You are required to verify yourself by entering your current password to change either value.</p>
@ -92,85 +90,41 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </form>
<div class="container settings__container" id="sessions"> <div class="container settings__container" id="sessions">
{{ container_title('<i class="fas fa-key fa-fw"></i> Sessions', '', true) }} {{ container_title('<i class="fas fa-key fa-fw"></i> Sessions', '', true) }}
{% set spagination = pagination(sessions_count, sessions_take, sessions_offset, '?m=sessions') %} {% set spagination = pagination(sessions_count, sessions_take, sessions_offset, '?m=sessions') %}
<div class="settings__description"> <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> <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 different colour so you don't accidentally force yourself to logout.</p>
</div> </div>
<div class="settings__sessions"> <div class="settings__sessions">
<!--form class="settings__sessions__actions" method="post" action="?m=sessions"> <form action="" method="post" class="settings__sessions__all">
{{ input_csrf('settings') }} {{ input_csrf('settings') }}
{{ input_hidden('session', 'all') }}
<button class="input__button" name="session_action" value="kill-all"> <button class="input__button">
Kill all active sessions <i class="fas fa-bomb"></i>&nbsp;Kill ALL active sessions
</button> </button>
</form--> </form>
<div class="settings__sessions__pagination">
{{ spagination }} {{ spagination }}
</div>
<div class="settings__sessions__list">
{% for session in user_sessions %} {% for session in user_sessions %}
{{ user_session(session) }} {{ user_session(session, session.session_id == active_session_id) }}
<div class="settings__sessions__column settings__sessions__column--ip">
<div class="settings__sessions__column__name">
IP
</div>
<div class="settings__sessions__column__value">
{{ session.session_ip_decoded }}
{% if session.session_country != 'XX' %}
<div class="flag flag--{{ session.session_country|lower }} settings__sessions__country" title="{{ session.session_country|country_name }}"></div>
{% endif %}
</div>
</div>
<div class="settings__sessions__column settings__sessions__column--created" title="{{ session.created_at|date('r') }}">
<div class="settings__sessions__column__name">
Created
</div>
<time class="settings__sessions__column__value" datetime="{{ session.created_at|date('c') }}">
{{ session.created_at|time_diff }}
</time>
</div>
<div class="settings__sessions__column settings__sessions__column--expires" title="{{ session.expires_on|date('r') }}">
<div class="settings__sessions__column__name">
Expires
</div>
<time class="settings__sessions__column__value" datetime="{{ session.expires_on|date('c') }}">
{{ session.expires_on|time_diff }}
</time>
</div>
{% if session.user_agent|length > 0 %}
<div class="settings__sessions__column settings__sessions__column--user_agent">
<div class="settings__sessions__column__name">
User Agent
</div>
<div class="settings__sessions__column__value">
{{ session.user_agent }}
</div>
</div>
{% endif %}
<!--form class="settings__sessions__column settings__sessions__column--options" method="post" action="?m=sessions">
{{ input_hidden('session', session.session_id) }}
{{ input_csrf('settings') }}
<button class="input__button settings__sessions__button">
{{ session.session_id == active_session_id ? 'Logout' : 'Kill' }}
</button>
</form-->
{% endfor %} {% endfor %}
</div>
<div class="settings__sessions__pagination">
{{ spagination }} {{ spagination }}
</div> </div>
</div> </div>
</div>
<div class="container settings__container" id="logins"> <div class="container settings__container" id="logins">
{{ container_title('<i class="fas fa-user-lock fa-fw"></i> Login History', '', true) }} {{ container_title('<i class="fas fa-user-lock fa-fw"></i> Login History', '', true) }}
@ -298,5 +252,4 @@
{{ alpagination }} {{ alpagination }}
</div> </div>
</div> </div>
</form>
{% endblock %} {% endblock %}