Monorepo for Tangled
Something went wrong. Try again.
3.7 kB · 173 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174package db
import ( "database/sql" "log/slog" "strconv" "time"
"github.com/bluesky-social/indigo/atproto/syntax" "tangled.org/core/api/tangled")
type PublicKey struct { Did syntax.DID Rkey syntax.RecordKey tangled.PublicKey}
func (d *DB) UpsertPublicKey(pk PublicKey) error { tx, err := d.db.Begin() if err != nil { return err } defer tx.Rollback()
if pk.Rkey != "" { if _, err := tx.Exec(`delete from public_keys where did = ? and rkey = ?`, pk.Did, pk.Rkey); err != nil { return err } }
if err := insertPublicKey(tx, d.logger, pk); err != nil { return err }
return tx.Commit()}
func insertPublicKey(tx *sql.Tx, logger *slog.Logger, pk PublicKey) error { if pk.Key == "" { logger.Warn("skipping public key with empty key value", "did", pk.Did, "rkey", pk.Rkey) return nil }
if pk.CreatedAt == "" { pk.CreatedAt = time.Now().Format(time.RFC3339) }
res, err := tx.Exec( `insert or ignore into public_keys (did, key, rkey, created) values (?, ?, ?, ?)`, pk.Did, pk.Key, pk.Rkey, pk.CreatedAt, ) if err != nil { return err }
if rows, err := res.RowsAffected(); err == nil && rows == 0 { logger.Warn("public key not stored, already registered to another did", "did", pk.Did, "rkey", pk.Rkey) }
return nil}
func (d *DB) DeletePublicKeyByRkey(did syntax.DID, rkey syntax.RecordKey) error { if rkey == "" { return nil }
query := `delete from public_keys where did = ? and rkey = ?` _, err := d.db.Exec(query, did, rkey) return err}
func (d *DB) ReplacePublicKeys(did syntax.DID, keys []PublicKey) error { tx, err := d.db.Begin() if err != nil { return err } defer tx.Rollback()
if _, err := tx.Exec(`delete from public_keys where did = ?`, did); err != nil { return err }
if err := insertPublicKeys(tx, d.logger, keys); err != nil { return err }
return tx.Commit()}
func insertPublicKeys(tx *sql.Tx, logger *slog.Logger, keys []PublicKey) error { if len(keys) == 0 { return nil }
if err := insertPublicKey(tx, logger, keys[0]); err != nil { return err }
return insertPublicKeys(tx, logger, keys[1:])}
func (pk *PublicKey) JSON() map[string]any { return map[string]any{ "did": pk.Did, "key": pk.Key, "createdAt": pk.CreatedAt, }}
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) { var keys []PublicKey
rows, err := d.db.Query(`select key, did, created from public_keys`) if err != nil { return nil, err } defer rows.Close()
for rows.Next() { var publicKey PublicKey if err := rows.Scan(&publicKey.Key, &publicKey.Did, &publicKey.CreatedAt); err != nil { return nil, err } keys = append(keys, publicKey) }
if err := rows.Err(); err != nil { return nil, err }
return keys, nil}
func (d *DB) GetPublicKeysPaginated(limit int, cursor string) ([]PublicKey, string, error) { var keys []PublicKey
offset := 0 if cursor != "" { if o, err := strconv.Atoi(cursor); err == nil && o >= 0 { offset = o } }
query := `select key, did, created from public_keys order by created desc limit ? offset ?` rows, err := d.db.Query(query, limit+1, offset) // +1 to check if there are more results if err != nil { return nil, "", err } defer rows.Close()
for rows.Next() { var publicKey PublicKey if err := rows.Scan(&publicKey.Key, &publicKey.Did, &publicKey.CreatedAt); err != nil { return nil, "", err } keys = append(keys, publicKey) }
if err := rows.Err(); err != nil { return nil, "", err }
// check if there are more results for pagination var nextCursor string if len(keys) > limit { keys = keys[:limit] // remove the extra item nextCursor = strconv.Itoa(offset + limit) }
return keys, nextCursor, nil}