229 lines
4.5 KiB
Go

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