345285d7a3
* A reason must be entered to impersonate a user, and it triggers a Report and email notification to the admin. * User gallery pages will show at the top whether the user had granted you access to their private photos.
177 lines
5.2 KiB
Go
177 lines
5.2 KiB
Go
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/config"
|
|
"code.nonshy.com/nonshy/website/pkg/models"
|
|
"code.nonshy.com/nonshy/website/pkg/photo"
|
|
"code.nonshy.com/nonshy/website/pkg/session"
|
|
"code.nonshy.com/nonshy/website/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, "Clicked from user reported Message via admin dashboard"); 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
|
|
}
|
|
}
|
|
case "comments":
|
|
// Get this comment.
|
|
comment, err := models.GetComment(fb.TableID)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't get comment ID %d: %s", fb.TableID, err)
|
|
} else {
|
|
// What was the comment on?
|
|
switch comment.TableName {
|
|
case "threads":
|
|
// Visit the thread.
|
|
templates.Redirect(w, fmt.Sprintf("/forum/thread/%d", comment.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(currentUser, 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
|
|
}
|
|
})
|
|
}
|