Merge remote-tracking branch 'upstream/main' into glenneth/recently-played-tracks

This commit is contained in:
Glenn Thompson 2025-11-22 10:23:45 +03:00
commit c36015747b
3 changed files with 96 additions and 15 deletions

View File

@ -157,3 +157,59 @@
(api-output `(("status" . "success")
("message" . ,(format nil "Password reset for user: ~a" username)))))))
(define-api asteroid/user/activate (user-id active) ()
"API endpoint for setting the active state of an user account"
(format t "Activation of user: #~a set to ~a~%" user-id active)
(require-role :admin)
(with-error-handling
(let ((user (when user-id
(find-user-by-id user-id)))
(active (if (stringp active)
(parse-integer active)
active)))
(unless user
(error 'not-found-error :message "User not found"))
;; Change user active state
(let ((result (if (= 0 active)
(deactivate-user user-id)
(activate-user user-id))))
(if result
(api-output `(("status" . "success")
("message" . ,(format nil "User '~a' ~a."
(dm:field user "username")
(if (= 0 active)
"deactivated"
"activated")))))
(api-output `(("status" . "error")
("message" . ,(format nil "Could not ~a user '~a'."
(if (= 0 active)
"deactivated"
"activated")
(dm:field user "username"))))))))))
(define-api asteroid/user/role (user-id role) ()
"API endpoint for setting the access role of an user account"
(format t "Role of user: #~a set to ~a~%" user-id role)
(require-role :admin)
(with-error-handling
(let ((user (when user-id
(find-user-by-id user-id)))
(user-role (intern (string-upcase role) :keyword)))
(unless user
(error 'not-found-error :message "User not found"))
;; Change user role
(let ((result (update-user-role user-id user-role)))
(if result
(api-output `(("status" . "success")
("message" . ,(format nil "User '~a' is now a ~a."
(dm:field user "username")
role))))
(api-output `(("status" . "error")
("message" . ,(format nil "Could not set user '~a' as ~a."
(dm:field user "username")
role)))))))))

View File

@ -90,20 +90,23 @@ function hideUsersTable() {
async function updateUserRole(userId, newRole) {
try {
const formData = new FormData();
formData.append('user-id', userId);
formData.append('role', newRole);
const response = await fetch(`/api/asteroid/users/${userId}/role`, {
const response = await fetch('/api/asteroid/user/role', {
method: 'POST',
body: formData
});
const result = await response.json();
// Handle Radiance API data wrapping
const data = result.data || result;
if (result.status === 'success') {
if (data.status === 'success') {
loadUserStats();
alert('User role updated successfully');
alert(data.message);
} else {
alert('Error updating user role: ' + result.message);
alert('Error updating user role: ' + data.message);
}
} catch (error) {
console.error('Error updating user role:', error);
@ -117,18 +120,25 @@ async function deactivateUser(userId) {
}
try {
const response = await fetch(`/api/asteroid/users/${userId}/deactivate`, {
method: 'POST'
const formData = new FormData();
formData.append('user-id', userId);
formData.append('active', 0);
const response = await fetch('/api/asteroid/user/activate', {
method: 'POST',
body: formData
});
const result = await response.json();
// Handle Radiance API data wrapping
const data = result.data || result;
if (result.status === 'success') {
if (data.status === 'success') {
loadUsers();
loadUserStats();
alert('User deactivated successfully');
alert(data.message);
} else {
alert('Error deactivating user: ' + result.message);
alert('Error deactivating user: ' + data.message);
}
} catch (error) {
console.error('Error deactivating user:', error);
@ -137,19 +147,31 @@ async function deactivateUser(userId) {
}
async function activateUser(userId) {
if (!confirm('Are you sure you want to activate this user?')) {
return;
}
try {
const response = await fetch(`/api/asteroid/users/${userId}/activate`, {
method: 'POST'
const formData = new FormData();
formData.append('user-id', userId);
formData.append('active', 1);
const response = await fetch('/api/asteroid/user/activate', {
method: 'POST',
body: formData
});
const result = await response.json();
// Handle Radiance API data wrapping
const data = result.data || result;
if (result.status === 'success') {
if (data.status === 'success') {
loadUsers();
loadUserStats();
alert('User activated successfully');
alert(data.message);
} else {
alert('Error activating user: ' + result.message);
alert('Error activating user: ' + data.message);
}
} catch (error) {
console.error('Error activating user:', error);

View File

@ -40,7 +40,10 @@
(defun find-user-by-id (user-id)
"Find a user by ID"
(format t "Looking for user with ID: ~a (type: ~a)~%" user-id (type-of user-id))
(let ((user (dm:get-one "USERS" (db:query (:= '_id user-id)))))
(let* ((user-id (if (stringp user-id)
(parse-integer user-id)
user-id))
(user (dm:get-one "USERS" (db:query (:= '_id user-id)))))
(when user
(format t "Found user '~a' with id #~a~%"
(dm:field user "username")