add unified drive-picker-token endpoint and GOOGLE_PICKER_API_KEY config

This commit is contained in:
CREDO23 2026-03-10 20:06:45 +02:00
parent 0bb1b730dd
commit 1e2c54eea6
4 changed files with 90 additions and 0 deletions

View file

@ -50,6 +50,7 @@ REGISTRATION_ENABLED=TRUE or FALSE
# For Google Auth Only
GOOGLE_OAUTH_CLIENT_ID=924507538m
GOOGLE_OAUTH_CLIENT_SECRET=GOCSV
GOOGLE_PICKER_API_KEY=your-google-picker-api-key
# Google Connector Specific Configurations
GOOGLE_CALENDAR_REDIRECT_URI=http://localhost:8000/api/v1/auth/google/calendar/connector/callback

View file

@ -235,6 +235,7 @@ class Config:
# Google OAuth
GOOGLE_OAUTH_CLIENT_ID = os.getenv("GOOGLE_OAUTH_CLIENT_ID")
GOOGLE_OAUTH_CLIENT_SECRET = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET")
GOOGLE_PICKER_API_KEY = os.getenv("GOOGLE_PICKER_API_KEY")
# Google Calendar redirect URI
GOOGLE_CALENDAR_REDIRECT_URI = os.getenv("GOOGLE_CALENDAR_REDIRECT_URI")

View file

@ -3054,3 +3054,78 @@ async def test_mcp_server_connection(
"message": f"Failed to test connection: {e!s}",
"tools": [],
}
# ---------------------------------------------------------------------------
# Google Picker token endpoint (unified for native & Composio Drive)
# ---------------------------------------------------------------------------
DRIVE_CONNECTOR_TYPES = {
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
}
@router.get("/connectors/{connector_id}/drive-picker-token")
async def get_drive_picker_token(
connector_id: int,
session: AsyncSession = Depends(get_async_session),
user: User = Depends(current_active_user),
):
"""Return an OAuth access token + client ID for the Google Picker API."""
result = await session.execute(
select(SearchSourceConnector).filter(SearchSourceConnector.id == connector_id)
)
connector = result.scalars().first()
if not connector:
raise HTTPException(status_code=404, detail="Connector not found")
if connector.connector_type not in DRIVE_CONNECTOR_TYPES:
raise HTTPException(
status_code=400,
detail="This endpoint is only for Google Drive connectors",
)
picker_api_key = config.GOOGLE_PICKER_API_KEY
if not picker_api_key:
raise HTTPException(
status_code=500,
detail="GOOGLE_PICKER_API_KEY is not configured on the server",
)
try:
if connector.connector_type == SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR:
from app.connectors.google_drive.credentials import get_valid_credentials
credentials = await get_valid_credentials(session, connector_id)
return {
"access_token": credentials.token,
"client_id": config.GOOGLE_OAUTH_CLIENT_ID,
"picker_api_key": picker_api_key,
}
# Composio path
composio_account_id = (connector.config or {}).get(
"composio_connected_account_id"
)
if not composio_account_id:
raise HTTPException(
status_code=400,
detail="Composio connected account not found. Please reconnect.",
)
service = ComposioService()
access_token = service.get_access_token(composio_account_id)
return {
"access_token": access_token,
"client_id": config.GOOGLE_OAUTH_CLIENT_ID,
"picker_api_key": picker_api_key,
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to get Drive picker token: {e!s}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"Failed to retrieve access token: {e!s}",
) from e

View file

@ -247,6 +247,19 @@ class ComposioService:
)
return False
def get_access_token(self, connected_account_id: str) -> str:
"""Retrieve the raw OAuth access token for a Composio connected account."""
account = self.client.connected_accounts.get(nanoid=connected_account_id)
token = getattr(getattr(account, "state", None), "val", None)
if token is None:
raise ValueError(
f"No state.val on connected account {connected_account_id}"
)
access_token = getattr(token, "access_token", None)
if not access_token:
raise ValueError(f"No access_token in state.val for {connected_account_id}")
return access_token
async def execute_tool(
self,
connected_account_id: str,