Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
364 lines
9.5 KiB
Go
364 lines
9.5 KiB
Go
// Package api provides HTTP handlers for the API Gateway
|
|
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// TokenRequest represents an OAuth token request
|
|
type TokenRequest struct {
|
|
GrantType string `json:"grant_type" binding:"required"`
|
|
ClientID string `json:"client_id" binding:"required"`
|
|
ClientSecret string `json:"client_secret" binding:"required"`
|
|
}
|
|
|
|
// TokenResponse represents an OAuth token response
|
|
type TokenResponse struct {
|
|
AccessToken string `json:"access_token"`
|
|
TokenType string `json:"token_type"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
RefreshToken string `json:"refresh_token,omitempty"`
|
|
}
|
|
|
|
// GetToken handles OAuth token requests
|
|
func GetToken(c *gin.Context) {
|
|
var req TokenRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Validate credentials (in production, check against database)
|
|
// For now, accept any valid-looking credentials
|
|
if req.GrantType != "client_credentials" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Unsupported grant type"})
|
|
return
|
|
}
|
|
|
|
// Extract tenant ID from client ID (format: sdk_tenantid)
|
|
tenantID := req.ClientID
|
|
if len(tenantID) > 4 {
|
|
tenantID = tenantID[4:] // Remove "sdk_" prefix
|
|
}
|
|
|
|
// Generate JWT
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
|
"tenant_id": tenantID,
|
|
"user_id": req.ClientID,
|
|
"scopes": []string{"read", "write"},
|
|
"exp": time.Now().Add(24 * time.Hour).Unix(),
|
|
"iat": time.Now().Unix(),
|
|
})
|
|
|
|
// Sign token (in production, use config.JWTSecret)
|
|
tokenString, _ := token.SignedString([]byte("your-secret-key-change-in-production"))
|
|
|
|
c.JSON(http.StatusOK, TokenResponse{
|
|
AccessToken: tokenString,
|
|
TokenType: "Bearer",
|
|
ExpiresIn: 86400,
|
|
})
|
|
}
|
|
|
|
// RefreshToken handles token refresh requests
|
|
func RefreshToken(c *gin.Context) {
|
|
// In production, validate refresh token and issue new access token
|
|
c.JSON(http.StatusOK, gin.H{"message": "Token refreshed"})
|
|
}
|
|
|
|
// =============================================================================
|
|
// State Management
|
|
// =============================================================================
|
|
|
|
// GetState retrieves the SDK state for a tenant
|
|
func GetState(c *gin.Context) {
|
|
tenantID := c.Param("tenantId")
|
|
|
|
// In production, fetch from database
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"tenant_id": tenantID,
|
|
"state": gin.H{
|
|
"version": 1,
|
|
"completedSteps": []string{},
|
|
"currentStep": "overview",
|
|
},
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// SaveState saves the SDK state for a tenant
|
|
func SaveState(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// In production, save to database with optimistic locking
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"version": 1,
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// ResetState resets the SDK state for a tenant
|
|
func ResetState(c *gin.Context) {
|
|
tenantID, _ := c.Get("tenant_id")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"tenant_id": tenantID,
|
|
"message": "State reset successfully",
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / Consent
|
|
// =============================================================================
|
|
|
|
// RecordConsent records a consent decision
|
|
func RecordConsent(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"created_at": time.Now().Format(time.RFC3339),
|
|
"status": "ACTIVE",
|
|
})
|
|
}
|
|
|
|
// GetConsents retrieves consents for a user
|
|
func GetConsents(c *gin.Context) {
|
|
userID := c.Param("userId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"user_id": userID,
|
|
"consents": []interface{}{},
|
|
})
|
|
}
|
|
|
|
// RevokeConsent revokes a consent
|
|
func RevokeConsent(c *gin.Context) {
|
|
consentID := c.Param("consentId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": consentID,
|
|
"status": "REVOKED",
|
|
"revoked_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / DSR
|
|
// =============================================================================
|
|
|
|
// SubmitDSR submits a new DSR request
|
|
func SubmitDSR(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"status": "PENDING",
|
|
"submitted_at": time.Now().Format(time.RFC3339),
|
|
"deadline": time.Now().AddDate(0, 1, 0).Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// ListDSRRequests lists DSR requests for a tenant
|
|
func ListDSRRequests(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"requests": []interface{}{},
|
|
"total": 0,
|
|
})
|
|
}
|
|
|
|
// UpdateDSRStatus updates the status of a DSR request
|
|
func UpdateDSRStatus(c *gin.Context) {
|
|
requestID := c.Param("requestId")
|
|
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": requestID,
|
|
"status": req["status"],
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / VVT
|
|
// =============================================================================
|
|
|
|
// GetProcessingActivities retrieves processing activities
|
|
func GetProcessingActivities(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"activities": []interface{}{},
|
|
"total": 0,
|
|
})
|
|
}
|
|
|
|
// CreateProcessingActivity creates a new processing activity
|
|
func CreateProcessingActivity(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"created_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// UpdateProcessingActivity updates a processing activity
|
|
func UpdateProcessingActivity(c *gin.Context) {
|
|
activityID := c.Param("activityId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": activityID,
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// DeleteProcessingActivity deletes a processing activity
|
|
func DeleteProcessingActivity(c *gin.Context) {
|
|
c.JSON(http.StatusNoContent, nil)
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / TOM
|
|
// =============================================================================
|
|
|
|
// GetTOMs retrieves TOMs
|
|
func GetTOMs(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"toms": []interface{}{},
|
|
"total": 0,
|
|
})
|
|
}
|
|
|
|
// CreateTOM creates a new TOM
|
|
func CreateTOM(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"created_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// UpdateTOM updates a TOM
|
|
func UpdateTOM(c *gin.Context) {
|
|
tomID := c.Param("tomId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": tomID,
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// DeleteTOM deletes a TOM
|
|
func DeleteTOM(c *gin.Context) {
|
|
c.JSON(http.StatusNoContent, nil)
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / DSFA
|
|
// =============================================================================
|
|
|
|
// GetDSFAs retrieves DSFAs
|
|
func GetDSFAs(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"dsfas": []interface{}{},
|
|
"total": 0,
|
|
})
|
|
}
|
|
|
|
// CreateDSFA creates a new DSFA
|
|
func CreateDSFA(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"created_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// UpdateDSFA updates a DSFA
|
|
func UpdateDSFA(c *gin.Context) {
|
|
dsfaID := c.Param("dsfaId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": dsfaID,
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// =============================================================================
|
|
// DSGVO / Retention
|
|
// =============================================================================
|
|
|
|
// GetRetentionPolicies retrieves retention policies
|
|
func GetRetentionPolicies(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"policies": []interface{}{},
|
|
"total": 0,
|
|
})
|
|
}
|
|
|
|
// CreateRetentionPolicy creates a new retention policy
|
|
func CreateRetentionPolicy(c *gin.Context) {
|
|
var req map[string]interface{}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"id": uuid.New().String(),
|
|
"created_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// UpdateRetentionPolicy updates a retention policy
|
|
func UpdateRetentionPolicy(c *gin.Context) {
|
|
policyID := c.Param("policyId")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"id": policyID,
|
|
"updated_at": time.Now().Format(time.RFC3339),
|
|
})
|
|
}
|
|
|
|
// DeleteRetentionPolicy deletes a retention policy
|
|
func DeleteRetentionPolicy(c *gin.Context) {
|
|
c.JSON(http.StatusNoContent, nil)
|
|
}
|