51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
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
|
|
}
|