forked from tangled.org/core
this repo has no description
1package db 2 3import ( 4 "crypto/rand" 5 "database/sql" 6 "encoding/hex" 7 "fmt" 8 "log" 9 "time" 10) 11 12type Registration struct { 13 Id int64 14 Domain string 15 ByDid string 16 Created *time.Time 17 Registered *time.Time 18} 19 20func (r *Registration) Status() Status { 21 if r.Registered != nil { 22 return Registered 23 } else { 24 return Pending 25 } 26} 27 28type Status uint32 29 30const ( 31 Registered Status = iota 32 Pending 33) 34 35// returns registered status, did of owner, error 36func RegistrationsByDid(e Execer, did string) ([]Registration, error) { 37 var registrations []Registration 38 39 rows, err := e.Query(` 40 select id, domain, did, created, registered from registrations 41 where did = ? 42 `, did) 43 if err != nil { 44 return nil, err 45 } 46 47 for rows.Next() { 48 var createdAt *string 49 var registeredAt *string 50 var registration Registration 51 err = rows.Scan(&registration.Id, &registration.Domain, &registration.ByDid, &createdAt, &registeredAt) 52 53 if err != nil { 54 log.Println(err) 55 } else { 56 createdAtTime, _ := time.Parse(time.RFC3339, *createdAt) 57 var registeredAtTime *time.Time 58 if registeredAt != nil { 59 x, _ := time.Parse(time.RFC3339, *registeredAt) 60 registeredAtTime = &x 61 } 62 63 registration.Created = &createdAtTime 64 registration.Registered = registeredAtTime 65 registrations = append(registrations, registration) 66 } 67 } 68 69 return registrations, nil 70} 71 72// returns registered status, did of owner, error 73func RegistrationByDomain(e Execer, domain string) (*Registration, error) { 74 var createdAt *string 75 var registeredAt *string 76 var registration Registration 77 78 err := e.QueryRow(` 79 select id, domain, did, created, registered from registrations 80 where domain = ? 81 `, domain).Scan(&registration.Id, &registration.Domain, &registration.ByDid, &createdAt, &registeredAt) 82 83 if err != nil { 84 if err == sql.ErrNoRows { 85 return nil, nil 86 } else { 87 return nil, err 88 } 89 } 90 91 createdAtTime, _ := time.Parse(time.RFC3339, *createdAt) 92 var registeredAtTime *time.Time 93 if registeredAt != nil { 94 x, _ := time.Parse(time.RFC3339, *registeredAt) 95 registeredAtTime = &x 96 } 97 98 registration.Created = &createdAtTime 99 registration.Registered = registeredAtTime 100 101 return &registration, nil 102} 103 104func genSecret() string { 105 key := make([]byte, 32) 106 rand.Read(key) 107 return hex.EncodeToString(key) 108} 109 110func GenerateRegistrationKey(e Execer, domain, did string) (string, error) { 111 // sanity check: does this domain already have a registration? 112 reg, err := RegistrationByDomain(e, domain) 113 if err != nil { 114 return "", err 115 } 116 117 // registration is open 118 if reg != nil { 119 switch reg.Status() { 120 case Registered: 121 // already registered by `owner` 122 return "", fmt.Errorf("%s already registered by %s", domain, reg.ByDid) 123 case Pending: 124 // TODO: be loud about this 125 log.Printf("%s registered by %s, status pending", domain, reg.ByDid) 126 } 127 } 128 129 secret := genSecret() 130 131 _, err = e.Exec(` 132 insert into registrations (domain, did, secret) 133 values (?, ?, ?) 134 on conflict(domain) do update set did = excluded.did, secret = excluded.secret, created = excluded.created 135 `, domain, did, secret) 136 137 if err != nil { 138 return "", err 139 } 140 141 return secret, nil 142} 143 144func GetRegistrationKey(e Execer, domain string) (string, error) { 145 res := e.QueryRow(`select secret from registrations where domain = ?`, domain) 146 147 var secret string 148 err := res.Scan(&secret) 149 if err != nil || secret == "" { 150 return "", err 151 } 152 153 return secret, nil 154} 155 156func GetCompletedRegistrations(e Execer) ([]string, error) { 157 rows, err := e.Query(`select domain from registrations where registered not null`) 158 if err != nil { 159 return nil, err 160 } 161 162 var domains []string 163 for rows.Next() { 164 var domain string 165 err = rows.Scan(&domain) 166 167 if err != nil { 168 log.Println(err) 169 } else { 170 domains = append(domains, domain) 171 } 172 } 173 174 if err = rows.Err(); err != nil { 175 return nil, err 176 } 177 178 return domains, nil 179} 180 181func Register(e Execer, domain string) error { 182 _, err := e.Exec(` 183 update registrations 184 set registered = strftime('%Y-%m-%dT%H:%M:%SZ', 'now') 185 where domain = ?; 186 `, domain) 187 188 return err 189}