Files
domrichardson 6e642da57a
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m27s
fix: fixes to session storage
2026-03-26 10:06:07 +00:00

115 lines
2.3 KiB
Go

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
}