diff --git a/assets/less/mio/classes/news/pagination.less b/assets/less/mio/classes/news/pagination.less index 131931a4..321a4e1c 100644 --- a/assets/less/mio/classes/news/pagination.less +++ b/assets/less/mio/classes/news/pagination.less @@ -2,14 +2,22 @@ border: 1px solid #9475b2; list-style: none; display: flex; - justify-content: space-between; padding: 1px; + &__separator { + flex-grow: 1; + flex-shrink: 1; + } + &__option { background: #9475b2; height: 20px; width: 20px; + &:not(:last-child){ + margin-right: 1px; + } + @media (max-width: @mio-news-mobile) { height: 30px; width: 30px; @@ -33,8 +41,4 @@ font-weight: bold; } } - - &__separator { - display: none; - } } diff --git a/assets/less/mio/classes/settings/pagination.less b/assets/less/mio/classes/settings/pagination.less new file mode 100644 index 00000000..1b4a3e1d --- /dev/null +++ b/assets/less/mio/classes/settings/pagination.less @@ -0,0 +1,46 @@ +.settings__pagination { + list-style: none; + display: flex; + max-width: 400px; + margin: 2px auto; + padding: 1px; + border: 1px solid #9475b2; + + &__separator { + flex-grow: 1; + flex-shrink: 1; + } + + &__option { + background: #9475b2; + height: 20px; + width: 20px; + + &:not(:last-child){ + margin-right: 1px; + } + + @media (max-width: @mio-news-mobile) { + height: 30px; + width: 30px; + font-size: 1.5em; + line-height: 1.5em; + } + } + + &__link { + display: block; + width: 100%; + height: 100%; + text-align: center; + text-decoration: none; + color: #306; + + &--prev, + &--next, + &--active, + &:hover { + font-weight: bold; + } + } +} diff --git a/assets/less/mio/main.less b/assets/less/mio/main.less index c3e8fb4e..402fe7fa 100644 --- a/assets/less/mio/main.less +++ b/assets/less/mio/main.less @@ -56,6 +56,7 @@ body { @import "classes/settings/content"; @import "classes/settings/description"; @import "classes/settings/errors"; +@import "classes/settings/pagination"; @import "classes/settings/account"; @import "classes/settings/avatar"; @import "classes/settings/login-history"; diff --git a/misuzu.php b/misuzu.php index 4dfdcf44..7c994f28 100644 --- a/misuzu.php +++ b/misuzu.php @@ -46,7 +46,7 @@ if (PHP_SAPI !== 'cli') { $app->templating->addPath('mio', __DIR__ . '/views/mio'); if ($manage_mode) { - if ($app->getSession() === null || $_SERVER['HTTP_HOST'] !== 'misuzu.misaka.nl') { + if ($app->getSession() === null || $app->getSession()->user->user_id !== 1) { http_response_code(403); echo $app->templating->render('errors.403'); exit; diff --git a/public/manage/forums.php b/public/manage/forums.php new file mode 100644 index 00000000..485f9b32 --- /dev/null +++ b/public/manage/forums.php @@ -0,0 +1,16 @@ +templating->render('@manage.general.overview'); +switch ($_GET['v'] ?? null) { + case 'overview': + echo $app->templating->render('@manage.general.overview'); + break; + + case 'logs': + echo 'soon'; + break; + + case 'emoticons': + echo 'soon as well'; + break; + + case 'settings': + echo 'somewhat soon i guess'; + break; + + case null: + header('Location: ?v=overview'); + break; +} diff --git a/public/manage/users-listing.php b/public/manage/users-listing.php deleted file mode 100644 index 86b3fff6..00000000 --- a/public/manage/users-listing.php +++ /dev/null @@ -1,11 +0,0 @@ -templating->vars(compact('manage_users', 'users_page')); - -echo $app->templating->render('@manage.users.listing'); diff --git a/public/manage/users-roles.php b/public/manage/users-roles.php deleted file mode 100644 index 59ee08d1..00000000 --- a/public/manage/users-roles.php +++ /dev/null @@ -1,110 +0,0 @@ - 255) { - echo 'invalid name length'; - break; - } - - $role_secret = !empty($_POST['role']['secret']); - - $role_hierarchy = (int)($_POST['role']['hierarchy'] ?? -1); - - if ($role_hierarchy < 1 || $role_hierarchy > 100) { - echo 'Invalid hierarchy value.'; - break; - } - - $role_colour = Colour::none(); - $role_colour->setInherit(!empty($_POST['role']['colour']['inherit'])); - - if (!$role_colour->getInherit()) { - foreach (['red', 'green', 'blue'] as $key) { - $value = (int)($_POST['role']['colour'][$key] ?? -1); - $setter = 'set' . ucfirst($key); - - if ($value < 0 || $value > 0xFF) { - echo 'invalid colour value'; - break 2; - } - - $role_colour->{$setter}($value); - } - } - - $role_description = $_POST['role']['description'] ?? ''; - - if (strlen($role_description) > 1000) { - echo 'description is too long'; - break; - } - - $edit_role = $role_id < 1 ? new Role : Role::find($role_id); - $edit_role->role_name = $role_name; - $edit_role->role_hierarchy = $role_hierarchy; - $edit_role->role_secret = $role_secret; - $edit_role->role_colour = $role_colour; - $edit_role->role_description = $role_description; - $edit_role->save(); - - header('Location: ?m=list'); - break; -} - -switch ($role_mode) { - case 'list': - $users_page = (int)($_GET['p'] ?? 1); - $manage_roles = Role::paginate(32, ['*'], 'p', $users_page); - $app->templating->vars(compact('manage_roles')); - - echo $app->templating->render('@manage.users.roles'); - break; - - case 'edit': - if (!isset($edit_role)) { - if ($role_id < 1) { - echo 'no'; - break; - } - - $edit_role = Role::find($role_id); - } - - if ($edit_role === null) { - echo 'invalid role'; - break; - } - - $app->templating->vars(compact('edit_role')); - // no break - - case 'create': - echo $app->templating->render('@manage.users.roles_create'); - break; -} diff --git a/public/manage/users.php b/public/manage/users.php new file mode 100644 index 00000000..786c2acc --- /dev/null +++ b/public/manage/users.php @@ -0,0 +1,129 @@ +templating->vars(compact('manage_users')); + echo $app->templating->render('@manage.users.listing'); + break; + + case 'view': + $user_id = $_GET['u'] ?? null; + + if ($user_id === null || ($user_id = (int)$user_id) < 1) { + echo 'no'; + break; + } + + $view_user = User::find($user_id); + + if ($view_user === null) { + echo 'Could not find that user.'; + break; + } + + $app->templating->var('view_user', $view_user); + echo $app->templating->render('@manage.users.view'); + break; + + case 'roles': + $manage_roles = Role::paginate(32, ['*'], 'p', $page_id); + $app->templating->vars(compact('manage_roles')); + echo $app->templating->render('@manage.users.roles'); + break; + + case 'role': + $role_id = $_GET['r'] ?? null; + + if ($is_post_request) { + if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { + echo 'csrf err'; + break; + } + + if (!isset($_POST['role'])) { + echo 'no'; + break; + } + + $role_name = $_POST['role']['name'] ?? ''; + $role_name_length = strlen($role_name); + + if ($role_name_length < 1 || $role_name_length > 255) { + echo 'invalid name length'; + break; + } + + $role_secret = !empty($_POST['role']['secret']); + + $role_hierarchy = (int)($_POST['role']['hierarchy'] ?? -1); + + if ($role_hierarchy < 1 || $role_hierarchy > 100) { + echo 'Invalid hierarchy value.'; + break; + } + + $role_colour = Colour::none(); + $role_colour->setInherit(!empty($_POST['role']['colour']['inherit'])); + + if (!$role_colour->getInherit()) { + foreach (['red', 'green', 'blue'] as $key) { + $value = (int)($_POST['role']['colour'][$key] ?? -1); + $setter = 'set' . ucfirst($key); + + if ($value < 0 || $value > 0xFF) { + echo 'invalid colour value'; + break 2; + } + + $role_colour->{$setter}($value); + } + } + + $role_description = $_POST['role']['description'] ?? ''; + + if (strlen($role_description) > 1000) { + echo 'description is too long'; + break; + } + + $edit_role = $role_id < 1 ? new Role : Role::find($role_id); + $edit_role->role_name = $role_name; + $edit_role->role_hierarchy = $role_hierarchy; + $edit_role->role_secret = $role_secret; + $edit_role->role_colour = $role_colour; + $edit_role->role_description = $role_description; + $edit_role->save(); + + header("Location: ?v=role&r={$edit_role->role_id}"); + break; + } + + if ($role_id !== null) { + if ($role_id < 1) { + echo 'no'; + break; + } + + $edit_role = Role::find($role_id); + + if ($edit_role === null) { + echo 'invalid role'; + break; + } + + $app->templating->vars(compact('edit_role')); + } + + echo $app->templating->render('@manage.users.roles_create'); + break; +} diff --git a/public/settings.php b/public/settings.php index fd4f791f..9cda11c8 100644 --- a/public/settings.php +++ b/public/settings.php @@ -8,6 +8,8 @@ require_once __DIR__ . '/../misuzu.php'; $settings_session = Application::getInstance()->getSession(); +$page_id = (int)($_GET['p'] ?? 1); + if (Application::getInstance()->getSession() === null) { http_response_code(403); echo $app->templating->render('errors.403'); @@ -345,11 +347,19 @@ switch ($settings_mode) { break; case 'sessions': - $app->templating->var('user_sessions', $settings_user->sessions->reverse()); + $sessions = $settings_user->sessions() + ->orderBy('session_id', 'desc') + ->paginate(15, ['*'], 'p', $page_id); + + $app->templating->var('user_sessions', $sessions); break; case 'login-history': - $app->templating->var('user_login_attempts', $settings_user->loginAttempts->reverse()); + $login_attempts = $settings_user->loginAttempts() + ->orderBy('attempt_id', 'desc') + ->paginate(15, ['*'], 'p', $page_id); + + $app->templating->var('user_login_attempts', $login_attempts); break; } diff --git a/src/Users/User.php b/src/Users/User.php index 557c6cff..97b49564 100644 --- a/src/Users/User.php +++ b/src/Users/User.php @@ -237,7 +237,7 @@ class User extends Model $this->attributes['register_ip'] = $ipAddress->getRaw(); } - public function getLastIpAttribute(string $ipAddress): string + public function getLastIpAttribute(string $ipAddress): IPAddress { return IPAddress::fromRaw($ipAddress); } diff --git a/views/manage/general/overview.twig b/views/manage/general/overview.twig index 26c2cc23..3ea0c56d 100644 --- a/views/manage/general/overview.twig +++ b/views/manage/general/overview.twig @@ -1 +1,7 @@ {% extends '@manage/general/master.twig' %} + +{% block content %} +
+

