diff --git a/nginx.conf b/nginx.conf index d07794342b..0ba4244fde 100644 --- a/nginx.conf +++ b/nginx.conf @@ -129,7 +129,7 @@ server { rewrite admin/api/(.*) /admin/api/index.php last; # Administration pages - rewrite admin/(attachments|backup|backup/export|backup/restore|configuration|elasticsearch|export|import|instance/edit|instance/update|instances|password|session-keep-alive|stopwords|system|update) /admin/front.php last; + rewrite admin/(attachments|backup|backup/export|backup/restore|configuration|elasticsearch|export|import|instance/edit|instance/update|instances|password|session-keep-alive|stopwords|system|update|user) /admin/front.php last; # REST API v3.0 and v3.1 rewrite ^api/v3\.[01]/(.*) /api/index.php last; diff --git a/phpmyfaq/.htaccess b/phpmyfaq/.htaccess index c7c500ea7e..bb12ac2661 100644 --- a/phpmyfaq/.htaccess +++ b/phpmyfaq/.htaccess @@ -143,7 +143,7 @@ Header set Access-Control-Allow-Headers "Content-Type, Authorization" # Administration API RewriteRule ^admin/api/(.*) admin/api/index.php [L,QSA] # Administration pages - RewriteRule ^admin/(attachments|backup|backup/export|backup/restore|configuration|elasticsearch|export|import|instance/edit|instance/update|instances|password|session-keep-alive|stopwords|system|update) admin/front.php [L,QSA] + RewriteRule ^admin/(attachments|backup|backup/export|backup/restore|configuration|elasticsearch|export|import|instance/edit|instance/update|instances|password|session-keep-alive|stopwords|system|update|user) admin/front.php [L,QSA] # Private APIs RewriteRule ^api/(autocomplete|bookmark/delete|bookmark/create|user/data/update|user/password/update|user/request-removal|user/remove-twofactor|contact|voting|register|captcha|share|comment/create|faq/create|question/create|webauthn/prepare|webauthn/register|webauthn/prepare-login|webauthn/login) api/index.php [L,QSA] # Setup APIs diff --git a/phpmyfaq/admin/assets/src/user/users.js b/phpmyfaq/admin/assets/src/user/users.js index 41fb9fb939..7261290d9a 100644 --- a/phpmyfaq/admin/assets/src/user/users.js +++ b/phpmyfaq/admin/assets/src/user/users.js @@ -51,12 +51,12 @@ const setUserData = async (userId) => { const superAdmin = document.getElementById('is_superadmin'); superAdmin.setAttribute('checked', 'checked'); document.querySelectorAll('.permission').forEach((checkbox) => { - checkbox.setAttribute('disabled', ''); + checkbox.removeAttribute('disabled'); }); document.querySelectorAll('#pmf-user-rights-save').forEach((element) => { - element.setAttribute('disabled', ''); + element.removeAttribute('disabled'); }); - document.getElementById('checkAll').setAttribute('disabled', ''); + document.getElementById('checkAll').removeAttribute('disabled'); } else { const superAdmin = document.getElementById('is_superadmin'); superAdmin.removeAttribute('checked'); @@ -74,6 +74,8 @@ const setUserData = async (userId) => { } const saveUser = document.getElementById('pmf-user-save'); saveUser.classList.remove('disabled'); + + window.history.pushState({}, '', `./user/edit/${userId}`); }; const setUserRights = async (userId) => { @@ -143,10 +145,10 @@ export const handleUsers = async () => { isSuperAdmin.addEventListener('click', () => { if (isSuperAdmin.checked) { document.querySelectorAll('.permission').forEach((checkbox) => { - checkbox.setAttribute('disabled', ''); + checkbox.removeAttribute('disabled'); }); document.querySelectorAll('#pmf-user-rights-save').forEach((element) => { - element.setAttribute('disabled', ''); + element.removeAttribute('disabled'); }); document.getElementById('checkAll').setAttribute('disabled', ''); } else { @@ -154,9 +156,9 @@ export const handleUsers = async () => { checkbox.removeAttribute('disabled'); }); document.querySelectorAll('#pmf-user-rights-save').forEach((element) => { - element.removeAttribute('disabled', ''); + element.removeAttribute('disabled'); }); - document.getElementById('checkAll').removeAttribute('disabled', ''); + document.getElementById('checkAll').removeAttribute('disabled'); } }); } diff --git a/phpmyfaq/admin/header.php b/phpmyfaq/admin/header.php index 814319eab0..7ba8c7f455 100644 --- a/phpmyfaq/admin/header.php +++ b/phpmyfaq/admin/header.php @@ -48,7 +48,8 @@ $secLevelEntries['user'] = $adminHelper->addMenuEntry( 'add_user+edit_user+delete_user', 'user', - 'ad_menu_user_administration' + 'ad_menu_user_administration', + 'user' ); if ($faqConfig->get('security.permLevel') !== 'basic') { $secLevelEntries['user'] .= $adminHelper->addMenuEntry( diff --git a/phpmyfaq/admin/index.php b/phpmyfaq/admin/index.php index b8e3b42212..15ac6366d6 100755 --- a/phpmyfaq/admin/index.php +++ b/phpmyfaq/admin/index.php @@ -21,7 +21,6 @@ use phpMyFAQ\Administration\AdminLog; use phpMyFAQ\Attachment\AttachmentFactory; -use phpMyFAQ\Configuration; use phpMyFAQ\Faq; use phpMyFAQ\Filter; use phpMyFAQ\Language; @@ -242,13 +241,6 @@ // [$currentAdminUser, $currentAdminGroups] = CurrentUser::getCurrentUserGroupId($user); -// are we running a PMF export file request? -switch ($action) { - case 'reportexport': - require 'report.export.php'; - exit(); -} - // Header of the admin page including the navigation require 'header.php'; @@ -265,9 +257,6 @@ // the various sections of the admin area switch ($action) { // functions for user administration - case 'user': - require 'user.php'; - break; case 'group': require 'group.php'; break; diff --git a/phpmyfaq/admin/user.php b/phpmyfaq/admin/user.php deleted file mode 100755 index fb36e89fd4..0000000000 --- a/phpmyfaq/admin/user.php +++ /dev/null @@ -1,191 +0,0 @@ - - * @author Uwe Pries - * @author Sarah Hermann - * @author Thorsten Rinne - * @copyright 2005-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2005-12-15 - */ - -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filter; -use phpMyFAQ\Pagination; -use phpMyFAQ\Session\Token; -use phpMyFAQ\Template\Extensions\PermissionTranslationTwigExtension; -use phpMyFAQ\Template\TwigWrapper; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -if ( - !$user->perm->hasPermission($user->getUserId(), PermissionType::USER_EDIT->value) || - !$user->perm->hasPermission($user->getUserId(), PermissionType::USER_DELETE->value) || - !$user->perm->hasPermission($user->getUserId(), PermissionType::USER_ADD->value) -) { - require __DIR__ . '/no-permission.php'; - exit(); -} - -$templateVars = []; - -$userId = Filter::filterInput(INPUT_GET, 'user_id', FILTER_VALIDATE_INT); - -// set some parameters -$selectSize = 10; -$defaultUserAction = 'list'; -$userActionList = [ - 'list', - 'listallusers' -]; - -// what shall we do? -// actions defined by url: user_action= -$userAction = Filter::filterInput(INPUT_GET, 'user_action', FILTER_SANITIZE_SPECIAL_CHARS, $defaultUserAction); -$currentUser = new CurrentUser($faqConfig); - -// show a list of all users -if ($userAction == 'listallusers') { - if (!$user->perm->hasPermission($user->getUserId(), PermissionType::USER_EDIT->value)) { - require __DIR__ . '/no-permission.php'; - exit(); - } - $allUsers = $user->getAllUsers(false); - $numUsers = is_countable($allUsers) ? count($allUsers) : 0; - $page = Filter::filterInput(INPUT_GET, 'page', FILTER_VALIDATE_INT, 0); - $perPage = 10; - $numPages = ceil($numUsers / $perPage); - $lastPage = $page * $perPage; - $firstPage = $lastPage - $perPage; - - $baseUrl = sprintf( - '%sadmin/?action=user&user_action=listallusers&page=%d', - $faqConfig->getDefaultUrl(), - $page - ); - - // Pagination options - $options = [ - 'baseUrl' => $baseUrl, - 'total' => $numUsers, - 'perPage' => $perPage, - 'pageParamName' => 'page', - ]; - $pagination = new Pagination($options); - - $counter = $displayedCounter = 0; - $users = []; - foreach ($allUsers as $listedUserId) { - $user->getUserById($listedUserId, true); - $tempUser = []; - - if ($displayedCounter >= $perPage) { - continue; - } - ++$counter; - if ($counter <= $firstPage) { - continue; - } - ++$displayedCounter; - - $tempUser = [ - 'display_name' => $user->getUserData('display_name'), - 'id' => $user->getUserId(), - 'email' => $user->getUserData('email'), - 'status' => $user->getStatus(), - 'isSuperAdmin' => $user->isSuperAdmin(), - 'isVisible' => $user->getUserData('is_visible'), - 'login' => $user->getLogin() - ]; - - $users[] = $tempUser; - } - - $user = CurrentUser::getCurrentUser($faqConfig); - - $templateVars = [ - ...$templateVars, - 'perPage' => $perPage, - 'numUsers' => $numUsers, - 'pagination' => $pagination->render(), - 'users' => $users, - 'userIsSuperAdmin' => $user->isSuperAdmin() - ]; -} - -$templateVars = [ - ...$templateVars, - 'userAction' => $userAction, - 'ad_user' => Translation::get('ad_user'), - 'permissionAddUser' => $currentUser->perm->hasPermission($user->getUserId(), PermissionType::USER_ADD->value), - 'ad_user_add' => Translation::get('ad_user_add'), - 'permissionEditUser' => $currentUser->perm->hasPermission($user->getUserId(), PermissionType::USER_EDIT->value), - 'list_all_users' => Translation::get('list_all_users'), - 'userId' => $userId, - 'msgSearch' => Translation::get('msgSearch'), - 'ad_auth_user' => Translation::get('ad_auth_user'), - 'ad_user_profou' => Translation::get('ad_user_profou'), - 'csrfToken_updateUserData' => Token::getInstance($container->get('session'))->getTokenString('update-user-data'), - 'msgAuthenticationSource' => Translation::get('msgAuthenticationSource'), - 'ad_user_status' => Translation::get('ad_user_status'), - 'ad_user_active' => Translation::get('ad_user_active'), - 'ad_user_blocked' => Translation::get('ad_user_blocked'), - 'ad_user_protected' => Translation::get('ad_user_protected'), - 'msgRealname' => Translation::get('msgRealname'), - 'msgEmail' => Translation::get('msgEmail'), - 'ad_user_is_superadmin' => Translation::get('ad_user_is_superadmin'), - 'ad_user_overwrite_passwd' => Translation::get('ad_user_overwrite_passwd'), - 'ad_user_overwrite_twofactor' => Translation::get('ad_user_overwrite_twofactor'), - 'ad_user_delete' => Translation::get('ad_user_delete'), - 'ad_gen_save' => Translation::get('ad_gen_save'), - 'csrfToken_updateUserRights' => Token::getInstance($container->get('session'))->getTokenString('update-user-rights'), - 'ad_user_rights' => Translation::get('ad_user_rights'), - 'ad_user_checkall' => Translation::get('ad_user_checkall'), - 'ad_user_uncheckall' => Translation::get('ad_user_uncheckall'), - 'userRights' => $user->perm->getAllRightsData(), - 'msgExportUsersAsCSV' => Translation::get('msgExportUsersAsCSV'), - 'msgNewContentName' => Translation::get('msgNewContentName'), - 'msgNewContentMail' => Translation::get('msgNewContentMail'), - 'ad_user_is_visible' => Translation::get('ad_user_is_visible'), - 'ad_user_edit' => Translation::get('ad_user_edit'), - 'csrfToken_activateUser' => Token::getInstance($container->get('session'))->getTokenString('activate-user'), - 'ad_news_set_active' => Translation::get('ad_news_set_active'), - 'permissionDeleteUser' => - $currentUser->perm->hasPermission($user->getUserId(), PermissionType::USER_DELETE->value), - 'csrfToken_deleteUser' => Token::getInstance($container->get('session'))->getTokenString('delete-user'), - 'ad_adus_adduser' => Translation::get('ad_adus_adduser'), - 'csrfToken_addUser' => Token::getInstance($container->get('session'))->getTokenString('add-user'), - 'ad_adus_name' => Translation::get('ad_adus_name'), - 'ad_add_user_change_password' => Translation::get('ad_add_user_change_password'), - 'ad_adus_password' => Translation::get('ad_adus_password'), - 'ad_passwd_con' => Translation::get('ad_passwd_con'), - 'ad_gen_cancel' => Translation::get('ad_gen_cancel'), - 'ad_menu_passwd' => Translation::get('ad_menu_passwd'), - 'csrfToken_overwritePassword' => Token::getInstance($container->get('session'))->getTokenString('overwrite-password'), - 'ad_passwd_new' => Translation::get('ad_passwd_new'), - 'msgWarning' => Translation::get('msgWarning'), - 'ad_gen_yes' => Translation::get('ad_gen_yes'), - 'ad_gen_no' => Translation::get('ad_gen_no'), - 'ad_user_deleteUser' => Translation::get('ad_user_deleteUser'), - 'msgUserList' => Translation::get('msgUserList') -]; - -$twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); -$twig->addExtension(new PermissionTranslationTwigExtension()); -$template = $twig->loadTemplate('@admin/user/users.twig'); - -echo $template->render($templateVars); diff --git a/phpmyfaq/assets/templates/admin/header.twig b/phpmyfaq/assets/templates/admin/header.twig index 4f6a042a94..0afaa2bbbe 100644 --- a/phpmyfaq/assets/templates/admin/header.twig +++ b/phpmyfaq/assets/templates/admin/header.twig @@ -106,7 +106,7 @@ {% if secondLevelEntries['user'] != '' %} -
+ {{ 'ad_user' | translate }} + + {% if permissionAddUser == true %} + + {% endif %} + +
+
+
+ + + + + + + + + + + + + + {% if perPage < numUsers %} + + + + + + {% endif %} + + {% for user in users %} + + + + + + + + + + + + {% endfor %} + +
{{ 'msgNewContentName' | translate }}{{ 'msgNewContentMail' | translate }}{{ 'ad_auth_user' | translate }}{{ 'ad_user_status' | translate }}{{ 'ad_user_is_superadmin' | translate }}{{ 'ad_user_is_visible' | translate }}Actions
{{ pagination|raw }}
{{ user.display_name|raw }} + + {{ user.email|raw }} + + {{ user.login|raw }} + + + + + + {{ ad_user_edit }} + + {% if user.status == 'blocked' %} + + {% endif %} + {% if user.status != 'protected' and permissionDeleteUser == true %} + + {% endif %} +
+{% endblock %} diff --git a/phpmyfaq/assets/templates/admin/user/user.twig b/phpmyfaq/assets/templates/admin/user/user.twig new file mode 100644 index 0000000000..d2df74ea34 --- /dev/null +++ b/phpmyfaq/assets/templates/admin/user/user.twig @@ -0,0 +1,195 @@ +{% extends '@admin/index.twig' %} + +{% block content %} +
+

+ + {{ 'ad_user' | translate }} +

+
+
+ {% if permissionAddUser == true %} + + {% endif %} + {% if permissionEditUser == true %} + + {{ 'list_all_users' | translate }} + + {% endif %} +
+
+
+ +
+
+
+ +
+
+ {{ 'msgSearch' | translate }} +
+
+
+ + +
+
+
+
+
+
+ +
+ +
+
+
+ {{ 'ad_user_profou' | translate }} +
+
+ + + + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+
+
+ + + +
+
+
+ + +
+
+
+ +
+ +
+
+ +
+ + + +
+
+
+ {{ 'ad_user_rights' | translate }} +
+
+ +
+
+
+
+ + +
+ {% for right in userRights %} +
+ + +
+ {% endfor %} +
+ +
+
+
+ + {{ include('@admin/user/modals.twig') }} + +{% endblock %} diff --git a/phpmyfaq/assets/templates/admin/user/users.twig b/phpmyfaq/assets/templates/admin/user/users.twig deleted file mode 100644 index e0e8c12c37..0000000000 --- a/phpmyfaq/assets/templates/admin/user/users.twig +++ /dev/null @@ -1,512 +0,0 @@ -{% if userAction == 'list' %} -
-

- - {{ ad_user }} -

-
-
- {% if permissionAddUser == true %} - - {% endif %} - {% if permissionEditUser == true %} - - {{ list_all_users }} - - {% endif %} -
-
-
- -
-
-
- -
-
- {{ msgSearch }} -
-
-
- - -
-
-
-
-
-
- -
- -
-
-
- {{ ad_user_profou }} -
-
- - - - -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
-
-
- - -
-
-
- - - -
-
-
- - -
-
-
- -
- -
-
- -
- - - -
-
-
- {{ ad_user_rights }} -
-
- -
-
-
-
- - -
- {% for right in userRights %} -
- - -
- {% endfor %} -
- -
-
-
-{% endif %} -{% if userAction == 'listallusers' and permissionEditUser == true %} -
-

- - {{ msgUserList }} -

-
-
- - {{ ad_user }} - - {% if permissionAddUser == true %} - - {% endif %} - -
-
-
- - - - - - - - - - - - - - {% if perPage < numUsers %} - - - - - - {% endif %} - - {% for user in users %} - - - - - - - - - - - - {% endfor %} - -
{{ msgNewContentName }}{{ msgNewContentMail }}{{ ad_auth_user }}{{ ad_user_status }}{{ ad_user_is_superadmin }}{{ ad_user_is_visible }}Actions
{{ pagination|raw }}
{{ user.display_name|raw }} - - {{ user.email|raw }} - - {{ user.login|raw }} - - - - - - {{ ad_user_edit }} - - {% if user.status == 'blocked' %} - - {% endif %} - {% if user.status != 'protected' and permissionDeleteUser == true %} - - {% endif %} -
-{% endif %} - - - - - - - -{% if permissionDeleteUser == true %} - -