feat: expose suffix and valedictory in user admin and esign (#6814)
[openemr.git] / interface / usergroup / usergroup_admin.php
blob490afe73691ca41138c4b68d94b5e35499ab5795
1 <?php
3 /**
4 * This script assigns ACL 'Emergency login'.
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Roberto Vasquez <robertogagliotta@gmail.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Daniel Pflieger <daniel@mi-squared.com> <daniel@growlingflea.com>
11 * @author Ken Chapple <ken@mi-squared.com>
12 * @author Rod Roark <rod@sunsetsystems.com>
13 * @author Robert DOwn <robertdown@live.com>
14 * @copyright Copyright (c) 2015 Roberto Vasquez <robertogagliotta@gmail.com>
15 * @copyright Copyright (c) 2017-2019 Brady Miller <brady.g.miller@gmail.com>
16 * @copyright Copyright (c) 2021 Daniel Pflieger <daniel@mi-squared.com> <daniel@growlingflea.com>
17 * @copyright Copyright (c) 2021 Ken Chapple <ken@mi-squared.com>
18 * @copyright Copyright (c) 2021 Rod Roark <rod@sunsetsystems.com>
19 * @copyright Copyright (c) 2022-2023 Robert Down <robertdown@live.com>
20 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
23 $sessionAllowWrite = true;
24 require_once("../globals.php");
26 use OpenEMR\Common\Acl\AclExtended;
27 use OpenEMR\Common\Acl\AclMain;
28 use OpenEMR\Common\Auth\AuthUtils;
29 use OpenEMR\Common\Csrf\CsrfUtils;
30 use OpenEMR\Common\Uuid\UuidRegistry;
31 use OpenEMR\Common\Twig\TwigContainer;
32 use OpenEMR\Core\Header;
33 use OpenEMR\Services\UserService;
34 use OpenEMR\Events\User\UserUpdatedEvent;
35 use OpenEMR\Events\User\UserCreatedEvent;
37 if (!empty($_POST)) {
38 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
39 CsrfUtils::csrfNotVerified();
43 if (!empty($_GET)) {
44 if (!CsrfUtils::verifyCsrfToken($_GET["csrf_token_form"])) {
45 CsrfUtils::csrfNotVerified();
49 if (!AclMain::aclCheckCore('admin', 'users')) {
50 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("User / Groups")]);
51 exit;
54 if (!AclMain::aclCheckCore('admin', 'super')) {
55 //block non-administrator user from create administrator
56 if (!empty($_POST['access_group'])) {
57 foreach ($_POST['access_group'] as $aro_group) {
58 if (AclExtended::isGroupIncludeSuperuser($aro_group)) {
59 die(xlt('Saving denied'));
63 if (($_POST['mode'] ?? '') === 'update') {
64 //block non-administrator user from update administrator
65 $user_service = new UserService();
66 $user = $user_service->getUser($_POST['id']);
67 $aro_groups = AclExtended::aclGetGroupTitles($user['username']);
68 foreach ($aro_groups as $aro_group) {
69 if (AclExtended::isGroupIncludeSuperuser($aro_group)) {
70 die(xlt('Saving denied'));
76 $alertmsg = '';
77 $bg_msg = '';
78 $set_active_msg = 0;
79 $show_message = 0;
81 /* Sending a mail to the admin when the breakglass user is activated only if $GLOBALS['Emergency_Login_email'] is set to 1 */
82 if (!empty($_POST['access_group']) && is_array($_POST['access_group'])) {
83 $bg_count = count($_POST['access_group']);
84 $mail_id = explode(".", $SMTP_HOST);
85 for ($i = 0; $i < $bg_count; $i++) {
86 if (($_POST['access_group'][$i] == "Emergency Login") && ($_POST['active'] == 'on') && ($_POST['pre_active'] == 0)) {
87 if (($_POST['get_admin_id'] == 1) && ($_POST['admin_id'] != "")) {
88 $res = sqlStatement("select username from users where id= ? ", array($_POST["id"]));
89 $row = sqlFetchArray($res);
90 $uname = $row['username'];
91 $mail = new MyMailer();
92 $mail->From = $GLOBALS["practice_return_email_path"];
93 $mail->FromName = "Administrator OpenEMR";
94 $text_body = "Hello Security Admin,\n\n The Emergency Login user " . $uname .
95 " was activated at " . date('l jS \of F Y h:i:s A') . " \n\nThanks,\nAdmin OpenEMR.";
96 $mail->Body = $text_body;
97 $mail->Subject = "Emergency Login User Activated";
98 $mail->AddAddress($_POST['admin_id']);
99 $mail->Send();
105 /* To refresh and save variables in mail frame */
106 if (isset($_POST["privatemode"]) && $_POST["privatemode"] == "user_admin") {
107 if ($_POST["mode"] == "update") {
108 $user_data = sqlFetchArray(sqlStatement("select * from users where id= ? ", array($_POST["id"])));
110 if (isset($_POST["username"])) {
111 sqlStatement("update users set username=? where id= ? ", array(trim($_POST["username"]), $_POST["id"]));
112 sqlStatement("update `groups` set user=? where user= ?", array(trim($_POST["username"]), $user_data["username"]));
115 if ($_POST["taxid"]) {
116 sqlStatement("update users set federaltaxid=? where id= ? ", array($_POST["taxid"], $_POST["id"]));
119 if ($_POST["state_license_number"]) {
120 sqlStatement("update users set state_license_number=? where id= ? ", array($_POST["state_license_number"], $_POST["id"]));
123 if ($_POST["drugid"]) {
124 sqlStatement("update users set federaldrugid=? where id= ? ", array($_POST["drugid"], $_POST["id"]));
127 if ($_POST["upin"]) {
128 sqlStatement("update users set upin=? where id= ? ", array($_POST["upin"], $_POST["id"]));
131 if ($_POST["npi"]) {
132 sqlStatement("update users set npi=? where id= ? ", array($_POST["npi"], $_POST["id"]));
135 if ($_POST["taxonomy"]) {
136 sqlStatement("update users set taxonomy = ? where id= ? ", array($_POST["taxonomy"], $_POST["id"]));
139 if ($_POST["lname"]) {
140 sqlStatement("update users set lname=? where id= ? ", array($_POST["lname"], $_POST["id"]));
143 if ($_POST["suffix"]) {
144 sqlStatement("update users set suffix=? where id= ? ", array($_POST["suffix"], $_POST["id"]));
147 if ($_POST["valedictory"]) {
148 sqlStatement("update users set valedictory=? where id= ? ", array($_POST["valedictory"], $_POST["id"]));
151 if ($_POST["job"]) {
152 sqlStatement("update users set specialty=? where id= ? ", array($_POST["job"], $_POST["id"]));
155 if ($_POST["mname"]) {
156 sqlStatement("update users set mname=? where id= ? ", array($_POST["mname"], $_POST["id"]));
159 if ($_POST["facility_id"]) {
160 sqlStatement("update users set facility_id = ? where id = ? ", array($_POST["facility_id"], $_POST["id"]));
161 //(CHEMED) Update facility name when changing the id
162 sqlStatement("UPDATE users, facility SET users.facility = facility.name WHERE facility.id = ? AND users.id = ?", array($_POST["facility_id"], $_POST["id"]));
163 //END (CHEMED)
166 if ($_POST["billing_facility_id"]) {
167 sqlStatement("update users set billing_facility_id = ? where id = ? ", array($_POST["billing_facility_id"], $_POST["id"]));
168 //(CHEMED) Update facility name when changing the id
169 sqlStatement("UPDATE users, facility SET users.billing_facility = facility.name WHERE facility.id = ? AND users.id = ?", array($_POST["billing_facility_id"], $_POST["id"]));
170 //END (CHEMED)
173 if (!empty($GLOBALS['gbl_fac_warehouse_restrictions']) || !empty($GLOBALS['restrict_user_facility'])) {
174 if (empty($_POST["schedule_facility"])) {
175 $_POST["schedule_facility"] = array();
177 $tmpres = sqlStatement(
178 "SELECT * FROM users_facility WHERE " .
179 "tablename = ? AND table_id = ?",
180 array('users', $_POST["id"])
182 // $olduf will become an array of entries to delete.
183 $olduf = array();
184 while ($tmprow = sqlFetchArray($tmpres)) {
185 $olduf[$tmprow['facility_id'] . '/' . $tmprow['warehouse_id']] = true;
187 // Now process the selection of facilities and warehouses.
188 foreach ($_POST["schedule_facility"] as $tqvar) {
189 if (($i = strpos($tqvar, '/')) !== false) {
190 $facid = substr($tqvar, 0, $i);
191 $whid = substr($tqvar, $i + 1);
192 // If there was also a facility-only selection for this warehouse then remove it.
193 if (isset($olduf["$facid/"])) {
194 $olduf["$facid/"] = true;
196 } else {
197 $facid = $tqvar;
198 $whid = '';
200 if (!isset($olduf["$facid/$whid"])) {
201 sqlStatement(
202 "INSERT INTO users_facility SET tablename = ?, table_id = ?, " .
203 "facility_id = ?, warehouse_id = ?",
204 array('users', $_POST["id"], $facid, $whid)
207 $olduf["$facid/$whid"] = false;
209 // Now delete whatever is left over for this user.
210 foreach ($olduf as $key => $value) {
211 if ($value && ($i = strpos($key, '/')) !== false) {
212 $facid = substr($key, 0, $i);
213 $whid = substr($key, $i + 1);
214 sqlStatement(
215 "DELETE FROM users_facility WHERE " .
216 "tablename = ? AND table_id = ? AND facility_id = ? AND warehouse_id = ?",
217 array('users', $_POST["id"], $facid, $whid)
218 // At one time binding here screwed up by matching all warehouse_id values
219 // when it's an empty string, and so the code below was used.
220 /**********************************************
221 "tablename = 'users' AND table_id = '" . add_escape_custom($_POST["id"]) . "'" .
222 " AND facility_id = '" . add_escape_custom($facid) . "'" .
223 " AND warehouse_id = '" . add_escape_custom($whid) . "'"
224 **********************************************/
230 if ($_POST["fname"]) {
231 sqlStatement("update users set fname=? where id= ? ", array($_POST["fname"], $_POST["id"]));
234 if (isset($_POST['default_warehouse'])) {
235 sqlStatement("UPDATE users SET default_warehouse = ? WHERE id = ?", array($_POST['default_warehouse'], $_POST["id"]));
238 if (isset($_POST['irnpool'])) {
239 sqlStatement("UPDATE users SET irnpool = ? WHERE id = ?", array($_POST['irnpool'], $_POST["id"]));
242 if (!empty($_POST['clear_2fa'])) {
243 sqlStatement("DELETE FROM login_mfa_registrations WHERE user_id = ?", array($_POST['id']));
246 if ($_POST["adminPass"] && $_POST["clearPass"]) {
247 $authUtilsUpdatePassword = new AuthUtils();
248 $success = $authUtilsUpdatePassword->updatePassword($_SESSION['authUserID'], $_POST['id'], $_POST['adminPass'], $_POST['clearPass']);
249 if (!$success) {
250 error_log(errorLogEscape($authUtilsUpdatePassword->getErrorMessage()));
251 $alertmsg .= $authUtilsUpdatePassword->getErrorMessage();
255 $tqvar = (!empty($_POST["authorized"])) ? 1 : 0;
256 $actvar = (!empty($_POST["active"])) ? 1 : 0;
257 $calvar = (!empty($_POST["calendar"])) ? 1 : 0;
258 $portalvar = (!empty($_POST["portal_user"])) ? 1 : 0;
260 sqlStatement("UPDATE users SET authorized = ?, active = ?, " .
261 "calendar = ?, portal_user = ?, see_auth = ? WHERE " .
262 "id = ? ", array($tqvar, $actvar, $calvar, $portalvar, $_POST['see_auth'], $_POST["id"]));
263 //Display message when Emergency Login user was activated
264 if (is_countable($_POST['access_group'])) {
265 $bg_count = count($_POST['access_group']);
266 for ($i = 0; $i < $bg_count; $i++) {
267 if (($_POST['access_group'][$i] == "Emergency Login") && ($_POST['pre_active'] == 0) && ($actvar == 1)) {
268 $show_message = 1;
272 if (($_POST['access_group'])) {
273 for ($i = 0; $i < $bg_count; $i++) {
274 if (($_POST['access_group'][$i] == "Emergency Login") && ($_POST['user_type']) == "" && ($_POST['check_acl'] == 1) && ($_POST['active']) != "") {
275 $set_active_msg = 1;
281 if ($_POST["comments"]) {
282 sqlStatement("update users set info = ? where id = ? ", array($_POST["comments"], $_POST["id"]));
285 $erxrole = isset($_POST['erxrole']) ? $_POST['erxrole'] : '';
286 sqlStatement("update users set newcrop_user_role = ? where id = ? ", array($erxrole, $_POST["id"]));
288 if ($_POST["physician_type"]) {
289 sqlStatement("update users set physician_type = ? where id = ? ", array($_POST["physician_type"], $_POST["id"]));
292 if ($_POST["main_menu_role"]) {
293 $mainMenuRole = filter_input(INPUT_POST, 'main_menu_role');
294 sqlStatement("update `users` set `main_menu_role` = ? where `id` = ? ", array($mainMenuRole, $_POST["id"]));
297 if ($_POST["patient_menu_role"]) {
298 $patientMenuRole = filter_input(INPUT_POST, 'patient_menu_role');
299 sqlStatement("update `users` set `patient_menu_role` = ? where `id` = ? ", array($patientMenuRole, $_POST["id"]));
302 if ($_POST["erxprid"]) {
303 sqlStatement("update users set weno_prov_id = ? where id = ? ", array($_POST["erxprid"], $_POST["id"]));
306 if (isset($_POST["supervisor_id"])) {
307 sqlStatement("update users set supervisor_id = ? where id = ? ", array((int)$_POST["supervisor_id"], $_POST["id"]));
309 if (isset($_POST["google_signin_email"])) {
310 if (empty($_POST["google_signin_email"])) {
311 $googleSigninEmail = null;
312 } else {
313 $googleSigninEmail = $_POST["google_signin_email"];
315 sqlStatement("update users set google_signin_email = ? where id = ? ", array($googleSigninEmail, $_POST["id"]));
318 // Set the access control group of user
319 $user_data = sqlFetchArray(sqlStatement("select username from users where id= ?", array($_POST["id"])));
320 AclExtended::setUserAro(
321 $_POST['access_group'],
322 $user_data["username"],
323 (isset($_POST['fname']) ? $_POST['fname'] : ''),
324 (isset($_POST['mname']) ? $_POST['mname'] : ''),
325 (isset($_POST['lname']) ? $_POST['lname'] : '')
328 // TODO: why are we sending $user_data here when its overwritten with just the 'username' of the user updated
329 // instead of the entire user data? This makes the pre event data not very useful w/o doing a database hit...
330 $userUpdatedEvent = new UserUpdatedEvent($user_data, $_POST);
331 $GLOBALS["kernel"]->getEventDispatcher()->dispatch($userUpdatedEvent, UserUpdatedEvent::EVENT_HANDLE, 10);
335 /* To refresh and save variables in mail frame - Arb*/
336 if (isset($_POST["mode"])) {
337 if ($_POST["mode"] == "new_user") {
338 if (empty($_POST["authorized"]) || $_POST["authorized"] != "1") {
339 $_POST["authorized"] = 0;
342 $calvar = (!empty($_POST["calendar"])) ? 1 : 0;
343 $portalvar = (!empty($_POST["portal_user"])) ? 1 : 0;
345 $res = sqlQuery("select username from users where username = ?", [trim($_POST['rumple'])]);
346 $doit = true;
347 if (!empty($res['username'])) {
348 $doit = false;
351 if ($doit == true) {
352 $insertUserSQL =
353 "insert into users set " .
354 "username = '" . add_escape_custom(trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))) .
355 "', password = '" . 'NoLongerUsed' .
356 "', fname = '" . add_escape_custom(trim((isset($_POST['fname']) ? $_POST['fname'] : ''))) .
357 "', mname = '" . add_escape_custom(trim((isset($_POST['mname']) ? $_POST['mname'] : ''))) .
358 "', lname = '" . add_escape_custom(trim((isset($_POST['lname']) ? $_POST['lname'] : ''))) .
359 "', suffix = '" . add_escape_custom(trim((isset($_POST['suffix']) ? $_POST['suffix'] : ''))) .
360 "', valedictory = '" . add_escape_custom(trim((isset($_POST['valedictory']) ? $_POST['valedictory'] : ''))) .
361 "', federaltaxid = '" . add_escape_custom(trim((isset($_POST['federaltaxid']) ? $_POST['federaltaxid'] : ''))) .
362 "', state_license_number = '" . add_escape_custom(trim((isset($_POST['state_license_number']) ? $_POST['state_license_number'] : ''))) .
363 "', newcrop_user_role = '" . add_escape_custom(trim((isset($_POST['erxrole']) ? $_POST['erxrole'] : ''))) .
364 "', physician_type = '" . add_escape_custom(trim((isset($_POST['physician_type']) ? $_POST['physician_type'] : ''))) .
365 "', main_menu_role = '" . add_escape_custom(trim((isset($_POST['main_menu_role']) ? $_POST['main_menu_role'] : ''))) .
366 "', patient_menu_role = '" . add_escape_custom(trim((isset($_POST['patient_menu_role']) ? $_POST['patient_menu_role'] : ''))) .
367 "', weno_prov_id = '" . add_escape_custom(trim((isset($_POST['erxprid']) ? $_POST['erxprid'] : ''))) .
368 "', authorized = '" . add_escape_custom(trim((isset($_POST['authorized']) ? $_POST['authorized'] : ''))) .
369 "', info = '" . add_escape_custom(trim((isset($_POST['info']) ? $_POST['info'] : ''))) .
370 "', federaldrugid = '" . add_escape_custom(trim((isset($_POST['federaldrugid']) ? $_POST['federaldrugid'] : ''))) .
371 "', upin = '" . add_escape_custom(trim((isset($_POST['upin']) ? $_POST['upin'] : ''))) .
372 "', npi = '" . add_escape_custom(trim((isset($_POST['npi']) ? $_POST['npi'] : ''))) .
373 "', taxonomy = '" . add_escape_custom(trim((isset($_POST['taxonomy']) ? $_POST['taxonomy'] : ''))) .
374 "', facility_id = '" . add_escape_custom(trim((isset($_POST['facility_id']) ? $_POST['facility_id'] : ''))) .
375 "', billing_facility_id = '" . add_escape_custom(trim((isset($_POST['billing_facility_id']) ? $_POST['billing_facility_id'] : ''))) .
376 "', specialty = '" . add_escape_custom(trim((isset($_POST['specialty']) ? $_POST['specialty'] : ''))) .
377 "', see_auth = '" . add_escape_custom(trim((isset($_POST['see_auth']) ? $_POST['see_auth'] : ''))) .
378 "', default_warehouse = '" . add_escape_custom(trim((isset($_POST['default_warehouse']) ? $_POST['default_warehouse'] : ''))) .
379 "', irnpool = '" . add_escape_custom(trim((isset($_POST['irnpool']) ? $_POST['irnpool'] : ''))) .
380 "', calendar = '" . add_escape_custom($calvar) .
381 "', portal_user = '" . add_escape_custom($portalvar) .
382 "', supervisor_id = '" . add_escape_custom((isset($_POST['supervisor_id']) ? (int)$_POST['supervisor_id'] : 0)) .
383 "'";
385 $authUtilsNewPassword = new AuthUtils();
386 $success = $authUtilsNewPassword->updatePassword(
387 $_SESSION['authUserID'],
389 $_POST['adminPass'],
390 $_POST['stiltskin'],
391 true,
392 $insertUserSQL,
393 trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))
395 if (!empty($authUtilsNewPassword->getErrorMessage())) {
396 $alertmsg .= $authUtilsNewPassword->getErrorMessage();
398 if ($success) {
399 // generate our uuid
400 $uuid = UuidRegistry::getRegistryForTable('users')->createUuid();
401 //set the facility name from the selected facility_id
402 sqlStatement(
403 "UPDATE users, facility SET users.facility = facility.name, users.uuid =? WHERE facility.id = ? AND users.username = ?",
404 array(
405 $uuid,
406 trim((isset($_POST['facility_id']) ? $_POST['facility_id'] : '')),
407 trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))
411 //set the billing facility name from the selected billing_facility_id
412 sqlStatement(
413 "UPDATE users, facility SET users.billing_facility = facility.name, users.uuid =? WHERE facility.id = ? AND users.username = ?",
414 array(
415 $uuid,
416 trim((isset($_POST['billing_facility_id']) ? $_POST['billing_facility_id'] : '')),
417 trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))
421 sqlStatement(
422 "insert into `groups` set name = ?, user = ?",
423 array(
424 trim((isset($_POST['groupname']) ? $_POST['groupname'] : '')),
425 trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))
429 if (trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))) {
430 // Set the access control group of user
431 AclExtended::setUserAro(
432 $_POST['access_group'],
433 trim((isset($_POST['rumple']) ? $_POST['rumple'] : '')),
434 trim((isset($_POST['fname']) ? $_POST['fname'] : '')),
435 trim((isset($_POST['mname']) ? $_POST['mname'] : '')),
436 trim((isset($_POST['lname']) ? $_POST['lname'] : ''))
440 } else {
441 $alertmsg .= xl('User') . ' ' . trim((isset($_POST['rumple']) ? $_POST['rumple'] : '')) . ' ' . xl('already exists.');
444 if ($_POST['access_group']) {
445 $bg_count = count($_POST['access_group']);
446 for ($i = 0; $i < $bg_count; $i++) {
447 if ($_POST['access_group'][$i] == "Emergency Login") {
448 $set_active_msg = 1;
453 // this event should only fire if we actually succeeded in creating the user...
454 if ($success) {
455 // let's make sure we send on our uuid alongside the id of the user
456 $submittedData = $_POST;
457 $submittedData['uuid'] = $uuid ?? null;
458 $submittedData['username'] = $submittedData['rumple'] ?? null;
459 $userCreatedEvent = new UserCreatedEvent($submittedData);
460 unset($submittedData); // clear things out in case we have any sensitive data here
461 $GLOBALS["kernel"]->getEventDispatcher()->dispatch($userCreatedEvent, UserCreatedEvent::EVENT_HANDLE, 10);
463 } elseif ($_POST["mode"] == "new_group") {
464 $res = sqlStatement("select distinct name, user from `groups`");
465 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
466 $result[$iter] = $row;
469 $doit = 1;
470 foreach ($result as $iter) {
471 if ($doit == 1 && $iter["name"] == (trim((isset($_POST['groupname']) ? $_POST['groupname'] : ''))) && $iter["user"] == (trim((isset($_POST['rumple']) ? $_POST['rumple'] : '')))) {
472 $doit--;
476 if ($doit == 1) {
477 sqlStatement(
478 "insert into `groups` set name = ?, user = ?",
479 array(
480 trim((isset($_POST['groupname']) ? $_POST['groupname'] : '')),
481 trim((isset($_POST['rumple']) ? $_POST['rumple'] : ''))
484 } else {
485 $alertmsg .= "User " . trim((isset($_POST['rumple']) ? $_POST['rumple'] : '')) .
486 " is already a member of group " . trim((isset($_POST['groupname']) ? $_POST['groupname'] : '')) . ". ";
491 if (isset($_GET["mode"])) {
492 /*******************************************************************
493 // This is the code to delete a user. Note that the link which invokes
494 // this is commented out. Somebody must have figured it was too dangerous.
496 if ($_GET["mode"] == "delete") {
497 $res = sqlStatement("select distinct username, id from users where id = '" .
498 $_GET["id"] . "'");
499 for ($iter = 0; $row = sqlFetchArray($res); $iter++)
500 $result[$iter] = $row;
502 // TBD: Before deleting the user, we should check all tables that
503 // reference users to make sure this user is not referenced!
505 foreach($result as $iter) {
506 sqlStatement("delete from `groups` where user = '" . $iter["username"] . "'");
508 sqlStatement("delete from users where id = '" . $_GET["id"] . "'");
510 *******************************************************************/
512 if ($_GET["mode"] == "delete_group") {
513 $res = sqlStatement("select distinct user from `groups` where id = ?", array($_GET["id"]));
514 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
515 $result[$iter] = $row;
518 foreach ($result as $iter) {
519 $un = $iter["user"];
522 $res = sqlStatement("select name, user from `groups` where user = ? " .
523 "and id != ?", array($un, $_GET["id"]));
525 // Remove the user only if they are also in some other group. I.e. every
526 // user must be a member of at least one group.
527 if (sqlFetchArray($res) != false) {
528 sqlStatement("delete from `groups` where id = ?", array($_GET["id"]));
529 } else {
530 $alertmsg .= "You must add this user to some other group before " .
531 "removing them from this group. ";
535 // added for form submit's from usergroup_admin_add and user_admin.php
536 // sjp 12/29/17
537 if (isset($_REQUEST["mode"])) {
538 exit(text(trim($alertmsg)));
541 $form_inactive = empty($_POST['form_inactive']) ? false : true;
544 <html>
545 <head>
546 <title><?php echo xlt('User / Groups');?></title>
548 <?php Header::setupHeader(['common']); ?>
550 <script>
552 $(function () {
554 tabbify();
556 $(".medium_modal").on('click', function(e) {
557 e.preventDefault();e.stopPropagation();
558 dlgopen('', '', 'modal-mlg', 450, '', '', {
559 type: 'iframe',
560 url: $(this).attr('href')
566 function authorized_clicked() {
567 var f = document.forms[0];
568 f.calendar.disabled = !f.authorized.checked;
569 f.calendar.checked = f.authorized.checked;
572 function resetCounter(username) {
573 top.restoreSession();
574 request = new FormData;
575 request.append("function", "resetUsernameCounter");
576 request.append("username", username);
577 request.append("csrf_token_form", <?php echo js_escape(CsrfUtils::collectCsrfToken('counter')); ?>);
578 fetch("<?php echo $GLOBALS["webroot"]; ?>/library/ajax/login_counter_ip_tracker.php", {
579 method: 'POST',
580 credentials: 'same-origin',
581 body: request
583 let loginCounterElement = document.getElementById('login-counter-' + username);
584 loginCounterElement.innerHTML = "0";
587 </script>
589 </head>
590 <body class="body_top">
592 <div class="container">
593 <div class="row">
594 <div class="col-12">
595 <div class="page-title">
596 <h2><?php echo xlt('User / Groups');?></h2>
597 </div>
598 </div>
599 </div>
600 <div class="row">
601 <div class="col-12">
602 <div class="btn-group">
603 <a href="usergroup_admin_add.php" class="medium_modal btn btn-secondary btn-add"><?php echo xlt('Add User'); ?></a>
604 <a href="facility_user.php" class="btn btn-secondary btn-show"><?php echo xlt('View Facility Specific User Information'); ?></a>
605 </div>
606 <form name='userlist' method='post' style="display: inline;" class="form-inline" class="float-right" action='usergroup_admin.php' onsubmit='return top.restoreSession()'>
607 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
608 <div class="checkbox">
609 <label for="form_inactive">
610 <input type='checkbox' class="form-control" id="form_inactive" name='form_inactive' value='1' onclick='submit()' <?php echo ($form_inactive) ? 'checked ' : ''; ?>>
611 <?php echo xlt('Include inactive users'); ?>
612 </label>
613 </div>
614 </form>
615 </div>
616 </div>
617 <div class="row">
618 <div class="col-12">
619 <?php
620 if ($set_active_msg == 1) {
621 echo "<div class='alert alert-danger'>" . xlt('Emergency Login ACL is chosen. The user is still in active state, please de-activate the user and activate the same when required during emergency situations. Visit Administration->Users for activation or de-activation.') . "</div><br />";
624 if ($show_message == 1) {
625 echo "<div class='alert alert-danger'>" . xlt('The following Emergency Login User is activated:') . " " . "<b>" . text($_GET['fname']) . "</b>" . "</div><br />";
626 echo "<div class='alert alert-danger'>" . xlt('Emergency Login activation email will be circulated only if following settings in the interface/globals.php file are configured:') . " \$GLOBALS['Emergency_Login_email'], \$GLOBALS['Emergency_Login_email_id']</div>";
630 <div class="table-responsive">
631 <table class="table table-striped table-sm">
632 <thead>
633 <tr>
634 <th><?php echo xlt('Username'); ?></th>
635 <th><?php echo xlt('Real Name'); ?></th>
636 <th><?php echo xlt('Additional Info'); ?></th>
637 <th><?php echo xlt('Authorized'); ?></th>
638 <th><?php echo xlt('MFA'); ?></th>
639 <?php
640 $checkPassExp = false;
641 if (($GLOBALS['password_expiration_days'] != 0) && (check_integer($GLOBALS['password_expiration_days'])) && (check_integer($GLOBALS['password_grace_time']))) {
642 $checkPassExp = true;
643 echo '<th>' . xlt('Password Expiration') . '</th>';
646 <th><?php echo xlt('Failed Login Counter'); ?></th>
647 </tr>
648 <tbody>
649 <?php
650 $query = "SELECT * FROM users WHERE username != '' ";
651 if (!$form_inactive) {
652 $query .= "AND active = '1' ";
655 $query .= "ORDER BY username";
656 $res = sqlStatement($query);
657 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
658 $result4[$iter] = $row;
661 foreach ($result4 as $iter) {
662 // Skip this user if logged-in user does not have all of its permissions.
663 // Note that a superuser now has all permissions.
664 if (!AclExtended::iHavePermissionsOf($iter['username'])) {
665 continue;
668 if ($iter["authorized"]) {
669 $iter["authorized"] = xl('yes');
670 } else {
671 $iter["authorized"] = xl('no');
674 $mfa = sqlQuery(
675 "SELECT `method` FROM `login_mfa_registrations` " .
676 "WHERE `user_id` = ? AND (`method` = 'TOTP' OR `method` = 'U2F')",
677 [$iter['id']]
679 if (!empty($mfa['method'])) {
680 $isMfa = xl('yes');
681 } else {
682 $isMfa = xl('no');
685 if ($checkPassExp && !empty($iter["active"])) {
686 $current_date = date("Y-m-d");
687 $userSecure = privQuery("SELECT `last_update_password` FROM `users_secure` WHERE `id` = ?", [$iter['id']]);
688 $pwd_expires = date("Y-m-d", strtotime($userSecure['last_update_password'] . "+" . $GLOBALS['password_expiration_days'] . " days"));
689 $grace_time = date("Y-m-d", strtotime($pwd_expires . "+" . $GLOBALS['password_grace_time'] . " days"));
692 print "<tr>
693 <td><a href='user_admin.php?id=" . attr_url($iter["id"]) . "&csrf_token_form=" . attr_url(CsrfUtils::collectCsrfToken()) .
694 "' class='medium_modal' onclick='top.restoreSession()'>" . text($iter["username"]) . "</a>" . "</td>
695 <td>" . text($iter["fname"]) . ' ' . text($iter["lname"]) . "&nbsp;</td>
696 <td>" . text($iter["info"]) . "&nbsp;</td>
697 <td align='left'><span>" . text($iter["authorized"]) . "</td>
698 <td align='left'><span>" . text($isMfa) . "</td>";
699 if ($checkPassExp) {
700 if (AuthUtils::useActiveDirectory($iter["username"]) || empty($iter["active"])) {
701 // LDAP bypasses expired password mechanism
702 echo '<td>';
703 echo xlt('Not Applicable');
704 } elseif (strtotime($current_date) > strtotime($grace_time)) {
705 echo '<td class="bg-danger text-light">';
706 echo xlt('Expired');
707 } elseif (strtotime($current_date) > strtotime($pwd_expires)) {
708 echo '<td class="bg-warning text-dark">';
709 echo xlt('Grace Period');
710 } else {
711 echo '<td>';
712 echo text(oeFormatShortDate($pwd_expires));
714 echo '</td>';
716 if (empty($iter["active"])) {
717 echo '<td>';
718 echo xlt('Not Applicable');
719 } else {
720 echo '<td id="login-counter-' . attr($iter["username"]) . '">';
721 $queryCounter = privQuery("SELECT `login_fail_counter`, `last_login_fail`, TIMESTAMPDIFF(SECOND, `last_login_fail`, NOW()) as `seconds_last_login_fail` FROM `users_secure` WHERE BINARY `username` = ?", [$iter["username"]]);
722 if (!empty($queryCounter['login_fail_counter'])) {
723 echo text($queryCounter['login_fail_counter']);
724 if (!empty($queryCounter['last_login_fail'])) {
725 echo ' (' . xlt('last on') . ' ' . text(oeFormatDateTime($queryCounter['last_login_fail'])) . ')';
727 echo ' ' . '<button type="button" class="btn btn-sm btn-danger ml-1" onclick="resetCounter(' . attr_js($iter["username"]) . ')">' . xlt("Reset Counter") . '</button>';
728 $autoBlocked = false;
729 $autoBlockEnd = null;
730 if ((int)$GLOBALS['password_max_failed_logins'] != 0 && ($queryCounter['login_fail_counter'] > (int)$GLOBALS['password_max_failed_logins'])) {
731 if ((int)$GLOBALS['time_reset_password_max_failed_logins'] != 0) {
732 if ($queryCounter['seconds_last_login_fail'] < (int)$GLOBALS['time_reset_password_max_failed_logins']) {
733 $autoBlocked = true;
734 $autoBlockEnd = date('Y-m-d H:i:s', (time() + ((int)$GLOBALS['time_reset_password_max_failed_logins'] - $queryCounter['seconds_last_login_fail'])));
736 } else {
737 $autoBlocked = true;
740 if ($autoBlocked) {
741 echo '<br>' . xlt("Currently Autoblocked");
742 if (!empty($autoBlockEnd)) {
743 echo ' (' . xlt("Autoblock ends on") . ' ' . text(oeFormatDateTime($autoBlockEnd)) . ')';
746 } else {
747 echo '0';
750 echo '</td>';
751 print "</tr>\n";
754 </tbody>
755 </table>
756 </div>
757 <?php
758 if (empty($GLOBALS['disable_non_default_groups'])) {
759 $res = sqlStatement("select * from `groups` order by name");
760 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
761 $result5[$iter] = $row;
764 foreach ($result5 as $iter) {
765 $grouplist[$iter["name"]] .= text($iter["user"]) .
766 "(<a class='link_submit' href='usergroup_admin.php?mode=delete_group&id=" .
767 attr_url($iter["id"]) . "&csrf_token_form=" . attr_url(CsrfUtils::collectCsrfToken()) . "' onclick='top.restoreSession()'>" . xlt('Remove') . "</a>), ";
770 foreach ($grouplist as $groupname => $list) {
771 print "<span class='bold'>" . text($groupname) . "</span><br />\n<span>" .
772 substr($list, 0, strlen($list) - 2) . "</span><br />\n";
776 </div>
777 </div>
778 </div>
779 <script>
780 <?php
781 if ($alertmsg = trim($alertmsg)) {
782 echo "alert(" . js_escape($alertmsg) . ");\n";
785 </script>
786 </body>
787 </html>