mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-04 05:56:23 -07:00
165 lines
4.6 KiB
Go
165 lines
4.6 KiB
Go
package manage
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gochan-org/gochan/pkg/config"
|
|
"github.com/gochan-org/gochan/pkg/gcsql"
|
|
"github.com/gochan-org/gochan/pkg/gctemplates"
|
|
"github.com/gochan-org/gochan/pkg/gcutil"
|
|
"github.com/gochan-org/gochan/pkg/server"
|
|
"github.com/gochan-org/gochan/pkg/server/serverutil"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
type reportData struct {
|
|
gcsql.Report
|
|
StaffUser *string `json:"staff_user"`
|
|
PostLink string `json:"post_link"`
|
|
}
|
|
|
|
func doReportHandling(request *http.Request, staff *gcsql.Staff, infoEv, errEv *zerolog.Event) error {
|
|
doDismissAll := request.PostFormValue("dismiss-all")
|
|
doDismissSel := request.PostFormValue("dismiss-sel")
|
|
doBlockSel := request.PostFormValue("block-sel")
|
|
|
|
if doDismissAll != "" {
|
|
_, err := gcsql.Exec(nil, `UPDATE DBPREFIXreports SET is_cleared = 1`)
|
|
if err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return err
|
|
}
|
|
infoEv.Msg("All reports dismissed")
|
|
return nil
|
|
}
|
|
|
|
if doDismissSel == "" && doBlockSel == "" {
|
|
return nil
|
|
}
|
|
|
|
if doBlockSel != "" && staff.Rank != 3 {
|
|
gcutil.LogWarning().Caller().
|
|
Str("IP", gcutil.GetRealIP(request)).
|
|
Str("staff", staff.Username).
|
|
Str("rejected", "not an admin").
|
|
Msg("only the administrator can block reports")
|
|
return server.NewServerError("only the administrator can block reports", http.StatusForbidden)
|
|
}
|
|
|
|
var checkedReports []int
|
|
for reportIDstr, val := range request.PostForm {
|
|
if len(val) == 0 {
|
|
continue
|
|
}
|
|
|
|
idStr, ok := strings.CutPrefix(reportIDstr, "report")
|
|
if !ok {
|
|
continue
|
|
}
|
|
id, err := strconv.Atoi(idStr)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
checkedReports = append(checkedReports, id)
|
|
}
|
|
|
|
if len(checkedReports) == 0 {
|
|
return nil
|
|
}
|
|
gcutil.LogArray("reportIDs", checkedReports, infoEv)
|
|
|
|
for _, reportID := range checkedReports {
|
|
matched, err := gcsql.ClearReport(reportID, staff.ID, doBlockSel != "")
|
|
if !matched {
|
|
errEv.Err(err).Caller().
|
|
Int("reportID", reportID).
|
|
Msg("report not found")
|
|
return server.NewServerError(fmt.Sprintf("report with id %d does not exist or is cleared", reportID), http.StatusBadRequest)
|
|
}
|
|
if err != nil {
|
|
errEv.Err(err).Caller().
|
|
Int("reportID", reportID).
|
|
Msg("failed to clear report")
|
|
return server.NewServerError(fmt.Sprintf("failed to clear report with id %d", reportID), http.StatusInternalServerError)
|
|
}
|
|
}
|
|
infoEv.Msg("Reports dismissed")
|
|
return nil
|
|
}
|
|
|
|
func reportsCallback(_ http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output any, err error) {
|
|
if err = doReportHandling(request, staff, infoEv, errEv); err != nil {
|
|
errEv.Discard() // doReportHandling logs errors
|
|
return nil, err
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), config.DefaultSQLTimeout*time.Second)
|
|
defer cancel()
|
|
|
|
requestOptions := &gcsql.RequestOptions{
|
|
Context: ctx,
|
|
Cancel: cancel,
|
|
}
|
|
|
|
if err = gcsql.DeleteReportsOfDeletedPosts(requestOptions); err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return nil, server.NewServerError("failed to clean up reports of deleted posts", http.StatusInternalServerError)
|
|
}
|
|
|
|
rows, err := gcsql.Query(requestOptions, `SELECT id, staff_id, staff_user, post_id, ip, reason, is_cleared FROM DBPREFIXv_post_reports`)
|
|
if err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
// reports := make([]map[string]any, 0)
|
|
var reports []reportData
|
|
for rows.Next() {
|
|
var report reportData
|
|
err = rows.Scan(&report.ID, &report.HandledByStaffID, &report.StaffUser, &report.PostID, &report.IP, &report.Reason, &report.IsCleared)
|
|
if report.StaffUser == nil {
|
|
user := "unassigned"
|
|
report.StaffUser = &user
|
|
handledByStaffID := 0
|
|
report.HandledByStaffID = &handledByStaffID
|
|
}
|
|
if err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return nil, server.NewServerError("failed to scan report row", http.StatusInternalServerError)
|
|
}
|
|
|
|
post, err := gcsql.GetPostFromID(report.PostID, true, requestOptions)
|
|
if err != nil {
|
|
errEv.Err(err).Caller().Msg("failed to get post from ID")
|
|
return nil, server.NewServerError("failed to get post from ID", http.StatusInternalServerError)
|
|
}
|
|
report.PostLink = post.WebPath()
|
|
reports = append(reports, report)
|
|
}
|
|
if err = rows.Close(); err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return nil, err
|
|
}
|
|
if wantsJSON {
|
|
return reports, nil
|
|
}
|
|
|
|
reportsBuffer := bytes.NewBufferString("")
|
|
err = serverutil.MinifyTemplate(gctemplates.ManageReports,
|
|
map[string]any{
|
|
"reports": reports,
|
|
"staff": staff,
|
|
}, reportsBuffer, "text/html")
|
|
if err != nil {
|
|
errEv.Err(err).Caller().Send()
|
|
return "", err
|
|
}
|
|
output = reportsBuffer.String()
|
|
return
|
|
}
|