feat: add warning with missing signature secret

This commit is contained in:
Sabiha Khan 2026-06-29 15:06:00 +05:30
parent f644933e28
commit e1e9782c48
10 changed files with 122 additions and 20 deletions

View file

@ -103,6 +103,30 @@ class TelephonyConfigurationClient(BaseDBClient):
)
return int(result.scalar() or 0)
async def count_vonage_configs_missing_signature_secret(
self, organization_id: int
) -> int:
"""Count Vonage configs in this org with no signature_secret."""
async with self.async_session() as session:
result = await session.execute(
select(func.count(TelephonyConfigurationModel.id)).where(
TelephonyConfigurationModel.organization_id == organization_id,
TelephonyConfigurationModel.provider == "vonage",
(
TelephonyConfigurationModel.credentials.op("->>")(
"signature_secret"
).is_(None)
)
| (
TelephonyConfigurationModel.credentials.op("->>")(
"signature_secret"
)
== ""
),
)
)
return int(result.scalar() or 0)
async def list_all_telephony_configurations_by_provider(
self, provider: str
) -> List[TelephonyConfigurationModel]:

View file

@ -145,6 +145,7 @@ class TelephonyConfigWarningsResponse(BaseModel):
"""
telnyx_missing_webhook_public_key_count: int
vonage_missing_signature_secret_count: int
@router.get("/context", response_model=OrganizationContextResponse)
@ -200,8 +201,7 @@ async def get_telephony_providers_metadata(user: UserModel = Depends(get_user)):
async def get_telephony_config_warnings(user: UserModel = Depends(get_user)):
"""Return aggregated warning counts for the current org's telephony configs.
Today this surfaces only Telnyx configs missing ``webhook_public_key``;
additional warning types should be added as new fields on the response.
Surfaces provider configs missing webhook-verification credentials.
"""
if not user.selected_organization_id:
raise HTTPException(status_code=400, detail="No organization selected")
@ -209,8 +209,12 @@ async def get_telephony_config_warnings(user: UserModel = Depends(get_user)):
telnyx_missing = await db_client.count_telnyx_configs_missing_webhook_public_key(
user.selected_organization_id
)
vonage_missing = await db_client.count_vonage_configs_missing_signature_secret(
user.selected_organization_id
)
return TelephonyConfigWarningsResponse(
telnyx_missing_webhook_public_key_count=telnyx_missing,
vonage_missing_signature_secret_count=vonage_missing,
)

View file

@ -13,8 +13,8 @@ class VonageConfigurationRequest(BaseModel):
api_secret: str = Field(..., description="Vonage API Secret")
application_id: str = Field(..., description="Vonage Application ID")
private_key: str = Field(..., description="Private key for JWT generation")
signature_secret: str = Field(
...,
signature_secret: Optional[str] = Field(
None,
description="Vonage signature secret used to verify signed webhooks",
)
from_numbers: List[str] = Field(

View file

@ -442,7 +442,7 @@ class VonageProvider(TelephonyProvider):
account_id=claims.get("api_key") or webhook_data.get("account_id"),
from_country=None,
to_country=None,
raw_data={**webhook_data, "signed_claims": claims},
raw_data=webhook_data,
)
@staticmethod
@ -630,13 +630,14 @@ class VonageProvider(TelephonyProvider):
capabilities = app_data.get("capabilities") or {}
voice = capabilities.get("voice") or {}
webhooks = voice.get("webhooks") or {}
backend_endpoint, _ = await get_backend_endpoints()
webhooks["answer_url"] = {
"address": webhook_url,
"http_method": "POST",
}
webhooks["event_url"] = {
"address": f"{webhook_url.rsplit('/inbound/run', 1)[0]}/vonage/events",
"address": f"{backend_endpoint}/api/v1/telephony/vonage/events",
"http_method": "POST",
}
voice["webhooks"] = webhooks