Spaces:
Sleeping
Sleeping
| import logging | |
| from typing import Dict, Any, Optional | |
| from fastapi import APIRouter, Depends, HTTPException, Header, Request, Body | |
| from sqlalchemy.orm import Session | |
| from core.database import get_db | |
| from core.integration_registry import IntegrationRegistry | |
| from core.tenant_discovery import TenantDiscoveryService | |
| from core.communication.adapters.teams import TeamsAdapter | |
| from api.routes.webhooks.base import get_webhook_registry | |
| from api.routes.webhooks.webhook_bridge import webhook_bridge | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter(prefix="/teams", tags=["Microsoft Teams Webhooks"]) | |
| async def teams_webhook( | |
| request: Request, | |
| db: Session = Depends(get_db), | |
| registry: IntegrationRegistry = Depends(get_webhook_registry) | |
| ): | |
| """ | |
| Unified Microsoft Teams webhook callback. | |
| Handles JWT verification and dispatches via UCB. | |
| """ | |
| body = await request.body() | |
| try: | |
| data = await request.json() | |
| except Exception: | |
| raise HTTPException(status_code=400, detail="Invalid JSON") | |
| # 1. Tenant Resolution | |
| # Teams usually provides tenantId in the activity object | |
| ms_tenant_id = data.get("conversation", {}).get("tenantId") | |
| if not ms_tenant_id: | |
| ms_tenant_id = data.get("channelData", {}).get("tenant", {}).get("id") | |
| if not ms_tenant_id: | |
| logger.warning("Teams webhook missing tenantId") | |
| raise HTTPException(status_code=400, detail="Missing tenantId") | |
| discoverer = TenantDiscoveryService(db) | |
| tenant_id = await discoverer.get_tenant_id_by_external_id("teams", ms_tenant_id) | |
| if not tenant_id: | |
| logger.warning(f"No tenant found for Microsoft Teams tenantId: {ms_tenant_id}") | |
| return {"status": "ignored", "reason": "tenant_not_found"} | |
| # 2. Security Verification | |
| adapter = TeamsAdapter() | |
| if not await adapter.verify_request(request, body): | |
| logger.error(f"Unauthorized Teams webhook for tenant {tenant_id}") | |
| raise HTTPException(status_code=401, detail="Invalid signature") | |
| # 3. Dispatch via Webhook Bridge | |
| result = await webhook_bridge.process_event( | |
| "teams", | |
| tenant_id, | |
| data, | |
| registry, | |
| db | |
| ) | |
| return result | |