311 lines
12 KiB
Python
311 lines
12 KiB
Python
"""
|
|
OAuth Token Monitoring API Routes
|
|
Provides endpoints for managing OAuth token monitoring tasks and manual triggers.
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Dict, Any, Optional
|
|
from datetime import datetime
|
|
from loguru import logger
|
|
|
|
from services.database import get_db_session
|
|
from middleware.auth_middleware import get_current_user
|
|
from models.oauth_token_monitoring_models import OAuthTokenMonitoringTask, OAuthTokenExecutionLog
|
|
from services.scheduler import get_scheduler
|
|
from services.oauth_token_monitoring_service import create_oauth_monitoring_tasks, get_connected_platforms
|
|
|
|
router = APIRouter(prefix="/api/oauth-tokens", tags=["oauth-tokens"])
|
|
|
|
|
|
@router.get("/status/{user_id}")
|
|
async def get_oauth_token_status(
|
|
user_id: str,
|
|
db: Session = Depends(get_db_session),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Get OAuth token monitoring status for all platforms for a user.
|
|
|
|
Returns:
|
|
- List of monitoring tasks with status
|
|
- Connection status for each platform
|
|
- Last check time, last success, last failure
|
|
"""
|
|
try:
|
|
# Verify user can only access their own data
|
|
if str(current_user.get('id')) != user_id:
|
|
raise HTTPException(status_code=403, detail="Access denied")
|
|
|
|
# Get all monitoring tasks for user
|
|
tasks = db.query(OAuthTokenMonitoringTask).filter(
|
|
OAuthTokenMonitoringTask.user_id == user_id
|
|
).all()
|
|
|
|
# Get connected platforms
|
|
logger.info(f"[OAuth Status API] Getting token status for user: {user_id}")
|
|
connected_platforms = get_connected_platforms(user_id)
|
|
logger.info(f"[OAuth Status API] Found {len(connected_platforms)} connected platforms: {connected_platforms}")
|
|
|
|
# Build status response
|
|
platform_status = {}
|
|
for platform in ['gsc', 'bing', 'wordpress', 'wix']:
|
|
task = next((t for t in tasks if t.platform == platform), None)
|
|
is_connected = platform in connected_platforms
|
|
|
|
platform_status[platform] = {
|
|
'connected': is_connected,
|
|
'monitoring_task': {
|
|
'id': task.id if task else None,
|
|
'status': task.status if task else 'not_created',
|
|
'last_check': task.last_check.isoformat() if task and task.last_check else None,
|
|
'last_success': task.last_success.isoformat() if task and task.last_success else None,
|
|
'last_failure': task.last_failure.isoformat() if task and task.last_failure else None,
|
|
'failure_reason': task.failure_reason if task else None,
|
|
'next_check': task.next_check.isoformat() if task and task.next_check else None,
|
|
} if task else None
|
|
}
|
|
|
|
logger.info(
|
|
f"[OAuth Status API] Platform {platform}: "
|
|
f"connected={is_connected}, "
|
|
f"task_exists={task is not None}, "
|
|
f"task_status={task.status if task else 'N/A'}"
|
|
)
|
|
|
|
response_data = {
|
|
"success": True,
|
|
"data": {
|
|
"user_id": user_id,
|
|
"platform_status": platform_status,
|
|
"connected_platforms": connected_platforms
|
|
}
|
|
}
|
|
|
|
logger.info(f"[OAuth Status API] Returning status for user {user_id}: {len(connected_platforms)} platforms connected")
|
|
return response_data
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting OAuth token status for user {user_id}: {e}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=f"Failed to get token status: {str(e)}")
|
|
|
|
|
|
@router.post("/refresh/{user_id}/{platform}")
|
|
async def manual_refresh_token(
|
|
user_id: str,
|
|
platform: str,
|
|
db: Session = Depends(get_db_session),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Manually trigger token refresh for a specific platform.
|
|
|
|
This will:
|
|
1. Find or create the monitoring task
|
|
2. Execute the token check/refresh immediately
|
|
3. Update the task status and next_check time
|
|
|
|
Args:
|
|
user_id: User ID
|
|
platform: Platform identifier ('gsc', 'bing', 'wordpress', 'wix')
|
|
"""
|
|
try:
|
|
# Verify user can only access their own data
|
|
if str(current_user.get('id')) != user_id:
|
|
raise HTTPException(status_code=403, detail="Access denied")
|
|
|
|
# Validate platform
|
|
valid_platforms = ['gsc', 'bing', 'wordpress', 'wix']
|
|
if platform not in valid_platforms:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Invalid platform. Must be one of: {', '.join(valid_platforms)}"
|
|
)
|
|
|
|
# Get or create monitoring task
|
|
task = db.query(OAuthTokenMonitoringTask).filter(
|
|
OAuthTokenMonitoringTask.user_id == user_id,
|
|
OAuthTokenMonitoringTask.platform == platform
|
|
).first()
|
|
|
|
if not task:
|
|
# Create task if it doesn't exist
|
|
task = OAuthTokenMonitoringTask(
|
|
user_id=user_id,
|
|
platform=platform,
|
|
status='active',
|
|
next_check=datetime.utcnow(), # Set to now to trigger immediately
|
|
created_at=datetime.utcnow(),
|
|
updated_at=datetime.utcnow()
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
db.refresh(task)
|
|
logger.info(f"Created monitoring task for manual refresh: user={user_id}, platform={platform}")
|
|
|
|
# Get scheduler and executor
|
|
scheduler = get_scheduler()
|
|
try:
|
|
executor = scheduler.registry.get_executor('oauth_token_monitoring')
|
|
except ValueError:
|
|
raise HTTPException(status_code=500, detail="OAuth token monitoring executor not available")
|
|
|
|
# Execute task immediately
|
|
logger.info(f"Manually triggering token refresh: user={user_id}, platform={platform}")
|
|
result = await executor.execute_task(task, db)
|
|
|
|
# Get updated task
|
|
db.refresh(task)
|
|
|
|
return {
|
|
"success": result.success,
|
|
"message": "Token refresh completed" if result.success else "Token refresh failed",
|
|
"data": {
|
|
"platform": platform,
|
|
"status": task.status,
|
|
"last_check": task.last_check.isoformat() if task.last_check else None,
|
|
"last_success": task.last_success.isoformat() if task.last_success else None,
|
|
"last_failure": task.last_failure.isoformat() if task.last_failure else None,
|
|
"failure_reason": task.failure_reason,
|
|
"next_check": task.next_check.isoformat() if task.next_check else None,
|
|
"execution_result": {
|
|
"success": result.success,
|
|
"error_message": result.error_message,
|
|
"execution_time_ms": result.execution_time_ms,
|
|
"result_data": result.result_data
|
|
}
|
|
}
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error manually refreshing token for user {user_id}, platform {platform}: {e}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=f"Failed to refresh token: {str(e)}")
|
|
|
|
|
|
@router.get("/execution-logs/{user_id}")
|
|
async def get_execution_logs(
|
|
user_id: str,
|
|
platform: Optional[str] = Query(None, description="Filter by platform"),
|
|
limit: int = Query(50, ge=1, le=100, description="Maximum number of logs"),
|
|
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
|
db: Session = Depends(get_db_session),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Get execution logs for OAuth token monitoring tasks.
|
|
|
|
Args:
|
|
user_id: User ID
|
|
platform: Optional platform filter
|
|
limit: Maximum number of logs to return
|
|
offset: Pagination offset
|
|
"""
|
|
try:
|
|
# Verify user can only access their own data
|
|
if str(current_user.get('id')) != user_id:
|
|
raise HTTPException(status_code=403, detail="Access denied")
|
|
|
|
# Build query
|
|
query = db.query(OAuthTokenExecutionLog).join(
|
|
OAuthTokenMonitoringTask,
|
|
OAuthTokenExecutionLog.task_id == OAuthTokenMonitoringTask.id
|
|
).filter(
|
|
OAuthTokenMonitoringTask.user_id == user_id
|
|
)
|
|
|
|
# Apply platform filter if provided
|
|
if platform:
|
|
query = query.filter(OAuthTokenMonitoringTask.platform == platform)
|
|
|
|
# Get total count
|
|
total_count = query.count()
|
|
|
|
# Get paginated logs
|
|
logs = query.order_by(
|
|
OAuthTokenExecutionLog.execution_date.desc()
|
|
).offset(offset).limit(limit).all()
|
|
|
|
# Format logs
|
|
logs_data = []
|
|
for log in logs:
|
|
logs_data.append({
|
|
"id": log.id,
|
|
"task_id": log.task_id,
|
|
"platform": log.task.platform, # Get platform from relationship
|
|
"execution_date": log.execution_date.isoformat(),
|
|
"status": log.status,
|
|
"result_data": log.result_data,
|
|
"error_message": log.error_message,
|
|
"execution_time_ms": log.execution_time_ms,
|
|
"created_at": log.created_at.isoformat()
|
|
})
|
|
|
|
return {
|
|
"success": True,
|
|
"data": {
|
|
"logs": logs_data,
|
|
"total_count": total_count,
|
|
"limit": limit,
|
|
"offset": offset
|
|
}
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting execution logs for user {user_id}: {e}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=f"Failed to get execution logs: {str(e)}")
|
|
|
|
|
|
@router.post("/create-tasks/{user_id}")
|
|
async def create_monitoring_tasks(
|
|
user_id: str,
|
|
platforms: Optional[List[str]] = None,
|
|
db: Session = Depends(get_db_session),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Manually create OAuth token monitoring tasks for a user.
|
|
|
|
If platforms are not provided, automatically detects connected platforms.
|
|
|
|
Args:
|
|
user_id: User ID
|
|
platforms: Optional list of platforms to create tasks for
|
|
"""
|
|
try:
|
|
# Verify user can only access their own data
|
|
if str(current_user.get('id')) != user_id:
|
|
raise HTTPException(status_code=403, detail="Access denied")
|
|
|
|
# Create tasks
|
|
tasks = create_oauth_monitoring_tasks(user_id, db, platforms)
|
|
|
|
return {
|
|
"success": True,
|
|
"message": f"Created {len(tasks)} monitoring task(s)",
|
|
"data": {
|
|
"tasks_created": len(tasks),
|
|
"tasks": [
|
|
{
|
|
"id": task.id,
|
|
"platform": task.platform,
|
|
"status": task.status,
|
|
"next_check": task.next_check.isoformat() if task.next_check else None
|
|
}
|
|
for task in tasks
|
|
]
|
|
}
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error creating monitoring tasks for user {user_id}: {e}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=f"Failed to create monitoring tasks: {str(e)}")
|
|
|