package store import ( "context" "errors" "fmt" "time" "github.com/jackc/pgx/v5" "github.com/shcizo/package-updater/internal/master/model" ) // CreateSession stores a new session and deletes expired ones, so the table // never grows without bound. func (s *Store) CreateSession(ctx context.Context, sess model.Session) error { if _, err := s.pool.Exec(ctx, `DELETE FROM sessions WHERE expires_at < now()`); err != nil { return fmt.Errorf("delete expired sessions: %w", err) } if _, err := s.pool.Exec(ctx, `INSERT INTO sessions (id, subject, name, email, csrf_token, expires_at) VALUES ($1, $2, $3, $4, $5, $6)`, sess.ID, sess.Subject, sess.Name, sess.Email, sess.CSRFToken, sess.ExpiresAt); err != nil { return fmt.Errorf("create session: %w", err) } return nil } // GetSession returns the session unless it is missing or expired at now, // in which case it returns model.ErrNotFound. func (s *Store) GetSession(ctx context.Context, id string, now time.Time) (model.Session, error) { var m model.Session err := s.pool.QueryRow(ctx, `SELECT id, subject, name, email, csrf_token, expires_at FROM sessions WHERE id = $1 AND expires_at > $2`, id, now).Scan(&m.ID, &m.Subject, &m.Name, &m.Email, &m.CSRFToken, &m.ExpiresAt) if errors.Is(err, pgx.ErrNoRows) { return model.Session{}, model.ErrNotFound } if err != nil { return model.Session{}, fmt.Errorf("get session: %w", err) } return m, nil } // DeleteSession removes a session (logout). func (s *Store) DeleteSession(ctx context.Context, id string) error { if _, err := s.pool.Exec(ctx, `DELETE FROM sessions WHERE id = $1`, id); err != nil { return fmt.Errorf("delete session: %w", err) } return nil }