Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): Mark J Crane */ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; //add multi-lingual support $language = new text; $text = $language->get(); //get the user uuid $user_uuid = $_SESSION['user_uuid']; //retrieve password requirements if (permission_exists('user_password')) { $required['length'] = $settings->get('users', 'password_length', 12); $required['number'] = $settings->get('users', 'password_number', false); $required['lowercase'] = $settings->get('users', 'password_lowercase', false); $required['uppercase'] = $settings->get('users', 'password_uppercase', false); $required['special'] = $settings->get('users', 'password_special', false); } //process the http post if (!empty($_POST)) { //get the HTTP values and set as variables $password = $_POST["password"]; $password_confirm = $_POST["password_confirm"]; $user_email = $_POST["user_email"]; $user_status = $_POST["user_status"] ?? ''; $user_language = $_POST["user_language"]; $user_time_zone = $_POST["user_time_zone"]; //if (permission_exists('api_key')) { // $api_key = $_POST["api_key"]; //} if (!empty($_SESSION['authentication']['methods']) && in_array('totp', $_SESSION['authentication']['methods'])) { $user_totp_secret = strtoupper($_POST["user_totp_secret"]); } //validate the token $token = new token; if (!$token->validate($_SERVER['PHP_SELF'])) { message::add($text['message-invalid_token'],'negative'); header('Location: users.php'); exit; } //validate the user status switch ($user_status) { case "Available" : break; case "Available (On Demand)" : break; case "On Break" : break; case "Do Not Disturb" : break; case "Logged Out" : break; default : $user_status = ''; } //check required values //require the passwords to match if (!empty($password) && $password != $password_confirm) { message::add($text['message-password_mismatch'], 'negative', 7500); } //require passwords not allowed to be empty if (permission_exists('user_password') && permission_exists('user_add') && $action == 'add') { if (empty($password)) { message::add($text['message-password_blank'], 'negative', 7500); } if (empty($group_uuid_name)) { $invalid[] = $text['label-group']; } } //require a value a valid email address format if (!valid_email($user_email)) { $invalid[] = $text['label-email']; } //require passwords with the defined required attributes: length, number, lower case, upper case, and special characters if (permission_exists('user_password') && !empty($password)) { if (!empty($required['length']) && is_numeric($required['length']) && $required['length'] != 0) { if (strlen($password) < $required['length']) { $invalid[] = $text['label-characters']; } } if ($required['number']) { if (!preg_match('/(?=.*[\d])/', $password)) { $invalid[] = $text['label-numbers']; } } if ($required['lowercase']) { if (!preg_match('/(?=.*[a-z])/', $password)) { $invalid[] = $text['label-lowercase_letters']; } } if ($required['uppercase']) { if (!preg_match('/(?=.*[A-Z])/', $password)) { $invalid[] = $text['label-uppercase_letters']; } } if ($required['special']) { if (!preg_match('/(?=.*[\W])/', $password)) { $invalid[] = $text['label-special_characters']; } } } //return if error if (message::count() != 0 || !empty($invalid)) { if ($invalid) { message::add($text['message-required'].implode(', ', $invalid), 'negative', 7500); } persistent_form_values('store', $_POST); header("Location: user_profile.php"); exit; } else { persistent_form_values('clear'); } //save the data $i = $n = $x = $c = 0; //set initial array indexes //check to see if user language is set $sql = "select user_setting_uuid, user_setting_value from v_user_settings "; $sql .= "where user_setting_category = 'domain' "; $sql .= "and user_setting_subcategory = 'language' "; $sql .= "and user_uuid = :user_uuid "; $parameters['user_uuid'] = $user_uuid; $row = $database->select($sql, $parameters, 'row'); if (!empty($user_language) && (empty($row) || (!empty($row['user_setting_uuid']) && !is_uuid($row['user_setting_uuid'])))) { //add user setting to array for insert $array['user_settings'][$i]['user_setting_uuid'] = uuid(); $array['user_settings'][$i]['user_uuid'] = $user_uuid; $array['user_settings'][$i]['domain_uuid'] = $domain_uuid; $array['user_settings'][$i]['user_setting_category'] = 'domain'; $array['user_settings'][$i]['user_setting_subcategory'] = 'language'; $array['user_settings'][$i]['user_setting_name'] = 'code'; $array['user_settings'][$i]['user_setting_value'] = $user_language; $array['user_settings'][$i]['user_setting_enabled'] = 'true'; $i++; } else { if (empty($row['user_setting_value']) || empty($user_language)) { $array_delete['user_settings'][0]['user_setting_category'] = 'domain'; $array_delete['user_settings'][0]['user_setting_subcategory'] = 'language'; $array_delete['user_settings'][0]['user_uuid'] = $user_uuid; $p = permissions::new(); $p->add('user_setting_delete', 'temp'); $database->delete($array_delete); unset($array_delete); $p->delete('user_setting_delete', 'temp'); } if (!empty($user_language)) { //add user setting to array for update $array['user_settings'][$i]['user_setting_uuid'] = $row['user_setting_uuid']; $array['user_settings'][$i]['user_uuid'] = $user_uuid; $array['user_settings'][$i]['domain_uuid'] = $domain_uuid; $array['user_settings'][$i]['user_setting_category'] = 'domain'; $array['user_settings'][$i]['user_setting_subcategory'] = 'language'; $array['user_settings'][$i]['user_setting_name'] = 'code'; $array['user_settings'][$i]['user_setting_value'] = $user_language; $array['user_settings'][$i]['user_setting_enabled'] = 'true'; $i++; } } unset($sql, $parameters, $row); //check to see if user time zone is set $sql = "select user_setting_uuid, user_setting_value from v_user_settings "; $sql .= "where user_setting_category = 'domain' "; $sql .= "and user_setting_subcategory = 'time_zone' "; $sql .= "and user_uuid = :user_uuid "; $parameters['user_uuid'] = $user_uuid; $row = $database->select($sql, $parameters, 'row'); if (!empty($user_time_zone) && (empty($row) || (!empty($row['user_setting_uuid']) && !is_uuid($row['user_setting_uuid'])))) { //add user setting to array for insert $array['user_settings'][$i]['user_setting_uuid'] = uuid(); $array['user_settings'][$i]['user_uuid'] = $user_uuid; $array['user_settings'][$i]['domain_uuid'] = $domain_uuid; $array['user_settings'][$i]['user_setting_category'] = 'domain'; $array['user_settings'][$i]['user_setting_subcategory'] = 'time_zone'; $array['user_settings'][$i]['user_setting_name'] = 'name'; $array['user_settings'][$i]['user_setting_value'] = $user_time_zone; $array['user_settings'][$i]['user_setting_enabled'] = 'true'; $i++; } else { if (empty($row['user_setting_value']) || empty($user_time_zone)) { $array_delete['user_settings'][0]['user_setting_category'] = 'domain'; $array_delete['user_settings'][0]['user_setting_subcategory'] = 'time_zone'; $array_delete['user_settings'][0]['user_uuid'] = $user_uuid; $p = permissions::new(); $p->add('user_setting_delete', 'temp'); $database->delete($array_delete); unset($array_delete); $p->delete('user_setting_delete', 'temp'); } if (!empty($user_time_zone)) { //add user setting to array for update $array['user_settings'][$i]['user_setting_uuid'] = $row['user_setting_uuid']; $array['user_settings'][$i]['user_uuid'] = $user_uuid; $array['user_settings'][$i]['domain_uuid'] = $domain_uuid; $array['user_settings'][$i]['user_setting_category'] = 'domain'; $array['user_settings'][$i]['user_setting_subcategory'] = 'time_zone'; $array['user_settings'][$i]['user_setting_name'] = 'name'; $array['user_settings'][$i]['user_setting_value'] = $user_time_zone; $array['user_settings'][$i]['user_setting_enabled'] = 'true'; $i++; } } unset($sql, $parameters, $row); //set the password hash cost $options = array('cost' => 10); //add user setting to array for update $array['users'][$x]['user_uuid'] = $user_uuid; if (permission_exists('user_password') && !empty($password) && $password == $password_confirm) { //remove the session id files $sql = "select session_id from v_user_logs "; $sql .= "where user_uuid = :user_uuid "; $sql .= "and timestamp > NOW() - INTERVAL '4 hours' "; $parameters['user_uuid'] = $user_uuid; $user_logs = $database->select($sql, $parameters, 'all'); foreach ($user_logs as $row) { if (preg_match('/^[a-zA-Z0-9,-]+$/', $row['session_id']) && file_exists(session_save_path() . "/sess_" . $row['session_id'])) { unlink(session_save_path() . "/sess_" . $row['session_id']); } } //create a one way hash for the user password $array['users'][$x]['password'] = password_hash($password, PASSWORD_DEFAULT, $options); $array['users'][$x]['salt'] = null; } $array['users'][$x]['user_email'] = $user_email; $array['users'][$x]['user_status'] = $user_status; if (permission_exists('user_add') || permission_exists('user_edit')) { if (!empty($_SESSION['authentication']['methods']) && in_array('totp', $_SESSION['authentication']['methods'])) { $array['users'][$x]['user_totp_secret'] = $user_totp_secret; } if ($action == 'add') { $array['users'][$x]['add_user'] = $_SESSION["user"]["username"]; $array['users'][$x]['add_date'] = date("Y-m-d H:i:s.uO"); } } $x++; //add the user_edit permission $p = permissions::new(); $p->add("user_setting_add", "temp"); $p->add("user_setting_edit", "temp"); $p->add("user_edit", "temp"); $p->add('user_group_add', 'temp'); //save the data $database->save($array); //$message = $database->message; //remove the temporary permission $p->delete("user_setting_add", "temp"); $p->delete("user_setting_edit", "temp"); $p->delete("user_edit", "temp"); $p->delete('user_group_add', 'temp'); //if call center installed if ($action == 'edit' && permission_exists('user_edit') && file_exists($_SERVER["PROJECT_ROOT"]."/app/call_centers/app_config.php")) { //get the call center agent uuid $sql = "select call_center_agent_uuid from v_call_center_agents "; $sql .= "where domain_uuid = :domain_uuid "; $sql .= "and user_uuid = :user_uuid "; $parameters['domain_uuid'] = $_SESSION['domain_uuid']; $parameters['user_uuid'] = $user_uuid; $call_center_agent_uuid = $database->select($sql, $parameters, 'column'); unset($sql, $parameters); //update the user_status if (isset($call_center_agent_uuid) && is_uuid($call_center_agent_uuid) && !empty($user_status)) { $esl = event_socket::create(); $switch_cmd = "callcenter_config agent set status ".$call_center_agent_uuid." '".$user_status."'"; $switch_result = event_socket::api($switch_cmd); } //update the user state if (isset($call_center_agent_uuid) && is_uuid($call_center_agent_uuid)) { $esl = event_socket::create(); $cmd = "callcenter_config agent set state ".$call_center_agent_uuid." Waiting"; $response = event_socket::api($cmd); } } //response message if ($action == 'edit') { message::add($text['message-update'],'positive'); } else { message::add($text['message-add'],'positive'); } } //populate form if (persistent_form_values('exists')) { //populate the form with values from session variable persistent_form_values('load'); //clear, set $unsaved flag persistent_form_values('clear'); } else { //populate the form with values from db $sql = "select domain_uuid, user_uuid, username, user_email, api_key, user_totp_secret, "; $sql .= "user_type, contact_uuid, user_enabled, user_status "; $sql .= "from v_users "; $sql .= "where user_uuid = :user_uuid "; if (!permission_exists('user_all')) { $sql .= "and domain_uuid = :domain_uuid "; $parameters['domain_uuid'] = $domain_uuid; } $parameters['user_uuid'] = $user_uuid; $row = $database->select($sql, $parameters, 'row'); if (is_array($row) && sizeof($row) > 0) { $domain_uuid = $row["domain_uuid"]; $user_uuid = $row["user_uuid"]; $username = $row["username"]; $user_email = $row["user_email"]; $api_key = $row["api_key"]; $user_totp_secret = $row["user_totp_secret"]; $user_type = $row["user_type"]; $user_enabled = $row["user_enabled"]; if (permission_exists('contact_view')) { $contact_uuid = $row["contact_uuid"]; } $user_status = $row["user_status"]; } else { message::add($text['message-invalid_user'], 'negative', 7500); header("Location: user_edit.php?id=".$_SESSION['user_uuid']); exit; } unset($sql, $parameters, $row); //get all language codes from database $sql = "select * from v_languages order by language asc "; $languages = $database->select($sql, null, 'all'); //get user settings $sql = "select * from v_user_settings "; $sql .= "where user_uuid = :user_uuid "; $sql .= "and user_setting_enabled = true "; $parameters['user_uuid'] = $user_uuid; $result = $database->select($sql, $parameters, 'all'); if (is_array($result)) { foreach($result as $row) { $name = $row['user_setting_name']; $category = $row['user_setting_category']; $subcategory = $row['user_setting_subcategory']; if (empty($subcategory)) { //$$category[$name] = $row['domain_setting_value']; $user_settings[$category][$name] = $row['user_setting_value']; } else { $user_settings[$category][$subcategory][$name] = $row['user_setting_value']; } } } unset($sql, $parameters, $result, $row); } //set the defaults if (empty($user_totp_secret)) { $user_totp_secret = ""; } //create token $object = new token; $token = $object->create($_SERVER['PHP_SELF']); //include the header require_once "resources/header.php"; $document['title'] = $text['title-user_edit']; //show the content if (permission_exists('user_password')) { echo "\n"; } echo "
\n"; echo "
\n"; echo "
".$text['title-user_profile']."
\n"; echo "
\n"; if (!empty($unsaved)) { echo "
".$text['message-unsaved_changes']."
"; } $button_margin = 'margin-left: 15px;'; if (permission_exists('user_add') || permission_exists('user_edit')) { echo button::create(['type'=>'button','label'=>$text['button-save'],'icon'=>$settings->get('theme', 'button_icon_save'),'id'=>'btn_save','style'=>'margin-left: 15px;','onclick'=>'submit_form();']); } echo "
\n"; echo "
\n"; echo "
\n"; echo $text['description-user_profile']."\n"; echo "

