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