// admin.js — admin user management page let resetTargetId = null; let deleteTargetId = null; let currentAdminId = null; document.addEventListener('DOMContentLoaded', async () => { // Verify admin access const user = Auth.getUser(); if (!user || !user.is_admin) { window.location.href = '/'; return; } currentAdminId = parseInt(user.sub); await loadUsers(); }); async function loadUsers() { try { const users = await API.get('/api/admin/users'); renderUsers(users); } catch (err) { showMessage(document.getElementById('msg'), err.message, 'error'); } } function renderUsers(users) { const tbody = document.getElementById('users-body'); if (!users.length) { tbody.innerHTML = 'No users found.'; return; } tbody.innerHTML = users.map(u => { const isSelf = u.id === currentAdminId; const roleLabel = u.is_admin ? 'Admin' : 'User'; const statusLabel = u.is_disabled ? 'Disabled' : 'Active'; const created = new Date(u.created_at).toLocaleDateString(); const toggleBtn = u.is_disabled ? `` : ``; const impersonateBtn = !isSelf ? `` : ''; const deleteBtn = !isSelf ? `` : ''; return ` ${escHtml(u.username)} ${roleLabel} ${statusLabel} ${created} ${toggleBtn} ${impersonateBtn} ${deleteBtn} `; }).join(''); } function showResetModal(id, username) { resetTargetId = id; document.getElementById('reset-username').textContent = username; document.getElementById('reset-password').value = ''; document.getElementById('reset-msg').className = 'message'; document.getElementById('reset-modal').style.display = 'flex'; document.getElementById('reset-password').focus(); } function hideResetModal() { document.getElementById('reset-modal').style.display = 'none'; resetTargetId = null; } async function submitReset() { const password = document.getElementById('reset-password').value; const msgEl = document.getElementById('reset-msg'); if (password.length < 6) { msgEl.textContent = 'Password must be at least 6 characters'; msgEl.className = 'message error visible'; return; } try { await API.post(`/api/admin/users/${resetTargetId}/reset-password`, { new_password: password }); msgEl.textContent = 'Password reset successfully.'; msgEl.className = 'message success visible'; setTimeout(hideResetModal, 1200); } catch (err) { msgEl.textContent = err.message; msgEl.className = 'message error visible'; } } async function toggleUser(id, disable) { const action = disable ? 'disable' : 'enable'; try { await API.post(`/api/admin/users/${id}/${action}`, {}); await loadUsers(); } catch (err) { showMessage(document.getElementById('msg'), err.message, 'error'); } } async function impersonateUser(id) { try { const data = await API.post(`/api/admin/users/${id}/impersonate`, {}); Auth.setToken(data.user); window.location.href = '/'; } catch (err) { showMessage(document.getElementById('msg'), err.message, 'error'); } } function showDeleteModal(id, username) { deleteTargetId = id; document.getElementById('delete-username').textContent = username; document.getElementById('delete-modal').style.display = 'flex'; } function hideDeleteModal() { document.getElementById('delete-modal').style.display = 'none'; deleteTargetId = null; } async function submitDelete() { try { await API.del(`/api/admin/users/${deleteTargetId}`); hideDeleteModal(); showMessage(document.getElementById('msg'), 'User deleted.'); await loadUsers(); } catch (err) { hideDeleteModal(); showMessage(document.getElementById('msg'), err.message, 'error'); } } // Close modals on overlay click document.addEventListener('click', (e) => { if (e.target.id === 'reset-modal') hideResetModal(); if (e.target.id === 'delete-modal') hideDeleteModal(); });