mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Basic account management
This commit is contained in:
		
							
								
								
									
										236
									
								
								public/scripts/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								public/scripts/user.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| import { callPopup, getRequestHeaders, renderTemplate } from '../script.js'; | ||||
|  | ||||
| /** | ||||
|  * @type {import('../../src/users.js').User} Logged in user | ||||
|  */ | ||||
| export let currentUser = null; | ||||
|  | ||||
| /** | ||||
|  * Enable or disable user account controls in the UI. | ||||
|  * @param {boolean} isEnabled User account controls enabled | ||||
|  * @returns {Promise<void>} | ||||
|  */ | ||||
| export async function setUserControls(isEnabled) { | ||||
|     if (!isEnabled) { | ||||
|         $('#account_controls').hide(); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     $('#account_controls').show(); | ||||
|     await getCurrentUser(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if the current user is an admin. | ||||
|  * @returns {boolean} True if the current user is an admin | ||||
|  */ | ||||
| function isAdmin() { | ||||
|     if (!currentUser) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     return Boolean(currentUser.admin); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get the current user. | ||||
|  * @returns {Promise<void>} | ||||
|  */ | ||||
| async function getCurrentUser() { | ||||
|     try { | ||||
|         const response = await fetch('/api/users/me', { | ||||
|             headers: getRequestHeaders(), | ||||
|         }); | ||||
|  | ||||
|         if (!response.ok) { | ||||
|             throw new Error('Failed to get current user'); | ||||
|         } | ||||
|  | ||||
|         currentUser = await response.json(); | ||||
|         $('#admin_button').toggle(isAdmin()); | ||||
|     } catch (error) { | ||||
|         console.error('Error getting current user:', error); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function getUsers() { | ||||
|     try { | ||||
|         const response = await fetch('/api/users/get', { | ||||
|             method: 'POST', | ||||
|             headers: getRequestHeaders(), | ||||
|         }); | ||||
|  | ||||
|         if (!response.ok) { | ||||
|             throw new Error('Failed to get users'); | ||||
|         } | ||||
|  | ||||
|         return response.json(); | ||||
|     } catch (error) { | ||||
|         console.error('Error getting users:', error); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Enable a user account. | ||||
|  * @param {string} handle User handle | ||||
|  * @param {function} callback Success callback | ||||
|  * @returns {Promise<void>} | ||||
|  */ | ||||
| async function enableUser(handle, callback) { | ||||
|     try { | ||||
|         const response = await fetch('/api/users/enable', { | ||||
|             method: 'POST', | ||||
|             headers: getRequestHeaders(), | ||||
|             body: JSON.stringify({ handle }), | ||||
|         }); | ||||
|  | ||||
|         if (!response.ok) { | ||||
|             const data = await response.json(); | ||||
|             toastr.error(data.error || 'Unknown error', 'Failed to enable user'); | ||||
|             throw new Error('Failed to enable user'); | ||||
|         } | ||||
|  | ||||
|         callback(); | ||||
|     } catch (error) { | ||||
|         console.error('Error enabling user:', error); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function disableUser(handle, callback) { | ||||
|     try { | ||||
|         const response = await fetch('/api/users/disable', { | ||||
|             method: 'POST', | ||||
|             headers: getRequestHeaders(), | ||||
|             body: JSON.stringify({ handle }), | ||||
|         }); | ||||
|  | ||||
|         if (!response.ok) { | ||||
|             const data = await response.json(); | ||||
|             toastr.error(data?.error || 'Unknown error', 'Failed to disable user'); | ||||
|             throw new Error('Failed to disable user'); | ||||
|         } | ||||
|  | ||||
|         callback(); | ||||
|     } catch (error) { | ||||
|         console.error('Error disabling user:', error); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Create a new user. | ||||
|  * @param {HTMLFormElement} form Form element | ||||
|  */ | ||||
| async function createUser(form, callback) { | ||||
|     const errors = []; | ||||
|     const formData = new FormData(form); | ||||
|  | ||||
|     if (!formData.get('handle')) { | ||||
|         errors.push('Handle is required'); | ||||
|     } | ||||
|  | ||||
|     if (formData.get('password') !== formData.get('confirm')) { | ||||
|         errors.push('Passwords do not match'); | ||||
|     } | ||||
|  | ||||
|     if (errors.length) { | ||||
|         toastr.error(errors.join(', '), 'Failed to create user'); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     const body = {}; | ||||
|     formData.forEach(function (value, key) { | ||||
|         if (key === 'confirm') { | ||||
|             return; | ||||
|         } | ||||
|         if (key.startsWith('_')) { | ||||
|             key = key.substring(1); | ||||
|         } | ||||
|         body[key] = value; | ||||
|     }); | ||||
|  | ||||
|     try { | ||||
|         const response = await fetch('/api/users/create', { | ||||
|             method: 'POST', | ||||
|             headers: getRequestHeaders(), | ||||
|             body: JSON.stringify(body), | ||||
|         }); | ||||
|  | ||||
|         if (!response.ok) { | ||||
|             const data = await response.json(); | ||||
|             toastr.error(data.error || 'Unknown error', 'Failed to create user'); | ||||
|             throw new Error('Failed to create user'); | ||||
|         } | ||||
|  | ||||
|         form.reset(); | ||||
|         callback(); | ||||
|     } catch (error) { | ||||
|         console.error('Error creating user:', error); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function openAdminPanel() { | ||||
|     async function renderUsers() { | ||||
|         const users = await getUsers(); | ||||
|         template.find('.usersList').empty(); | ||||
|         for (const user of users) { | ||||
|             const userBlock = template.find('.userAccountTemplate .userAccount').clone(); | ||||
|             userBlock.find('.userName').text(user.name); | ||||
|             userBlock.find('.userHandle').text(user.handle); | ||||
|             userBlock.find('.userStatus').text(user.enabled ? 'Enabled' : 'Disabled'); | ||||
|             userBlock.find('.userRole').text(user.admin ? 'Admin' : 'User'); | ||||
|             userBlock.find('.avatar img').attr('src', user.avatar); | ||||
|             userBlock.find('.hasPassword').toggle(user.password); | ||||
|             userBlock.find('.noPassword').toggle(!user.password); | ||||
|             userBlock.find('.userCreated').text(new Date(user.created).toLocaleString()); | ||||
|             userBlock.find('.userEnableButton').toggle(!user.enabled).on('click', () => enableUser(user.handle, renderUsers)); | ||||
|             userBlock.find('.userDisableButton').toggle(user.enabled).on('click', () => disableUser(user.handle, renderUsers)); | ||||
|             template.find('.usersList').append(userBlock); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const template = $(renderTemplate('admin')); | ||||
|  | ||||
|     template.find('.adminNav > button').on('click', function () { | ||||
|         const target = String($(this).data('target-tab')); | ||||
|         template.find('.navTab').each(function () { | ||||
|             $(this).toggle(this.classList.contains(target)); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     template.find('.userCreateForm').on('submit', function (event) { | ||||
|         if (!(event.target instanceof HTMLFormElement)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         event.preventDefault(); | ||||
|         createUser(event.target, () => { | ||||
|             template.find('.manageUsersButton').trigger('click'); | ||||
|             renderUsers(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     callPopup(template, 'text', '', { okButton: 'Close', wide: true, large: true, allowVerticalScrolling: true, allowHorizontalScrolling: false }); | ||||
|     renderUsers(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Log out the current user. | ||||
|  * @returns {Promise<void>} | ||||
|  */ | ||||
| async function logout() { | ||||
|     await fetch('/api/users/logout', { | ||||
|         method: 'POST', | ||||
|         headers: getRequestHeaders(), | ||||
|     }); | ||||
|  | ||||
|     window.location.reload(); | ||||
| } | ||||
|  | ||||
| jQuery(() => { | ||||
|     $('#logout_button').on('click', () => { | ||||
|         logout(); | ||||
|     }); | ||||
|     $('#admin_button').on('click', () => { | ||||
|         openAdminPanel(); | ||||
|     }); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user