""" 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)}" )