feat(backend): add create user report endpoint

This commit is contained in:
Sam 2023-03-21 17:16:16 +01:00
parent 799d27b58c
commit 3bb97b8274
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
3 changed files with 88 additions and 9 deletions

View file

@ -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
}

View 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
}

View file

@ -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 {