A community based topic aggregation platform built on atproto
1package adminreport
2
3import (
4 "Coves/internal/api/middleware"
5 "Coves/internal/core/adminreports"
6 "encoding/json"
7 "log"
8 "net/http"
9)
10
11// SubmitHandler handles report submission requests
12type SubmitHandler struct {
13 service adminreports.Service
14}
15
16// NewSubmitHandler creates a new handler for submitting admin reports
17func NewSubmitHandler(service adminreports.Service) *SubmitHandler {
18 return &SubmitHandler{
19 service: service,
20 }
21}
22
23// SubmitReportInput matches the lexicon input schema for social.coves.admin.submitReport
24type SubmitReportInput struct {
25 TargetURI string `json:"targetUri"`
26 Reason string `json:"reason"`
27 Explanation string `json:"explanation"`
28}
29
30// SubmitReportOutput matches the lexicon output schema
31type SubmitReportOutput struct {
32 Success bool `json:"success"`
33 ReportID int64 `json:"reportId"`
34}
35
36// HandleSubmit handles report submission requests
37// POST /xrpc/social.coves.admin.submitReport
38//
39// Request body: { "targetUri": "at://...", "reason": "csam", "explanation": "..." }
40// Response: { "success": true, "reportId": 123 }
41func (h *SubmitHandler) HandleSubmit(w http.ResponseWriter, r *http.Request) {
42 // 1. Check method is POST
43 if r.Method != http.MethodPost {
44 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
45 return
46 }
47
48 // 2. Limit request body size to 10KB to prevent DoS attacks
49 r.Body = http.MaxBytesReader(w, r.Body, 10*1024)
50
51 // 3. Parse JSON body into SubmitReportInput
52 var input SubmitReportInput
53 if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
54 // Log the decode error for debugging (but don't expose to client)
55 log.Printf("[ADMIN_REPORT] Failed to decode JSON request: %v", err)
56 writeError(w, http.StatusBadRequest, "InvalidRequest", "Invalid request body")
57 return
58 }
59
60 // 4. Get user DID from context (injected by auth middleware)
61 userDID := middleware.GetUserDID(r)
62 if userDID == "" {
63 writeError(w, http.StatusUnauthorized, "AuthRequired", "Authentication required")
64 return
65 }
66
67 // 5. Convert input to SubmitReportRequest
68 req := adminreports.SubmitReportRequest{
69 ReporterDID: userDID,
70 TargetURI: input.TargetURI,
71 Reason: input.Reason,
72 Explanation: input.Explanation,
73 }
74
75 // 6. Call service to submit report
76 result, err := h.service.SubmitReport(r.Context(), req)
77 if err != nil {
78 handleServiceError(w, err)
79 return
80 }
81
82 // 7. Return JSON response indicating success with report ID
83 output := SubmitReportOutput{
84 Success: true,
85 ReportID: result.ReportID,
86 }
87
88 w.Header().Set("Content-Type", "application/json")
89 w.WriteHeader(http.StatusOK)
90 if err := json.NewEncoder(w).Encode(output); err != nil {
91 log.Printf("Failed to encode response: %v", err)
92 }
93}