fix: DSR export type-cast bug + session rollback on partial failures
- tenant_id kept as string (PostgreSQL handles UUID cast) - Einwilligungen query uses CAST(:tid AS VARCHAR) for compatibility - Each data source query wrapped with rollback on failure to prevent cascading "transaction aborted" errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ class DSRExportService:
|
|||||||
def aggregate_user_data(self, tenant_id: str, email: str) -> dict[str, Any]:
|
def aggregate_user_data(self, tenant_id: str, email: str) -> dict[str, Any]:
|
||||||
"""Collect ALL data about a user from all CMP sources."""
|
"""Collect ALL data about a user from all CMP sources."""
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
tid = uuid.UUID(tenant_id) if len(tenant_id) > 20 else tenant_id
|
tid = tenant_id # Keep as string — let PostgreSQL cast
|
||||||
|
|
||||||
# 1. Banner consents + audit trail
|
# 1. Banner consents + audit trail
|
||||||
banner_data: dict[str, Any] = {"banner_consents": [], "audit_trail": []}
|
banner_data: dict[str, Any] = {"banner_consents": [], "audit_trail": []}
|
||||||
@@ -49,6 +49,10 @@ class DSRExportService:
|
|||||||
banner_data = banner_svc.export_for_dsr(tenant_id, email)
|
banner_data = banner_svc.export_for_dsr(tenant_id, email)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("Banner DSR export failed: %s", e)
|
logger.warning("Banner DSR export failed: %s", e)
|
||||||
|
try:
|
||||||
|
self.db.rollback()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 2. Einwilligungen (user-based consents)
|
# 2. Einwilligungen (user-based consents)
|
||||||
einwilligungen: list[dict] = []
|
einwilligungen: list[dict] = []
|
||||||
@@ -57,7 +61,7 @@ class DSRExportService:
|
|||||||
SELECT c.id, c.data_point_id, c.granted, c.granted_at, c.revoked_at,
|
SELECT c.id, c.data_point_id, c.granted, c.granted_at, c.revoked_at,
|
||||||
c.consent_version, c.source, c.ip_address, c.user_agent, c.created_at
|
c.consent_version, c.source, c.ip_address, c.user_agent, c.created_at
|
||||||
FROM compliance_einwilligungen_consents c
|
FROM compliance_einwilligungen_consents c
|
||||||
WHERE c.tenant_id = :tid AND c.user_id = :email
|
WHERE c.tenant_id = CAST(:tid AS VARCHAR) AND c.user_id = :email
|
||||||
ORDER BY c.created_at DESC
|
ORDER BY c.created_at DESC
|
||||||
""")
|
""")
|
||||||
rows = self.db.execute(q, {"tid": tid, "email": email}).fetchall()
|
rows = self.db.execute(q, {"tid": tid, "email": email}).fetchall()
|
||||||
@@ -83,6 +87,10 @@ class DSRExportService:
|
|||||||
einwilligungen.append(entry)
|
einwilligungen.append(entry)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("Einwilligungen export failed: %s", e)
|
logger.warning("Einwilligungen export failed: %s", e)
|
||||||
|
try:
|
||||||
|
self.db.rollback()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# 3. DSR requests by this user
|
# 3. DSR requests by this user
|
||||||
dsr_requests: list[dict] = []
|
dsr_requests: list[dict] = []
|
||||||
@@ -104,6 +112,10 @@ class DSRExportService:
|
|||||||
dsr_requests.append(entry)
|
dsr_requests.append(entry)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("DSR requests export failed: %s", e)
|
logger.warning("DSR requests export failed: %s", e)
|
||||||
|
try:
|
||||||
|
self.db.rollback()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"export_date": now.isoformat(),
|
"export_date": now.isoformat(),
|
||||||
|
|||||||
Reference in New Issue
Block a user