Files
2025-07-07 01:44:12 +02:00

134 lines
2.9 KiB
Go

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)
}