package wireguard import ( "context" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "git.netcell-it.de/projekte/edgeguard-native/internal/models" ) var ErrPeerNotFound = errors.New("wireguard peer not found") type PeersRepo struct { Pool *pgxpool.Pool } func NewPeersRepo(pool *pgxpool.Pool) *PeersRepo { return &PeersRepo{Pool: pool} } const peerBaseSelect = ` SELECT id, interface_id, name, public_key, private_key_enc, psk_enc, allowed_ips, keepalive, last_handshake, transfer_rx, transfer_tx, enabled, description, created_at, updated_at FROM wireguard_peers ` func (r *PeersRepo) ListForInterface(ctx context.Context, ifaceID int64) ([]models.WireguardPeer, error) { rows, err := r.Pool.Query(ctx, peerBaseSelect+" WHERE interface_id = $1 ORDER BY name ASC", ifaceID) if err != nil { return nil, err } defer rows.Close() out := make([]models.WireguardPeer, 0, 8) for rows.Next() { p, err := scanPeer(rows) if err != nil { return nil, err } out = append(out, *p) } return out, rows.Err() } func (r *PeersRepo) ListAll(ctx context.Context) ([]models.WireguardPeer, error) { rows, err := r.Pool.Query(ctx, peerBaseSelect+" ORDER BY interface_id, name ASC") if err != nil { return nil, err } defer rows.Close() out := make([]models.WireguardPeer, 0, 16) for rows.Next() { p, err := scanPeer(rows) if err != nil { return nil, err } out = append(out, *p) } return out, rows.Err() } func (r *PeersRepo) Get(ctx context.Context, id int64) (*models.WireguardPeer, error) { row := r.Pool.QueryRow(ctx, peerBaseSelect+" WHERE id = $1", id) p, err := scanPeer(row) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrPeerNotFound } return nil, err } return p, nil } func (r *PeersRepo) Create(ctx context.Context, p models.WireguardPeer) (*models.WireguardPeer, error) { row := r.Pool.QueryRow(ctx, ` INSERT INTO wireguard_peers ( interface_id, name, public_key, private_key_enc, psk_enc, allowed_ips, keepalive, enabled, description ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) RETURNING id, interface_id, name, public_key, private_key_enc, psk_enc, allowed_ips, keepalive, last_handshake, transfer_rx, transfer_tx, enabled, description, created_at, updated_at`, p.InterfaceID, p.Name, p.PublicKey, p.PrivateKeyEnc, p.PSKEnc, p.AllowedIPs, p.Keepalive, p.Enabled, p.Description) return scanPeer(row) } func (r *PeersRepo) Update(ctx context.Context, id int64, p models.WireguardPeer) (*models.WireguardPeer, error) { row := r.Pool.QueryRow(ctx, ` UPDATE wireguard_peers SET name = $1, public_key = $2, private_key_enc = $3, psk_enc = $4, allowed_ips = $5, keepalive = $6, enabled = $7, description = $8, updated_at = NOW() WHERE id = $9 RETURNING id, interface_id, name, public_key, private_key_enc, psk_enc, allowed_ips, keepalive, last_handshake, transfer_rx, transfer_tx, enabled, description, created_at, updated_at`, p.Name, p.PublicKey, p.PrivateKeyEnc, p.PSKEnc, p.AllowedIPs, p.Keepalive, p.Enabled, p.Description, id) out, err := scanPeer(row) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrPeerNotFound } return nil, err } return out, nil } func (r *PeersRepo) Delete(ctx context.Context, id int64) error { tag, err := r.Pool.Exec(ctx, `DELETE FROM wireguard_peers WHERE id = $1`, id) if err != nil { return err } if tag.RowsAffected() == 0 { return ErrPeerNotFound } return nil } func scanPeer(row interface{ Scan(...any) error }) (*models.WireguardPeer, error) { var p models.WireguardPeer if err := row.Scan( &p.ID, &p.InterfaceID, &p.Name, &p.PublicKey, &p.PrivateKeyEnc, &p.PSKEnc, &p.AllowedIPs, &p.Keepalive, &p.LastHandshake, &p.TransferRX, &p.TransferTX, &p.Enabled, &p.Description, &p.CreatedAt, &p.UpdatedAt, ); err != nil { return nil, err } p.HasPrivateKey = len(p.PrivateKeyEnc) > 0 return &p, nil }