This repository has no description
1package state
2
3import (
4 "net/http"
5 "time"
6
7 comatproto "github.com/bluesky-social/indigo/api/atproto"
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 lexutil "github.com/bluesky-social/indigo/lex/util"
10 "github.com/ipfs/go-cid"
11 "tangled.org/core/api/tangled"
12 "tangled.org/core/appview/db"
13 "tangled.org/core/appview/models"
14 "tangled.org/core/log"
15)
16
17func (s *State) Vouch(w http.ResponseWriter, r *http.Request) {
18 l := log.SubLogger(s.logger, "vouch")
19 l = s.logger.With("handler", "Vouch")
20 currentUser := s.oauth.GetMultiAccountUser(r)
21
22 var subject string
23
24 subject = r.FormValue("subject")
25
26 if subject == "" {
27 l.Warn("invalid form: missing subject")
28 s.pages.Notice(w, "error", "Missing subject user.")
29 return
30 }
31
32 subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject)
33 if err != nil {
34 l.Error("failed to vouch, invalid did", "subject", subject, "err", err)
35 s.pages.Notice(w, "error", "Could not find that user.")
36 return
37 }
38
39 if currentUser.Did == subjectIdent.DID.String() {
40 l.Warn("cant vouch or denounce yourself")
41 s.pages.Notice(w, "error", "You cannot vouch for yourself.")
42 return
43 }
44
45 client, err := s.oauth.AuthorizedClient(r)
46 if err != nil {
47 l.Error("failed to authorize client", "err", err)
48 s.pages.Notice(w, "error", "Authentication required.")
49 return
50 }
51
52 if err := r.ParseForm(); err != nil {
53 l.Warn("failed to parse form", "err", err)
54 s.pages.Notice(w, "error", "Invalid form data.")
55 return
56 }
57
58 subjectDid := subjectIdent.DID.String()
59
60 // handle "none" by deleting any existing vouch
61 if r.FormValue("kind") == "none" {
62 _, err := db.GetVouch(s.db, currentUser.Did, subjectDid)
63 if err != nil {
64 l.Info("no existing vouch to delete")
65 s.pages.HxRefresh(w)
66 return
67 }
68
69 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{
70 Collection: tangled.GraphVouchNSID,
71 Repo: currentUser.Did,
72 Rkey: subjectDid,
73 })
74
75 if err != nil {
76 l.Error("failed to delete vouch record", "err", err)
77 s.pages.Notice(w, "error", "Failed to delete vouch record.")
78 return
79 }
80
81 err = db.DeleteVouch(s.db, currentUser.Did, subjectDid)
82 if err != nil {
83 l.Warn("failed to delete vouch from DB", "err", err)
84 }
85
86 l.Info("deleted vouch record")
87 s.pages.HxRefresh(w)
88 return
89 }
90
91 kind, err := models.ParseVouchKind(r.FormValue("kind"))
92 if err != nil {
93 l.Warn("failed to parse vouch kind", "err", err)
94 s.pages.Notice(w, "error", "Invalid action type.")
95 return
96 }
97
98 reason := r.FormValue("reason")
99 createdAt := time.Now().Format(time.RFC3339)
100
101 var reasonPtr *string
102 if reason != "" {
103 reasonPtr = &reason
104 }
105
106 var swapCid *string
107 existingVouch, err := db.GetVouch(s.db, currentUser.Did, subjectDid)
108 if err == nil {
109 cidStr := existingVouch.Cid.String()
110 swapCid = &cidStr
111 }
112
113 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
114 Collection: tangled.GraphVouchNSID,
115 Repo: currentUser.Did,
116 Rkey: subjectDid,
117 SwapRecord: swapCid,
118 Record: &lexutil.LexiconTypeDecoder{
119 Val: &tangled.GraphVouch{
120 Kind: string(kind),
121 Reason: reasonPtr,
122 CreatedAt: createdAt,
123 }},
124 })
125 if err != nil {
126 l.Error("failed to create atproto record", "err", err)
127 s.pages.Notice(w, "error", "Failed to create vouch record.")
128 return
129 }
130
131 l.Info("created atproto record", "uri", resp.Uri, "kind", kind)
132
133 newCid, err := cid.Parse(resp.Cid)
134 if err != nil {
135 l.Error("failed to parse returned cid", "err", err)
136 s.pages.Notice(w, "error", "Failed to save vouch.")
137 return
138 }
139
140 vouch := &models.Vouch{
141 Did: syntax.DID(currentUser.Did),
142 SubjectDid: subjectIdent.DID,
143 Cid: newCid,
144 Kind: kind,
145 Reason: reasonPtr,
146 }
147
148 err = db.AddVouch(s.db, vouch)
149 if err != nil {
150 l.Error("failed to add vouch to db", "err", err)
151 s.pages.Notice(w, "error", "Failed to save vouch.")
152 return
153 }
154
155 s.pages.HxRefresh(w)
156}