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 err := d.db.QueryRow(` 111 select domain, did, created, registered from registrations 112 where domain = ? 113 `, domain).Scan(&registration.Domain, &registration.ByDid, &createdAt, &registeredAt) 114 115 createdAtTime := time.Unix(*createdAt, 0) 116 var registeredAtTime *time.Time 117 if registeredAt != nil { 118 x := time.Unix(*registeredAt, 0) 119 registeredAtTime = &x 120 } 121 122 registration.Created = &createdAtTime 123 registration.Registered = registeredAtTime 124 125 if err != nil { 126 if err == sql.ErrNoRows { 127 return nil, nil 128 } else { 129 return nil, err 130 } 131 } 132 133 return &registration, nil 134} 135 136func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) { 137 // sanity check: does this domain already have a registration? 138 reg, err := d.RegistrationByDomain(domain) 139 if err != nil { 140 return "", err 141 } 142 143 // registration is open 144 if reg != nil { 145 switch reg.Status() { 146 case Registered: 147 // already registered by `owner` 148 return "", fmt.Errorf("%s already registered by %s", domain, reg.ByDid) 149 case Pending: 150 // TODO: be loud about this 151 log.Printf("%s registered by %s, status pending", domain, reg.ByDid) 152 } 153 } 154 155 secret := uuid.New().String() 156 157 _, err = d.db.Exec(` 158 insert into registrations (domain, did, secret) 159 values (?, ?, ?) 160 on conflict(domain) do update set did = excluded.did, secret = excluded.secret 161 `, domain, did, secret) 162 163 if err != nil { 164 return "", err 165 } 166 167 return secret, nil 168} 169 170func (d *DB) GetRegistrationKey(domain string) (string, error) { 171 res := d.db.QueryRow(`select secret from registrations where domain = ?`, domain) 172 173 var secret string 174 err := res.Scan(&secret) 175 if err != nil || secret == "" { 176 return "", err 177 } 178 179 log.Println("domain, secret: ", domain, secret) 180 181 return secret, nil 182} 183 184func (d *DB) Register(domain string) error { 185 _, err := d.db.Exec(` 186 update registrations 187 set registered = strftime('%s', 'now') 188 where domain = ?; 189 `, domain) 190 191 if err != nil { 192 return err 193 } 194 195 return nil 196}