package session import ( "dk/internal/cookies" "dk/internal/router" "time" ) const SessionCookieName = "dk_session" var Manager *SessionManager type SessionManager struct { store *Store } func Init(sessionsFilePath string) { if Manager != nil { panic("session manager already initialized") } Manager = &SessionManager{ store: NewStore(sessionsFilePath), } } func GetManager() *SessionManager { if Manager == nil { panic("session manager not initialized") } return Manager } func (sm *SessionManager) Create(userID int, username, email string) *Session { sess := New(userID, username, email) sm.store.Save(sess) return sess } func (sm *SessionManager) Get(sessionID string) (*Session, bool) { return sm.store.Get(sessionID) } func (sm *SessionManager) GetFromContext(ctx router.Ctx) (*Session, bool) { sessionID := cookies.GetCookie(ctx, SessionCookieName) if sessionID == "" { return nil, false } return sm.Get(sessionID) } func (sm *SessionManager) Update(sessionID string) bool { sess, exists := sm.store.Get(sessionID) if !exists { return false } sess.Touch() sm.store.Save(sess) return true } func (sm *SessionManager) Delete(sessionID string) { sm.store.Delete(sessionID) } func (sm *SessionManager) SetSessionCookie(ctx router.Ctx, sessionID string) { cookies.SetSecureCookie(ctx, cookies.CookieOptions{ Name: SessionCookieName, Value: sessionID, Path: "/", Expires: time.Now().Add(DefaultExpiration), HTTPOnly: true, Secure: cookies.IsHTTPS(ctx), SameSite: "lax", }) } func (sm *SessionManager) DeleteSessionCookie(ctx router.Ctx) { cookies.DeleteCookie(ctx, SessionCookieName) } func (sm *SessionManager) SetFlashMessage(ctx router.Ctx, msgType, message string) bool { sess, exists := sm.GetFromContext(ctx) if !exists { return false } sess.SetFlash("message", FlashMessage{ Type: msgType, Message: message, }) sm.store.Save(sess) return true } func (sm *SessionManager) GetFlashMessage(ctx router.Ctx) *FlashMessage { sess, exists := sm.GetFromContext(ctx) if !exists { return nil } value, exists := sess.GetFlash("message") if !exists { return nil } sm.store.Save(sess) if msg, ok := value.(FlashMessage); ok { return &msg } if msgMap, ok := value.(map[string]interface{}); ok { msg := &FlashMessage{} if t, ok := msgMap["type"].(string); ok { msg.Type = t } if m, ok := msgMap["message"].(string); ok { msg.Message = m } return msg } return nil } func (sm *SessionManager) SetFormData(ctx router.Ctx, data map[string]string) bool { sess, exists := sm.GetFromContext(ctx) if !exists { return false } sess.Set("form_data", data) sm.store.Save(sess) return true } func (sm *SessionManager) GetFormData(ctx router.Ctx) map[string]string { sess, exists := sm.GetFromContext(ctx) if !exists { return nil } value, exists := sess.Get("form_data") if !exists { return nil } sess.Delete("form_data") sm.store.Save(sess) if formData, ok := value.(map[string]string); ok { return formData } if formMap, ok := value.(map[string]interface{}); ok { result := make(map[string]string) for k, v := range formMap { if str, ok := v.(string); ok { result[k] = str } } return result } return nil } func (sm *SessionManager) Stats() (total, active int) { return sm.store.Stats() } func (sm *SessionManager) Close() error { return sm.store.Close() } // Package-level convenience functions that use the global Manager func Create(userID int, username, email string) *Session { return Manager.Create(userID, username, email) } func Get(sessionID string) (*Session, bool) { return Manager.Get(sessionID) } func GetFromContext(ctx router.Ctx) (*Session, bool) { return Manager.GetFromContext(ctx) } func Update(sessionID string) bool { return Manager.Update(sessionID) } func Delete(sessionID string) { Manager.Delete(sessionID) } func SetSessionCookie(ctx router.Ctx, sessionID string) { Manager.SetSessionCookie(ctx, sessionID) } func DeleteSessionCookie(ctx router.Ctx) { Manager.DeleteSessionCookie(ctx) } func SetFlashMessage(ctx router.Ctx, msgType, message string) bool { return Manager.SetFlashMessage(ctx, msgType, message) } func GetFlashMessage(ctx router.Ctx) *FlashMessage { return Manager.GetFlashMessage(ctx) } func SetFormData(ctx router.Ctx, data map[string]string) bool { return Manager.SetFormData(ctx, data) } func GetFormData(ctx router.Ctx) map[string]string { return Manager.GetFormData(ctx) } func Stats() (total, active int) { return Manager.Stats() } func Close() error { return Manager.Close() }