import React, { useEffect, useState } from 'react'; import { User } from '../types'; import { fetchUsers, createUser, deleteUser, updateUser } from '../graphService'; import { TrashIcon, PlusIcon, UserIcon, EditIcon, SettingsIcon } from './Icons'; const UserManagement: React.FC = () => { const [users, setUsers] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(''); const [showDBHelper, setShowDBHelper] = useState(false); // Form State const [formData, setFormData] = useState({ username: '', password: '', email: '', role: 'editor' as 'admin'|'editor', auth_source: 'local' as 'local'|'azure'|'ldap', sendEmail: true }); const [isFormVisible, setIsFormVisible] = useState(false); const [editingUserId, setEditingUserId] = useState(null); const loadUsers = async () => { setIsLoading(true); try { const data = await fetchUsers(); setUsers(data); setError(''); } catch (err: any) { setError(err.message); } finally { setIsLoading(false); } }; useEffect(() => { loadUsers(); }, []); const handleCreateOrUpdate = async (e: React.FormEvent) => { e.preventDefault(); try { const payload = { ...formData }; // If editing, only send password if it has been typed if (editingUserId) { if (!payload.password) { delete (payload as any).password; } await updateUser(editingUserId, payload); } else { await createUser(payload); } resetForm(); loadUsers(); } catch (err: any) { alert('Operation Failed: ' + err.message); } }; const resetForm = () => { setFormData({ username: '', password: '', email: '', role: 'editor', auth_source: 'local', sendEmail: true }); setIsFormVisible(false); setEditingUserId(null); }; const handleEdit = (user: User) => { setEditingUserId(user.id); setFormData({ username: user.username, password: '', email: user.email || '', role: user.role, auth_source: user.auth_source || 'local', sendEmail: false }); setIsFormVisible(true); }; const handleDelete = async (id: number) => { if (id === 1) return; if (!window.confirm('Are you sure you want to delete this user?')) return; try { await deleteUser(id); loadUsers(); } catch (err: any) { alert('Error deleting user: ' + err.message); } }; if (isLoading && users.length === 0) return
Establishing Secure DB Connection...
; return (

System Accounts

MariaDB Production Instance

{!isFormVisible && ( )}
{error &&
Error: {error}
}
{users.map(user => ( ))}
Username Privilege Source Actions
{user.username} {user.id === 1 && PRIMARY ADMIN} {user.role} {user.auth_source} {user.id !== 1 && ( )}
{isFormVisible && (

{editingUserId ? 'Edit Account' : 'New Account'}

setFormData({...formData, username: e.target.value})} />
setFormData({...formData, email: e.target.value})} />
setFormData({...formData, password: e.target.value})} placeholder={editingUserId ? "••••••••" : ""} />
)}
{showDBHelper && (

Fix: Apply Verified Working Hash

Use the exact Blowfish hash you verified for the 'admin' user recovery.

Confirmed Hash for 'admin123':

Step 1: Open Terminal

docker compose exec db mariadb -u root -p

Step 2: Update Password Field

{`USE license_tracker; -- Apply the verified Blowfish hash ($2a$ format) for password 'admin123': UPDATE users SET password = '$2a$12$.UrnKUhUx9ypgARYW7VF2.okk.PyKqzSlCflAi5aDKhSrbKU.ciii' WHERE username = 'admin'; FLUSH PRIVILEGES; EXIT;`}
)}
); }; export default UserManagement;