1<?php
2/**
3 * Displays the user management frontend.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public License,
6 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
7 * obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * @package phpMyFAQ
10 * @author Lars Tiedemann <php@larstiedemann.de>
11 * @author Uwe Pries <uwe.pries@digartis.de>
12 * @author Sarah Hermann <sayh@gmx.de>
13 * @author Thorsten Rinne <thorsten@phpmyfaq.de>
14 * @copyright 2005-2020 phpMyFAQ Team
15 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
16 * @link https://www.phpmyfaq.de
17 * @since 2005-12-15
18 */
19
20use phpMyFAQ\Category;
21use phpMyFAQ\Filter;
22use phpMyFAQ\Mail;
23use phpMyFAQ\Pagination;
24use phpMyFAQ\Permission;
25use phpMyFAQ\User;
26use phpMyFAQ\User\CurrentUser;
27use phpMyFAQ\Utils;
28
29if (!defined('IS_VALID_PHPMYFAQ')) {
30    http_response_code(400);
31    exit();
32}
33
34if ($user->perm->checkRight($user->getUserId(), 'edit_user') ||
35    $user->perm->checkRight($user->getUserId(), 'delete_user') ||
36    $user->perm->checkRight($user->getUserId(), 'add_user')) {
37    ?>
38  <script src="assets/js/user.js"></script>
39    <?php
40
41    // set some parameters
42    $selectSize = 10;
43    $defaultUserAction = 'list';
44    $defaultUserStatus = 'active';
45    $userActionList = [
46        'udpate_rights',
47        'update_data',
48        'delete_confirm',
49        'delete',
50        'addsave',
51        'add',
52        'list',
53        'listallusers'
54    ];
55
56    // what shall we do?
57    // actions defined by url: user_action=
58    $userAction = Filter::filterInput(INPUT_GET, 'user_action', FILTER_SANITIZE_STRING, $defaultUserAction);
59    $currentUser = new CurrentUser($faqConfig);
60
61    // actions defined by submit button
62    if (isset($_POST['user_action_deleteConfirm'])) {
63        $userAction = 'delete_confirm';
64    }
65    if (isset($_POST['cancel'])) {
66        $userAction = $defaultUserAction;
67    }
68
69    // update user rights
70    if ($userAction == 'update_rights' && $user->perm->checkRight($user->getUserId(), 'edit_user')) {
71        $message = '';
72        $userAction = $defaultUserAction;
73        $userId = Filter::filterInput(INPUT_POST, 'user_id', FILTER_VALIDATE_INT, 0);
74        $csrfOkay = true;
75        $csrfToken = Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
76        if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
77            $csrfOkay = false;
78        }
79        if (0 === (int)$userId || !$csrfOkay) {
80            $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_noId']);
81        } else {
82            $user = new User($faqConfig);
83            $perm = $user->perm;
84            // @todo: Add Filter::filterInput[]
85            $userRights = isset($_POST['user_rights']) ? $_POST['user_rights'] : [];
86            if (!$perm->refuseAllUserRights($userId)) {
87                $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_msg_mysqlerr']);
88            }
89            foreach ($userRights as $rightId) {
90                $perm->grantUserRight($userId, $rightId);
91            }
92            $idUser = $user->getUserById($userId, true);
93            $message .= sprintf(
94                '<p class="alert alert-success">%s <strong>%s</strong> %s</p>',
95                $PMF_LANG['ad_msg_savedsuc_1'],
96                $user->getLogin(),
97                $PMF_LANG['ad_msg_savedsuc_2']
98            );
99            $message .= '<script>updateUser(' . $userId . ');</script>';
100            $user = new CurrentUser($faqConfig);
101        }
102    }
103
104    // update user data
105    if ($userAction == 'update_data' && $user->perm->checkRight($user->getUserId(), 'edit_user')) {
106        $message = '';
107        $userAction = $defaultUserAction;
108        $userId = Filter::filterInput(INPUT_POST, 'user_id', FILTER_VALIDATE_INT, 0);
109        if ($userId == 0) {
110            $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_noId']);
111        } else {
112            $userData = [];
113            $userData['display_name'] = Filter::filterInput(INPUT_POST, 'display_name', FILTER_SANITIZE_STRING, '');
114            $userData['email'] = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL, '');
115            $userData['last_modified'] = Filter::filterInput(INPUT_POST, 'last_modified', FILTER_SANITIZE_STRING, '');
116            $userStatus = Filter::filterInput(INPUT_POST, 'user_status', FILTER_SANITIZE_STRING, $defaultUserStatus);
117            $isSuperAdmin = Filter::filterInput(INPUT_POST, 'is_superadmin', FILTER_SANITIZE_STRING);
118            $isSuperAdmin = $isSuperAdmin === 'on' ? true : false;
119
120            $user = new User($faqConfig);
121            $user->getUserById($userId, true);
122
123            $stats = $user->getStatus();
124
125            // set new password an send email if user is switched to active
126            if ($stats == 'blocked' && $userStatus == 'active') {
127                if (!$user->activateUser()) {
128                    $userStatus = 'invalid_status';
129                }
130            }
131
132            // Set super-admin flag
133            $user->setSuperAdmin($isSuperAdmin);
134
135            if (!$user->userdata->set(array_keys($userData), array_values($userData)) ||
136                !$user->setStatus($userStatus)) {
137                $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_msg_mysqlerr']);
138            } else {
139                $message .= sprintf(
140                    '<p class="alert alert-success">%s <strong>%s</strong> %s</p>',
141                    $PMF_LANG['ad_msg_savedsuc_1'],
142                    $user->getLogin(),
143                    $PMF_LANG['ad_msg_savedsuc_2']
144                );
145                $message .= '<script>updateUser(' . $userId . ');</script>';
146            }
147        }
148    }
149
150    // delete user confirmation
151    if ($userAction == 'delete_confirm' && $user->perm->checkRight($user->getUserId(), 'delete_user')) {
152        $message = '';
153        $user = new CurrentUser($faqConfig);
154
155        $userId = Filter::filterInput(INPUT_GET, 'user_delete_id', FILTER_VALIDATE_INT, 0);
156        if ($userId == 0) {
157            $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_noId']);
158            $userAction = $defaultUserAction;
159        } else {
160            $user->getUserById($userId, true);
161            // account is protected
162            if ($user->getStatus() == 'protected' || $userId == 1) {
163                $message .= sprintf(
164                    '<p class="alert alert-danger">%s</p>',
165                    $PMF_LANG['ad_user_error_protectedAccount']
166                );
167                $userAction = $defaultUserAction;
168            } else {
169                ?>
170
171              <div
172                  class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
173                <h1 class="h2">
174                  <i aria-hidden="" class="fa fa-user"></i>
175                    <?= $PMF_LANG['ad_user_deleteUser'] ?> <?= $user->getLogin() ?>
176                </h1>
177              </div>
178
179              <p class="alert alert-danger">
180                  <?= $PMF_LANG['ad_user_del_3'] . ' ' . $PMF_LANG['ad_user_del_1'] . ' ' . $PMF_LANG['ad_user_del_2'] ?>
181              </p>
182              <form action="?action=user&amp;user_action=delete" method="post" accept-charset="utf-8">
183                <input type="hidden" name="user_id" value="<?= $userId ?>">
184                <input type="hidden" name="csrf" value="<?= $currentUser->getCsrfTokenFromSession() ?>">
185                <p class="text-center">
186                  <button class="btn btn-danger" type="submit">
187                      <?= $PMF_LANG['ad_gen_yes'] ?>
188                  </button>
189                  <a class="btn btn-info" href="?action=user">
190                      <?= $PMF_LANG['ad_gen_no'] ?>
191                  </a>
192                </p>
193              </form>
194                <?php
195            }
196        }
197    }
198
199    // delete user
200    if ($userAction == 'delete' && $user->perm->checkRight($user->getUserId(), 'delete_user')) {
201        $message = '';
202        $user = new User($faqConfig);
203        $userId = Filter::filterInput(INPUT_POST, 'user_id', FILTER_VALIDATE_INT, 0);
204        $csrfOkay = true;
205        $csrfToken = Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
206        $userAction = $defaultUserAction;
207
208        if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
209            $csrfOkay = false;
210        }
211        $userAction = $defaultUserAction;
212        if (0 === (int)$userId || !$csrfOkay) {
213            $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_noId']);
214        } else {
215            if (!$user->getUserById($userId, true)) {
216                $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_noId']);
217            }
218            if (!$user->deleteUser()) {
219                $message .= sprintf('<p class="alert alert-danger">%s</p>', $PMF_LANG['ad_user_error_delete']);
220            } else {
221                // Move the categories ownership to admin (id == 1)
222                $oCat = new Category($faqConfig, [], false);
223                $oCat->setUser($currentAdminUser);
224                $oCat->setGroups($currentAdminGroups);
225                $oCat->moveOwnership($userId, 1);
226
227                // Remove the user from groups
228                if ('basic' !== $faqConfig->get('security.permLevel')) {
229                    $oPerm = Permission::selectPerm('medium', $faqConfig);
230                    $oPerm->removeFromAllGroups($userId);
231                }
232
233                $message .= sprintf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_user_deleted']);
234            }
235            $userError = $user->error();
236            if ($userError != '') {
237                $message .= sprintf('<p class="alert alert-danger">%s</p>', $userError);
238            }
239        }
240    }
241
242    // save new user
243    if ($userAction === 'addsave' && $user->perm->checkRight($user->getUserId(), 'add_user')) {
244        $newUser = new User($faqConfig);
245        $message = '';
246        $messages = [];
247        $userName = Filter::filterInput(INPUT_POST, 'user_name', FILTER_SANITIZE_STRING, '');
248        $userRealName = Filter::filterInput(INPUT_POST, 'user_realname', FILTER_SANITIZE_STRING, '');
249        $userPassword = Filter::filterInput(INPUT_POST, 'user_password', FILTER_SANITIZE_STRING, '');
250        $userEmail = Filter::filterInput(INPUT_POST, 'user_email', FILTER_VALIDATE_EMAIL);
251        $userPassword = Filter::filterInput(INPUT_POST, 'user_password', FILTER_SANITIZE_STRING, '');
252        $userPasswordConfirm = Filter::filterInput(INPUT_POST, 'user_password_confirm', FILTER_SANITIZE_STRING, '');
253        $userIsSuperAdmin = Filter::filterInput(INPUT_POST, 'user_is_superadmin', FILTER_SANITIZE_STRING);
254        $csrfToken = Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
255        $csrfOkay = true;
256
257        if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
258            $csrfOkay = false;
259        }
260
261        if ($userPassword !== $userPasswordConfirm) {
262            $userPassword = '';
263            $userPasswordConfirm = '';
264            $messages[] = $PMF_LANG['ad_user_error_passwordsDontMatch'];
265        }
266
267        // check login name
268        if (!$newUser->isValidLogin($userName)) {
269            $userName = '';
270            $messages[] = $PMF_LANG['ad_user_error_loginInvalid'];
271        }
272        if ($newUser->getUserByLogin($userName)) {
273            $userName = '';
274            $messages[] = $PMF_LANG['ad_adus_exerr'];
275        }
276        // check realname
277        if ($userRealName == '') {
278            $userRealName = '';
279            $messages[] = $PMF_LANG['ad_user_error_noRealName'];
280        }
281        // check e-mail
282        if (is_null($userEmail)) {
283            $userEmail = '';
284            $messages[] = $PMF_LANG['ad_user_error_noEmail'];
285        }
286
287        // ok, let's go
288        if (count($messages) === 0 && $csrfOkay) {
289            // create user account (login and password)
290            if (!$newUser->createUser($userName, $userPassword)) {
291                $messages[] = $newUser->error();
292            } else {
293                // set user data (realname, email)
294                $newUser->userdata->set(['display_name', 'email'], [$userRealName, $userEmail]);
295                // set user status
296                $newUser->setStatus($defaultUserStatus);
297                $newUser->setSuperAdmin($userIsSuperAdmin === 'on' ? true : false);
298            }
299        }
300
301        // no errors, send notification to user and show list
302        if (count($messages) === 0) {
303            $text = sprintf(
304                "You have been registered as a new user:\n\nName: %s\nLogin name: %s\nPassword: %s\n\n" .
305                'Check it out here: %s',
306                $userRealName,
307                $userName,
308                $userPassword,
309                $faqConfig->getDefaultUrl()
310            );
311
312            $mail = new Mail($faqConfig);
313            $mail->addTo($userEmail, $userName);
314            $mail->subject = Utils::resolveMarkers($PMF_LANG['emailRegSubject'], $faqConfig);
315            $mail->message = $text;
316            $result = $mail->send();
317
318            $userAction = $defaultUserAction;
319            $message = sprintf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_adus_suc']);
320            // display error messages and show form again
321        } else {
322            $userAction = 'add';
323            $message = '<p class="alert alert-danger">';
324            foreach ($messages as $err) {
325                $message .= $err . '<br>';
326            }
327            $message .= '</p>';
328        }
329    }
330
331    if (!isset($message)) {
332        $message = '';
333    }
334
335    // show new user form
336    if ($userAction === 'add' && $user->perm->checkRight($user->getUserId(), 'add_user')) { ?>
337
338      <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
339        <h1 class="h2">
340          <i aria-hidden="true" class="fa fa-user-plus"></i>
341            <?= $PMF_LANG['ad_adus_adduser'] ?>
342        </h1>
343      </div>
344
345      <div id="user_message"><?= $message ?></div>
346      <div id="user_create">
347
348        <form action="?action=user&amp;user_action=addsave" method="post" role="form">
349          <input type="hidden" name="csrf" value="<?= $currentUser->getCsrfTokenFromSession() ?>">
350
351          <div class="form-group row">
352            <label class="col-lg-2 col-form-label" for="user_name"><?= $PMF_LANG['ad_adus_name'] ?></label>
353            <div class="col-lg-4">
354              <input type="text" name="user_name" id="user_name" required tabindex="1" class="form-control"
355                     value="<?= (isset($userName) ? $userName : '') ?>">
356            </div>
357          </div>
358
359          <div class="form-group row">
360            <label class="col-lg-2 col-form-label" for="user_realname"><?= $PMF_LANG['ad_user_realname'] ?></label>
361            <div class="col-lg-4">
362              <input type="text" name="user_realname" id="user_realname" required tabindex="2" class="form-control"
363                     value="<?= (isset($userRealName) ? $userRealName : '') ?>">
364            </div>
365          </div>
366
367          <div class="form-group row">
368            <label class="col-lg-2 col-form-label" for="user_email"><?= $PMF_LANG['ad_entry_email'] ?></label>
369            <div class="col-lg-4">
370              <input type="email" name="user_email" id="user_email" required tabindex="3" class="form-control"
371                     value="<?= (isset($userEmail) ? $userEmail : '') ?>">
372            </div>
373          </div>
374
375          <div class="form-group row">
376            <label class="col-lg-2 col-form-label" for="password"><?= $PMF_LANG['ad_adus_password'] ?></label>
377            <div class="col-lg-4">
378              <input type="password" name="user_password" id="password" required tabindex="4" class="form-control"
379                     value="<?= (isset($userPassword) ? $userPassword : '') ?>">
380            </div>
381          </div>
382
383          <div class="form-group row">
384            <label class="col-lg-2 col-form-label" for="password_confirm"><?= $PMF_LANG['ad_passwd_con'] ?></label>
385            <div class="col-lg-4">
386              <input type="password" name="user_password_confirm" id="password_confirm" required class="form-control"
387                     tabindex="5" value="<?= (isset($userPasswordConfirm) ? $userPasswordConfirm : '') ?>">
388            </div>
389          </div>
390
391          <div class="form-group form-check row">
392            <div class="offset-lg-2 col-lg-4">
393              <input class="form-check-input" type="checkbox" id="is_superadmin" name="user_is_superadmin">
394              <label class="form-check-label" for="is_superadmin">
395                  <?= $PMF_LANG['ad_user_is_superadmin'] ?>
396              </label>
397            </div>
398          </div>
399
400          <div class="form-group row">
401            <div class="offset-lg-2 col-lg-10">
402              <a class="btn btn-info" href="?action=user">
403                  <?= $PMF_LANG['ad_gen_cancel'] ?>
404              </a>
405              <button class="btn btn-success" type="submit">
406                  <?= $PMF_LANG['ad_gen_save'] ?>
407              </button>
408            </div>
409          </div>
410        </form>
411      </div>
412        <?php
413    }
414
415    // show list of users
416    if ($userAction === 'list') { ?>
417
418      <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
419        <h1 class="h2">
420          <i aria-hidden="true" class="fa fa-user"></i>
421            <?= $PMF_LANG['ad_user'] ?>
422        </h1>
423        <div class="btn-toolbar mb-2 mb-md-0">
424          <div class="btn-group mr-2">
425            <a class="btn btn-sm btn-success" href="?action=user&amp;user_action=add">
426              <i class="fa fa-user-plus" aria-label="true"></i> <?= $PMF_LANG['ad_user_add'] ?>
427            </a>
428              <?php if ($currentUser->perm->checkRight($user->getUserId(), 'edit_user')): ?>
429                <a class="btn btn-sm btn-info" href="?action=user&amp;user_action=listallusers">
430                  <i class="fa fa-users" aria-label="true"></i> <?= $PMF_LANG['list_all_users'] ?>
431                </a>
432              <?php endif ?>
433          </div>
434        </div>
435      </div>
436
437      <script>
438        /**
439         * Returns the user data as JSON object
440         *
441         * @param user_id User ID
442         */
443        function getUserData(user_id) {
444          $('#user_data_table').empty();
445          $.getJSON('index.php?action=ajax&ajax=user&ajaxaction=get_user_data&user_id=' + user_id, function(data) {
446            $('#update_user_id').val(data.user_id);
447            $('#user_status_select').val(data.status);
448            $('#user_list_autocomplete').val(data.login);
449            $('#user_list_select').val(data.user_id);
450            $('#modal_user_id').val(data.user_id);
451            // Append input fields
452            $('#user_data_table').append(
453              '<div class="form-group row">' +
454              '<label class="col-lg-4 col-form-label"><?= $PMF_LANG['ad_user_realname'] ?></label>' +
455              '<div class="col-lg-8">' +
456              '<input type="text" name="display_name" value="' + data.display_name + '" class="form-control" required>' +
457              '</div>' +
458              '</div>' +
459              '<div class="form-group row">' +
460              '<label class="col-lg-4 col-form-label"><?= $PMF_LANG['ad_entry_email'] ?></label>' +
461              '<div class="col-lg-8">' +
462              '<input type="email" name="email" value="' + data.email + '" class="form-control" required>' +
463              '</div>' +
464              '</div>' +
465              '<div class="form-group row">' +
466              '<div class="offset-lg-4 col-lg-8">' +
467              '<div class="form-check">' +
468              '<input class="form-check-input" type="checkbox" id="is_superadmin" name="is_superadmin">' +
469              '<label class="form-check-label" for="is_superadmin"><?= $PMF_LANG['ad_user_is_superadmin'] ?></label>' +
470              '</div>' +
471              '</div>' +
472              '</div>' +
473              '<div class="form-group row">' +
474              '<div class="offset-lg-4 col-lg-8">' +
475              '<a class="btn btn-danger pmf-admin-override-password" data-toggle="modal" ' +
476              '   href="#pmf-modal-user-password-override"><?= $PMF_LANG['ad_user_override_passwd'] ?></a>' +
477              '</div>' +
478              '</div>' +
479              '<input type="hidden" name="last_modified" value="' + data.last_modified + '">',
480            );
481            if (data.is_superadmin) {
482              $('#is_superadmin').attr('checked', 'checked');
483            }
484          });
485        }
486      </script>
487
488
489      <div id="user_message"><?= $message ?></div>
490
491      <div class="row">
492        <div class="col-lg-4">
493          <form name="user_select" id="user_select" action="?action=user&amp;user_action=delete_confirm"
494                method="post" role="form" class="form_inline">
495            <div class="card mb-4">
496              <div class="card-header">
497                <i aria-hidden="true" class="fa fa-search"></i> <?= $PMF_LANG['msgSearch'] ?>
498              </div>
499              <div class="card-body">
500                <div class="input-group">
501                  <input type="text" id="user_list_autocomplete" name="user_list_search"
502                         class="form-control pmf-user-autocomplete" autocomplete="off"
503                         placeholder="<?= $PMF_LANG['ad_auth_user'] ?>">
504                </div>
505              </div>
506            </div>
507          </form>
508        </div>
509
510        <div class="col-lg-4">
511          <div class="card mb-4">
512            <div class="card-header" id="user_data_legend">
513              <i aria-hidden="true" class="fa fa-user"></i> <?= $PMF_LANG['ad_user_profou'] ?>
514            </div>
515            <form action="?action=user&amp;user_action=update_data" method="post">
516              <div class="card-body">
517                <input id="update_user_id" type="hidden" name="user_id" value="0">
518                <input type="hidden" name="csrf" value="<?= $currentUser->getCsrfTokenFromSession(); ?>">
519                <div class="form-group row">
520                  <label for="user_status_select" class="col-lg-4 col-form-label">
521                      <?= $PMF_LANG['ad_user_status'] ?>
522                  </label>
523                  <div class="col-lg-8">
524                    <select id="user_status_select" class="form-control" name="user_status">
525                      <option value="active"><?= $PMF_LANG['ad_user_active'] ?></option>
526                      <option value="blocked"><?= $PMF_LANG['ad_user_blocked'] ?></option>
527                      <option value="protected"><?= $PMF_LANG['ad_user_protected'] ?></option>
528                    </select>
529                  </div>
530                </div>
531                <div id="user_data_table"></div>
532              </div>
533              <div class="card-footer">
534                <div class="card-button text-right">
535                  <button class="btn btn-success" type="submit">
536                    <i aria-hidden="true" class="fa fa-check"></i> <?= $PMF_LANG['ad_gen_save'] ?>
537                  </button>
538                </div>
539              </div>
540            </form>
541          </div>
542        </div>
543        <div class="col-lg-4" id="userRights">
544          <form id="rightsForm" action="?action=user&amp;user_action=update_rights" method="post"
545                accept-charset="utf-8">
546            <input type="hidden" name="csrf" value="<?= $currentUser->getCsrfTokenFromSession() ?>">
547            <input type="hidden" name="user_id" id="rights_user_id" value="0">
548
549            <div class="card mb-4">
550              <div class="card-header" id="user_rights_legend">
551                <i aria-hidden="true" class="fa fa-lock"></i> <?= $PMF_LANG['ad_user_rights'] ?>
552                <span class="float-right">
553                  <a class="btn btn-primary btn-sm" href="#" id="checkAll">
554                    <?= $PMF_LANG['ad_user_checkall'] ?>
555                    /
556                    <?= $PMF_LANG['ad_user_uncheckall'] ?>
557                  </a>
558                </span>
559              </div>
560              <div class="card-body">
561                  <?php foreach ($user->perm->getAllRightsData() as $right): ?>
562                    <div class="form-check">
563                      <input id="user_right_<?= $right['right_id'] ?>" type="checkbox"
564                             name="user_rights[]" value="<?= $right['right_id'] ?>"
565                             class="form-check-input permission">
566                      <label class="form-check-label">
567                          <?php
568                          if (isset($PMF_LANG['rightsLanguage'][$right['name']])) {
569                              echo $PMF_LANG['rightsLanguage'][$right['name']];
570                          } else {
571                              echo $right['description'];
572                          }
573                          ?>
574                      </label>
575                    </div>
576                  <?php endforeach; ?>
577              </div>
578              <div class="card-footer">
579                <div class="card-button text-right">
580                  <button class="btn btn-success" type="submit">
581                      <?= $PMF_LANG['ad_gen_save'] ?>
582                  </button>
583                </div>
584              </div>
585            </div>
586          </form>
587        </div>
588      </div>
589
590      <div class="modal fade" id="pmf-modal-user-password-override">
591        <div class="modal-dialog">
592          <div class="modal-content">
593            <div class="modal-header">
594              <h4><?= $PMF_LANG['ad_menu_passwd'] ?></h4>
595              <button type="button" class="close" data-dismiss="modal" aria-label="Close">
596                <span aria-hidden="true">&times;</span>
597              </button>
598            </div>
599            <div class="modal-body">
600              <form action="#" method="post" accept-charset="utf-8">
601                <input type="hidden" name="csrf" value="<?= $currentUser->getCsrfTokenFromSession() ?>">
602                <input type="hidden" name="user_id" id="modal_user_id" value="<?= $userId ?>">
603
604                <div class="form-group row">
605                  <label class="col-lg-4 col-form-label" for="npass">
606                      <?= $PMF_LANG['ad_passwd_new'] ?>
607                  </label>
608                  <div class="col-lg-8">
609                    <input type="password" name="npass" id="npass" class="form-control" required>
610                  </div>
611                </div>
612
613                <div class="form-group row">
614                  <label class="col-lg-4 col-form-label" for="bpass">
615                      <?= $PMF_LANG['ad_passwd_con'] ?>
616                  </label>
617                  <div class="col-lg-8">
618                    <input type="password" name="bpass" id="bpass" class="form-control" required>
619                  </div>
620                </div>
621
622              </form>
623            </div>
624            <div class="modal-footer">
625              <button class="btn btn-primary pmf-user-password-override-action">
626                  <?= $PMF_LANG['ad_user_override_passwd'] ?>
627              </button>
628            </div>
629          </div>
630        </div>
631      </div>
632        <?php
633    }
634
635    // show list of all users
636    if ($userAction == 'listallusers' && $user->perm->checkRight($user->getUserId(), 'edit_user')) {
637        $allUsers = $user->getAllUsers(false);
638        $numUsers = count($allUsers);
639        $page = Filter::filterInput(INPUT_GET, 'page', FILTER_VALIDATE_INT, 0);
640        $perPage = 10;
641        $numPages = ceil($numUsers / $perPage);
642        $lastPage = $page * $perPage;
643        $firstPage = $lastPage - $perPage;
644
645        $baseUrl = sprintf(
646            '%sadmin/?action=user&amp;user_action=listallusers&amp;page=%d',
647            $faqConfig->getDefaultUrl(),
648            $page
649        );
650
651        // Pagination options
652        $options = [
653            'baseUrl' => $baseUrl,
654            'total' => $numUsers,
655            'perPage' => $perPage,
656            'useRewrite' => false,
657            'pageParamName' => 'page',
658        ];
659        $pagination = new Pagination($faqConfig, $options);
660        ?>
661
662      <div
663          class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
664        <h1 class="h2">
665          <i aria-hidden="true" class="fa fa-user"></i>
666            <?= $PMF_LANG['ad_user'] ?>
667        </h1>
668        <div class="btn-toolbar mb-2 mb-md-0">
669          <div class="btn-group mr-2">
670            <a class="btn btn-sm btn-success" href="?action=user&amp;user_action=add">
671              <i class="fa fa-user-plus" aria-label="true"></i>
672              <?= $PMF_LANG['ad_user_add'] ?>
673            </a>
674          </div>
675        </div>
676      </div>
677
678      <div id="user_message"><?= $message ?></div>
679
680      <table class="table table-striped">
681        <thead class="thead-dark">
682        <tr>
683          <th><?= $PMF_LANG['ad_entry_id'] ?></th>
684          <th><?= $PMF_LANG['ad_user_status'] ?></th>
685          <th><?= $PMF_LANG['ad_user_is_superadmin'] ?></th>
686          <th><?= $PMF_LANG['msgNewContentName'] ?></th>
687          <th><?= $PMF_LANG['ad_auth_user'] ?></th>
688          <th><?= $PMF_LANG['msgNewContentMail'] ?></th>
689          <th colspan="3">&nbsp;</th>
690        </tr>
691        </thead>
692          <?php if ($perPage < $numUsers): ?>
693            <tfoot>
694            <tr>
695              <td colspan="8"><?= $pagination->render() ?></td>
696            </tr>
697            </tfoot>
698          <?php endif;
699          ?>
700        <tbody>
701        <?php
702        $counter = $displayedCounter = 0;
703        foreach ($allUsers as $userId) {
704            $user->getUserById($userId, true);
705
706            if ($displayedCounter >= $perPage) {
707                continue;
708            }
709            ++$counter;
710            if ($counter <= $firstPage) {
711                continue;
712            }
713            ++$displayedCounter;
714
715            ?>
716          <tr class="row_user_id_<?= $user->getUserId() ?>">
717            <td><?= $user->getUserId() ?></td>
718            <td class="text-center"><i class="fa <?php
719                switch ($user->getStatus()) {
720                    case 'active':
721                        echo 'fa-check-circle-o';
722                        break;
723                    case 'blocked':
724                        echo 'fa-ban';
725                        break;
726                    case 'protected':
727                        echo 'fa-lock';
728                        break;
729                }
730                ?> icon_user_id_<?= $user->getUserId() ?>"></i></td>
731            <td class="text-center">
732              <i class="fa <?= $user->isSuperAdmin() ? 'fa-user-secret' : 'fa-user-times' ?>"></i>
733            </td>
734            <td><?= $user->getUserData('display_name') ?></td>
735            <td><?= $user->getLogin() ?></td>
736            <td>
737              <a href="mailto:<?= $user->getUserData('email') ?>">
738                  <?= $user->getUserData('email') ?>
739              </a>
740            </td>
741            <td>
742              <a href="?action=user&amp;user_id=<?= $user->getUserData('user_id') ?>" class="btn btn-info">
743                <i class="fa fa-pencil"></i> <?= $PMF_LANG['ad_user_edit'] ?>
744              </a>
745            </td>
746            <td>
747                <?php if ($user->getStatus() === 'blocked'): ?>
748                  <a onclick="activateUser(this); return false;"
749                     href="#" class="btn btn-success btn_user_id_<?= $user->getUserData('user_id') ?>"
750                     data-csrf-token="<?= $currentUser->getCsrfTokenFromSession() ?>"
751                     data-user-id="<?= $user->getUserData('user_id') ?>">
752                      <?= $PMF_LANG['ad_news_set_active'] ?>
753                  </a>
754                <?php endif;
755                ?>
756            </td>
757            <td>
758                <?php if ($user->getStatus() !== 'protected'): ?>
759                  <a href="#" onclick="deleteUser(this); return false;" class="btn btn-danger"
760                     data-csrf-token="<?= $currentUser->getCsrfTokenFromSession() ?>"
761                     data-user-id="<?= $user->getUserData('user_id') ?>">
762                    <i class="fa fa-trash"></i> <?= $PMF_LANG['ad_user_delete'] ?>
763                  </a>
764                <?php endif;
765                ?>
766            </td>
767          </tr>
768            <?php
769        }
770        ?>
771        </tbody>
772      </table>
773
774      <script>
775        /**
776         * Ajax call to delete user
777         *
778         * @param identifier
779         */
780        function deleteUser(identifier) {
781          if (confirm('<?= $PMF_LANG['ad_user_del_3'] ?>')) {
782            const csrf = $(identifier).data('csrf-token');
783            const userId = $(identifier).data('user-id');
784
785            $.getJSON('index.php?action=ajax&ajax=user&ajaxaction=delete_user&user_id=' + userId + '&csrf=' + csrf,
786              (response) => {
787                $('#user_message').html(response);
788                $('.row_user_id_' + userId).fadeOut('slow');
789              });
790          }
791        }
792
793        /**
794         * Ajax call to delete user
795         *
796         * @param identifier
797         */
798        function activateUser(identifier) {
799          if (confirm('<?= $PMF_LANG['ad_user_active'] ?>')) {
800            const csrf = $(identifier).data('csrf-token');
801            const userId = $(identifier).data('user-id');
802            $.getJSON('index.php?action=ajax&ajax=user&ajaxaction=activate_user&user_id=' + userId + '&csrf=' + csrf,
803              () => {
804                const icon = $('.icon_user_id_' + userId);
805                icon.toggleClass('fa-lock fa-check');
806                $('.btn_user_id_' + userId).remove();
807              });
808          }
809        }
810
811      </script>
812        <?php
813    }
814    if (isset($_GET['user_id'])) {
815        $userId = Filter::filterInput(INPUT_GET, 'user_id', FILTER_VALIDATE_INT, 0);
816        echo '        <script>updateUser(' . $userId . ');</script>';
817    }
818} else {
819    echo $PMF_LANG['err_NotAuth'];
820}
821