From 0f0486d8d48036ae4aa1d124100708e5f9d0dc04 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 19 Mar 2026 14:01:59 -0400 Subject: [PATCH] fix: resolve user dashboard field mapping and session consistency Added JSON tags to the User struct to match frontend expectations and excluded sensitive fields. Updated session management to include and persist DisplayName. Unified user field names (using display_name) across backend, sessions, and frontend UI. --- internal/db/db.go | 14 +++++------ internal/server/dashboard.go | 23 ++++++++---------- internal/server/sessions.go | 46 ++++++++++++++++++++---------------- static/js/auth.js | 2 +- 4 files changed, 43 insertions(+), 42 deletions(-) diff --git a/internal/db/db.go b/internal/db/db.go index a82a63bd..292f2b30 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -244,13 +244,13 @@ type ModelConfig struct { } type User struct { - ID int `db:"id"` - Username string `db:"username"` - PasswordHash string `db:"password_hash"` - DisplayName *string `db:"display_name"` - Role string `db:"role"` - MustChangePassword bool `db:"must_change_password"` - CreatedAt time.Time `db:"created_at"` + ID int `db:"id" json:"id"` + Username string `db:"username" json:"username"` + PasswordHash string `db:"password_hash" json:"-"` + DisplayName *string `db:"display_name" json:"display_name"` + Role string `db:"role" json:"role"` + MustChangePassword bool `db:"must_change_password" json:"must_change_password"` + CreatedAt time.Time `db:"created_at" json:"created_at"` } type ClientToken struct { diff --git a/internal/server/dashboard.go b/internal/server/dashboard.go index 78fe1080..f97bdf05 100644 --- a/internal/server/dashboard.go +++ b/internal/server/dashboard.go @@ -83,25 +83,21 @@ func (s *Server) handleLogin(c *gin.Context) { return } - token, err := s.sessions.CreateSession(user.Username, user.Role) - if err != nil { - c.JSON(http.StatusInternalServerError, ErrorResponse("Failed to create session")) - return - } - displayName := user.Username if user.DisplayName != nil { displayName = *user.DisplayName } + token, err := s.sessions.CreateSession(user.Username, displayName, user.Role) + if err != nil { + c.JSON(http.StatusInternalServerError, ErrorResponse("Failed to create session")) + return + } + c.JSON(http.StatusOK, SuccessResponse(gin.H{ "token": token, "must_change_password": user.MustChangePassword, - "user": gin.H{ - "username": user.Username, - "name": displayName, - "role": user.Role, - }, + "user": user, })) } @@ -116,8 +112,9 @@ func (s *Server) handleAuthStatus(c *gin.Context) { c.JSON(http.StatusOK, SuccessResponse(gin.H{ "authenticated": true, "user": gin.H{ - "username": session.Username, - "role": session.Role, + "username": session.Username, + "role": session.Role, + "display_name": session.DisplayName, }, })) } diff --git a/internal/server/sessions.go b/internal/server/sessions.go index 0d4065da..39975de6 100644 --- a/internal/server/sessions.go +++ b/internal/server/sessions.go @@ -14,11 +14,12 @@ import ( ) type Session struct { - Username string `json:"username"` - Role string `json:"role"` - CreatedAt time.Time `json:"created_at"` - ExpiresAt time.Time `json:"expires_at"` - SessionID string `json:"session_id"` + Username string `json:"username"` + DisplayName string `json:"display_name"` + Role string `json:"role"` + CreatedAt time.Time `json:"created_at"` + ExpiresAt time.Time `json:"expires_at"` + SessionID string `json:"session_id"` } type SessionManager struct { @@ -29,10 +30,11 @@ type SessionManager struct { } type sessionPayload struct { - SessionID string `json:"session_id"` - Username string `json:"username"` - Role string `json:"role"` - Exp int64 `json:"exp"` + SessionID string `json:"session_id"` + Username string `json:"username"` + DisplayName string `json:"display_name"` + Role string `json:"role"` + Exp int64 `json:"exp"` } func NewSessionManager(secret []byte, ttl time.Duration) *SessionManager { @@ -43,30 +45,32 @@ func NewSessionManager(secret []byte, ttl time.Duration) *SessionManager { } } -func (m *SessionManager) CreateSession(username, role string) (string, error) { +func (m *SessionManager) CreateSession(username, displayName, role string) (string, error) { sessionID := uuid.New().String() now := time.Now() expiresAt := now.Add(m.ttl) m.mu.Lock() m.sessions[sessionID] = Session{ - Username: username, - Role: role, - CreatedAt: now, - ExpiresAt: expiresAt, - SessionID: sessionID, + Username: username, + DisplayName: displayName, + Role: role, + CreatedAt: now, + ExpiresAt: expiresAt, + SessionID: sessionID, } m.mu.Unlock() - return m.createSignedToken(sessionID, username, role, expiresAt.Unix()) + return m.createSignedToken(sessionID, username, displayName, role, expiresAt.Unix()) } -func (m *SessionManager) createSignedToken(sessionID, username, role string, exp int64) (string, error) { +func (m *SessionManager) createSignedToken(sessionID, username, displayName, role string, exp int64) (string, error) { payload := sessionPayload{ - SessionID: sessionID, - Username: username, - Role: role, - Exp: exp, + SessionID: sessionID, + Username: username, + DisplayName: displayName, + Role: role, + Exp: exp, } payloadJSON, err := json.Marshal(payload) diff --git a/static/js/auth.js b/static/js/auth.js index 060a9c0e..29ce4dc9 100644 --- a/static/js/auth.js +++ b/static/js/auth.js @@ -167,7 +167,7 @@ class AuthManager { const userRoleElement = document.querySelector('.user-role'); if (userNameElement && this.user) { - userNameElement.textContent = this.user.name || this.user.username || 'User'; + userNameElement.textContent = this.user.display_name || this.user.username || 'User'; } if (userRoleElement && this.user) {