Fix last-login timezone handling
- Add cl-time-to-unix helper to convert CL universal time to Unix epoch - Store last-login as UTC time for correct timezone conversion - Handle Unix epoch in JavaScript (detect seconds vs milliseconds)
This commit is contained in:
parent
bc7da82d84
commit
349fa31d8f
|
|
@ -53,6 +53,14 @@
|
|||
(setf (session:field "user-id") nil)
|
||||
(radiance:redirect "/"))
|
||||
|
||||
;; Helper to convert Common Lisp universal time to Unix epoch
|
||||
(defun cl-time-to-unix (cl-time)
|
||||
"Convert Common Lisp universal time to Unix epoch.
|
||||
CL epoch is 1900-01-01, Unix epoch is 1970-01-01.
|
||||
Difference is 2208988800 seconds."
|
||||
(when cl-time
|
||||
(- cl-time 2208988800)))
|
||||
|
||||
;; API: Get all users (admin only)
|
||||
(define-api asteroid/users () ()
|
||||
"API endpoint to get all users"
|
||||
|
|
@ -66,8 +74,8 @@
|
|||
("email" . ,(dm:field user "email"))
|
||||
("role" . ,(dm:field user "role"))
|
||||
("active" . ,(= (dm:field user "active") 1))
|
||||
("created-date" . ,(dm:field user "created-date"))
|
||||
("last-login" . ,(dm:field user "last-login"))))
|
||||
("created-date" . ,(cl-time-to-unix (dm:field user "created-date")))
|
||||
("last-login" . ,(cl-time-to-unix (dm:field user "last-login")))))
|
||||
users)))))
|
||||
(error (e)
|
||||
(api-output `(("status" . "error")
|
||||
|
|
|
|||
|
|
@ -57,9 +57,13 @@
|
|||
"</select>"
|
||||
"</td>"
|
||||
"<td>" (if (ps:@ user active) "✅ Active" "❌ Inactive") "</td>"
|
||||
"<td>" (if (ps:getprop user "last-login")
|
||||
(ps:chain (ps:new (-date (ps:getprop user "last-login"))) (to-locale-string))
|
||||
"Never") "</td>"
|
||||
"<td>" (let ((login-val (ps:getprop user "last-login")))
|
||||
(if login-val
|
||||
(let ((date-val (if (> login-val 9999999999)
|
||||
login-val ; Already milliseconds
|
||||
(* login-val 1000)))) ; Convert seconds to ms
|
||||
(ps:chain (ps:new (-date date-val)) (to-locale-string)))
|
||||
"Never")) "</td>"
|
||||
"<td class=\"user-actions\">"
|
||||
(if (ps:@ user active)
|
||||
(+ "<button class=\"btn btn-danger\" onclick=\"deactivateUser('" (ps:@ user id) "')\">Deactivate</button>")
|
||||
|
|
|
|||
|
|
@ -70,13 +70,14 @@
|
|||
(when (and (= 1 user-active)
|
||||
(verify-password password user-password))
|
||||
;; Update last login using data-model (database agnostic)
|
||||
;; Use ISO 8601 format that PostgreSQL TIMESTAMP can parse
|
||||
;; Use ISO 8601 format in UTC that PostgreSQL TIMESTAMP can parse
|
||||
(handler-case
|
||||
(progn
|
||||
(setf (dm:field user "last-login")
|
||||
(local-time:format-timestring nil (local-time:now)
|
||||
:format '(:year "-" (:month 2) "-" (:day 2) " "
|
||||
(:hour 2) ":" (:min 2) ":" (:sec 2))))
|
||||
(:hour 2) ":" (:min 2) ":" (:sec 2))
|
||||
:timezone local-time:+utc-zone+))
|
||||
(dm:save user))
|
||||
(error (e)
|
||||
(format t "Warning: Could not update last-login: ~a~%" e)))
|
||||
|
|
|
|||
Loading…
Reference in New Issue