// User Management functionality // Function to load users from the backend async function loadUsers() { try { const response = await fetch('/users/', { credentials: 'include' }); if (!response.ok) { throw new Error(`Failed to load users: ${response.statusText}`); } const users = await response.json(); console.log('Loaded users:', users); const tableBody = document.getElementById('users-table-body'); if (!tableBody) { console.error('users-table-body element not found'); return; } if (users.length === 0) { tableBody.innerHTML = 'No users found'; return; } tableBody.innerHTML = users.map(user => ` ${user.username} ${user.email || 'N/A'} ${user.role || 'User'} ${user.last_login ? formatDateInUserTimezone(user.last_login) : 'Never'} `).join(''); // Add event listeners to edit buttons document.querySelectorAll('.edit-user-btn').forEach(button => { button.addEventListener('click', function() { const username = this.getAttribute('data-username'); editUser(username); }); }); // Add event listeners to delete buttons document.querySelectorAll('.delete-user-btn').forEach(button => { button.addEventListener('click', function() { const username = this.getAttribute('data-username'); deleteUser(username); }); }); } catch (error) { console.error('Error loading users:', error); const tableBody = document.getElementById('users-table-body'); if (tableBody) { tableBody.innerHTML = `Error loading users: ${error.message}`; } } } // Function to edit a user async function editUser(username) { try { // Fetch user details const response = await fetch(`/users/${username}`, { credentials: 'include' }); if (!response.ok) { throw new Error(`Failed to load user details: ${response.statusText}`); } const user = await response.json(); console.log('User details:', user); // Create a modal for editing the user const modalHtml = ` `; // Add the modal to the DOM const modalContainer = document.createElement('div'); modalContainer.innerHTML = modalHtml; document.body.appendChild(modalContainer); // Show the modal $('#edit-user-modal').modal('show'); // Toggle new password field visibility document.getElementById('edit-reset-password').addEventListener('change', function() { document.getElementById('new-password-container').style.display = this.checked ? 'block' : 'none'; }); // Add password matching validation for edit form const editNewPassword = document.getElementById('edit-new-password'); const editConfirmPassword = document.getElementById('edit-confirm-password'); const editPasswordMatchFeedback = document.getElementById('edit-password-match-feedback'); function validateEditPasswordMatch() { if (editConfirmPassword.value === '') { editPasswordMatchFeedback.innerHTML = ''; return false; } else if (editNewPassword.value === editConfirmPassword.value) { editPasswordMatchFeedback.innerHTML = '
Passwords match
'; return true; } else { editPasswordMatchFeedback.innerHTML = '
Passwords do not match
'; return false; } } editNewPassword.addEventListener('input', validateEditPasswordMatch); editConfirmPassword.addEventListener('input', validateEditPasswordMatch); // Handle save button click document.getElementById('save-user-btn').addEventListener('click', async function() { const email = document.getElementById('edit-email').value; const role = document.getElementById('edit-role').value; const resetPassword = document.getElementById('edit-reset-password').checked; const newPassword = document.getElementById('edit-new-password').value; const forcePasswordChange = document.getElementById('edit-force-password-change').checked; // Validate form if (!email) { alert('Email is required'); return; } if (resetPassword) { const confirmPassword = document.getElementById('edit-confirm-password').value; if (!newPassword) { alert('New password is required when resetting password'); return; } if (!confirmPassword) { alert('Password confirmation is required'); return; } if (newPassword !== confirmPassword) { alert('Passwords do not match'); return; } } // Prepare data for API const userData = { email: email, role: role, reset_password: resetPassword, force_password_change: forcePasswordChange }; if (resetPassword) { userData.new_password = newPassword; } try { // Update user via API const response = await fetch(`/users/${username}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(userData) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || `Failed to update user: ${response.statusText}`); } // Close modal and reload users $('#edit-user-modal').modal('hide'); document.body.removeChild(modalContainer); // Show success message alert(`User ${username} updated successfully`); // Reload users list loadUsers(); } catch (error) { console.error('Error updating user:', error); alert(`Error updating user: ${error.message}`); } }); // Clean up when modal is closed $('#edit-user-modal').on('hidden.bs.modal', function() { document.body.removeChild(modalContainer); }); } catch (error) { console.error('Error editing user:', error); alert(`Error editing user: ${error.message}`); } } // Function to delete a user async function deleteUser(username) { // Confirm deletion const confirmDelete = confirm(`Are you sure you want to delete user ${username}?`); if (!confirmDelete) return; try { // Delete user via API const response = await fetch(`/users/${username}`, { method: 'DELETE', credentials: 'include' }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || `Failed to delete user: ${response.statusText}`); } // Show success message alert(`User ${username} deleted successfully`); // Reload users list loadUsers(); } catch (error) { console.error('Error deleting user:', error); alert(`Error deleting user: ${error.message}`); } } // Function to add a new user function setupAddUserModal() { // Create a modal for adding a new user const modalHtml = ` `; // Add the modal to the DOM const modalContainer = document.createElement('div'); modalContainer.innerHTML = modalHtml; document.body.appendChild(modalContainer); // Add password matching validation const addPassword = document.getElementById('add-password'); const addConfirmPassword = document.getElementById('add-confirm-password'); const passwordMatchFeedback = document.getElementById('password-match-feedback'); function validatePasswordMatch() { if (addConfirmPassword.value === '') { passwordMatchFeedback.innerHTML = ''; return false; } else if (addPassword.value === addConfirmPassword.value) { passwordMatchFeedback.innerHTML = '
Passwords match
'; return true; } else { passwordMatchFeedback.innerHTML = '
Passwords do not match
'; return false; } } addPassword.addEventListener('input', validatePasswordMatch); addConfirmPassword.addEventListener('input', validatePasswordMatch); // Handle create button click document.getElementById('create-user-btn').addEventListener('click', async function() { const username = document.getElementById('add-username').value; const email = document.getElementById('add-email').value; const password = document.getElementById('add-password').value; const confirmPassword = document.getElementById('add-confirm-password').value; const role = document.getElementById('add-role').value; const forcePasswordChange = document.getElementById('add-force-password-change').checked; // Validate form if (!username || !email || !password || !confirmPassword) { alert('All fields are required'); return; } // Check if passwords match if (password !== confirmPassword) { alert('Passwords do not match'); return; } // Prepare data for API const userData = { username: username, email: email, password: password, role: role, force_password_change: forcePasswordChange }; try { // Create user via API const response = await fetch('/users/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(userData) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || `Failed to create user: ${response.statusText}`); } // Close modal and reload users $('#add-user-modal').modal('hide'); // Show success message alert(`User ${username} created successfully`); // Reload users list loadUsers(); } catch (error) { console.error('Error creating user:', error); alert(`Error creating user: ${error.message}`); } }); } // Initialize user management when the DOM is loaded document.addEventListener('DOMContentLoaded', function() { console.log('Initializing user management from user-management.js'); // Override the initializeUserManagement function window.initializeUserManagement = function() { console.log('Initializing user management...'); // Load users when the page loads loadUsers(); // Add event listener to the "Add User" button const addUserBtn = document.querySelector('[data-target="#add-user-modal"]'); if (addUserBtn) { addUserBtn.addEventListener('click', function() { setupAddUserModal(); $('#add-user-modal').modal('show'); }); } }; // If we're already on the users page, initialize it if (window.location.hash === '#users') { window.initializeUserManagement(); } }); // Helper function to format dates function formatDateInUserTimezone(dateString) { if (!dateString) return ""; const date = new Date(dateString); const options = { year: "numeric", month: "long", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", timeZoneName: "short", }; return date.toLocaleDateString("en-US", options); }