mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-22 11:51:04 +02:00
* ViciDial Working * feat(telephony): add FreeSWITCH provider to upstream-PBX seam Generalize the upstream-PBX capture and control paths to dispatch by provider. FreeSWITCH bridges in with X-PBX-* headers and is driven over the Event Socket Library (uuid_kill / uuid_transfer) by the channel UUID, alongside the existing VICIdial ra_call_control path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add vici specific configs * feat(telephony): env-based VICIdial config + address3 post-call routing Move VICIdial agent/non-agent API and FreeSWITCH ESL connection settings out of hardcoded POC values into environment variables so the same image works against a PBX on another server. Add VICIdial update_lead forwarding: X-VICI-UPDATE-LEAD_* extracted variables are mapped to lead columns and pushed via the non-agent API before a transfer, with reserved API-control params dropped. Add hardcoded address3 disposition routing (Y/N -> in-group transfer, else hang up) and a synchronous final variable extraction so the transfer path sees the freshest conversation state. Skip upstream_pbx capture on non-PJSIP channels to avoid Asterisk 500s. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: run formatter * feat: make vici configurable from UI * chore: clean up PR * fix: incorporate review comments * chore: incorporate review comments * chore: generate client * chore: incporporate review comments * chore: incorporate review comments --------- Co-authored-by: Dograh POC <payment@dograh.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
80 lines
2.4 KiB
Python
80 lines
2.4 KiB
Python
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
|
|
from api.routes import organization
|
|
from api.services import tool_management
|
|
|
|
|
|
def _credentials(password: str = "agent-secret") -> dict:
|
|
return {
|
|
"ari_endpoint": "https://asterisk.example.com",
|
|
"app_name": "dograh",
|
|
"app_password": "ari-secret",
|
|
"external_pbx": {
|
|
"type": "vicidial",
|
|
"agent_api": {
|
|
"url": "https://vici.example.com/agc/api.php",
|
|
"username": "agent-user",
|
|
"password": password,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def test_nested_external_pbx_secrets_are_masked_without_mutating_source():
|
|
credentials = _credentials()
|
|
|
|
masked = organization._mask_sensitive("ari", credentials)
|
|
|
|
assert masked["app_password"] != "ari-secret"
|
|
assert masked["external_pbx"]["agent_api"]["password"] != "agent-secret"
|
|
assert credentials["external_pbx"]["agent_api"]["password"] == "agent-secret"
|
|
|
|
|
|
def test_nested_masked_external_pbx_secrets_are_restored_on_update():
|
|
existing = _credentials()
|
|
request = organization._mask_sensitive("ari", existing)
|
|
|
|
organization.preserve_masked_fields("ari", request, existing)
|
|
|
|
assert request["app_password"] == "ari-secret"
|
|
assert request["external_pbx"]["agent_api"]["password"] == "agent-secret"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_disabled_feature_preserves_existing_tool_mapping(monkeypatch):
|
|
monkeypatch.setattr(
|
|
tool_management,
|
|
"external_pbx_integrations_enabled",
|
|
AsyncMock(return_value=False),
|
|
)
|
|
definition = {
|
|
"type": "transfer_call",
|
|
"config": {
|
|
"destination_source": "context_mapping",
|
|
"context_mapping": {
|
|
"context_path": "qualified",
|
|
"routes": [{"context_value": "yes", "destination": "sales"}],
|
|
},
|
|
},
|
|
}
|
|
|
|
await tool_management.validate_external_pbx_tool_definition(
|
|
definition,
|
|
organization_id=7,
|
|
existing_definition=definition,
|
|
)
|
|
|
|
changed = {
|
|
"type": "transfer_call",
|
|
"config": {"destination_source": "static", "destination": "+15555550100"},
|
|
}
|
|
with pytest.raises(tool_management.ToolManagementError) as exc_info:
|
|
await tool_management.validate_external_pbx_tool_definition(
|
|
changed,
|
|
organization_id=7,
|
|
existing_definition=definition,
|
|
)
|
|
|
|
assert exc_info.value.status_code == 403
|