Files
bakery-ia/services/auth/app/api/data_export.py

122 lines
3.8 KiB
Python
Raw Permalink Normal View History

2025-10-16 07:28:04 +02:00
"""
User data export API endpoints for GDPR compliance
Implements Article 15 (Right to Access) and Article 20 (Right to Data Portability)
"""
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import JSONResponse
import structlog
from shared.auth.decorators import get_current_user_dep
from app.core.database import get_db
from app.services.data_export_service import DataExportService
logger = structlog.get_logger()
router = APIRouter()
2025-10-27 16:33:26 +01:00
@router.get("/api/v1/auth/me/export")
2025-10-16 07:28:04 +02:00
async def export_my_data(
current_user: dict = Depends(get_current_user_dep),
db = Depends(get_db)
):
"""
Export all personal data for the current user
GDPR Article 15 - Right of access by the data subject
GDPR Article 20 - Right to data portability
Returns complete user data in machine-readable JSON format including:
- Personal information
- Account data
- Consent history
- Security logs
- Audit trail
Response is provided in JSON format for easy data portability.
"""
try:
2025-10-27 16:33:26 +01:00
user_id = UUID(current_user["user_id"])
2025-10-16 07:28:04 +02:00
export_service = DataExportService(db)
data = await export_service.export_user_data(user_id)
logger.info(
"data_export_requested",
user_id=str(user_id),
email=current_user.get("email")
)
return JSONResponse(
content=data,
status_code=status.HTTP_200_OK,
headers={
"Content-Disposition": f'attachment; filename="user_data_export_{user_id}.json"',
"Content-Type": "application/json"
}
)
except Exception as e:
logger.error(
"data_export_failed",
2025-10-27 16:33:26 +01:00
user_id=current_user.get("user_id"),
2025-10-16 07:28:04 +02:00
error=str(e)
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to export user data"
)
2025-10-27 16:33:26 +01:00
@router.get("/api/v1/auth/me/export/summary")
2025-10-16 07:28:04 +02:00
async def get_export_summary(
current_user: dict = Depends(get_current_user_dep),
db = Depends(get_db)
):
"""
Get a summary of what data would be exported
Useful for showing users what data we have about them
before they request full export.
"""
try:
2025-10-27 16:33:26 +01:00
user_id = UUID(current_user["user_id"])
2025-10-16 07:28:04 +02:00
export_service = DataExportService(db)
data = await export_service.export_user_data(user_id)
summary = {
"user_id": str(user_id),
"data_categories": {
"personal_data": bool(data.get("personal_data")),
"account_data": bool(data.get("account_data")),
"consent_data": bool(data.get("consent_data")),
"security_data": bool(data.get("security_data")),
"onboarding_data": bool(data.get("onboarding_data")),
"audit_logs": bool(data.get("audit_logs"))
},
"data_counts": {
"active_sessions": data.get("account_data", {}).get("active_sessions_count", 0),
"consent_changes": data.get("consent_data", {}).get("total_consent_changes", 0),
"login_attempts": len(data.get("security_data", {}).get("recent_login_attempts", [])),
"audit_logs": data.get("audit_logs", {}).get("total_logs_exported", 0)
},
"export_format": "JSON",
"gdpr_articles": ["Article 15 (Right to Access)", "Article 20 (Data Portability)"]
}
return summary
except Exception as e:
logger.error(
"export_summary_failed",
2025-10-27 16:33:26 +01:00
user_id=current_user.get("user_id"),
2025-10-16 07:28:04 +02:00
error=str(e)
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to generate export summary"
)