Welcome to Manage, here you can manage things.

+
+{% endblock %} diff --git a/views/manage/master.twig b/views/manage/master.twig index 35975c7d..e7a7e488 100644 --- a/views/manage/master.twig +++ b/views/manage/master.twig @@ -9,21 +9,24 @@ { 'name': 'overview', 'title': 'Overview', - 'url': '/manage/index.php', + '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', }, ], ], @@ -36,30 +39,36 @@ { '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', }, ], ], @@ -72,14 +81,17 @@ { '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', }, ], ], @@ -112,7 +124,7 @@ {% for section in menu.sections %}
{% for item in section %} - {{ item.title }} + {{ item.title }} {% endfor %}
{% endfor %} @@ -124,7 +136,7 @@
- +
Profile @@ -142,7 +154,7 @@ {% block content %}
-

This page has no content.

+

This page has no content.

{% endblock %} diff --git a/views/manage/users/listing.twig b/views/manage/users/listing.twig index 474f21e6..8f6d8096 100644 --- a/views/manage/users/listing.twig +++ b/views/manage/users/listing.twig @@ -4,19 +4,18 @@ {% block content %}
{% for user in manage_users %} - + {% endfor %}
- {{ paginate(manage_users) }} + {{ paginate(manage_users, '?v=listing') }}
{% endblock %} diff --git a/views/manage/users/roles.twig b/views/manage/users/roles.twig index bb6eb0b2..d0807818 100644 --- a/views/manage/users/roles.twig +++ b/views/manage/users/roles.twig @@ -8,7 +8,7 @@
{% for role in manage_roles %} - +
{{ role.role_name }} {{ role.users.count }} users @@ -18,6 +18,6 @@
- {{ paginate(manage_roles) }} + {{ paginate(manage_roles, '?v=roles') }}
{% endblock %} diff --git a/views/manage/users/roles_create.twig b/views/manage/users/roles_create.twig index c92bc986..731a23e0 100644 --- a/views/manage/users/roles_create.twig +++ b/views/manage/users/roles_create.twig @@ -1,9 +1,15 @@ {% extends '@manage/users/master.twig' %} {% block content %} -
+
-

