Moonshark/core/sessions/Manager.go
2025-04-05 22:26:01 -05:00

133 lines
3.2 KiB
Go

package sessions
import (
"crypto/rand"
"encoding/base64"
"sync"
"time"
"github.com/VictoriaMetrics/fastcache"
"github.com/goccy/go-json"
)
const (
// Default settings
DefaultMaxSize = 100 * 1024 * 1024 // 100MB default cache size
DefaultCookieName = "MSESSID"
DefaultCookiePath = "/"
DefaultMaxAge = 86400 // 1 day in seconds
)
// SessionManager handles multiple sessions using fastcache for storage
type SessionManager struct {
cache *fastcache.Cache
cookieName string
cookiePath string
cookieDomain string
cookieSecure bool
cookieHTTPOnly bool
cookieMaxAge int
mu sync.RWMutex // Only for cookie settings
}
// NewSessionManager creates a new session manager with optional cache size
func NewSessionManager(maxSize ...int) *SessionManager {
size := DefaultMaxSize
if len(maxSize) > 0 && maxSize[0] > 0 {
size = maxSize[0]
}
return &SessionManager{
cache: fastcache.New(size),
cookieName: DefaultCookieName,
cookiePath: DefaultCookiePath,
cookieHTTPOnly: true,
cookieMaxAge: DefaultMaxAge,
}
}
// generateSessionID creates a cryptographically secure random session ID
func generateSessionID() string {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
return time.Now().String() // Fallback
}
return base64.URLEncoding.EncodeToString(b)
}
// GetSession retrieves a session by ID, or creates a new one if it doesn't exist
func (sm *SessionManager) GetSession(id string) *Session {
// Check if session exists
data := sm.cache.Get(nil, []byte(id))
if len(data) > 0 {
// Session exists, unmarshal it
session := &Session{}
if err := json.Unmarshal(data, session); err == nil {
// Update last accessed time
session.UpdatedAt = time.Now()
// Store back with updated timestamp
updatedData, _ := json.Marshal(session)
sm.cache.Set([]byte(id), updatedData)
return session
}
}
// Create new session
session := NewSession(id)
data, _ = json.Marshal(session)
sm.cache.Set([]byte(id), data)
return session
}
// CreateSession generates a new session with a unique ID
func (sm *SessionManager) CreateSession() *Session {
id := generateSessionID()
// Create new session
session := NewSession(id)
data, _ := json.Marshal(session)
sm.cache.Set([]byte(id), data)
return session
}
// DestroySession removes a session
func (sm *SessionManager) DestroySession(id string) {
sm.cache.Del([]byte(id))
}
// CookieOptions returns the cookie options for this session manager
func (sm *SessionManager) CookieOptions() map[string]any {
sm.mu.RLock()
defer sm.mu.RUnlock()
return map[string]any{
"name": sm.cookieName,
"path": sm.cookiePath,
"domain": sm.cookieDomain,
"secure": sm.cookieSecure,
"http_only": sm.cookieHTTPOnly,
"max_age": sm.cookieMaxAge,
}
}
// SetCookieOptions configures cookie parameters
func (sm *SessionManager) SetCookieOptions(name, path, domain string, secure, httpOnly bool, maxAge int) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.cookieName = name
sm.cookiePath = path
sm.cookieDomain = domain
sm.cookieSecure = secure
sm.cookieHTTPOnly = httpOnly
sm.cookieMaxAge = maxAge
}
// GlobalSessionManager is the default session manager instance
var GlobalSessionManager = NewSessionManager()