1package db
2
3import (
4 "database/sql"
5 "fmt"
6 "strings"
7 "time"
8)
9
10// Registration represents a knot registration. Knot would've been a better
11// name but we're stuck with this for historical reasons.
12type Registration struct {
13 Id int64
14 Domain string
15 ByDid string
16 Created *time.Time
17 Registered *time.Time
18 NeedsUpgrade bool
19}
20
21func (r *Registration) Status() Status {
22 if r.NeedsUpgrade {
23 return NeedsUpgrade
24 } else if r.Registered != nil {
25 return Registered
26 } else {
27 return Pending
28 }
29}
30
31func (r *Registration) IsRegistered() bool {
32 return r.Status() == Registered
33}
34
35func (r *Registration) IsNeedsUpgrade() bool {
36 return r.Status() == NeedsUpgrade
37}
38
39func (r *Registration) IsPending() bool {
40 return r.Status() == Pending
41}
42
43type Status uint32
44
45const (
46 Registered Status = iota
47 Pending
48 NeedsUpgrade
49)
50
51func GetRegistrations(e Execer, filters ...filter) ([]Registration, error) {
52 var registrations []Registration
53
54 var conditions []string
55 var args []any
56 for _, filter := range filters {
57 conditions = append(conditions, filter.Condition())
58 args = append(args, filter.Arg()...)
59 }
60
61 whereClause := ""
62 if conditions != nil {
63 whereClause = " where " + strings.Join(conditions, " and ")
64 }
65
66 query := fmt.Sprintf(`
67 select id, domain, did, created, registered, needs_upgrade
68 from registrations
69 %s
70 order by created
71 `,
72 whereClause,
73 )
74
75 rows, err := e.Query(query, args...)
76 if err != nil {
77 return nil, err
78 }
79
80 for rows.Next() {
81 var createdAt string
82 var registeredAt sql.Null[string]
83 var needsUpgrade int
84 var reg Registration
85
86 err = rows.Scan(®.Id, ®.Domain, ®.ByDid, &createdAt, ®isteredAt, &needsUpgrade)
87 if err != nil {
88 return nil, err
89 }
90
91 if t, err := time.Parse(time.RFC3339, createdAt); err == nil {
92 reg.Created = &t
93 }
94
95 if registeredAt.Valid {
96 if t, err := time.Parse(time.RFC3339, registeredAt.V); err == nil {
97 reg.Registered = &t
98 }
99 }
100
101 if needsUpgrade != 0 {
102 reg.NeedsUpgrade = true
103 }
104
105 registrations = append(registrations, reg)
106 }
107
108 return registrations, nil
109}
110
111func MarkRegistered(e Execer, filters ...filter) error {
112 var conditions []string
113 var args []any
114 for _, filter := range filters {
115 conditions = append(conditions, filter.Condition())
116 args = append(args, filter.Arg()...)
117 }
118
119 query := "update registrations set registered = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), needs_upgrade = 0"
120 if len(conditions) > 0 {
121 query += " where " + strings.Join(conditions, " and ")
122 }
123
124 _, err := e.Exec(query, args...)
125 return err
126}
127
128func AddKnot(e Execer, domain, did string) error {
129 _, err := e.Exec(`
130 insert into registrations (domain, did)
131 values (?, ?)
132 `, domain, did)
133 return err
134}
135
136func DeleteKnot(e Execer, filters ...filter) error {
137 var conditions []string
138 var args []any
139 for _, filter := range filters {
140 conditions = append(conditions, filter.Condition())
141 args = append(args, filter.Arg()...)
142 }
143
144 whereClause := ""
145 if conditions != nil {
146 whereClause = " where " + strings.Join(conditions, " and ")
147 }
148
149 query := fmt.Sprintf(`delete from registrations %s`, whereClause)
150
151 _, err := e.Exec(query, args...)
152 return err
153}