mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-11-09 21:45:13 +00:00
feat: Add compliance handler with DSR management, consent tracking, audit logging, and data residency endpoints
- Add ComplianceHandler struct with service and logger dependencies and NewComplianceHandler constructor - Add CreateDSR, GetDSR, ListDSRs, and ProcessDSR methods for data subject request management - Add RecordConsent, RevokeConsent, and GetConsents methods for consent tracking with IP and user agent capture - Add QueryAuditLogs method with jurisdiction, actor, and action filtering - Add SetDataRes
This commit is contained in:
@@ -0,0 +1,171 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/compliance"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComplianceHandler handles compliance API requests
|
||||||
|
type ComplianceHandler struct {
|
||||||
|
service *compliance.Service
|
||||||
|
logger *logrus.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewComplianceHandler creates a new compliance handler
|
||||||
|
func NewComplianceHandler(service *compliance.Service, logger *logrus.Logger) *ComplianceHandler {
|
||||||
|
return &ComplianceHandler{service: service, logger: logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDSR creates a data subject request
|
||||||
|
func (h *ComplianceHandler) CreateDSR(c *gin.Context) {
|
||||||
|
var req compliance.DataSubjectRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.TenantID = c.GetHeader("X-Tenant-ID")
|
||||||
|
if err := h.service.CreateDSR(c.Request.Context(), &req); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusCreated, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDSR retrieves a data subject request
|
||||||
|
func (h *ComplianceHandler) GetDSR(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
dsr, err := h.service.GetDSR(c.Request.Context(), id)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, dsr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDSRs lists data subject requests
|
||||||
|
func (h *ComplianceHandler) ListDSRs(c *gin.Context) {
|
||||||
|
tenantID := c.GetHeader("X-Tenant-ID")
|
||||||
|
var status *compliance.DSRStatus
|
||||||
|
if s := c.Query("status"); s != "" {
|
||||||
|
st := compliance.DSRStatus(s)
|
||||||
|
status = &st
|
||||||
|
}
|
||||||
|
|
||||||
|
dsrs, err := h.service.ListDSRs(c.Request.Context(), tenantID, status)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, dsrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessDSR processes a data subject request
|
||||||
|
func (h *ComplianceHandler) ProcessDSR(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
if err := h.service.ProcessDSR(c.Request.Context(), id); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{"status": "processing"})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordConsent records user consent
|
||||||
|
func (h *ComplianceHandler) RecordConsent(c *gin.Context) {
|
||||||
|
var consent compliance.ConsentRecord
|
||||||
|
if err := c.ShouldBindJSON(&consent); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
consent.TenantID = c.GetHeader("X-Tenant-ID")
|
||||||
|
consent.IPAddress = c.ClientIP()
|
||||||
|
consent.UserAgent = c.GetHeader("User-Agent")
|
||||||
|
|
||||||
|
if err := h.service.RecordConsent(c.Request.Context(), &consent); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusCreated, consent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeConsent revokes user consent
|
||||||
|
func (h *ComplianceHandler) RevokeConsent(c *gin.Context) {
|
||||||
|
subjectID := c.Param("subject_id")
|
||||||
|
consentType := compliance.ConsentType(c.Query("type"))
|
||||||
|
|
||||||
|
if err := h.service.RevokeConsent(c.Request.Context(), subjectID, consentType); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{"status": "revoked"})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConsents retrieves consent records for a subject
|
||||||
|
func (h *ComplianceHandler) GetConsents(c *gin.Context) {
|
||||||
|
subjectID := c.Param("subject_id")
|
||||||
|
consents, err := h.service.GetConsents(c.Request.Context(), subjectID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, consents)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryAuditLogs queries audit logs
|
||||||
|
func (h *ComplianceHandler) QueryAuditLogs(c *gin.Context) {
|
||||||
|
tenantID := c.GetHeader("X-Tenant-ID")
|
||||||
|
filter := &compliance.AuditLogFilter{
|
||||||
|
Jurisdiction: c.Query("jurisdiction"),
|
||||||
|
ActorID: c.Query("actor_id"),
|
||||||
|
Action: c.Query("action"),
|
||||||
|
Limit: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
logs, err := h.service.QueryAuditLogs(c.Request.Context(), tenantID, filter)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, logs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDataResidency sets data residency configuration
|
||||||
|
func (h *ComplianceHandler) SetDataResidency(c *gin.Context) {
|
||||||
|
var config compliance.DataResidencyConfig
|
||||||
|
if err := c.ShouldBindJSON(&config); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config.TenantID = c.GetHeader("X-Tenant-ID")
|
||||||
|
if err := h.service.SetDataResidency(c.Request.Context(), &config); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDataResidency retrieves data residency configuration
|
||||||
|
func (h *ComplianceHandler) GetDataResidency(c *gin.Context) {
|
||||||
|
tenantID := c.GetHeader("X-Tenant-ID")
|
||||||
|
config, err := h.service.GetDataResidency(c.Request.Context(), tenantID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, config)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user