feat: Add password change and reset API endpoints
NEW API ENDPOINTS: 1. /api/asteroid/user/change-password (authenticated users) - Users can change their own password - Requires current password verification - Returns 401 if current password is incorrect - Returns 200 on success 2. /api/asteroid/admin/reset-password (admin only) - Admins can reset any user's password - No current password required - Returns 404 if user not found - Returns 200 on success USAGE EXAMPLES: User changes own password: curl -X POST http://localhost:8080/api/asteroid/user/change-password \ -d 'current-password=asteroid123&new-password=newsecurepass' \ -b cookies.txt Admin resets user password: curl -X POST http://localhost:8080/api/asteroid/admin/reset-password \ -d 'username=admin&new-password=newsecurepass' \ -b cookies.txt This addresses the security concern about the default admin password. Admins can now reset it via API without needing REPL access. Ref: TODO.org Problem 4 - Default admin password
This commit is contained in:
parent
dbe9a06247
commit
86eef472a9
|
|
@ -105,3 +105,59 @@
|
||||||
(api-output `(("status" . "error")
|
(api-output `(("status" . "error")
|
||||||
("message" . ,(format nil "Error creating user: ~a" e)))
|
("message" . ,(format nil "Error creating user: ~a" e)))
|
||||||
:status 500))))
|
:status 500))))
|
||||||
|
|
||||||
|
;; API: Change own password (authenticated users)
|
||||||
|
(define-api asteroid/user/change-password (current-password new-password) ()
|
||||||
|
"API endpoint for users to change their own password"
|
||||||
|
(require-authentication)
|
||||||
|
(handler-case
|
||||||
|
(if (and current-password new-password)
|
||||||
|
(let* ((current-user (auth:current-user))
|
||||||
|
(username (gethash "username" current-user))
|
||||||
|
(stored-hash (gethash "password-hash" current-user)))
|
||||||
|
;; Verify current password
|
||||||
|
(if (verify-password current-password
|
||||||
|
(if (listp stored-hash) (first stored-hash) stored-hash))
|
||||||
|
;; Current password is correct, update to new password
|
||||||
|
(if (reset-user-password username new-password)
|
||||||
|
(api-output `(("status" . "success")
|
||||||
|
("message" . "Password changed successfully")))
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . "Failed to update password"))
|
||||||
|
:status 500))
|
||||||
|
;; Current password is incorrect
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . "Current password is incorrect"))
|
||||||
|
:status 401)))
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . "Missing required fields"))
|
||||||
|
:status 400))
|
||||||
|
(error (e)
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . ,(format nil "Error changing password: ~a" e)))
|
||||||
|
:status 500))))
|
||||||
|
|
||||||
|
;; API: Reset user password (admin only)
|
||||||
|
(define-api asteroid/admin/reset-password (username new-password) ()
|
||||||
|
"API endpoint for admins to reset any user's password"
|
||||||
|
(require-role :admin)
|
||||||
|
(handler-case
|
||||||
|
(if (and username new-password)
|
||||||
|
(let ((user (find-user-by-username username)))
|
||||||
|
(if user
|
||||||
|
(if (reset-user-password username new-password)
|
||||||
|
(api-output `(("status" . "success")
|
||||||
|
("message" . ,(format nil "Password reset for user: ~a" username))))
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . "Failed to reset password"))
|
||||||
|
:status 500))
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . ,(format nil "User not found: ~a" username)))
|
||||||
|
:status 404)))
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . "Missing required fields"))
|
||||||
|
:status 400))
|
||||||
|
(error (e)
|
||||||
|
(api-output `(("status" . "error")
|
||||||
|
("message" . ,(format nil "Error resetting password: ~a" e)))
|
||||||
|
:status 500))))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue