forked from mirrors/pronouns.cc
feat(backend): add create user report endpoint
This commit is contained in:
parent
799d27b58c
commit
3bb97b8274
3 changed files with 88 additions and 9 deletions
|
@ -10,16 +10,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Report struct {
|
type Report struct {
|
||||||
ID int64
|
ID int64 `json:"id"`
|
||||||
UserID xid.ID
|
UserID xid.ID `json:"user_id"`
|
||||||
MemberID *xid.ID
|
MemberID *xid.ID `json:"member_id"`
|
||||||
Reason string
|
Reason string `json:"reason"`
|
||||||
ReporterID xid.ID
|
ReporterID xid.ID `json:"reporter_id"`
|
||||||
|
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time `json:"created_at"`
|
||||||
ResolvedAt *time.Time
|
ResolvedAt *time.Time `json:"resolved_at"`
|
||||||
AdminID *xid.ID
|
AdminID *xid.ID `json:"admin_id"`
|
||||||
AdminComment *string
|
AdminComment *string `json:"admin_comment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReportPageSize = 100
|
const ReportPageSize = 100
|
||||||
|
@ -88,3 +88,21 @@ func (db *DB) ReportsByReporter(ctx context.Context, reporterID xid.ID, before i
|
||||||
}
|
}
|
||||||
return rs, nil
|
return rs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DB) CreateReport(ctx context.Context, reporterID, userID xid.ID, memberID *xid.ID, reason string) (r Report, err error) {
|
||||||
|
sql, args, err := sq.Insert("reports").SetMap(map[string]any{
|
||||||
|
"user_id": userID,
|
||||||
|
"reporter_id": reporterID,
|
||||||
|
"member_id": memberID,
|
||||||
|
"reason": reason,
|
||||||
|
}).Suffix("RETURNING *").ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return r, errors.Wrap(err, "building sql")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pgxscan.Get(ctx, db, &r, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return r, errors.Wrap(err, "executing query")
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
58
backend/routes/mod/create_report.go
Normal file
58
backend/routes/mod/create_report.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package mod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"codeberg.org/u1f320/pronouns.cc/backend/db"
|
||||||
|
"codeberg.org/u1f320/pronouns.cc/backend/log"
|
||||||
|
"codeberg.org/u1f320/pronouns.cc/backend/server"
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/render"
|
||||||
|
"github.com/rs/xid"
|
||||||
|
)
|
||||||
|
|
||||||
|
const MaxReasonLength = 2000
|
||||||
|
|
||||||
|
type CreateReportRequest struct {
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) createUserReport(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
ctx := r.Context()
|
||||||
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
userID, err := xid.FromString(chi.URLParam(r, "id"))
|
||||||
|
if err != nil {
|
||||||
|
return server.APIError{Code: server.ErrBadRequest, Details: "Invalid user ID"}
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := s.DB.User(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
if err == db.ErrUserNotFound {
|
||||||
|
return server.APIError{Code: server.ErrUserNotFound}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Errorf("getting user %v: %v", userID, err)
|
||||||
|
return errors.Wrap(err, "getting user")
|
||||||
|
}
|
||||||
|
|
||||||
|
var req CreateReportRequest
|
||||||
|
err = render.Decode(r, &req)
|
||||||
|
if err != nil {
|
||||||
|
return server.APIError{Code: server.ErrBadRequest}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.Reason) > MaxReasonLength {
|
||||||
|
return server.APIError{Code: server.ErrBadRequest, Details: "Reason cannot exceed 2000 characters"}
|
||||||
|
}
|
||||||
|
|
||||||
|
report, err := s.DB.CreateReport(ctx, claims.UserID, u.ID, nil, req.Reason)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("creating report for %v: %v", u.ID, err)
|
||||||
|
return errors.Wrap(err, "creating report")
|
||||||
|
}
|
||||||
|
|
||||||
|
render.JSON(w, r, map[string]any{"created": true, "created_at": report.CreatedAt})
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -22,6 +22,9 @@ func Mount(srv *server.Server, r chi.Router) {
|
||||||
|
|
||||||
r.Patch("/reports/{id}", nil)
|
r.Patch("/reports/{id}", nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.With(server.MustAuth).Post("/users/{id}/reports", server.WrapHandler(s.createUserReport))
|
||||||
|
r.With(server.MustAuth).Post("/members/{id}/reports", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustAdmin(next http.Handler) http.Handler {
|
func MustAdmin(next http.Handler) http.Handler {
|
||||||
|
|
Loading…
Reference in a new issue