\n"; echo "
\n"; echo ""; echo " "; echo " "; echo " "; echo " "; if (permission_exists('user_password')) { echo " "; echo " "; echo " "; echo " "; echo " "; echo " "; echo " "; echo " "; } echo " "; echo " "; echo " "; echo " "; echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo " \n"; if (permission_exists("user_status")) { echo " \n"; echo " \n"; echo " \n"; echo " \n"; } //if (permission_exists('api_key')) { // echo " "; // echo " "; // echo " "; // echo " "; // //user time based one time password secret if (!empty($_SESSION['authentication']['methods']) && in_array('totp', $_SESSION['authentication']['methods'])) { if (!empty($user_totp_secret) && !empty($username)) { $otpauth = "otpauth://totp/".$username."?secret=".$user_totp_secret."&issuer=".$_SESSION['domain_name']; require_once 'resources/qr_code/QRErrorCorrectLevel.php'; require_once 'resources/qr_code/QRCode.php'; require_once 'resources/qr_code/QRCodeImage.php'; try { $code = new QRCode (- 1, QRErrorCorrectLevel::H); $code->addData($otpauth); $code->make(); $img = new QRCodeImage ($code, $width=210, $height=210, $quality=50); $img->draw(); $image = $img->getImage(); $img->finish(); } catch (Exception $error) { echo $error; } } echo "\n"; echo "\n"; echo "\n"; echo "\n"; } echo "
".$text['label-username'].""; echo " ".escape($username)."\n"; echo "
".$text['label-password'].""; echo " "; //help defeat browser auto-fill echo " "; echo "

