package firewall import ( "context" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "git.netcell-it.de/projekte/edgeguard-native/internal/models" ) var ErrRuleNotFound = errors.New("firewall rule not found") type RulesRepo struct { Pool *pgxpool.Pool } func NewRulesRepo(pool *pgxpool.Pool) *RulesRepo { return &RulesRepo{Pool: pool} } const ruleBaseSelect = ` SELECT id, name, priority, enabled, action, src_zone, src_address_object_id, src_address_group_id, src_cidr, dst_zone, dst_address_object_id, dst_address_group_id, dst_cidr, service_object_id, service_group_id, log, comment, created_at, updated_at FROM firewall_rules ` func (r *RulesRepo) List(ctx context.Context) ([]models.FirewallRule, error) { rows, err := r.Pool.Query(ctx, ruleBaseSelect+" ORDER BY priority DESC, id ASC") if err != nil { return nil, err } defer rows.Close() out := make([]models.FirewallRule, 0, 16) for rows.Next() { x, err := scanRule(rows) if err != nil { return nil, err } out = append(out, *x) } return out, rows.Err() } func (r *RulesRepo) Get(ctx context.Context, id int64) (*models.FirewallRule, error) { row := r.Pool.QueryRow(ctx, ruleBaseSelect+" WHERE id = $1", id) x, err := scanRule(row) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrRuleNotFound } return nil, err } return x, nil } func (r *RulesRepo) Create(ctx context.Context, x models.FirewallRule) (*models.FirewallRule, error) { row := r.Pool.QueryRow(ctx, ` INSERT INTO firewall_rules ( name, priority, enabled, action, src_zone, src_address_object_id, src_address_group_id, src_cidr, dst_zone, dst_address_object_id, dst_address_group_id, dst_cidr, service_object_id, service_group_id, log, comment ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16 ) RETURNING id, name, priority, enabled, action, src_zone, src_address_object_id, src_address_group_id, src_cidr, dst_zone, dst_address_object_id, dst_address_group_id, dst_cidr, service_object_id, service_group_id, log, comment, created_at, updated_at`, x.Name, x.Priority, x.Enabled, x.Action, x.SrcZone, x.SrcAddressObjectID, x.SrcAddressGroupID, x.SrcCIDR, x.DstZone, x.DstAddressObjectID, x.DstAddressGroupID, x.DstCIDR, x.ServiceObjectID, x.ServiceGroupID, x.Log, x.Comment) return scanRule(row) } func (r *RulesRepo) Update(ctx context.Context, id int64, x models.FirewallRule) (*models.FirewallRule, error) { row := r.Pool.QueryRow(ctx, ` UPDATE firewall_rules SET name = $1, priority = $2, enabled = $3, action = $4, src_zone = $5, src_address_object_id = $6, src_address_group_id = $7, src_cidr = $8, dst_zone = $9, dst_address_object_id = $10, dst_address_group_id = $11, dst_cidr = $12, service_object_id = $13, service_group_id = $14, log = $15, comment = $16, updated_at = NOW() WHERE id = $17 RETURNING id, name, priority, enabled, action, src_zone, src_address_object_id, src_address_group_id, src_cidr, dst_zone, dst_address_object_id, dst_address_group_id, dst_cidr, service_object_id, service_group_id, log, comment, created_at, updated_at`, x.Name, x.Priority, x.Enabled, x.Action, x.SrcZone, x.SrcAddressObjectID, x.SrcAddressGroupID, x.SrcCIDR, x.DstZone, x.DstAddressObjectID, x.DstAddressGroupID, x.DstCIDR, x.ServiceObjectID, x.ServiceGroupID, x.Log, x.Comment, id) out, err := scanRule(row) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrRuleNotFound } return nil, err } return out, nil } func (r *RulesRepo) Delete(ctx context.Context, id int64) error { tag, err := r.Pool.Exec(ctx, `DELETE FROM firewall_rules WHERE id = $1`, id) if err != nil { return err } if tag.RowsAffected() == 0 { return ErrRuleNotFound } return nil } func scanRule(row interface{ Scan(...any) error }) (*models.FirewallRule, error) { var x models.FirewallRule if err := row.Scan( &x.ID, &x.Name, &x.Priority, &x.Enabled, &x.Action, &x.SrcZone, &x.SrcAddressObjectID, &x.SrcAddressGroupID, &x.SrcCIDR, &x.DstZone, &x.DstAddressObjectID, &x.DstAddressGroupID, &x.DstCIDR, &x.ServiceObjectID, &x.ServiceGroupID, &x.Log, &x.Comment, &x.CreatedAt, &x.UpdatedAt, ); err != nil { return nil, err } return &x, nil }