diff --git a/backend/internal/api/auth.go b/backend/internal/api/auth.go index 9e0348b..f6ad350 100644 --- a/backend/internal/api/auth.go +++ b/backend/internal/api/auth.go @@ -359,23 +359,27 @@ func (h *AuthHandler) GetSessions(w http.ResponseWriter, r *http.Request) { defer rows.Close() type Session struct { - ID int64 `json:"id"` - UserAgent string `json:"user_agent"` - IP string `json:"ip"` - CreatedAt time.Time `json:"created_at"` - LastUsedAt *time.Time `json:"last_used_at"` - ExpiresAt time.Time `json:"expires_at"` + ID int64 `json:"id"` + UserAgent string `json:"user_agent"` + IP string `json:"ip"` + CreatedAt string `json:"created_at"` + LastUsedAt *string `json:"last_used_at"` + ExpiresAt string `json:"expires_at"` } sessions := []Session{} for rows.Next() { var s Session - var lastUsed sql.NullTime - if err := rows.Scan(&s.ID, &s.UserAgent, &s.IP, &s.CreatedAt, &lastUsed, &s.ExpiresAt); err != nil { + var createdAt, expiresAt sql.NullString + var lastUsedAt sql.NullString + if err := rows.Scan(&s.ID, &s.UserAgent, &s.IP, &createdAt, &lastUsedAt, &expiresAt); err != nil { + log.Printf("[GetSessions] scan error userID=%d: %v", claims.UserID, err) continue } - if lastUsed.Valid { - s.LastUsedAt = &lastUsed.Time + s.CreatedAt = createdAt.String + s.ExpiresAt = expiresAt.String + if lastUsedAt.Valid && lastUsedAt.String != "" { + s.LastUsedAt = &lastUsedAt.String } sessions = append(sessions, s) } diff --git a/frontend/js/app.js b/frontend/js/app.js index 82a47c3..dd903e7 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -686,9 +686,12 @@ document.addEventListener('alpine:init', () => { this.revoking = { ...this.revoking, [id]: false } }, - formatDate(iso) { - if (!iso) return '—' - const d = new Date(iso) + formatDate(raw) { + if (!raw) return '—' + // SQLite retourne "YYYY-MM-DD HH:MM:SS" ou RFC3339 selon le driver + // new Date() gère les deux si on normalise le séparateur + const d = new Date(raw.includes('T') ? raw : raw.replace(' ', 'T') + 'Z') + if (isNaN(d.getTime())) return raw return d.toLocaleString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) },