admin.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // ==================== Admin Panel Functions ====================
  2. async function loadSettings() {
  3. try {
  4. const response = await fetch('/api/admin/settings');
  5. if (response.status === 401) {
  6. window.location.href = '/login';
  7. return;
  8. }
  9. if (response.status === 403) {
  10. showMessage('Admin access required', 'error');
  11. return;
  12. }
  13. const data = await response.json();
  14. // Update checkbox state
  15. document.getElementById('allow-registration').checked =
  16. data.allow_registration === 'true' || data.allow_registration === true;
  17. } catch (error) {
  18. console.error('Error loading settings:', error);
  19. showMessage('Error loading settings: ' + error.message, 'error');
  20. }
  21. }
  22. async function toggleRegistration(checkbox) {
  23. try {
  24. const formData = new FormData();
  25. formData.append('value', checkbox.checked ? 'true' : 'false');
  26. const response = await fetch('/api/admin/settings/allow_registration', {
  27. method: 'PUT',
  28. body: formData
  29. });
  30. if (response.status === 401) {
  31. window.location.href = '/login';
  32. return;
  33. }
  34. if (response.status === 403) {
  35. showMessage('Admin access required', 'error');
  36. return;
  37. }
  38. const data = await response.json();
  39. if (data.status === 'success') {
  40. showMessage(
  41. checkbox.checked ? 'Registration enabled' : 'Registration disabled',
  42. 'success'
  43. );
  44. } else {
  45. showMessage(data.message || 'Failed to update setting', 'error');
  46. // Revert checkbox
  47. checkbox.checked = !checkbox.checked;
  48. }
  49. } catch (error) {
  50. showMessage('Error updating setting: ' + error.message, 'error');
  51. // Revert checkbox
  52. checkbox.checked = !checkbox.checked;
  53. }
  54. }
  55. async function loadUsers() {
  56. try {
  57. const loadingEl = document.getElementById('users-loading');
  58. const containerEl = document.getElementById('users-container');
  59. loadingEl.classList.remove('hidden');
  60. containerEl.classList.add('hidden');
  61. const response = await fetch('/api/admin/users');
  62. if (response.status === 401) {
  63. window.location.href = '/login';
  64. return;
  65. }
  66. if (response.status === 403) {
  67. showMessage('Admin access required', 'error');
  68. return;
  69. }
  70. const data = await response.json();
  71. loadingEl.classList.add('hidden');
  72. containerEl.classList.remove('hidden');
  73. renderUsers(data.users || []);
  74. } catch (error) {
  75. console.error('Error loading users:', error);
  76. showMessage('Error loading users: ' + error.message, 'error');
  77. document.getElementById('users-loading').classList.add('hidden');
  78. }
  79. }
  80. function renderUsers(users) {
  81. const listEl = document.getElementById('users-list');
  82. if (users.length === 0) {
  83. listEl.innerHTML = '<tr><td colspan="8" style="text-align: center;">No users found</td></tr>';
  84. return;
  85. }
  86. const html = users.map(user => {
  87. const createdDate = new Date(user.created_at).toLocaleDateString();
  88. const lastLogin = user.last_login ? new Date(user.last_login).toLocaleDateString() : 'Never';
  89. return `
  90. <tr>
  91. <td>${user.username}</td>
  92. <td>${user.email}</td>
  93. <td>${user.display_name || '-'}</td>
  94. <td>${user.is_admin ? '<span class="badge badge-admin">Admin</span>' : '-'}</td>
  95. <td>${user.is_active ? '<span class="badge badge-active">Active</span>' : '<span class="badge badge-inactive">Inactive</span>'}</td>
  96. <td>${createdDate}</td>
  97. <td>${lastLogin}</td>
  98. <td>
  99. <button class="btn btn-small" onclick="showChangePasswordModal(${user.id}, '${user.username}')">Change Password</button>
  100. ${!user.is_admin ? `
  101. <button class="btn btn-small btn-secondary" onclick="toggleAdmin(${user.id}, true)">Make Admin</button>
  102. ` : ''}
  103. ${!user.is_current ? `
  104. <button class="btn btn-small btn-danger" onclick="deleteUser(${user.id}, '${user.username}')">Delete</button>
  105. ` : '<span class="text-muted">Current User</span>'}
  106. </td>
  107. </tr>
  108. `;
  109. }).join('');
  110. listEl.innerHTML = html;
  111. }
  112. async function toggleAdmin(userId, makeAdmin) {
  113. if (!confirm(`Are you sure you want to ${makeAdmin ? 'grant' : 'remove'} admin privileges ${makeAdmin ? 'to' : 'from'} this user?`)) {
  114. return;
  115. }
  116. try {
  117. const formData = new FormData();
  118. formData.append('is_admin', makeAdmin ? 'true' : 'false');
  119. const response = await fetch(`/api/admin/users/${userId}/admin`, {
  120. method: 'PUT',
  121. body: formData
  122. });
  123. if (response.status === 401) {
  124. window.location.href = '/login';
  125. return;
  126. }
  127. const data = await response.json();
  128. if (data.status === 'success') {
  129. showMessage('User privileges updated successfully', 'success');
  130. loadUsers(); // Reload user list
  131. } else {
  132. showMessage(data.message || 'Failed to update user', 'error');
  133. }
  134. } catch (error) {
  135. showMessage('Error updating user: ' + error.message, 'error');
  136. }
  137. }
  138. async function deleteUser(userId, username) {
  139. if (!confirm(`Are you sure you want to delete user "${username}"? This action cannot be undone and will delete all their data.`)) {
  140. return;
  141. }
  142. try {
  143. const response = await fetch(`/api/admin/users/${userId}`, {
  144. method: 'DELETE'
  145. });
  146. if (response.status === 401) {
  147. window.location.href = '/login';
  148. return;
  149. }
  150. const data = await response.json();
  151. if (data.status === 'success') {
  152. showMessage('User deleted successfully', 'success');
  153. loadUsers(); // Reload user list
  154. } else {
  155. showMessage(data.message || 'Failed to delete user', 'error');
  156. }
  157. } catch (error) {
  158. showMessage('Error deleting user: ' + error.message, 'error');
  159. }
  160. }
  161. // ==================== Add User Modal ====================
  162. function showAddUserModal() {
  163. document.getElementById('add-user-modal').classList.remove('hidden');
  164. document.getElementById('add-user-form').reset();
  165. }
  166. function hideAddUserModal() {
  167. document.getElementById('add-user-modal').classList.add('hidden');
  168. document.getElementById('add-user-form').reset();
  169. }
  170. async function submitAddUser(event) {
  171. event.preventDefault();
  172. const form = event.target;
  173. const formData = new FormData(form);
  174. try {
  175. const response = await fetch('/api/admin/users', {
  176. method: 'POST',
  177. body: formData
  178. });
  179. if (response.status === 401) {
  180. window.location.href = '/login';
  181. return;
  182. }
  183. const data = await response.json();
  184. if (data.status === 'success') {
  185. showMessage(data.message || 'User created successfully', 'success');
  186. hideAddUserModal();
  187. loadUsers(); // Reload user list
  188. } else {
  189. showMessage(data.message || 'Failed to create user', 'error');
  190. }
  191. } catch (error) {
  192. showMessage('Error creating user: ' + error.message, 'error');
  193. }
  194. }
  195. // ==================== Change Password Modal ====================
  196. function showChangePasswordModal(userId, username) {
  197. document.getElementById('change-password-user-id').value = userId;
  198. document.getElementById('change-password-username').textContent = username;
  199. document.getElementById('change-password-modal').classList.remove('hidden');
  200. document.getElementById('change-password-form').reset();
  201. // Re-set the hidden user ID after reset
  202. document.getElementById('change-password-user-id').value = userId;
  203. }
  204. function hideChangePasswordModal() {
  205. document.getElementById('change-password-modal').classList.add('hidden');
  206. document.getElementById('change-password-form').reset();
  207. }
  208. async function submitChangePassword(event) {
  209. event.preventDefault();
  210. const form = event.target;
  211. const userId = document.getElementById('change-password-user-id').value;
  212. const formData = new FormData(form);
  213. try {
  214. const response = await fetch(`/api/admin/users/${userId}/password`, {
  215. method: 'PUT',
  216. body: formData
  217. });
  218. if (response.status === 401) {
  219. window.location.href = '/login';
  220. return;
  221. }
  222. const data = await response.json();
  223. if (data.status === 'success') {
  224. showMessage(data.message || 'Password changed successfully', 'success');
  225. hideChangePasswordModal();
  226. } else {
  227. showMessage(data.message || 'Failed to change password', 'error');
  228. }
  229. } catch (error) {
  230. showMessage('Error changing password: ' + error.message, 'error');
  231. }
  232. }