This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/backend/dsr_api.py
BreakPilot Dev 19855efacc
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
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
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.
2026-02-11 13:25:58 +01:00

112 lines
4.0 KiB
Python

"""
Data Subject Request (DSR) API - Betroffenenanfragen nach DSGVO
Benutzer-Endpunkte zum Erstellen und Verwalten eigener Betroffenenanfragen
"""
from fastapi import APIRouter, HTTPException, Header, Query
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, EmailStr
import httpx
import os
from consent_client import generate_jwt_token, JWT_SECRET
# Consent Service URL
CONSENT_SERVICE_URL = os.getenv("CONSENT_SERVICE_URL", "http://localhost:8081")
router = APIRouter(prefix="/v1/dsr", tags=["dsr"])
# Request Models
class CreateDSRRequest(BaseModel):
"""Anfrage zum Erstellen einer Betroffenenanfrage"""
request_type: str # access, rectification, erasure, restriction, portability
requester_email: Optional[str] = None
requester_name: Optional[str] = None
requester_phone: Optional[str] = None
request_details: Optional[Dict[str, Any]] = None
# Helper to extract token
def get_token(authorization: Optional[str]) -> str:
if authorization:
parts = authorization.split(" ")
if len(parts) == 2 and parts[0] == "Bearer":
return parts[1]
raise HTTPException(status_code=401, detail="Authorization required")
async def proxy_request(method: str, path: str, token: str, json_data=None, query_params=None):
"""Proxied Anfragen an den Go Consent Service"""
url = f"{CONSENT_SERVICE_URL}/api/v1{path}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
async with httpx.AsyncClient() as client:
try:
if method == "GET":
response = await client.get(url, headers=headers, params=query_params, timeout=10.0)
elif method == "POST":
response = await client.post(url, headers=headers, json=json_data, timeout=10.0)
elif method == "PUT":
response = await client.put(url, headers=headers, json=json_data, timeout=10.0)
elif method == "DELETE":
response = await client.delete(url, headers=headers, timeout=10.0)
else:
raise HTTPException(status_code=400, detail="Invalid method")
if response.status_code >= 400:
error_detail = response.json() if response.content else {"error": "Unknown error"}
raise HTTPException(status_code=response.status_code, detail=error_detail)
return response.json() if response.content else {"success": True}
except httpx.RequestError as e:
raise HTTPException(status_code=503, detail=f"Consent Service unavailable: {str(e)}")
# ==========================================
# User DSR Endpoints
# ==========================================
@router.post("")
async def create_dsr(
request: CreateDSRRequest,
authorization: str = Header(...)
):
"""
Erstellt eine neue Betroffenenanfrage.
request_type muss einer der folgenden Werte sein:
- access: Auskunftsrecht (Art. 15 DSGVO)
- rectification: Recht auf Berichtigung (Art. 16 DSGVO)
- erasure: Recht auf Löschung (Art. 17 DSGVO)
- restriction: Recht auf Einschränkung (Art. 18 DSGVO)
- portability: Recht auf Datenübertragbarkeit (Art. 20 DSGVO)
"""
token = get_token(authorization)
return await proxy_request("POST", "/dsr", token, request.dict(exclude_none=True))
@router.get("")
async def get_my_dsrs(authorization: str = Header(...)):
"""Gibt alle eigenen Betroffenenanfragen zurück"""
token = get_token(authorization)
return await proxy_request("GET", "/dsr", token)
@router.get("/{dsr_id}")
async def get_my_dsr(dsr_id: str, authorization: str = Header(...)):
"""Gibt Details einer eigenen Betroffenenanfrage zurück"""
token = get_token(authorization)
return await proxy_request("GET", f"/dsr/{dsr_id}", token)
@router.post("/{dsr_id}/cancel")
async def cancel_my_dsr(dsr_id: str, authorization: str = Header(...)):
"""Storniert eine eigene Betroffenenanfrage"""
token = get_token(authorization)
return await proxy_request("POST", f"/dsr/{dsr_id}/cancel", token)