package store import ( "context" "errors" "github.com/jackc/pgx/v5" "git.unkin.net/unkin/tomswallapi/internal/model" ) // ---- Secmarks -------------------------------------------------------------- func (s *Store) ListSecmarks(ctx context.Context) ([]model.SecmarkRule, error) { rows, err := s.pool.Query(ctx, `SELECT id, secmark, chain, source, dest, proto, dport, sport, comment FROM secmarks ORDER BY id`) if err != nil { return nil, err } defer rows.Close() var out []model.SecmarkRule for rows.Next() { r, err := scanSecmark(rows) if err != nil { return nil, err } out = append(out, r) } return out, rows.Err() } func (s *Store) GetSecmark(ctx context.Context, id int64) (model.SecmarkRule, error) { rows, err := s.pool.Query(ctx, `SELECT id, secmark, chain, source, dest, proto, dport, sport, comment FROM secmarks WHERE id = $1`, id) if err != nil { return model.SecmarkRule{}, err } defer rows.Close() if !rows.Next() { return model.SecmarkRule{}, ErrNotFound } return scanSecmark(rows) } func scanSecmark(rows pgx.Rows) (model.SecmarkRule, error) { var r model.SecmarkRule var dport, sport []byte if err := rows.Scan(&r.ID, &r.Secmark, &r.Chain, &r.Source, &r.Dest, &r.Proto, &dport, &sport, &r.Comment); err != nil { return r, err } if err := unmarshalStrings(dport, &r.DPort); err != nil { return r, err } return r, unmarshalStrings(sport, &r.SPort) } func (s *Store) CreateSecmark(ctx context.Context, r model.SecmarkRule) (int64, error) { dport, _ := jsonb(r.DPort) sport, _ := jsonb(r.SPort) var id int64 err := pgx.BeginFunc(ctx, s.pool, func(tx pgx.Tx) error { if err := tx.QueryRow(ctx, ` INSERT INTO secmarks (secmark, chain, source, dest, proto, dport, sport, comment) VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING id`, r.Secmark, r.Chain, r.Source, r.Dest, r.Proto, dport, sport, r.Comment).Scan(&id); err != nil { return err } return bump(ctx, tx) }) return id, err } func (s *Store) DeleteSecmark(ctx context.Context, id int64) error { return s.deleteOne(ctx, `DELETE FROM secmarks WHERE id = $1`, id) } // ---- Vars (key-keyed) ------------------------------------------------------ func (s *Store) ListVars(ctx context.Context) ([]model.Var, error) { rows, err := s.pool.Query(ctx, `SELECT key, value FROM vars ORDER BY key`) if err != nil { return nil, err } defer rows.Close() var out []model.Var for rows.Next() { var v model.Var if err := rows.Scan(&v.Key, &v.Value); err != nil { return nil, err } out = append(out, v) } return out, rows.Err() } func (s *Store) GetVar(ctx context.Context, key string) (model.Var, error) { var v model.Var err := s.pool.QueryRow(ctx, `SELECT key, value FROM vars WHERE key = $1`, key).Scan(&v.Key, &v.Value) if errors.Is(err, pgx.ErrNoRows) { return v, ErrNotFound } return v, err } func (s *Store) UpsertVar(ctx context.Context, v model.Var) error { return pgx.BeginFunc(ctx, s.pool, func(tx pgx.Tx) error { if _, err := tx.Exec(ctx, `INSERT INTO vars (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`, v.Key, v.Value); err != nil { return err } return bump(ctx, tx) }) } func (s *Store) DeleteVar(ctx context.Context, key string) error { return s.deleteOne(ctx, `DELETE FROM vars WHERE key = $1`, key) }