2026-02-25 18:53:04 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"net/http"
|
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
|
2026-03-06 23:54:35 +00:00
|
|
|
apperrors "veza-backend-api/internal/errors"
|
2026-02-25 18:53:04 +00:00
|
|
|
"veza-backend-api/internal/services"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ReportHandler handles moderation report endpoints (v0.803 ADM1)
|
|
|
|
|
type ReportHandler struct {
|
|
|
|
|
reportService *services.ReportService
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewReportHandler creates a new ReportHandler
|
|
|
|
|
func NewReportHandler(reportService *services.ReportService) *ReportHandler {
|
|
|
|
|
return &ReportHandler{reportService: reportService}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListReports returns paginated reports (admin only)
|
|
|
|
|
func (h *ReportHandler) ListReports(c *gin.Context) {
|
|
|
|
|
status := c.DefaultQuery("status", "all")
|
|
|
|
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
2026-03-12 05:13:38 +00:00
|
|
|
limit = clampLimit(limit) // SECURITY(MEDIUM-004)
|
2026-02-25 18:53:04 +00:00
|
|
|
offset, _ := strconv.Atoi(c.DefaultQuery("offset", "0"))
|
|
|
|
|
|
|
|
|
|
reports, total, err := h.reportService.List(c.Request.Context(), services.ListReportsParams{
|
|
|
|
|
Status: status,
|
|
|
|
|
Limit: limit,
|
|
|
|
|
Offset: offset,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to list reports", err))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
"reports": reports,
|
|
|
|
|
"pagination": gin.H{
|
|
|
|
|
"total": total,
|
|
|
|
|
"limit": limit,
|
|
|
|
|
"offset": offset,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ResolveReport resolves a report (admin only)
|
|
|
|
|
func (h *ReportHandler) ResolveReport(c *gin.Context) {
|
|
|
|
|
reportIDStr := c.Param("id")
|
|
|
|
|
reportID, err := uuid.Parse(reportIDStr)
|
|
|
|
|
if err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewValidationError("Invalid report ID"))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userID, ok := GetUserIDUUID(c)
|
|
|
|
|
if !ok || userID == uuid.Nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var req services.ResolveReportRequest
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewValidationError("action is required"))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := h.reportService.Resolve(c.Request.Context(), reportID, userID, req.Action); err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to resolve report", err))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Report resolved"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CreateReport creates a report (authenticated user)
|
|
|
|
|
func (h *ReportHandler) CreateReport(c *gin.Context) {
|
|
|
|
|
userID, ok := GetUserIDUUID(c)
|
|
|
|
|
if !ok || userID == uuid.Nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var req services.CreateReportRequest
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewValidationError("content_type and reason are required"))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
report, err := h.reportService.Create(c.Request.Context(), userID, req)
|
|
|
|
|
if err != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create report", err))
|
2026-02-25 18:53:04 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusCreated, report)
|
|
|
|
|
}
|