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