\n"; if ((!empty($required['length']) && is_numeric($required['length']) && $required['length'] != 0) || $required['number'] || $required['lowercase'] || $required['uppercase'] || $required['special']) { echo $text['label-required'].': '; if (is_numeric($required['length']) && $required['length'] != 0) { echo $required['length']." ".$text['label-characters']; if ($required['number'] || $required['lowercase'] || $required['uppercase'] || $required['special']) { echo " ("; } } if ($required['number']) { $required_temp[] = $text['label-number']; } if ($required['lowercase']) { $required_temp[] = $text['label-lowercase']; } if ($required['uppercase']) { $required_temp[] = $text['label-uppercase']; } if ($required['special']) { $required_temp[] = $text['label-special']; } if (!empty($required_temp)) { echo implode(', ',$required_temp); if (is_numeric($required['length']) && $required['length'] != 0) { echo ")"; } } unset($required_temp); } echo "
".$text['label-confirm_password'].""; echo "
\n"; echo " ".$text['message-green_border_passwords_match']."\n"; echo "
".$text['label-email']."
\n"; echo " ".$text['label-user_language']."\n"; echo " \n"; echo " \n"; echo "
\n"; echo " ".$text['description-user_language']."
\n"; echo "
\n"; echo " ".$text['label-time_zone']."\n"; echo " \n"; echo " \n"; echo "
\n"; echo " ".$text['description-time_zone']."
\n"; echo "
\n"; echo " ".$text['label-status']."\n"; echo " \n"; echo " \n"; echo "
\n"; echo " ".$text['description-status']."
\n"; echo "
".$text['label-api_key']."\n"; // echo " "; // if (empty($api_key)) { // //generate api key // echo button::create(['type'=>'button', // 'label'=>$text['button-generate'], // 'icon'=>'key', // 'style'=>'margin-top: 1px; margin-bottom: 1px;', // 'onclick'=>"document.getElementById('api_key').value = '".generate_password(32,3)."'; // document.getElementById('frm').submit();"]); // } // else { // //view the api key // echo button::create(['type'=>'button', // 'label'=>$text['button-view'], // 'id'=>'button-api_key_view', // 'icon'=>'key', // 'style'=>'margin-top: 1px; margin-bottom: 1px;', // 'onclick'=>"document.getElementById ('button-api_key_view').style.display = 'none'; // document.getElementById('api_key').style.display = 'inline'; // document.getElementById('button-api_key_hide').style.display = 'inline'; // document.getElementById('button-api_key_view').style.display = 'none';"]); // echo button::create(['type'=>'button', // 'label'=>$text['button-hide'], // 'id'=>'button-api_key_hide', // 'icon'=>'key', // 'style'=>'display: none;', // 'onclick'=>"document.getElementById('api_key').style.display = 'none'; // document.getElementById('button-api_key_hide').style.display = 'none'; // document.getElementById('button-api_key_view').style.display = 'inline';"]); // } // if (!empty($text['description-api_key'])) { // echo "
".$text['description-api_key']."
\n"; // } // echo "
\n"; echo " ".$text['label-user_totp_secret']."\n"; echo "\n"; echo " "; if (empty($user_totp_secret)) { $base32 = new base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', FALSE, TRUE, TRUE); $user_totp_secret = $base32->encode(generate_password(20,3)); echo button::create(['type'=>'button', 'label'=>$text['button-setup'], 'icon'=>'key', 'onclick'=>"document.getElementById('user_totp_secret').value = '".$user_totp_secret."'; document.getElementById('frm').submit();"]); } else { echo " \n"; echo button::create(['type'=>'button', 'label'=>$text['button-view'], 'id'=>'button-totp_view', 'icon'=>'key', 'onclick'=>"document.getElementById('totp_qr').style.display = 'inline'; document.getElementById('button-totp_hide').style.display = 'inline'; document.getElementById('button-totp_disable').style.display = 'inline'; document.getElementById('button-totp_view').style.display = 'none';"]); echo button::create(['type'=>'button', 'label'=>$text['button-hide'], 'id'=>'button-totp_hide', 'icon'=>'key', 'style'=>'display: none;', 'onclick'=>"document.getElementById('totp_qr').style.display = 'none'; document.getElementById('button-totp_hide').style.display = 'none'; document.getElementById('button-totp_disable').style.display = 'none'; document.getElementById('button-totp_view').style.display = 'inline';"]); echo button::create(['type'=>'button', 'label'=>$text['button-disable'], 'id'=>'button-totp_disable', 'icon'=>'trash', 'style'=>'display: none;', 'onclick'=>"document.getElementById('user_totp_secret').value = ''; document.getElementById('frm').submit();"]); } if (empty($user_totp_secret)) { echo "
".$text['description-user_totp_secret']."
\n"; } else { echo "
".$text['description-user_totp_view']."
\n"; } echo "
"; echo "
\n"; echo "

"; echo "\n"; echo "
"; //hide password fields before submit echo "\n"; //include the footer require_once "resources/footer.php"; ?>