+23
appview/db/db.go
+23
appview/db/db.go
···
140
140
return nil
141
141
})
142
142
143
+
runMigration(db, "add-rkey-to-pubkeys", func(tx *sql.Tx) error {
144
+
// add unconstrained column
145
+
_, err := tx.Exec(`
146
+
alter table public_keys
147
+
add column rkey text;
148
+
`)
149
+
if err != nil {
150
+
return err
151
+
}
152
+
153
+
// backfill
154
+
_, err = tx.Exec(`
155
+
update public_keys
156
+
set rkey = ''
157
+
where rkey is null;
158
+
`)
159
+
if err != nil {
160
+
return err
161
+
}
162
+
163
+
return nil
164
+
})
165
+
143
166
return &DB{db}, nil
144
167
}
145
168
+15
-10
appview/db/pubkeys.go
+15
-10
appview/db/pubkeys.go
···
5
5
"time"
6
6
)
7
7
8
-
func AddPublicKey(e Execer, did, name, key string) error {
9
-
query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`
10
-
_, err := e.Exec(query, did, name, key)
8
+
func AddPublicKey(e Execer, did, name, key, rkey string) error {
9
+
_, err := e.Exec(
10
+
`insert or ignore into public_keys (did, name, key, rkey)
11
+
values (?, ?, ?, ?)`,
12
+
did, name, key, rkey)
11
13
return err
12
14
}
13
15
14
-
func RemovePublicKey(e Execer, did string) error {
15
-
query := `delete from public_keys where did = ?`
16
-
_, err := e.Exec(query, did)
16
+
func RemovePublicKey(e Execer, did, name, key string) error {
17
+
_, err := e.Exec(`
18
+
delete from public_keys
19
+
where did = ? and name = ? and key = ?`,
20
+
did, name, key)
17
21
return err
18
22
}
19
23
···
21
25
Did string `json:"did"`
22
26
Key string `json:"key"`
23
27
Name string `json:"name"`
28
+
Rkey string `json:"rkey"`
24
29
Created *time.Time
25
30
}
26
31
···
38
43
func GetAllPublicKeys(e Execer) ([]PublicKey, error) {
39
44
var keys []PublicKey
40
45
41
-
rows, err := e.Query(`select key, name, did, created from public_keys`)
46
+
rows, err := e.Query(`select key, name, did, rkey, created from public_keys`)
42
47
if err != nil {
43
48
return nil, err
44
49
}
···
47
52
for rows.Next() {
48
53
var publicKey PublicKey
49
54
var createdAt string
50
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &createdAt); err != nil {
55
+
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &publicKey.Rkey, &createdAt); err != nil {
51
56
return nil, err
52
57
}
53
58
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
···
65
70
func GetPublicKeys(e Execer, did string) ([]PublicKey, error) {
66
71
var keys []PublicKey
67
72
68
-
rows, err := e.Query(`select did, key, name, created from public_keys where did = ?`, did)
73
+
rows, err := e.Query(`select did, key, name, rkey, created from public_keys where did = ?`, did)
69
74
if err != nil {
70
75
return nil, err
71
76
}
···
74
79
for rows.Next() {
75
80
var publicKey PublicKey
76
81
var createdAt string
77
-
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
82
+
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &publicKey.Rkey, &createdAt); err != nil {
78
83
return nil, err
79
84
}
80
85
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
+2
-2
appview/pages/templates/repo/issues/issue.html
+2
-2
appview/pages/templates/repo/issues/issue.html
···
5
5
6
6
{{ define "repoContent" }}
7
7
<header>
8
-
<p class="text-2xl font-bold">
8
+
<p class="text-2xl">
9
9
{{ .Issue.Title }}
10
10
<span class="text-gray-500">#{{ .Issue.IssueId }}</span>
11
11
</p>
···
18
18
{{ $icon = "circle-dot" }}
19
19
{{ end }}
20
20
21
-
<section>
21
+
<section class="mt-2">
22
22
<div class="inline-flex items-center gap-2">
23
23
<div id="state"
24
24
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }} text-sm">
+15
-6
appview/pages/templates/settings.html
+15
-6
appview/pages/templates/settings.html
···
32
32
<section class="rounded bg-white drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
33
33
<div id="key-list" class="flex flex-col gap-6 mb-8">
34
34
{{ range .PubKeys }}
35
-
<div>
36
-
<div class="inline-flex items-center gap-4">
37
-
<i class="w-3 h-3" data-lucide="key"></i>
38
-
<p class="font-bold">{{ .Name }} </p>
39
-
<p class="text-sm text-gray-500">added {{ .Created | timeFmt }}</p>
35
+
<div class="flex justify-between items-center gap-4">
36
+
<div>
37
+
<div class="inline-flex items-center gap-4">
38
+
<i class="w-3 h-3" data-lucide="key"></i>
39
+
<p class="font-bold">{{ .Name }}</p>
40
+
<p class="text-sm text-gray-500">added {{ .Created | timeFmt }}</p>
41
+
</div>
42
+
<code class="block break-all text-sm break-all text-gray-500">{{ .Key }}</code>
40
43
</div>
41
-
<code class="block text-sm break-all text-gray-500">{{ .Key }}</code>
44
+
<button
45
+
class="btn text-red-500 hover:text-red-700"
46
+
title="Delete key"
47
+
hx-delete="/settings/keys?name={{urlquery .Name}}&rkey={{urlquery .Rkey}}&key={{urlquery .Key}}"
48
+
hx-confirm="Are you sure you wish to delete the key '{{ .Name }}'?">
49
+
<i class="w-5 h-5" data-lucide="trash-2"></i>
50
+
</button>
42
51
</div>
43
52
{{ end }}
44
53
</div>
+60
-2
appview/state/settings.go
+60
-2
appview/state/settings.go
···
48
48
return
49
49
}
50
50
51
-
if err := db.AddPublicKey(s.db, did, name, key); err != nil {
51
+
rkey := s.TID()
52
+
53
+
tx, err := s.db.Begin()
54
+
if err != nil {
55
+
log.Printf("failed to start tx; adding public key: %s", err)
56
+
s.pages.Notice(w, "settings-keys", "Unable to add public key at this moment, try again later.")
57
+
return
58
+
}
59
+
defer tx.Rollback()
60
+
61
+
if err := db.AddPublicKey(tx, did, name, key, rkey); err != nil {
52
62
log.Printf("adding public key: %s", err)
53
63
s.pages.Notice(w, "settings-keys", "Failed to add public key.")
54
64
return
···
58
68
resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
59
69
Collection: tangled.PublicKeyNSID,
60
70
Repo: did,
61
-
Rkey: s.TID(),
71
+
Rkey: rkey,
62
72
Record: &lexutil.LexiconTypeDecoder{
63
73
Val: &tangled.PublicKey{
64
74
Created: time.Now().Format(time.RFC3339),
···
74
84
}
75
85
76
86
log.Println("created atproto record: ", resp.Uri)
87
+
88
+
err = tx.Commit()
89
+
if err != nil {
90
+
log.Printf("failed to commit tx; adding public key: %s", err)
91
+
s.pages.Notice(w, "settings-keys", "Unable to add public key at this moment, try again later.")
92
+
return
93
+
}
94
+
95
+
s.pages.HxLocation(w, "/settings")
96
+
return
97
+
98
+
case http.MethodDelete:
99
+
did := s.auth.GetDid(r)
100
+
q := r.URL.Query()
101
+
102
+
name := q.Get("name")
103
+
rkey := q.Get("rkey")
104
+
key := q.Get("key")
105
+
106
+
log.Println(name)
107
+
log.Println(rkey)
108
+
log.Println(key)
109
+
110
+
client, _ := s.auth.AuthorizedClient(r)
111
+
112
+
if err := db.RemovePublicKey(s.db, did, name, key); err != nil {
113
+
log.Printf("removing public key: %s", err)
114
+
s.pages.Notice(w, "settings-keys", "Failed to remove public key.")
115
+
return
116
+
}
117
+
118
+
if rkey != "" {
119
+
// remove from pds too
120
+
_, err := comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{
121
+
Collection: tangled.PublicKeyNSID,
122
+
Repo: did,
123
+
Rkey: rkey,
124
+
})
125
+
126
+
// invalid record
127
+
if err != nil {
128
+
log.Printf("failed to delete record from PDS: %s", err)
129
+
s.pages.Notice(w, "settings-keys", "Failed to remove key from PDS.")
130
+
return
131
+
}
132
+
}
133
+
log.Println("deleted successfully")
134
+
77
135
s.pages.HxLocation(w, "/settings")
78
136
return
79
137
}