current_user_id = $_SESSION[self::USER_ID] ?? ""; $this->current_user_name = $_SESSION[self::USER_NAME] ?? ""; $this->current_user_email = $_SESSION[self::USER_EMAIL] ?? ""; $this->current_user_client_name = $_SESSION[self::USER_CLIENT_NAME] ?? ""; $this->pagination_page = $_SESSION[self::PAGINATION_PAGE] ?? 1; } // =========== // Setup Users // =========== public function setupUsers() { $users = $this->getUsersPage(); $popovers = (new Popovers())->getPopovers(); $XML = $this->mergeXML($users, ""); $XML = $this->mergeXML($popovers, $XML); $html = $this->applyXSL($XML, $this->getXSL("setupUsers")); $this->displayContent($html); } // ============ // User Summary // ============ public function userSummary() { $user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $user = $this->getUser($user_serial); if ($user->count() == 0) { $this->logError("Invalid User ({$user_serial}). " . __METHOD__); } $notes = (new Notes())->getAllNotes($user_serial); $subscriptions = (new Subscriptions())->getAllUsersSubscriptions($user_serial); $XML = $this->mergeXML($user, ""); $XML = $this->mergeXML($subscriptions, $XML); $XML = $this->mergeXML($notes, $XML); $content = $this->applyXSL($XML, $this->getXSL("userSummary")); $this->displayContent($content); } // ======== // Add User // ======== public function addUser() { $step = filter_input(INPUT_POST, "step") ?: "prompt"; switch ($step) { case "prompt": $popovers = (new Popovers())->getPopovers(); $constants = $this->getConstants(); $XML = $this->mergeXML($popovers, ""); $XML = $this->mergeXML($constants, $XML); $content = $this->applyXSL($XML, $this->getXSL("addUser")); $this->displayContent($content); break; case "add": $user_name = filter_input(INPUT_POST, "user_name") ?: ""; $user_client_name = filter_input(INPUT_POST, "user_client_name") ?: ""; $user_email = filter_input(INPUT_POST, "user_email") ?: ""; $user_role = filter_input(INPUT_POST, "user_role") ?: ""; $user_name = strtoupper(preg_replace("/\s+/", " ", $user_name)); $user_random_password = $this->generateRandomPassword(); $user_temp_password = password_hash($user_random_password, PASSWORD_DEFAULT); $user_change_password = (boolean) true; $user_active = (boolean) true; // Add the User $connection = $this->connect(); $SQL = "insert into users ( user_name, user_email, user_client_name, user_password, user_role, user_change_password, user_active, user_creator, user_created ) values ( :user_name, :user_email, :user_client_name, :user_password, :user_role, :user_change_password, :user_active, :user_creator, :user_created )"; $statement = $connection->prepare($SQL); $statement->bindValue(":user_name", $user_name); $statement->bindValue(":user_email", $user_email); $statement->bindValue(":user_client_name", $user_client_name); $statement->bindValue(":user_password", $user_temp_password); $statement->bindValue(":user_role", $user_role); $statement->bindValue(":user_change_password", $user_change_password, PDO::PARAM_BOOL); $statement->bindValue(":user_active", $user_active, PDO::PARAM_BOOL); $statement->bindValue(":user_creator", $this->current_user_name); $statement->bindValue(":user_created", $this->getTimestamp()); if (!$statement->execute()) { trigger_error($statement->errorInfo()[2]); } $user = $this->getUserByUserName($user_name); // Send User Credentials (new Email())->emailNewUserCredentials($user, $user_random_password); break; default: $this->displayHome(); } } // =========== // Delete User // =========== public function deleteUser() { $user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $users = $this->getUser($user_serial); if ($users->count() == 0) { $this->logError("Invalid User ({$user_serial}): " . __METHOD__); } $SQL = "delete from users where user_serial = {$user_serial}"; $this->executeSQL($SQL); } // ========= // Edit User // ========= public function editUser() { $step = filter_input(INPUT_POST, "step") ?: "prompt"; switch ($step) { case "prompt": $user_serial = (integer) filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $user = $this->getUser($user_serial); if ($user->count() === 0) { $this->logError("Invalid User ({$user_serial}): " . __METHOD__); } $popovers = (new Popovers())->getPopovers(); $constants = $this->getConstants(); $XML = $this->mergeXML($user, ""); $XML = $this->mergeXML($popovers, $XML); $XML = $this->mergeXML($constants, $XML); $content = $this->applyXSL($XML, $this->getXSL("editUser")); $this->displayContent($content); break; case "update": $user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $user_name = filter_input(INPUT_POST, "user_name") ?: ""; $user_email = filter_input(INPUT_POST, "user_email") ?: ""; $user_client_name = filter_input(INPUT_POST, "user_client_name") ?: ""; $user_role = filter_input(INPUT_POST, "user_role") ?: ""; $user_active = filter_input(INPUT_POST, "user_active", FILTER_VALIDATE_BOOLEAN) ?: false; $users = $this->getUser($user_serial); if ($users->count() == 0) { $this->logError("Invalid User ({$user_serial}): " . __METHOD__); } // Update the User $SQL = "update users set user_name = :user_name, user_email = :user_email, user_client_name = :user_client_name, user_role = :user_role, user_active = :user_active, user_changer = :user_changer, user_changed = :user_changed where user_serial = :user_serial"; $statement = $this->connect()->prepare($SQL); $statement->bindValue(":user_serial", $user_serial); $statement->bindValue(":user_name", $user_name); $statement->bindValue(":user_email", $user_email); $statement->bindValue(":user_client_name", $user_client_name); $statement->bindValue(":user_role", $user_role); $statement->bindValue(":user_active", $user_active, PDO::PARAM_BOOL); $statement->bindValue(":user_changer", $this->current_user_name); $statement->bindValue(":user_changed", $this->getTimestamp()); $statement->execute(); break; default: $this->displayHome(); } } // ==================== // Return a User Object // ==================== public function getUser($user_serial = 0) { $SQL = "select view_users.* from view_users where user_serial = {$user_serial}"; return $this->getTable("users", $SQL); } // ==================== // Return a User Object // ==================== public function getUserByUserName($user_name) { $SQL = "select view_users.* from view_users where user_name = '{$user_name}' or user_client_name = '{$user_name}'"; return $this->getTable("user", $SQL); } // ====================== // Return a User's Serial // ====================== public function getUserSerial($user_id = "") { $users = $this->getUserByUserId($user_id); return ($users->count() === 0) ? 0 : (integer) $users->record->user_serial; } // ===================== // Return a Users Object // ===================== public function getUsers() { $SQL = "select view_users.* from view_users"; return $this->getTable("users", $SQL); } // ========================== // Return a Users Page Object // ========================== public function getUsersPage() { // Find Criteria $find_user = filter_input(INPUT_POST, "find_user") ?: ""; $find_user = $this->sanitizeString($find_user); $find_words = implode("|", explode(" ", $find_user)); // Record Count $connection = $this->connect(); $SQL = "select count(*) as count from view_users where user_name regexp :user_name or user_client_name regexp :user_client_name or user_email regexp :user_email or user_role regexp :user_role"; $statement = $connection->prepare($SQL); $statement->bindValue(":user_name", $find_words); $statement->bindValue(":user_client_name", $find_words); $statement->bindValue(":user_email", $find_words); $statement->bindValue(":user_role", $find_words); $statement->execute(); $recordset = $statement->fetch(PDO::FETCH_ASSOC); $count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0; // Pagination $pagination = filter_input(INPUT_POST, "pagination") ?: ""; switch ($pagination) { case "first" : $this->pagination_page = 1; break; case "previous" : $this->pagination_page = max(($this->pagination_page - 1), 1); break; case "next" : $this->pagination_page = ($this->pagination_page + 1); break; case "last" : $this->pagination_page = ($count / $this->pagination_size); break; } $offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size); $start = ($offset + 1); $end = min($count, (($start + $this->pagination_size) - 1)); // Data $SQL = "select view_users.* from view_users where user_name regexp :user_name or user_client_name regexp :user_client_name or user_email regexp :user_email or user_role regexp :user_role limit {$this->pagination_size} offset {$offset}"; $statement = $connection->prepare($SQL); $statement->bindValue(":user_name", $find_words); $statement->bindValue(":user_client_name", $find_words); $statement->bindValue(":user_email", $find_words); $statement->bindValue(":user_role", $find_words); $statement->execute(); $users = $this->getTableXML("users", $statement); // Insert Pagination Attributes $users->addAttribute("count", $count); $users->addAttribute("start", $start); $users->addAttribute("end", $end); $users->addAttribute("page", $this->pagination_page); $_SESSION[self::PAGINATION_PAGE] = $this->pagination_page; return $users; } // =========================== // Return an User Object(AJAX) // =========================== public function getUser_AJAX($user_name = "") { $user_name = filter_input(INPUT_POST, "user_name") ?: $user_name; $users = $this->getUserByUserName($user_name); // Create the User Object. $User = array(); $User["exists"] = ($users->count() > 0) ? true : false; if ($_SESSION[self::AJAX]) { echo json_encode($User); } else { return $User; } } // ========================== // Determine if a User Exists // ========================== public function userExists() { $user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $user_id = filter_input(INPUT_POST, "user_id") ?: ""; $user_id = strtolower(trim(preg_replace("/\s+/", " ", $user_id))); $SQL = "select user_id from view_users where user_serial != :user_serial and user_id = :user_id"; $statement = $this->connect()->prepare($SQL); $statement->bindValue(":user_serial", $user_serial); $statement->bindValue(":user_id", $user_id); $statement->execute(); $recordset = $statement->fetchAll(PDO::FETCH_ASSOC); $exists = (count($recordset) > 0) ? true : false; echo json_encode($exists); } // ============================= // Determine if a User is Active // ============================= public function userActive() { $user_serial = (integer) filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $SQL = "select request_serial from requests where request_user = {$user_serial}"; $requests = $this->getTable("requests", $SQL); $active = ($requests->count() > 0) ? true : $active; echo json_encode($active); } // ======================== // Login to the application // ======================== public function login() { $step = filter_input(INPUT_POST, "step") ?: "prompt"; switch ($step) { case "prompt": $XSLParms["BTN_SUBMIT"] = "main.php?action=Users.login&step=authenticate"; $XSLParms["INVALID_SIGNIN"] = "FALSE"; echo $this->applyXSL("", $this->getXSL("signIn"), $XSLParms); exit(); break; case "authenticate": $user_name = filter_input(INPUT_POST, "user_name") ?: ""; $user_password = filter_input(INPUT_POST, "user_password") ?: ""; // The User must exist in the Users Table $user = $this->getUserByUserName($user_name); // Automatically deny authentication if user is inactive if ($user->record->user_active == 0) { $XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate"; $XSLParms["INVALID_SIGNIN"] = "TRUE"; echo $this->applyXSL("", $this->getXSL("signIn"), $XSLParms); die(); } if ($user->count() > 0) { $stored_hashed_password = $user->record->user_password; // Verify Password if (password_verify($user_password, $stored_hashed_password)) { $_SESSION[self::USER_AUTHENTICATED] = true; $_SESSION[self::USER_SERIAL] = (integer) $user->record->user_serial; $_SESSION[self::USER_ID] = (string) $user->record->user_id; $_SESSION[self::USER_NAME] = (string) $user->record->user_name; $_SESSION[self::USER_EMAIL] = (string) $user->record->user_email; $_SESSION[self::USER_CLIENT_NAME] = (string) $user->record->user_client_name; $_SESSION[self::USER_ROLE] = (string) $user->record->user_role; $this->current_user_id = $_SESSION[self::USER_ID] ?? ""; $this->current_user_serial = $_SESSION[self::USER_SERIAL] ?? 0; $this->current_user_name = $_SESSION[self::USER_NAME] ?? ""; $this->current_user_email = $_SESSION[self::USER_EMAIL] ?? ""; // Determine if this is a System Administrator if (count($this->getSettings()->xpath("//SystemAdministrator[. = '{$user_name}']")) > 0) { $_SESSION[self::USER_ROLE] = "System Administrator"; } // Create Journal Entry and finish (new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} logged in ({$_SESSION[self::USER_ROLE]})."); $this->updateLogin(); header("Location: ./"); exit(); } else { $XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate"; $XSLParms["INVALID_SIGNIN"] = "TRUE"; echo $this->applyXSL("", $this->getXSL("signIn"), $XSLParms); die(); } } else { $XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate"; $XSLParms["INVALID_SIGNIN"] = "TRUE"; echo $this->applyXSL("", $this->getXSL("signIn"), $XSLParms); die(); } break; default: // User NOT Validated. header("Location: ./"); exit(); } } // =============== // Change Password // =============== public function changePassword() { $step = filter_input(INPUT_POST, "step") ?: "prompt"; switch ($step) { case "prompt": $popovers = (new Popovers())->getPopovers(); $XML = $this->mergeXML($popovers, ""); $content = $this->applyXSL($XML, $this->getXSL("changePassword")); $this->displayContent($content); break; case "change": $user_serial = $_SESSION[self::USER_SERIAL]; $user_new_password = filter_input(INPUT_POST, "user_new_password") ?: ""; $user_verify_password = filter_input(INPUT_POST, "user_verify_password") ?: ""; if (!$user_new_password == $user_verify_password) { $this->initializeSession(); } $user_new_hashed_password = password_hash($user_new_password, PASSWORD_DEFAULT); // Update User Password $connection = $this->connect(); $SQL = "update users set user_password = :user_password, user_change_password = :user_change_password, user_changer = :user_changer, user_changed = :user_changed where user_serial = :user_serial"; $statement = $connection->prepare($SQL); $statement->bindValue(":user_serial", $user_serial); $statement->bindValue(":user_password", $user_new_hashed_password); $statement->bindValue(":user_change_password", 0); $statement->bindValue(":user_changer", $this->current_user_name); $statement->bindValue(":user_changed", $this->getTimestamp()); if (!$statement->execute()) { $this->debug($statement->errorInfo()[2]); } (new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} changed their password."); break; default: $this->displayHome(); } } // ============== // Reset Password // ============== public function resetPassword() { $reset = false; $user_serial = filter_input(INPUT_POST, "user_serial") ?: ""; $user = $this->getUser($user_serial); $user_name = $user->record->user_name; $user_random_password = $this->generateRandomPassword(); $user_temp_password = password_hash($user_random_password, PASSWORD_DEFAULT); // Update User Password $connection = $this->connect(); $SQL = "update users set user_password = :user_password, user_change_password = :user_change_password where user_serial = :user_serial"; $statement = $connection->prepare($SQL); $statement->bindValue(":user_serial", $user_serial); $statement->bindValue(":user_password", $user_temp_password); $statement->bindValue(":user_change_password", 1); if (!$statement->execute()) { $this->debug($statement->errorInfo()[2]); } else { $reset = true; } // Send User Credentials (new Email())->emailUserPasswordResetLink($user, $user_random_password); (new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} reset {$user_name}'s password."); echo json_encode($reset); } // =============================================== // Update the Login timestamp for the current User // =============================================== public function updateLogin() { $SQL = "update users set user_login = :user_login where user_serial = :user_serial"; $statement = $this->connect()->prepare($SQL); $statement->bindValue(":user_login", $this->getTimestamp()); $statement->bindValue(":user_serial", $this->current_user_serial); $statement->execute(); } // ==================== // Update Active Status // ==================== public function updateActiveStatus() { $user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0; $user_active = filter_input(INPUT_POST, "user_active", FILTER_SANITIZE_NUMBER_INT) ?: 0; $SQL = "update users set user_active = :user_active, user_changed = :user_changed, user_changer = :user_changer where user_serial = :user_serial"; $statement = $this->connect()->prepare($SQL); $statement->bindValue(":user_serial", $user_serial); $statement->bindValue(":user_active", $user_active); $statement->bindValue(":user_changed", $this->getTimestamp()); $statement->bindValue(":user_changer", $this->current_user_name); if (!$statement->execute()) { error_log($statement->errorInfo()[2]); } } } ?>