Monorepo for Tangled
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222package state
import ( "net/http" "time"
comatproto "github.com/bluesky-social/indigo/api/atproto" "github.com/bluesky-social/indigo/atproto/syntax" lexutil "github.com/bluesky-social/indigo/lex/util" "github.com/ipfs/go-cid" "tangled.org/core/api/tangled" "tangled.org/core/appview/db" "tangled.org/core/appview/models" "tangled.org/core/log")
func (s *State) SkipVouchSuggestion(w http.ResponseWriter, r *http.Request) { l := log.SubLogger(s.logger, "skipVouchSuggestion") currentUser := s.oauth.GetMultiAccountUser(r)
subject := r.FormValue("subject") if subject == "" { l.Warn("missing subject") s.pages.Notice(w, "error", "Missing subject user.") return }
subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject) if err != nil { l.Error("failed to resolve subject", "subject", subject, "err", err) s.pages.Notice(w, "error", "Could not find that user.") return }
if currentUser.Did == subjectIdent.DID.String() { l.Warn("cannot skip yourself") s.pages.Notice(w, "error", "You cannot skip yourself.") return }
if err := db.SkipVouchSuggestion(s.db, currentUser.Did, subjectIdent.DID.String()); err != nil { l.Error("failed to skip vouch suggestion", "err", err) s.pages.Notice(w, "error", "Failed to skip suggestion.") return }
s.pages.HxRefresh(w)}
func (s *State) Vouch(w http.ResponseWriter, r *http.Request) { l := log.SubLogger(s.logger, "vouch") l = s.logger.With("handler", "Vouch") currentUser := s.oauth.GetMultiAccountUser(r)
var subject string
subject = r.FormValue("subject")
if subject == "" { l.Warn("invalid form: missing subject") s.pages.Notice(w, "error", "Missing subject user.") return }
subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject) if err != nil { l.Error("failed to vouch, invalid did", "subject", subject, "err", err) s.pages.Notice(w, "error", "Could not find that user.") return }
if currentUser.Did == subjectIdent.DID.String() { l.Warn("cant vouch or denounce yourself") s.pages.Notice(w, "error", "You cannot vouch for yourself.") return }
client, err := s.oauth.AuthorizedClient(r) if err != nil { l.Error("failed to authorize client", "err", err) s.pages.Notice(w, "error", "Authentication required.") return }
if err := r.ParseForm(); err != nil { l.Warn("failed to parse form", "err", err) s.pages.Notice(w, "error", "Invalid form data.") return }
subjectDid := subjectIdent.DID.String()
// handle "none" by deleting any existing vouch if r.FormValue("kind") == "none" { _, err := db.GetVouch(s.db, currentUser.Did, subjectDid) if err != nil { l.Info("no existing vouch to delete") s.pages.HxRefresh(w) return }
_, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ Collection: tangled.GraphVouchNSID, Repo: currentUser.Did, Rkey: subjectDid, })
if err != nil { l.Error("failed to delete vouch record", "err", err) s.pages.Notice(w, "error", "Failed to delete vouch record.") return }
err = db.DeleteVouch(s.db, currentUser.Did, subjectDid) if err != nil { l.Warn("failed to delete vouch from DB", "err", err) }
l.Info("deleted vouch record") s.pages.HxRefresh(w) return }
kind, err := models.ParseVouchKind(r.FormValue("kind")) if err != nil { l.Warn("failed to parse vouch kind", "err", err) s.pages.Notice(w, "error", "Invalid action type.") return }
reason := r.FormValue("reason") createdAt := time.Now().Format(time.RFC3339)
var reasonPtr *string if reason != "" { reasonPtr = &reason }
var evidences []syntax.ATURI for _, raw := range r.Form["evidences"] { uri, err := syntax.ParseATURI(raw) if err != nil { l.Warn("invalid evidence AT-URI, skipping", "uri", raw, "err", err) continue } evidences = append(evidences, uri) }
var swapCid *string existingVouch, err := db.GetVouch(s.db, currentUser.Did, subjectDid) if err == nil { cidStr := existingVouch.Cid.String() swapCid = &cidStr }
resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ Collection: tangled.GraphVouchNSID, Repo: currentUser.Did, Rkey: subjectDid, SwapRecord: swapCid, Record: &lexutil.LexiconTypeDecoder{ Val: &tangled.GraphVouch{ Kind: string(kind), Reason: reasonPtr, CreatedAt: createdAt, Evidences: func() []string { ss := make([]string, len(evidences)) for i, e := range evidences { ss[i] = e.String() } return ss }(), }}, }) if err != nil { l.Error("failed to create atproto record", "err", err) s.pages.Notice(w, "error", "Failed to create vouch record.") return }
l.Info("created atproto record", "uri", resp.Uri, "kind", kind)
newCid, err := cid.Parse(resp.Cid) if err != nil { l.Error("failed to parse returned cid", "err", err) s.pages.Notice(w, "error", "Failed to save vouch.") return }
vouch := &models.Vouch{ Did: syntax.DID(currentUser.Did), SubjectDid: subjectIdent.DID, Cid: newCid, Kind: kind, Reason: reasonPtr, Evidences: evidences, }
tx, err := s.db.Begin() if err != nil { l.Error("failed to start transaction", "err", err) s.pages.Notice(w, "error", "Failed to save vouch.") return } defer tx.Rollback()
err = db.AddVouch(tx, vouch) if err != nil { l.Error("failed to add vouch to db", "err", err) s.pages.Notice(w, "error", "Failed to save vouch.") return }
if err = tx.Commit(); err != nil { l.Error("failed to commit vouch transaction", "err", err) s.pages.Notice(w, "error", "Failed to save vouch.") return }
s.pages.HxRefresh(w)}