package admin import ( "fmt" "net/http" "strconv" "git.kirsle.net/apps/gosocial/pkg/config" "git.kirsle.net/apps/gosocial/pkg/models" "git.kirsle.net/apps/gosocial/pkg/photo" "git.kirsle.net/apps/gosocial/pkg/session" "git.kirsle.net/apps/gosocial/pkg/templates" ) // Feedback controller (/admin/feedback) func Feedback() http.HandlerFunc { tmpl := templates.Must("admin/feedback.html") return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Query params. var ( acknowledged = r.FormValue("acknowledged") == "true" intent = r.FormValue("intent") visit = r.FormValue("visit") == "true" // visit the linked table ID profile = r.FormValue("profile") == "true" // visit associated user profile verdict = r.FormValue("verdict") fb *models.Feedback ) currentUser, err := session.CurrentUser(r) if err != nil { session.FlashError(w, r, "Couldn't get your current user: %s", err) } // Working on a target message? if idStr := r.FormValue("id"); idStr != "" { if idInt, err := strconv.Atoi(idStr); err != nil { session.FlashError(w, r, "Couldn't parse id param: %s", err) } else { fb, err = models.GetFeedback(uint64(idInt)) if err != nil { session.FlashError(w, r, "Couldn't load feedback message %d: %s", idInt, err) } } } // Are we visiting a linked resource (via TableID)? if fb != nil && fb.TableID > 0 && visit { switch fb.TableName { case "users": user, err := models.GetUser(fb.TableID) if err != nil { session.FlashError(w, r, "Couldn't visit user %d: %s", fb.TableID, err) } else { templates.Redirect(w, "/u/"+user.Username) return } case "photos": pic, err := models.GetPhoto(fb.TableID) if err != nil { session.FlashError(w, r, "Couldn't get photo %d: %s", fb.TableID, err) } else { // Going to the user's profile page? if profile { user, err := models.GetUser(pic.UserID) if err != nil { session.FlashError(w, r, "Couldn't visit user %d: %s", fb.TableID, err) } else { templates.Redirect(w, "/u/"+user.Username) return } } // Direct link to the photo. templates.Redirect(w, photo.URLPath(pic.Filename)) return } case "messages": // To read this message we will need to impersonate the reporter. user, err := models.GetUser(fb.UserID) if err != nil { session.FlashError(w, r, "Couldn't get reporting user ID %d: %s", fb.UserID, err) } else { if err := session.ImpersonateUser(w, r, user, currentUser); err != nil { session.FlashError(w, r, "Couldn't impersonate user: %s", err) } else { // Redirect to the thread. session.Flash(w, r, "NOTICE: You are now impersonating %s to view their inbox.", user.Username) templates.Redirect(w, fmt.Sprintf("/messages/read/%d", fb.TableID)) return } } default: session.FlashError(w, r, "Couldn't visit TableID %s/%d: not a supported TableName", fb.TableName, fb.TableID) } } // Are we (un)acknowledging a message? if r.Method == http.MethodPost { if fb == nil { session.FlashError(w, r, "Missing feedback ID for this POST!") } else { switch verdict { case "acknowledge": fb.Acknowledged = true if err := fb.Save(); err != nil { session.FlashError(w, r, "Couldn't save message: %s", err) } else { session.Flash(w, r, "Message acknowledged!") } case "unacknowledge": fb.Acknowledged = false if err := fb.Save(); err != nil { session.FlashError(w, r, "Couldn't save message: %s", err) } else { session.Flash(w, r, "Message acknowledged!") } default: session.FlashError(w, r, "Unsupported verdict: %s", verdict) } } templates.Redirect(w, r.URL.Path) return } // Get the feedback. pager := &models.Pagination{ Page: 1, PerPage: config.PageSizeAdminFeedback, Sort: "updated_at desc", } pager.ParsePage(r) page, err := models.PaginateFeedback(acknowledged, intent, pager) if err != nil { session.FlashError(w, r, "Couldn't load feedback from DB: %s", err) } // Map user IDs. var userIDs = []uint64{} for _, p := range page { if p.UserID > 0 { userIDs = append(userIDs, p.UserID) } } userMap, err := models.MapUsers(userIDs) if err != nil { session.FlashError(w, r, "Couldn't map user IDs: %s", err) } var vars = map[string]interface{}{ "Intent": intent, "Acknowledged": acknowledged, "Feedback": page, "UserMap": userMap, "Pager": pager, } if err := tmpl.Execute(w, r, vars); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }) }