this repo has no description
1package db
2
3import (
4 "database/sql"
5 "fmt"
6 "log"
7
8 "github.com/google/uuid"
9 _ "github.com/mattn/go-sqlite3"
10)
11
12type DB struct {
13 db *sql.DB
14}
15
16func Make(dbPath string) (*DB, error) {
17 db, err := sql.Open("sqlite3", dbPath)
18 if err != nil {
19 return nil, err
20 }
21 _, err = db.Exec(`
22 create table if not exists registrations (
23 id integer primary key autoincrement,
24 domain text not null unique,
25 did text not null,
26 secret text not null,
27 created integer default (strftime('%s', 'now')),
28 registered integer
29 );
30 `)
31 if err != nil {
32 return nil, err
33 }
34 return &DB{db: db}, nil
35}
36
37type RegStatus uint32
38
39const (
40 Registered RegStatus = iota
41 Unregistered
42 Pending
43)
44
45// returns registered status, did of owner, error
46func (d *DB) RegistrationStatus(domain string) (RegStatus, string, error) {
47 var registeredBy string
48 var registratedAt *uint64
49 err := d.db.QueryRow(`
50 select did, registered from registrations
51 where domain = ?
52 `, domain).Scan(®isteredBy, ®istratedAt)
53 if err != nil {
54 if err == sql.ErrNoRows {
55 return Unregistered, "", nil
56 } else {
57 return Unregistered, "", err
58 }
59 }
60
61 if registratedAt != nil {
62 return Registered, registeredBy, nil
63 } else {
64 return Pending, registeredBy, nil
65 }
66}
67
68func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) {
69 // sanity check: does this domain already have a registration?
70 status, owner, err := d.RegistrationStatus(domain)
71 if err != nil {
72 return "", err
73 }
74 switch status {
75 case Registered:
76 // already registered by `owner`
77 return "", fmt.Errorf("%s already registered by %s", domain, owner)
78 case Pending:
79 log.Printf("%s registered by %s, status pending", domain, owner)
80 // TODO: provide a warning here, and allow the current user to overwrite
81 // the registration, this prevents users from registering domains that they
82 // do not own
83 default:
84 // ok, we can register this domain
85 }
86
87 secret := uuid.New().String()
88
89 if err != nil {
90 return "", err
91 }
92
93 _, err = d.db.Exec(`
94 insert into registrations (domain, did, secret)
95 values (?, ?, ?)
96 on conflict(domain) do update set did = excluded.did, secret = excluded.secret
97 `, domain, did, secret)
98
99 if err != nil {
100 return "", err
101 }
102
103 return secret, nil
104}
105
106func (d *DB) GetRegistrationKey(domain string) (string, error) {
107 res := d.db.QueryRow(`select secret from registrations where domain = ?`, domain)
108
109 var secret string
110 err := res.Scan(&secret)
111 if err != nil {
112 return "", nil
113 }
114
115 return secret, nil
116}
117
118func (d *DB) Register(domain string) error {
119 _, err := d.db.Exec(`
120 update registrations
121 set registered = strftime('%s', 'now')
122 where domain = ?;
123 `, domain)
124
125 if err != nil {
126 return err
127 }
128
129 return nil
130}
131
132// type Registration struct {
133// status RegStatus
134// }
135// func (d *DB) RegistrationsForDid(did string) ()