this repo has no description
1package db 2 3import ( 4 "database/sql" 5 "fmt" 6 "log" 7 "time" 8 9 "github.com/google/uuid" 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 timestamp default current_timestamp, 29 registered timestamp); 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 Registration struct { 46 Domain string 47 ByDid string 48 Created *time.Time 49 Registered *time.Time 50} 51 52func (r *Registration) Status() Status { 53 if r.Registered != nil { 54 return Registered 55 } else { 56 return Pending 57 } 58} 59 60type Status uint32 61 62const ( 63 Registered Status = iota 64 Pending 65) 66 67// returns registered status, did of owner, error 68func (d *DB) RegistrationsByDid(did string) ([]Registration, error) { 69 var registrations []Registration 70 71 rows, err := d.db.Query(` 72 select domain, did, created, registered from registrations 73 where did = ? 74 `, did) 75 if err != nil { 76 return nil, err 77 } 78 79 for rows.Next() { 80 var createdAt *int64 81 var registeredAt *int64 82 var registration Registration 83 err = rows.Scan(&registration.Domain, &registration.ByDid, &createdAt, &registeredAt) 84 85 if err != nil { 86 log.Println(err) 87 } else { 88 createdAtTime := time.Unix(*createdAt, 0) 89 90 var registeredAtTime *time.Time 91 if registeredAt != nil { 92 x := time.Unix(*registeredAt, 0) 93 registeredAtTime = &x 94 } 95 96 registration.Created = &createdAtTime 97 registration.Registered = registeredAtTime 98 registrations = append(registrations, registration) 99 } 100 } 101 102 return registrations, nil 103} 104 105// returns registered status, did of owner, error 106func (d *DB) RegistrationByDomain(domain string) (*Registration, error) { 107 var createdAt *int64 108 var registeredAt *int64 109 var registration Registration 110 111 err := d.db.QueryRow(` 112 select domain, did, created, registered from registrations 113 where domain = ? 114 `, domain).Scan(&registration.Domain, &registration.ByDid, &createdAt, &registeredAt) 115 116 if err != nil { 117 if err == sql.ErrNoRows { 118 return nil, nil 119 } else { 120 return nil, err 121 } 122 } 123 124 createdAtTime := time.Unix(*createdAt, 0) 125 var registeredAtTime *time.Time 126 if registeredAt != nil { 127 x := time.Unix(*registeredAt, 0) 128 registeredAtTime = &x 129 } 130 131 registration.Created = &createdAtTime 132 registration.Registered = registeredAtTime 133 134 return &registration, nil 135} 136 137func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) { 138 // sanity check: does this domain already have a registration? 139 reg, err := d.RegistrationByDomain(domain) 140 if err != nil { 141 return "", err 142 } 143 144 // registration is open 145 if reg != nil { 146 switch reg.Status() { 147 case Registered: 148 // already registered by `owner` 149 return "", fmt.Errorf("%s already registered by %s", domain, reg.ByDid) 150 case Pending: 151 // TODO: be loud about this 152 log.Printf("%s registered by %s, status pending", domain, reg.ByDid) 153 } 154 } 155 156 secret := uuid.New().String() 157 158 _, err = d.db.Exec(` 159 insert into registrations (domain, did, secret) 160 values (?, ?, ?) 161 on conflict(domain) do update set did = excluded.did, secret = excluded.secret 162 `, domain, did, secret) 163 164 if err != nil { 165 return "", err 166 } 167 168 return secret, nil 169} 170 171func (d *DB) GetRegistrationKey(domain string) (string, error) { 172 res := d.db.QueryRow(`select secret from registrations where domain = ?`, domain) 173 174 var secret string 175 err := res.Scan(&secret) 176 if err != nil || secret == "" { 177 return "", err 178 } 179 180 log.Println("domain, secret: ", domain, secret) 181 182 return secret, nil 183} 184 185func (d *DB) Register(domain string) error { 186 _, err := d.db.Exec(` 187 update registrations 188 set registered = strftime('%s', 'now') 189 where domain = ?; 190 `, domain) 191 192 return err 193}