package auth import ( "context" "errors" "time" "gorm.io/gorm" "ws_usernode/internal/model" "ws_usernode/internal/pkg" ) // 会话用户类型。 const ( SessionUserAdmin = "admin" SessionUserUser = "user" ) // Session 为一次会话的元数据(对 model.Session 的轻量封装)。 type Session struct { ID string UserType string RefID uint ExpireAt time.Time } // ErrSessionNotFound 表示会话不存在或已过期。 var ErrSessionNotFound = errors.New("auth: session not found") // SessionStore 为会话存储接口(DB 实现,兼容多实例)。 type SessionStore interface { Create(ctx context.Context, userType string, refID uint, ttl time.Duration, ip, userAgent string) (string, error) Get(ctx context.Context, sessionID string) (*Session, error) Delete(ctx context.Context, sessionID string) error } // DBSessionStore 基于 model.Session 的存储实现。 type DBSessionStore struct { db *gorm.DB } // NewDBSessionStore 创建会话存储。 func NewDBSessionStore(db *gorm.DB) *DBSessionStore { return &DBSessionStore{db: db} } func (s *DBSessionStore) Create(ctx context.Context, userType string, refID uint, ttl time.Duration, ip, userAgent string) (string, error) { id, err := pkg.RandomHex(24) if err != nil { return "", err } sess := model.Session{ ID: id, UserType: userType, RefID: refID, ExpireAt: time.Now().Add(ttl), IP: ip, UserAgent: userAgent, } if err := s.db.WithContext(ctx).Create(&sess).Error; err != nil { return "", err } return id, nil } func (s *DBSessionStore) Get(ctx context.Context, sessionID string) (*Session, error) { var m model.Session err := s.db.WithContext(ctx).First(&m, "id = ?", sessionID).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrSessionNotFound } return nil, err } if time.Now().After(m.ExpireAt) { return nil, ErrSessionNotFound } return &Session{ID: m.ID, UserType: m.UserType, RefID: m.RefID, ExpireAt: m.ExpireAt}, nil } func (s *DBSessionStore) Delete(ctx context.Context, sessionID string) error { return s.db.WithContext(ctx).Delete(&model.Session{}, "id = ?", sessionID).Error }