forked from tangled.org/core
Monorepo for Tangled

add delete-key feature

Changed files
+116 -20
appview
db
pages
templates
state
+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
··· 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
··· 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
··· 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
··· 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 }
+1
appview/state/state.go
··· 965 965 r.Use(AuthMiddleware(s)) 966 966 r.Get("/", s.Settings) 967 967 r.Put("/keys", s.SettingsKeys) 968 + r.Delete("/keys", s.SettingsKeys) 968 969 }) 969 970 970 971 r.Get("/keys/{user}", s.Keys)