package auth import ( "crypto/rand" "encoding/hex" "net/http" "sync" "time" ) // Session represents a user session type Session struct { ID string UserID uint Username string CreatedAt time.Time ExpiresAt time.Time } // SessionManager manages user sessions type SessionManager struct { sessions map[string]*Session mutex sync.RWMutex } // NewSessionManager creates a new session manager func NewSessionManager() *SessionManager { return &SessionManager{ sessions: make(map[string]*Session), } } // generateSessionID generates a random session ID func generateSessionID() string { bytes := make([]byte, 32) rand.Read(bytes) return hex.EncodeToString(bytes) } // CreateSession creates a new session for a user func (sm *SessionManager) CreateSession(userID int, username string) *Session { sm.mutex.Lock() defer sm.mutex.Unlock() // Clean up expired sessions sm.cleanupExpiredSessions() sessionID := generateSessionID() session := &Session{ ID: sessionID, UserID: uint(userID), Username: username, CreatedAt: time.Now(), ExpiresAt: time.Now().Add(24 * time.Hour), // 24 hours } sm.sessions[sessionID] = session return session } // GetSession retrieves a session by ID func (sm *SessionManager) GetSession(sessionID string) (*Session, bool) { sm.mutex.RLock() defer sm.mutex.RUnlock() session, exists := sm.sessions[sessionID] if !exists { return nil, false } // Check if session is expired if time.Now().After(session.ExpiresAt) { delete(sm.sessions, sessionID) return nil, false } return session, true } // DeleteSession deletes a session func (sm *SessionManager) DeleteSession(sessionID string) { sm.mutex.Lock() defer sm.mutex.Unlock() delete(sm.sessions, sessionID) } // cleanupExpiredSessions removes expired sessions func (sm *SessionManager) cleanupExpiredSessions() { now := time.Now() for id, session := range sm.sessions { if now.After(session.ExpiresAt) { delete(sm.sessions, id) } } } // SetSessionCookie sets a session cookie func SetSessionCookie(w http.ResponseWriter, sessionID string) { cookie := &http.Cookie{ Name: "session_id", Value: sessionID, Expires: time.Now().Add(24 * time.Hour), HttpOnly: true, Secure: false, // Set to true in production with HTTPS SameSite: http.SameSiteLaxMode, Path: "/", } http.SetCookie(w, cookie) } // GetSessionCookie gets the session ID from cookie func GetSessionCookie(r *http.Request) (string, error) { cookie, err := r.Cookie("session_id") if err != nil { return "", err } return cookie.Value, nil } // ClearSessionCookie clears the session cookie func ClearSessionCookie(w http.ResponseWriter) { cookie := &http.Cookie{ Name: "session_id", Value: "", Expires: time.Unix(0, 0), HttpOnly: true, Secure: false, // Set to true in production with HTTPS SameSite: http.SameSiteLaxMode, Path: "/", } http.SetCookie(w, cookie) }