Creating a new Role

+

+ {% if edit_role is defined %} + Editing {{ edit_role.role_name }} ({{ edit_role.role_id }}) + {% else %} + Creating a new Role + {% endif %} +

+ @@ -64,6 +66,7 @@ ''|date('Y') }} / {{ link('https://github.com/flashwave/misuzu/tree/' ~ git_branch(), git_branch(), 'footer__copyright__link') }} # {{ link('https://github.com/flashwave/misuzu/commit/' ~ git_hash(true), git_hash(), 'footer__copyright__link') }}
+ {% endblock %} diff --git a/views/mio/settings/sessions.twig b/views/mio/settings/sessions.twig index 6304b747..26b1cb9b 100644 --- a/views/mio/settings/sessions.twig +++ b/views/mio/settings/sessions.twig @@ -1,4 +1,5 @@ {% extends '@mio/settings/master.twig' %} +{% from '@mio/macros.twig' import paginate %} {% block settings_content %}
@@ -19,6 +20,7 @@ {% endif %}
+
Created @@ -27,6 +29,7 @@ {{ session.created_at.diffForHumans }}
+
Expires @@ -35,6 +38,7 @@ {{ session.expires_on.diffForHumans }}
+ {% if session.user_agent|length > 0 %}
@@ -45,6 +49,7 @@
{% endif %} + @@ -52,5 +57,7 @@
{% endfor %} + + {{ paginate(user_sessions, '?m=sessions', 'settings__') }}
{% endblock %} diff --git a/views/mio/user/view.twig b/views/mio/user/view.twig index 96709b45..cf09b8bf 100644 --- a/views/mio/user/view.twig +++ b/views/mio/user/view.twig @@ -4,6 +4,7 @@ {% set image = '/profile.php?u=' ~ profile.user_id ~ '&m=avatar' %} {% set canonical_url = '/profile.php?u=' ~ profile.user_id %} {% set title = 'Profile of ' ~ profile.username %} +{% set manage_link = '/manage/users.php?v=view&u=' ~ profile.user_id %} {% set youtube_is_channel_id = profile.user_youtube|slice(0, 2) == 'UC' and profile.user_youtube|length == 24 %}