Signed-off-by: oppiliappan me@oppi.li
+172
-16
Diff
round #1
+40
-5
appview/db/db.go
+40
-5
appview/db/db.go
···
651
651
foreign key (repo_at) references repos(at_uri) on delete cascade
652
652
);
653
653
654
-
create table if not exists migrations (
655
-
id integer primary key autoincrement,
656
-
name text unique
657
-
);
658
-
659
654
create table if not exists punchcard_preferences (
660
655
id integer primary key autoincrement,
661
656
user_did text not null unique,
···
671
666
updated_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
672
667
);
673
668
669
+
create table if not exists vouch_evidences (
670
+
id integer primary key autoincrement,
671
+
vouch_id integer not null,
672
+
at_uri text not null,
673
+
unique(vouch_id, at_uri),
674
+
foreign key (vouch_id) references vouches(id) on delete cascade
675
+
);
676
+
677
+
create table if not exists migrations (
678
+
id integer primary key autoincrement,
679
+
name text unique
680
+
);
681
+
674
682
-- indexes for better performance
675
683
create index if not exists idx_notifications_recipient_created on notifications(recipient_did, created desc);
676
684
create index if not exists idx_notifications_recipient_read on notifications(recipient_did, read);
···
1475
1483
return err
1476
1484
})
1477
1485
1486
+
conn.ExecContext(ctx, "pragma foreign_keys = off;")
1487
+
orm.RunMigration(conn, logger, "add-id-to-vouches", func(tx *sql.Tx) error {
1488
+
_, err := tx.Exec(`
1489
+
create table vouches_new (
1490
+
id integer primary key autoincrement,
1491
+
did text not null,
1492
+
subject_did text not null,
1493
+
cid text not null,
1494
+
kind text not null default 'vouch',
1495
+
reason text,
1496
+
created_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
1497
+
unique(did, subject_did),
1498
+
check (did <> subject_did),
1499
+
check (kind in ('vouch', 'denounce'))
1500
+
);
1501
+
1502
+
insert into vouches_new (did, subject_did, cid, kind, reason, created_at)
1503
+
select did, subject_did, cid, kind, reason, created_at
1504
+
from vouches;
1505
+
1506
+
drop table vouches;
1507
+
alter table vouches_new rename to vouches;
1508
+
`)
1509
+
return err
1510
+
})
1511
+
conn.ExecContext(ctx, "pragma foreign_keys = on;")
1512
+
1478
1513
return &DB{
1479
1514
db,
1480
1515
logger,
+77
-9
appview/db/vouch.go
+77
-9
appview/db/vouch.go
···
15
15
)
16
16
17
17
func AddVouch(e Execer, vouch *models.Vouch) error {
18
-
query := `insert or replace into vouches (did, subject_did, cid, kind, reason) values (?, ?, ?, ?, ?)`
19
-
_, err := e.Exec(query, vouch.Did, vouch.SubjectDid, vouch.Cid.String(), vouch.Kind, vouch.Reason)
20
-
return err
18
+
// insert if not exists
19
+
_, err := e.Exec(
20
+
`insert or ignore into vouches (did, subject_did, cid, kind, reason) values (?, ?, ?, ?, ?)`,
21
+
vouch.Did, vouch.SubjectDid, vouch.Cid.String(), vouch.Kind, vouch.Reason,
22
+
)
23
+
if err != nil {
24
+
return err
25
+
}
26
+
27
+
// then update
28
+
_, err = e.Exec(
29
+
`update vouches set cid = ?, kind = ?, reason = ? where did = ? and subject_did = ?`,
30
+
vouch.Cid.String(), vouch.Kind, vouch.Reason, vouch.Did, vouch.SubjectDid,
31
+
)
32
+
if err != nil {
33
+
return err
34
+
}
35
+
36
+
// replace evidences: delete all existing, then insert new ones.
37
+
_, err = e.Exec(
38
+
`delete from vouch_evidences where vouch_id = (select id from vouches where did = ? and subject_did = ?)`,
39
+
vouch.Did, vouch.SubjectDid,
40
+
)
41
+
if err != nil {
42
+
return err
43
+
}
44
+
for _, uri := range vouch.Evidences {
45
+
_, err = e.Exec(
46
+
`insert into vouch_evidences (vouch_id, at_uri)
47
+
values ((select id from vouches where did = ? and subject_did = ?), ?)`,
48
+
vouch.Did, vouch.SubjectDid, uri.String(),
49
+
)
50
+
if err != nil {
51
+
return err
52
+
}
53
+
}
54
+
return nil
21
55
}
22
56
23
57
func GetVouch(e Execer, did, subjectDid string) (*models.Vouch, error) {
···
101
135
return vouches, nil
102
136
}
103
137
138
+
func GetVouchEvidences(e Execer, did, subjectDid string) ([]syntax.ATURI, error) {
139
+
rows, err := e.Query(
140
+
`select at_uri from vouch_evidences
141
+
where vouch_id = (select id from vouches where did = ? and subject_did = ?)
142
+
order by id asc`,
143
+
did, subjectDid,
144
+
)
145
+
if err != nil {
146
+
return nil, err
147
+
}
148
+
defer rows.Close()
149
+
150
+
var evidences []syntax.ATURI
151
+
for rows.Next() {
152
+
var uri string
153
+
if err := rows.Scan(&uri); err != nil {
154
+
log.Println("error scanning vouch evidence:", err)
155
+
continue
156
+
}
157
+
evidences = append(evidences, syntax.ATURI(uri))
158
+
}
159
+
return evidences, nil
160
+
}
161
+
104
162
func DeleteVouch(e Execer, did, subjectDid string) error {
105
163
_, err := e.Exec(`delete from vouches where did = ? and subject_did = ?`, did, subjectDid)
106
164
return err
···
118
176
}
119
177
120
178
query := fmt.Sprintf(
121
-
`select did, subject_did, cid, kind, reason, created_at
122
-
from vouches
179
+
`select v.did, v.subject_did, v.cid, v.kind, v.reason, v.created_at,
180
+
group_concat(ve.at_uri, '|') as evidences
181
+
from vouches v
182
+
left join vouch_evidences ve on ve.vouch_id = v.id
123
183
where (
124
-
subject_did = ? and did in (select subject_did from vouches where did = ? and kind = 'vouch')
184
+
v.subject_did = ? and v.did in (select subject_did from vouches where did = ? and kind = 'vouch')
125
185
) or (
126
-
did = ? and subject_did in (select subject_did from vouches where did = ? and kind = 'vouch')
186
+
v.did = ? and v.subject_did in (select subject_did from vouches where did = ? and kind = 'vouch')
127
187
)
128
-
order by created_at desc
188
+
group by v.did, v.subject_did
189
+
order by v.created_at desc
129
190
%s`,
130
191
pageClause)
131
192
···
141
202
var cidStr string
142
203
var createdAt string
143
204
var reason sql.NullString
205
+
var evidences sql.NullString
144
206
145
-
if err := rows.Scan(&v.Did, &v.SubjectDid, &cidStr, &v.Kind, &reason, &createdAt); err != nil {
207
+
if err := rows.Scan(&v.Did, &v.SubjectDid, &cidStr, &v.Kind, &reason, &createdAt, &evidences); err != nil {
146
208
log.Println("error scanning vouch:", err)
147
209
continue
148
210
}
···
165
227
v.Reason = &reason.String
166
228
}
167
229
230
+
if evidences.Valid && evidences.String != "" {
231
+
for _, s := range strings.Split(evidences.String, "|") {
232
+
v.Evidences = append(v.Evidences, syntax.ATURI(s))
233
+
}
234
+
}
235
+
168
236
vouches = append(vouches, v)
169
237
}
170
238
return vouches, nil
+28
-1
appview/ingester.go
+28
-1
appview/ingester.go
···
260
260
return fmt.Errorf("invalid cid: %w", err)
261
261
}
262
262
263
-
err = db.AddVouch(i.Db, &models.Vouch{
263
+
var evidences []syntax.ATURI
264
+
for _, raw := range record.Evidences {
265
+
uri, parseErr := syntax.ParseATURI(raw)
266
+
if parseErr != nil {
267
+
l.Warn("invalid evidence AT-URI, skipping", "uri", raw, "err", parseErr)
268
+
continue
269
+
}
270
+
evidences = append(evidences, uri)
271
+
}
272
+
273
+
ddb, ok := i.Db.Execer.(*db.DB)
274
+
if !ok {
275
+
return fmt.Errorf("failed to ingest vouch record, invalid db cast")
276
+
}
277
+
278
+
tx, txErr := ddb.Begin()
279
+
if txErr != nil {
280
+
return fmt.Errorf("failed to start transaction: %w", txErr)
281
+
}
282
+
283
+
addErr := db.AddVouch(tx, &models.Vouch{
264
284
Did: syntax.DID(did),
265
285
SubjectDid: subjectId.DID,
266
286
Cid: recordCid,
267
287
Kind: kind,
268
288
Reason: record.Reason,
289
+
Evidences: evidences,
269
290
})
291
+
if addErr != nil {
292
+
tx.Rollback()
293
+
err = addErr
294
+
} else {
295
+
err = tx.Commit()
296
+
}
270
297
271
298
case jmodels.CommitOperationDelete:
272
299
err = db.DeleteVouchByRkey(i.Db, did, e.Commit.RKey)
+1
appview/models/vouch.go
+1
appview/models/vouch.go
+26
-1
appview/state/vouch.go
+26
-1
appview/state/vouch.go
···
103
103
reasonPtr = &reason
104
104
}
105
105
106
+
var evidences []string
107
+
for _, raw := range r.Form["evidences"] {
108
+
if _, err := syntax.ParseATURI(raw); err != nil {
109
+
l.Warn("invalid evidence AT-URI, skipping", "uri", raw, "err", err)
110
+
continue
111
+
}
112
+
evidences = append(evidences, raw)
113
+
}
114
+
106
115
var swapCid *string
107
116
existingVouch, err := db.GetVouch(s.db, currentUser.Did, subjectDid)
108
117
if err == nil {
···
120
129
Kind: string(kind),
121
130
Reason: reasonPtr,
122
131
CreatedAt: createdAt,
132
+
Evidences: evidences,
123
133
}},
124
134
})
125
135
if err != nil {
···
143
153
Cid: newCid,
144
154
Kind: kind,
145
155
Reason: reasonPtr,
156
+
Evidences: evidences,
157
+
}
158
+
159
+
tx, err := s.db.Begin()
160
+
if err != nil {
161
+
l.Error("failed to start transaction", "err", err)
162
+
s.pages.Notice(w, "error", "Failed to save vouch.")
163
+
return
146
164
}
165
+
defer tx.Rollback()
147
166
148
-
err = db.AddVouch(s.db, vouch)
167
+
err = db.AddVouch(tx, vouch)
149
168
if err != nil {
150
169
l.Error("failed to add vouch to db", "err", err)
151
170
s.pages.Notice(w, "error", "Failed to save vouch.")
152
171
return
153
172
}
154
173
174
+
if err = tx.Commit(); err != nil {
175
+
l.Error("failed to commit vouch transaction", "err", err)
176
+
s.pages.Notice(w, "error", "Failed to save vouch.")
177
+
return
178
+
}
179
+
155
180
s.pages.HxRefresh(w)
156
181
}