forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
Monorepo for Tangled
fork
Configure Feed
Select the types of activity you want to include in your feed.
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(®istration.Domain, ®istration.ByDid, &createdAt, ®isteredAt)
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(®istration.Domain, ®istration.ByDid, &createdAt, ®isteredAt)
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 ®istration, 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}