From 294380d7bcb3b66d6174e5279cc73ec00b364e47 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sat, 11 Aug 2018 20:56:54 +0200 Subject: [PATCH] Merged account and avatar settings pages. --- public/manage/users.php | 2 +- public/settings.php | 442 +++++++++++--------------- src/Application.php | 1 + views/mio/settings/account.twig | 271 ++++++++++------ views/mio/settings/images.twig | 77 ----- views/mio/settings/log.twig | 90 +++--- views/mio/settings/login-history.twig | 92 +++--- views/mio/settings/master.twig | 12 +- views/mio/settings/sessions.twig | 106 +++--- 9 files changed, 524 insertions(+), 569 deletions(-) delete mode 100644 views/mio/settings/images.twig diff --git a/public/manage/users.php b/public/manage/users.php index e532fd6d..94664842 100644 --- a/public/manage/users.php +++ b/public/manage/users.php @@ -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` diff --git a/public/settings.php b/public/settings.php index cb03fe87..55bc972e 100644 --- a/public/settings.php +++ b/public/settings.php @@ -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,228 +76,201 @@ $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 (!tmp_csrf_verify($_POST['csrf'] ?? '')) { + $settingsErrors[] = $csrfErrorString; + } else { + if (!empty($_POST['profile']) && is_array($_POST['profile'])) { + $setUserFieldErrors = user_profile_fields_set($app->getUserId(), $_POST['profile']); - if (isset($_POST['profile']) && is_array($_POST['profile'])) { - $setUserFieldErrors = user_profile_fields_set($app->getUserId(), $_POST['profile']); - - if (count($setUserFieldErrors) > 0) { - foreach ($setUserFieldErrors as $name => $error) { - switch ($error) { - case MSZ_USER_PROFILE_INVALID_FIELD: - $settingsErrors[] = sprintf("Field '%s' does not exist!", $name); - break; - - case MSZ_USER_PROFILE_FILTER_FAILED: - $settingsErrors[] = sprintf( - '%s field was invalid!', - user_profile_field_get_display_name($name) - ); - break; - - case MSZ_USER_PROFILE_UPDATE_FAILED: - $settingsErrors[] = 'Failed to update values, contact an administator.'; - break; - - default: - $settingsErrors[] = 'An unexpected error occurred, contact an administator.'; - break; - } - } - } - } - - 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.'; + if (count($setUserFieldErrors) > 0) { + foreach ($setUserFieldErrors as $name => $error) { + switch ($error) { + case MSZ_USER_PROFILE_INVALID_FIELD: + $settingsErrors[] = sprintf("Field '%s' does not exist!", $name); 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']) { - case 'delete': - user_avatar_delete($app->getUserId()); - break; - - case 'upload': - if (empty($_FILES['avatar']) - || !is_array($_FILES['avatar']) - || empty($_FILES['avatar']['name']['file'])) { - break; - } - - if ($_FILES['avatar']['error']['file'] !== UPLOAD_ERR_OK) { + case MSZ_USER_PROFILE_FILTER_FAILED: $settingsErrors[] = sprintf( - $avatarErrorStrings['upload'][$_FILES['avatar']['error']['file']] - ?? $avatarErrorStrings['upload']['default'], - $_FILES['avatar']['error']['file'], - byte_symbol($avatarFileSizeMax, true), - $avatarWidthMax, - $avatarHeightMax + '%s field was invalid!', + user_profile_field_get_display_name($name) ); break; - } - $setAvatar = user_avatar_set_from_path( - $app->getUserId(), - $_FILES['avatar']['tmp_name']['file'] + case MSZ_USER_PROFILE_UPDATE_FAILED: + $settingsErrors[] = 'Failed to update values, contact an administator.'; + break; + + default: + $settingsErrors[] = 'An unexpected error occurred, contact an administator.'; + break; + } + } + } + } + + if (!empty($_POST['avatar']) && is_array($_POST['avatar'])) { + switch ($_POST['avatar']['mode'] ?? '') { + case 'delete': + user_avatar_delete($app->getUserId()); + break; + + case 'upload': + if (empty($_FILES['avatar']) + || !is_array($_FILES['avatar']) + || empty($_FILES['avatar']['name']['file'])) { + break; + } + + if ($_FILES['avatar']['error']['file'] !== UPLOAD_ERR_OK) { + $settingsErrors[] = sprintf( + $avatarErrorStrings['upload'][$_FILES['avatar']['error']['file']] + ?? $avatarErrorStrings['upload']['default'], + $_FILES['avatar']['error']['file'], + byte_symbol($avatarFileSizeMax, true), + $avatarWidthMax, + $avatarHeightMax ); - - if ($setAvatar !== MSZ_USER_AVATAR_NO_ERRORS) { - $settingsErrors[] = sprintf( - $avatarErrorStrings['set'][$setAvatar] - ?? $avatarErrorStrings['set']['default'], - $setAvatar, - byte_symbol($avatarFileSizeMax, true), - $avatarWidthMax, - $avatarHeightMax - ); - } break; - } - } - break; + } - case 'sessions': - if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { - $settingsErrors[] = $csrfErrorString; - break; - } + $setAvatar = user_avatar_set_from_path( + $app->getUserId(), + $_FILES['avatar']['tmp_name']['file'] + ); + if ($setAvatar !== MSZ_USER_AVATAR_NO_ERRORS) { + $settingsErrors[] = sprintf( + $avatarErrorStrings['set'][$setAvatar] + ?? $avatarErrorStrings['set']['default'], + $setAvatar, + byte_symbol($avatarFileSizeMax, true), + $avatarWidthMax, + $avatarHeightMax + ); + } + 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` + WHERE `session_id` = :session_id + '); + $findSession->bindValue('session_id', $session_id); + $session = $findSession->execute() ? $findSession->fetch() : null; - $findSession = Database::prepare(' - SELECT `session_id`, `user_id` - FROM `msz_sessions` - WHERE `session_id` = :session_id + if (!$session || (int)$session['user_id'] !== $app->getUserId()) { + $settingsErrors[] = 'You may only end your own sessions.'; + } else { + if ((int)$session['session_id'] === $app->getSessionId()) { + header('Location: /auth.php?m=logout&s=' . tmp_csrf_token()); + return; + } + + user_session_delete($session['session_id']); + 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 '); - $findSession->bindValue('session_id', $session_id); - $session = $findSession->execute() ? $findSession->fetch() : null; + $fetchPassword->bindValue('user_id', $app->getUserId()); + $currentPassword = $fetchPassword->execute() ? $fetchPassword->fetchColumn() : null; - if (!$session || (int)$session['user_id'] !== $app->getUserId()) { - $settingsErrors[] = 'You may only end your own sessions.'; - break; + 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); + } + } + } } - - if ((int)$session['session_id'] === $app->getSessionId()) { - header('Location: /auth.php?m=logout&s=' . tmp_csrf_token()); - return; - } - - user_session_delete($session['session_id']); - audit_log('PERSONAL_SESSION_DESTROY', $app->getUserId(), [ - $session['session_id'], - ]); - break; + } } } -$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; diff --git a/src/Application.php b/src/Application.php index 7a6aa8c1..ea20ac45 100644 --- a/src/Application.php +++ b/src/Application.php @@ -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'); diff --git a/views/mio/settings/account.twig b/views/mio/settings/account.twig index 72e3467f..7d3b20f5 100644 --- a/views/mio/settings/account.twig +++ b/views/mio/settings/account.twig @@ -1,114 +1,195 @@ {% extends '@mio/settings/master.twig' %} {% block settings_content %} -
-