Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook) and split all 44 files exceeding 500 LOC into domain-focused modules: - consent-service (Go): models, handlers, services, database splits - backend-core (Python): security_api, rbac_api, pdf_service, auth splits - admin-core (TypeScript): 5 page.tsx + sidebar extractions - pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits - voice-service (Python): enhanced_task_orchestrator split Result: 0 violations, 36 exempted (pipeline, tests, pure-data files). Go build verified clean. No behavior changes — pure structural splits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/breakpilot/consent-service/internal/middleware"
|
|
"github.com/breakpilot/consent-service/internal/models"
|
|
"github.com/breakpilot/consent-service/internal/services"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// DSRHandler handles Data Subject Request HTTP endpoints
|
|
type DSRHandler struct {
|
|
dsrService *services.DSRService
|
|
}
|
|
|
|
// NewDSRHandler creates a new DSR handler
|
|
func NewDSRHandler(dsrService *services.DSRService) *DSRHandler {
|
|
return &DSRHandler{
|
|
dsrService: dsrService,
|
|
}
|
|
}
|
|
|
|
// ========================================
|
|
// USER ENDPOINTS
|
|
// ========================================
|
|
|
|
// CreateDSR creates a new data subject request (user-facing)
|
|
func (h *DSRHandler) CreateDSR(c *gin.Context) {
|
|
userID, err := middleware.GetUserID(c)
|
|
if err != nil || userID == uuid.Nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
|
return
|
|
}
|
|
|
|
var req models.CreateDSRRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Get user email if not provided
|
|
if req.RequesterEmail == "" {
|
|
var email string
|
|
ctx := context.Background()
|
|
h.dsrService.GetPool().QueryRow(ctx, "SELECT email FROM users WHERE id = $1", userID).Scan(&email)
|
|
req.RequesterEmail = email
|
|
}
|
|
|
|
// Set source as API
|
|
req.Source = "api"
|
|
|
|
dsr, err := h.dsrService.CreateRequest(c.Request.Context(), req, &userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"message": "Ihre Anfrage wurde erfolgreich eingereicht",
|
|
"request_number": dsr.RequestNumber,
|
|
"dsr": dsr,
|
|
})
|
|
}
|
|
|
|
// GetMyDSRs returns DSRs for the current user
|
|
func (h *DSRHandler) GetMyDSRs(c *gin.Context) {
|
|
userID, err := middleware.GetUserID(c)
|
|
if err != nil || userID == uuid.Nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
|
return
|
|
}
|
|
|
|
dsrs, err := h.dsrService.ListByUser(c.Request.Context(), userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch requests"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"requests": dsrs})
|
|
}
|
|
|
|
// GetMyDSR returns a specific DSR for the current user
|
|
func (h *DSRHandler) GetMyDSR(c *gin.Context) {
|
|
userID, err := middleware.GetUserID(c)
|
|
if err != nil || userID == uuid.Nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
|
return
|
|
}
|
|
|
|
dsrID, err := uuid.Parse(c.Param("id"))
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
|
|
return
|
|
}
|
|
|
|
dsr, err := h.dsrService.GetByID(c.Request.Context(), dsrID)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Request not found"})
|
|
return
|
|
}
|
|
|
|
// Verify ownership
|
|
if dsr.UserID == nil || *dsr.UserID != userID {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "Access denied"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, dsr)
|
|
}
|
|
|
|
// CancelMyDSR cancels a user's own DSR
|
|
func (h *DSRHandler) CancelMyDSR(c *gin.Context) {
|
|
userID, err := middleware.GetUserID(c)
|
|
if err != nil || userID == uuid.Nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
|
return
|
|
}
|
|
|
|
dsrID, err := uuid.Parse(c.Param("id"))
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
|
|
return
|
|
}
|
|
|
|
err = h.dsrService.CancelRequest(c.Request.Context(), dsrID, userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Anfrage wurde storniert"})
|
|
}
|