""" Internal API for Demo Session Service Handles internal service-to-service operations """ from fastapi import APIRouter, Depends, HTTPException, Header from sqlalchemy.ext.asyncio import AsyncSession import structlog from app.core import get_db, settings from app.core.redis_wrapper import get_redis, DemoRedisWrapper from app.services.data_cloner import DemoDataCloner logger = structlog.get_logger() router = APIRouter() async def verify_internal_api_key(x_internal_api_key: str = Header(None)): """Verify internal API key for service-to-service communication""" required_key = settings.INTERNAL_API_KEY if x_internal_api_key != required_key: logger.warning("Unauthorized internal API access attempted") raise HTTPException(status_code=403, detail="Invalid internal API key") return True @router.post("/internal/demo/cleanup") async def cleanup_demo_session_internal( cleanup_request: dict, db: AsyncSession = Depends(get_db), redis: DemoRedisWrapper = Depends(get_redis), _: bool = Depends(verify_internal_api_key) ): """ Internal endpoint to cleanup demo session data for a specific tenant Used by rollback mechanisms """ try: tenant_id = cleanup_request.get('tenant_id') session_id = cleanup_request.get('session_id') if not all([tenant_id, session_id]): raise HTTPException( status_code=400, detail="Missing required parameters: tenant_id, session_id" ) logger.info( "Internal cleanup requested", tenant_id=tenant_id, session_id=session_id ) data_cloner = DemoDataCloner(db, redis) # Delete session data for this tenant await data_cloner.delete_session_data( str(tenant_id), session_id ) logger.info( "Internal cleanup completed", tenant_id=tenant_id, session_id=session_id ) return { "status": "completed", "tenant_id": tenant_id, "session_id": session_id } except Exception as e: logger.error( "Internal cleanup failed", error=str(e), tenant_id=cleanup_request.get('tenant_id'), session_id=cleanup_request.get('session_id'), exc_info=True ) raise HTTPException(status_code=500, detail=f"Failed to cleanup demo session: {str(e)}")