diff --git a/appview/db/db.go b/appview/db/db.go index 48427743..75bfb47f 100644 --- a/appview/db/db.go +++ b/appview/db/db.go @@ -674,6 +674,15 @@ func Make(ctx context.Context, dbPath string) (*DB, error) { foreign key (vouch_id) references vouches(id) on delete cascade ); + create table if not exists vouch_skips ( + did text not null, + subject_did text not null, + created_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), + primary key (did, subject_did), + check (did <> subject_did) + ); + + create table if not exists migrations ( id integer primary key autoincrement, name text unique diff --git a/appview/db/vouch.go b/appview/db/vouch.go index 02db7883..088477a4 100644 --- a/appview/db/vouch.go +++ b/appview/db/vouch.go @@ -308,6 +308,14 @@ func GetVouchRelationship(e Execer, viewerDid, subjectDid syntax.DID) (*models.V return batch[subjectDid], nil } +func SkipVouchSuggestion(e Execer, did, subjectDid string) error { + _, err := e.Exec( + `insert or ignore into vouch_skips (did, subject_did) values (?, ?)`, + did, subjectDid, + ) + return err +} + // priority: // 1. collaborator invites sent // 2. knot member invites sent @@ -390,6 +398,8 @@ func GetVouchSuggestions(e Execer, did string, limit int) ([]models.VouchSuggest ) where did not in ( select subject_did from vouches where vouches.did = ? + union + select subject_did from vouch_skips where vouch_skips.did = ? ) group by did order by min(priority) asc, max(created) desc @@ -405,7 +415,7 @@ func GetVouchSuggestions(e Execer, did string, limit int) ([]models.VouchSuggest did, did, // issue_comments did, did, // follows did, did, // stars - did, // vouches exclusion + did, did, // existing vouches + skips exclusion limit, } diff --git a/appview/pages/templates/user/vouches.html b/appview/pages/templates/user/vouches.html index 6b9f675f..05b03d81 100644 --- a/appview/pages/templates/user/vouches.html +++ b/appview/pages/templates/user/vouches.html @@ -43,7 +43,7 @@ {{ if .Suggestions }}
{{ range .Suggestions }} -
+
{{ resolve .Did.String }} @@ -52,6 +52,16 @@
{{ template "user/fragments/vouch" . }}
+
{{ end }}
diff --git a/appview/state/router.go b/appview/state/router.go index 75641f3a..61e4a8e6 100644 --- a/appview/state/router.go +++ b/appview/state/router.go @@ -189,6 +189,7 @@ func (s *State) StandardRouter(mw *middleware.Middleware) http.Handler { r.With(middleware.AuthMiddleware(s.oauth)).Route("/vouch", func(r chi.Router) { r.Post("/", s.Vouch) + r.Post("/skip", s.SkipVouchSuggestion) }) r.With(middleware.AuthMiddleware(s.oauth)).Route("/star", func(r chi.Router) { diff --git a/appview/state/vouch.go b/appview/state/vouch.go index d19a7ad8..aa03ee48 100644 --- a/appview/state/vouch.go +++ b/appview/state/vouch.go @@ -14,6 +14,39 @@ import ( "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")