package auth import ( "context" "encoding/json" "errors" "time" "github.com/redis/go-redis/v9" ) // SessionData stores authenticated identity data in Redis. type SessionData struct { UserID string `json:"user_id"` Email string `json:"email"` Username string `json:"username"` } // SessionManager handles Redis-backed session lifecycle operations. type SessionManager struct { redis *redis.Client ttl time.Duration prefix string } func NewSessionManager(redisClient *redis.Client, ttl time.Duration) *SessionManager { if ttl <= 0 { ttl = 7 * 24 * time.Hour } return &SessionManager{ redis: redisClient, ttl: ttl, prefix: "session:", } } func (m *SessionManager) TTL() time.Duration { return m.ttl } func (m *SessionManager) CreateSession(ctx context.Context, data *SessionData) (string, error) { if data == nil { return "", errors.New("session data is required") } sessionID, err := GenerateRandomToken(32) if err != nil { return "", err } payload, err := json.Marshal(data) if err != nil { return "", err } if err := m.redis.Set(ctx, m.key(sessionID), payload, m.ttl).Err(); err != nil { return "", err } return sessionID, nil } func (m *SessionManager) GetSession(ctx context.Context, sessionID string) (*SessionData, error) { if sessionID == "" { return nil, errors.New("session id is required") } payload, err := m.redis.Get(ctx, m.key(sessionID)).Result() if err != nil { if errors.Is(err, redis.Nil) { return nil, errors.New("session not found") } return nil, err } var data SessionData if err := json.Unmarshal([]byte(payload), &data); err != nil { return nil, err } return &data, nil } func (m *SessionManager) RefreshSession(ctx context.Context, sessionID string) error { if sessionID == "" { return errors.New("session id is required") } if err := m.redis.Expire(ctx, m.key(sessionID), m.ttl).Err(); err != nil { if errors.Is(err, redis.Nil) { return errors.New("session not found") } return err } return nil } func (m *SessionManager) DeleteSession(ctx context.Context, sessionID string) error { if sessionID == "" { return nil } if err := m.redis.Del(ctx, m.key(sessionID)).Err(); err != nil { return err } return nil } func (m *SessionManager) key(sessionID string) string { return m.prefix + sessionID }