4 * This script assigns ACL 'Emergency login'.
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
;
38 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
39 CsrfUtils
::csrfNotVerified();
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")]);
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'));
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']);
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"]));
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"]));
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"]));
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"]));
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.
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;
200 if (!isset($olduf["$facid/$whid"])) {
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);
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']);
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)) {
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']) != "") {
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;
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'])]);
347 if (!empty($res['username'])) {
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)) .
385 $authUtilsNewPassword = new AuthUtils();
386 $success = $authUtilsNewPassword->updatePassword(
387 $_SESSION['authUserID'],
393 trim((isset($_POST['rumple']) ?
$_POST['rumple'] : ''))
395 if (!empty($authUtilsNewPassword->getErrorMessage())) {
396 $alertmsg .= $authUtilsNewPassword->getErrorMessage();
400 $uuid = UuidRegistry
::getRegistryForTable('users')->createUuid();
401 //set the facility name from the selected facility_id
403 "UPDATE users, facility SET users.facility = facility.name, users.uuid =? WHERE facility.id = ? AND users.username = ?",
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
413 "UPDATE users, facility SET users.billing_facility = facility.name, users.uuid =? WHERE facility.id = ? AND users.username = ?",
416 trim((isset($_POST['billing_facility_id']) ?
$_POST['billing_facility_id'] : '')),
417 trim((isset($_POST['rumple']) ?
$_POST['rumple'] : ''))
422 "insert into `groups` set name = ?, user = ?",
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'] : ''))
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") {
453 // this event should only fire if we actually succeeded in creating the user...
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;
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'] : '')))) {
478 "insert into `groups` set name = ?, user = ?",
480 trim((isset($_POST['groupname']) ?
$_POST['groupname'] : '')),
481 trim((isset($_POST['rumple']) ?
$_POST['rumple'] : ''))
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 = '" .
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) {
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"]));
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
537 if (isset($_REQUEST["mode"])) {
538 exit(text(trim($alertmsg)));
541 $form_inactive = empty($_POST['form_inactive']) ?
false : true;
546 <title
><?php
echo xlt('User / Groups');?
></title
>
548 <?php Header
::setupHeader(['common']); ?
>
556 $
(".medium_modal").on('click', function(e
) {
557 e
.preventDefault();e
.stopPropagation();
558 dlgopen('', '', 'modal-mlg', 450, '', '', {
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", {
580 credentials
: 'same-origin',
583 let loginCounterElement
= document
.getElementById('login-counter-' + username
);
584 loginCounterElement
.innerHTML
= "0";
590 <body
class="body_top">
592 <div
class="container">
595 <div
class="page-title">
596 <h2
><?php
echo xlt('User / Groups');?
></h2
>
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
>
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'); ?
>
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">
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
>
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
>
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'])) {
668 if ($iter["authorized"]) {
669 $iter["authorized"] = xl('yes');
671 $iter["authorized"] = xl('no');
675 "SELECT `method` FROM `login_mfa_registrations` " .
676 "WHERE `user_id` = ? AND (`method` = 'TOTP' OR `method` = 'U2F')",
679 if (!empty($mfa['method'])) {
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"));
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"]) . " </td>
696 <td>" . text($iter["info"]) . " </td>
697 <td align='left'><span>" . text($iter["authorized"]) . "</td>
698 <td align='left'><span>" . text($isMfa) . "</td>";
700 if (AuthUtils
::useActiveDirectory($iter["username"]) ||
empty($iter["active"])) {
701 // LDAP bypasses expired password mechanism
703 echo xlt('Not Applicable');
704 } elseif (strtotime($current_date) > strtotime($grace_time)) {
705 echo '<td class="bg-danger text-light">';
707 } elseif (strtotime($current_date) > strtotime($pwd_expires)) {
708 echo '<td class="bg-warning text-dark">';
709 echo xlt('Grace Period');
712 echo text(oeFormatShortDate($pwd_expires));
716 if (empty($iter["active"])) {
718 echo xlt('Not Applicable');
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']) {
734 $autoBlockEnd = date('Y-m-d H:i:s', (time() +
((int)$GLOBALS['time_reset_password_max_failed_logins'] - $queryCounter['seconds_last_login_fail'])));
741 echo '<br>' . xlt("Currently Autoblocked");
742 if (!empty($autoBlockEnd)) {
743 echo ' (' . xlt("Autoblock ends on") . ' ' . text(oeFormatDateTime($autoBlockEnd)) . ')';
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";
781 if ($alertmsg = trim($alertmsg)) {
782 echo "alert(" . js_escape($alertmsg) . ");\n";