diff --git a/auth-routes.lisp b/auth-routes.lisp
index 406915f..0734465 100644
--- a/auth-routes.lisp
+++ b/auth-routes.lisp
@@ -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")
diff --git a/parenscript/users.lisp b/parenscript/users.lisp
index a2c5971..ffeca08 100644
--- a/parenscript/users.lisp
+++ b/parenscript/users.lisp
@@ -57,9 +57,13 @@
""
""
"
" (if (ps:@ user active) "✅ Active" "❌ Inactive") " | "
- "" (if (ps:getprop user "last-login")
- (ps:chain (ps:new (-date (ps:getprop user "last-login"))) (to-locale-string))
- "Never") " | "
+ "" (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")) " | "
""
(if (ps:@ user active)
(+ "")
diff --git a/user-management.lisp b/user-management.lisp
index 4f23df6..d579a0a 100644
--- a/user-management.lisp
+++ b/user-management.lisp
@@ -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)))
|