gateway/modules/routes/routeDataConnections.py
2025-05-30 01:12:59 +02:00

164 lines
No EOL
5.7 KiB
Python

"""
Connection routes for the backend API.
Implements the endpoints for connection management.
"""
from fastapi import APIRouter, HTTPException, Depends, Body, Path, Request, Response
from typing import List, Dict, Any, Optional
from fastapi import status
from datetime import datetime
import logging
from modules.interfaces.serviceAppModel import User, UserConnection, AuthAuthority, ConnectionStatus
from modules.security.auth import getCurrentUser, limiter
from modules.interfaces.serviceAppClass import getInterface, getRootInterface
# Configure logger
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/api/connections",
tags=["Manage Connections"],
responses={404: {"description": "Not found"}}
)
@router.get("/", response_model=List[UserConnection])
@limiter.limit("30/minute")
async def get_connections(
request: Request,
currentUser: User = Depends(getCurrentUser)
) -> List[UserConnection]:
"""Get all connections for the current user or all connections if admin"""
try:
interface = getInterface(currentUser)
if currentUser.privilege in ['admin', 'sysadmin']:
# Admins can see all connections
users = interface.getAllUsers()
connections = []
for user in users:
connections.extend(user.connections)
return connections
else:
# Regular users can only see their own connections
return currentUser.connections
except Exception as e:
logger.error(f"Error getting connections: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get connections: {str(e)}"
)
@router.post("/{connectionId}/connect")
@limiter.limit("10/minute")
async def connect_service(
request: Request,
connectionId: str = Path(..., description="The ID of the connection to connect"),
currentUser: User = Depends(getCurrentUser)
) -> Dict[str, Any]:
"""Connect to an external service"""
try:
interface = getInterface(currentUser)
# Find the connection
connection = None
if currentUser.privilege in ['admin', 'sysadmin']:
# Admins can connect any connection
users = interface.getAllUsers()
for user in users:
for conn in user.connections:
if conn.id == connectionId:
connection = conn
break
if connection:
break
else:
# Regular users can only connect their own connections
for conn in currentUser.connections:
if conn.id == connectionId:
connection = conn
break
if not connection:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Connection not found"
)
# Initiate OAuth flow with state=connect
auth_url = None
if connection.authority == AuthAuthority.MSFT:
auth_url = f"/api/msft/login?state=connect&connectionId={connectionId}"
elif connection.authority == AuthAuthority.GOOGLE:
auth_url = f"/api/google/login?state=connect&connectionId={connectionId}"
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Unsupported authority: {connection.authority}"
)
return {"authUrl": auth_url}
except HTTPException:
raise
except Exception as e:
logger.error(f"Error connecting service: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to connect service: {str(e)}"
)
@router.post("/{connectionId}/disconnect")
@limiter.limit("10/minute")
async def disconnect_service(
request: Request,
connectionId: str = Path(..., description="The ID of the connection to disconnect"),
currentUser: User = Depends(getCurrentUser)
) -> Dict[str, Any]:
"""Disconnect from an external service"""
try:
interface = getInterface(currentUser)
# Find the connection
connection = None
if currentUser.privilege in ['admin', 'sysadmin']:
# Admins can disconnect any connection
users = interface.getAllUsers()
for user in users:
for conn in user.connections:
if conn.id == connectionId:
connection = conn
break
if connection:
break
else:
# Regular users can only disconnect their own connections
for conn in currentUser.connections:
if conn.id == connectionId:
connection = conn
break
if not connection:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Connection not found"
)
# Update connection status
connection.status = ConnectionStatus.INACTIVE
connection.lastChecked = datetime.now()
# Update user record
interface.db.recordModify("users", connection.userId, {
"connections": [c.to_dict() for c in currentUser.connections]
})
return {"message": "Service disconnected successfully"}
except HTTPException:
raise
except Exception as e:
logger.error(f"Error disconnecting service: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to disconnect service: {str(e)}"
)