package db import ( "database/sql" "github.com/bluesky-social/indigo/atproto/syntax" ) // bans match either the repo or owner did type BanEntry struct { SubjectDid syntax.DID CreatedAt string } func (d *DB) PutBan(ban BanEntry) error { _, err := d.Exec( `insert into bans (subject_did) values (?) on conflict(subject_did) do nothing`, ban.SubjectDid.String(), ) return err } func (d *DB) DeleteBan(subject syntax.DID) (bool, error) { res, err := d.Exec(`delete from bans where subject_did = ?`, subject.String()) if err != nil { return false, err } n, err := res.RowsAffected() return n > 0, err } func (d *DB) GetBan(subject syntax.DID) (*BanEntry, error) { row := d.QueryRow( `select subject_did, created_at from bans where subject_did = ?`, subject.String(), ) return scanBan(row) } func (d *DB) BanList() ([]BanEntry, error) { rows, err := d.Query(`select subject_did, created_at from bans order by subject_did`) if err != nil { return nil, err } defer rows.Close() var bans []BanEntry for rows.Next() { b, err := scanBan(rows) if err != nil { return nil, err } bans = append(bans, *b) } return bans, rows.Err() } // check both roles for a preemptive ban func (d *DB) IsBanned(repoDid, ownerDid syntax.DID) (*BanEntry, error) { row := d.QueryRow( `select subject_did, created_at from bans where subject_did in (?, ?) limit 1`, repoDid.String(), ownerDid.String(), ) return scanBan(row) } func scanBan(row interface{ Scan(...any) error }) (*BanEntry, error) { var b BanEntry var subject string if err := row.Scan(&subject, &b.CreatedAt); err != nil { if err == sql.ErrNoRows { return nil, nil } return nil, err } b.SubjectDid = syntax.DID(subject) return &b, nil }