mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-01 14:42:15 +00:00
🚚(backend) rename TelephonyService to SIPManagement
Rename the telephony service to a more descriptive name, SIPManagementService, which clearly states what the service is used for. It is no longer used only by the telephony feature; the roomkit feature also relies on it now.
This commit is contained in:
@@ -27,6 +27,7 @@ and this project adheres to
|
||||
- 📝(legal) update terms of service
|
||||
- 💄(frontend) render Avatar initials in uppercase
|
||||
- 💄(frontend) improve participant name rendering in the list
|
||||
- 🚚(backend) rename TelephonyService to SIPManagement
|
||||
|
||||
## Fixed
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ from rest_framework import (
|
||||
from core import analytics, models
|
||||
from core.api import permissions, throttling
|
||||
from core.api.feature_flag import FeatureFlag
|
||||
from core.services.telephony import TelephonyException, TelephonyService
|
||||
from core.services.sip_management import SIPException, SIPManagement
|
||||
|
||||
from . import authentication, serializers
|
||||
|
||||
@@ -50,7 +50,7 @@ class RoomKitViewSet(viewsets.ViewSet):
|
||||
without waiting for a WebRTC user.
|
||||
|
||||
The webhook-based creation path is kept: both converge on the same rule
|
||||
through the shared TelephonyService.
|
||||
through the shared SIPManagement.
|
||||
"""
|
||||
|
||||
serializer = serializers.RoomKitJoinSerializer(data=request.data)
|
||||
@@ -64,8 +64,8 @@ class RoomKitViewSet(viewsets.ViewSet):
|
||||
raise drf_exceptions.NotFound("No room found for this PIN code.") from e
|
||||
|
||||
try:
|
||||
created = TelephonyService().ensure_dispatch_rule(room)
|
||||
except TelephonyException as e:
|
||||
created = SIPManagement().ensure_dispatch_rule(room)
|
||||
except SIPException as e:
|
||||
raise drf_exceptions.APIException("Could not create dispatch rule.") from e
|
||||
|
||||
analytics.capture(
|
||||
|
||||
@@ -28,7 +28,7 @@ from .room_management import (
|
||||
RoomManagementException,
|
||||
RoomNotFoundException,
|
||||
)
|
||||
from .telephony import TelephonyException, TelephonyService
|
||||
from .sip_management import SIPException, SIPManagement
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
@@ -107,7 +107,7 @@ class LiveKitEventsService:
|
||||
)
|
||||
self.webhook_receiver = api.WebhookReceiver(token_verifier)
|
||||
self.lobby_service = LobbyService()
|
||||
self.telephony_service = TelephonyService()
|
||||
self.sip_management = SIPManagement()
|
||||
self.recording_events = RecordingEventsService()
|
||||
|
||||
self._filter_regex = None
|
||||
@@ -247,10 +247,10 @@ class LiveKitEventsService:
|
||||
|
||||
if settings.ROOM_TELEPHONY_ENABLED or settings.ROOMKIT_ENABLED:
|
||||
try:
|
||||
self.telephony_service.create_dispatch_rule(room)
|
||||
except TelephonyException as e:
|
||||
self.sip_management.create_dispatch_rule(room)
|
||||
except SIPException as e:
|
||||
raise ActionFailedError(
|
||||
f"Failed to create telephony dispatch rule for room {room_id}"
|
||||
f"Failed to create sip dispatch rule for room {room_id}"
|
||||
) from e
|
||||
|
||||
def _handle_room_finished(self, data):
|
||||
@@ -267,10 +267,10 @@ class LiveKitEventsService:
|
||||
|
||||
if settings.ROOM_TELEPHONY_ENABLED or settings.ROOMKIT_ENABLED:
|
||||
try:
|
||||
self.telephony_service.delete_dispatch_rule(room_id)
|
||||
except TelephonyException as e:
|
||||
self.sip_management.delete_dispatch_rule(room_id)
|
||||
except SIPException as e:
|
||||
raise ActionFailedError(
|
||||
f"Failed to delete telephony dispatch rule for room {room_id}"
|
||||
f"Failed to delete sip dispatch rule for room {room_id}"
|
||||
) from e
|
||||
|
||||
try:
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
"""Telephony service for managing SIP dispatch rules for room access."""
|
||||
"""SIP management service for managing SIP dispatch rules for room access."""
|
||||
|
||||
from logging import getLogger
|
||||
|
||||
@@ -17,16 +17,16 @@ from core import utils
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class TelephonyException(Exception):
|
||||
"""Exception raised when telephony operations fail."""
|
||||
class SIPException(Exception):
|
||||
"""Exception raised when SIP operations fail."""
|
||||
|
||||
|
||||
class DispatchRuleConflictError(TelephonyException):
|
||||
class DispatchRuleConflictError(SIPException):
|
||||
"""Raised when a dispatch rule already exists for the same routing criteria."""
|
||||
|
||||
|
||||
class TelephonyService:
|
||||
"""Service for managing participant access through the telephony system (SIP)."""
|
||||
class SIPManagement:
|
||||
"""Service for managing SIP access through the telephony or roomkit system (SIP)."""
|
||||
|
||||
def _rule_name(self, room_id):
|
||||
"""Generate the rule name for a room based on its ID."""
|
||||
@@ -36,7 +36,7 @@ class TelephonyService:
|
||||
async def create_dispatch_rule(self, room):
|
||||
"""Create a SIP inbound dispatch rule for direct room routing.
|
||||
|
||||
Configures telephony to route incoming SIP calls directly to the specified room
|
||||
Configures livekit-sip to route incoming SIP calls directly to the specified room
|
||||
using the room's ID and PIN code for authentication.
|
||||
"""
|
||||
|
||||
@@ -60,7 +60,7 @@ class TelephonyService:
|
||||
logger.exception(
|
||||
"Unexpected error creating dispatch rule for room %s", room.id
|
||||
)
|
||||
raise TelephonyException("Could not create dispatch rule") from e
|
||||
raise SIPException("Could not create dispatch rule") from e
|
||||
|
||||
finally:
|
||||
await lkapi.aclose()
|
||||
@@ -85,7 +85,7 @@ class TelephonyService:
|
||||
)
|
||||
except TwirpError as e:
|
||||
logger.exception("Failed to list dispatch rules for room %s", room_id)
|
||||
raise TelephonyException("Could not list dispatch rules") from e
|
||||
raise SIPException("Could not list dispatch rules") from e
|
||||
finally:
|
||||
await lkapi.aclose()
|
||||
|
||||
@@ -146,7 +146,7 @@ class TelephonyService:
|
||||
|
||||
except TwirpError as e:
|
||||
logger.exception("Failed to delete dispatch rules for room %s", room_id)
|
||||
raise TelephonyException("Could not delete dispatch rules") from e
|
||||
raise SIPException("Could not delete dispatch rules") from e
|
||||
|
||||
finally:
|
||||
await lkapi.aclose()
|
||||
@@ -9,19 +9,19 @@ from unittest import mock
|
||||
import pytest
|
||||
|
||||
from ...factories import RoomFactory
|
||||
from ...services.telephony import TelephonyException
|
||||
from ...services.sip_management import SIPException
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_telephony_service():
|
||||
"""Mock the TelephonyService used by the roomkit viewset."""
|
||||
with mock.patch("core.roomkit.viewsets.TelephonyService") as mock_service_class:
|
||||
def mock_sip_management():
|
||||
"""Mock the SIPManagement used by the roomkit viewset."""
|
||||
with mock.patch("core.roomkit.viewsets.SIPManagement") as mock_service_class:
|
||||
yield mock_service_class.return_value
|
||||
|
||||
|
||||
def test_join_anonymous(settings, mock_telephony_service, client):
|
||||
def test_join_anonymous(settings, mock_sip_management, client):
|
||||
"""Requests without an Authorization header should be rejected."""
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
@@ -32,10 +32,10 @@ def test_join_anonymous(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 401
|
||||
assert response.json() == {"detail": "Authorization header is missing."}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_malformed_authorization_header(settings, mock_telephony_service, client):
|
||||
def test_join_malformed_authorization_header(settings, mock_sip_management, client):
|
||||
"""Requests with a malformed Authorization header should be rejected."""
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
@@ -50,10 +50,10 @@ def test_join_malformed_authorization_header(settings, mock_telephony_service, c
|
||||
|
||||
assert response.status_code == 401
|
||||
assert response.json() == {"detail": "Invalid authorization header."}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_wrong_bearer(settings, mock_telephony_service, client):
|
||||
def test_join_wrong_bearer(settings, mock_sip_management, client):
|
||||
"""Requests with an incorrect bearer token should be rejected."""
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
@@ -68,10 +68,10 @@ def test_join_wrong_bearer(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 401
|
||||
assert response.json() == {"detail": "Invalid server-to-server token."}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_token_not_configured(settings, mock_telephony_service, client):
|
||||
def test_join_token_not_configured(settings, mock_sip_management, client):
|
||||
"""Requests should be rejected when no server-to-server token is configured."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
@@ -86,10 +86,10 @@ def test_join_token_not_configured(settings, mock_telephony_service, client):
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_roomkit_disabled(settings, mock_telephony_service, client):
|
||||
def test_join_roomkit_disabled(settings, mock_sip_management, client):
|
||||
"""The endpoint should not be exposed when the roomkit integration is disabled."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = False
|
||||
@@ -104,10 +104,10 @@ def test_join_roomkit_disabled(settings, mock_telephony_service, client):
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_missing_pin(settings, mock_telephony_service, client):
|
||||
def test_join_missing_pin(settings, mock_sip_management, client):
|
||||
"""Requests without a PIN code should be rejected."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
@@ -121,10 +121,10 @@ def test_join_missing_pin(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 400
|
||||
assert response.json() == {"pin_code": ["This field is required."]}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_blank_pin(settings, mock_telephony_service, client):
|
||||
def test_join_blank_pin(settings, mock_sip_management, client):
|
||||
"""Requests with a blank PIN code should be rejected."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
@@ -138,10 +138,10 @@ def test_join_blank_pin(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 400
|
||||
assert response.json() == {"pin_code": ["This field may not be blank."]}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_wrong_pin_length(settings, mock_telephony_service, client):
|
||||
def test_join_wrong_pin_length(settings, mock_sip_management, client):
|
||||
"""Requests with a PIN code of unexpected length should be rejected."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
@@ -156,10 +156,10 @@ def test_join_wrong_pin_length(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 400
|
||||
assert response.json() == {"pin_code": ["PIN code length is invalid."]}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_unknown_pin(settings, mock_telephony_service, client):
|
||||
def test_join_unknown_pin(settings, mock_sip_management, client):
|
||||
"""Requests with a PIN matching no room should return 404 and create no rule."""
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
@@ -174,16 +174,16 @@ def test_join_unknown_pin(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 404
|
||||
assert response.json() == {"detail": "No room found for this PIN code."}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_not_called()
|
||||
mock_sip_management.ensure_dispatch_rule.assert_not_called()
|
||||
|
||||
|
||||
def test_join_success(settings, mock_telephony_service, client):
|
||||
def test_join_success(settings, mock_sip_management, client):
|
||||
"""Requests with a valid PIN should create the dispatch rule."""
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
|
||||
room = RoomFactory(pin_code="1234567890")
|
||||
mock_telephony_service.ensure_dispatch_rule.return_value = True
|
||||
mock_sip_management.ensure_dispatch_rule.return_value = True
|
||||
|
||||
response = client.post(
|
||||
"/api/v1.0/roomkit/join/",
|
||||
@@ -193,17 +193,17 @@ def test_join_success(settings, mock_telephony_service, client):
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "success"}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
mock_sip_management.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
|
||||
|
||||
def test_join_dispatch_rule_already_exists(settings, mock_telephony_service, client):
|
||||
def test_join_dispatch_rule_already_exists(settings, mock_sip_management, client):
|
||||
"""Requests should succeed when the dispatch rule already exists (idempotency)."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
|
||||
room = RoomFactory(pin_code="1234567890")
|
||||
mock_telephony_service.ensure_dispatch_rule.return_value = False
|
||||
mock_sip_management.ensure_dispatch_rule.return_value = False
|
||||
|
||||
response = client.post(
|
||||
"/api/v1.0/roomkit/join/",
|
||||
@@ -213,17 +213,17 @@ def test_join_dispatch_rule_already_exists(settings, mock_telephony_service, cli
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "success"}
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
mock_sip_management.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
|
||||
|
||||
def test_join_tracks_analytics_event(settings, mock_telephony_service, client):
|
||||
def test_join_tracks_analytics_event(settings, mock_sip_management, client):
|
||||
"""Successful joins should be tracked with an analytics event."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
|
||||
room = RoomFactory(pin_code="1234567890")
|
||||
mock_telephony_service.ensure_dispatch_rule.return_value = True
|
||||
mock_sip_management.ensure_dispatch_rule.return_value = True
|
||||
|
||||
with mock.patch("core.roomkit.viewsets.analytics.capture") as mock_capture:
|
||||
response = client.post(
|
||||
@@ -242,14 +242,14 @@ def test_join_tracks_analytics_event(settings, mock_telephony_service, client):
|
||||
}
|
||||
|
||||
|
||||
def test_join_telephony_failure(settings, mock_telephony_service, client):
|
||||
"""Requests should fail with a server error when the telephony service fails."""
|
||||
def test_join_sip_failure(settings, mock_sip_management, client):
|
||||
"""Requests should fail with a server error when the sip management service fails."""
|
||||
|
||||
settings.ROOMKIT_ENABLED = True
|
||||
settings.ROOMKIT_SERVER_TO_SERVER_API_TOKEN = "testAuthToken"
|
||||
|
||||
room = RoomFactory(pin_code="1234567890")
|
||||
mock_telephony_service.ensure_dispatch_rule.side_effect = TelephonyException(
|
||||
mock_sip_management.ensure_dispatch_rule.side_effect = SIPException(
|
||||
"Could not create dispatch rule"
|
||||
)
|
||||
|
||||
@@ -262,5 +262,5 @@ def test_join_telephony_failure(settings, mock_telephony_service, client):
|
||||
)
|
||||
|
||||
assert response.status_code == 500
|
||||
mock_telephony_service.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
mock_sip_management.ensure_dispatch_rule.assert_called_once_with(room)
|
||||
mock_capture.assert_not_called()
|
||||
|
||||
@@ -21,7 +21,7 @@ from core.services.livekit_events import (
|
||||
)
|
||||
from core.services.lobby import LobbyService
|
||||
from core.services.room_management import RoomManagementException
|
||||
from core.services.telephony import TelephonyException, TelephonyService
|
||||
from core.services.sip_management import SIPException, SIPManagement
|
||||
from core.utils import NotificationError
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
@@ -59,7 +59,7 @@ def test_initialization(
|
||||
mock_token_verifier.assert_called_once_with(api_key, api_secret)
|
||||
mock_webhook_receiver.assert_called_once_with(mock_token_verifier.return_value)
|
||||
assert isinstance(service.lobby_service, LobbyService)
|
||||
assert isinstance(service.telephony_service, TelephonyService)
|
||||
assert isinstance(service.sip_management, SIPManagement)
|
||||
assert isinstance(service.recording_events, RecordingEventsService)
|
||||
|
||||
|
||||
@@ -469,11 +469,11 @@ def test_handle_egress_ended_ignores_non_savable_recording(
|
||||
|
||||
|
||||
@mock.patch.object(LobbyService, "clear_room_cache")
|
||||
@mock.patch.object(TelephonyService, "delete_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "delete_dispatch_rule")
|
||||
def test_handle_room_finished_clears_cache_and_deletes_dispatch_rule(
|
||||
mock_delete_dispatch_rule, mock_clear_cache, service, settings
|
||||
):
|
||||
"""Should clear lobby cache and delete telephony dispatch rule when room finishes."""
|
||||
"""Should clear lobby cache and delete SIP dispatch rule when room finishes."""
|
||||
settings.ROOM_TELEPHONY_ENABLED = True
|
||||
mock_room_name = uuid.uuid4()
|
||||
mock_data = mock.MagicMock()
|
||||
@@ -486,7 +486,7 @@ def test_handle_room_finished_clears_cache_and_deletes_dispatch_rule(
|
||||
|
||||
|
||||
@mock.patch.object(LobbyService, "clear_room_cache")
|
||||
@mock.patch.object(TelephonyService, "delete_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "delete_dispatch_rule")
|
||||
def test_handle_room_finished_deletes_dispatch_rule_when_only_roomkit_enabled(
|
||||
mock_delete_dispatch_rule, mock_clear_cache, service, settings
|
||||
):
|
||||
@@ -504,7 +504,7 @@ def test_handle_room_finished_deletes_dispatch_rule_when_only_roomkit_enabled(
|
||||
|
||||
|
||||
@mock.patch.object(LobbyService, "clear_room_cache")
|
||||
@mock.patch.object(TelephonyService, "delete_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "delete_dispatch_rule")
|
||||
def test_handle_room_finished_skips_telephony_when_disabled(
|
||||
mock_delete_dispatch_rule, mock_clear_cache, service, settings
|
||||
):
|
||||
@@ -524,7 +524,7 @@ def test_handle_room_finished_skips_telephony_when_disabled(
|
||||
@mock.patch.object(
|
||||
LobbyService, "clear_room_cache", side_effect=Exception("Test error")
|
||||
)
|
||||
@mock.patch.object(TelephonyService, "delete_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "delete_dispatch_rule")
|
||||
def test_handle_room_finished_raises_error_when_cache_clearing_fails(
|
||||
mock_delete_dispatch_rule, mock_clear_cache, service, settings
|
||||
):
|
||||
@@ -547,9 +547,9 @@ def test_handle_room_finished_raises_error_when_cache_clearing_fails(
|
||||
|
||||
@mock.patch.object(LobbyService, "clear_room_cache")
|
||||
@mock.patch.object(
|
||||
TelephonyService,
|
||||
SIPManagement,
|
||||
"delete_dispatch_rule",
|
||||
side_effect=TelephonyException("Test error"),
|
||||
side_effect=SIPException("Test error"),
|
||||
)
|
||||
def test_handle_room_finished_raises_error_when_telephony_deletion_fails(
|
||||
mock_delete_dispatch_rule, mock_clear_cache, service, settings
|
||||
@@ -581,11 +581,11 @@ def test_handle_room_finished_raises_error_for_invalid_room_name(service):
|
||||
service._handle_room_finished(mock_data)
|
||||
|
||||
|
||||
@mock.patch.object(TelephonyService, "create_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "create_dispatch_rule")
|
||||
def test_handle_room_started_creates_dispatch_rule_successfully(
|
||||
mock_create_dispatch_rule, service, settings
|
||||
):
|
||||
"""Should create telephony dispatch rule when room starts successfully."""
|
||||
"""Should create SIP dispatch rule when room starts successfully."""
|
||||
settings.ROOM_TELEPHONY_ENABLED = True
|
||||
room = RoomFactory()
|
||||
mock_data = mock.MagicMock()
|
||||
@@ -596,7 +596,7 @@ def test_handle_room_started_creates_dispatch_rule_successfully(
|
||||
mock_create_dispatch_rule.assert_called_once_with(room)
|
||||
|
||||
|
||||
@mock.patch.object(TelephonyService, "create_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "create_dispatch_rule")
|
||||
def test_handle_room_started_creates_dispatch_rule_when_only_roomkit_enabled(
|
||||
mock_create_dispatch_rule, service, settings
|
||||
):
|
||||
@@ -612,11 +612,11 @@ def test_handle_room_started_creates_dispatch_rule_when_only_roomkit_enabled(
|
||||
mock_create_dispatch_rule.assert_called_once_with(room)
|
||||
|
||||
|
||||
@mock.patch.object(TelephonyService, "create_dispatch_rule")
|
||||
@mock.patch.object(SIPManagement, "create_dispatch_rule")
|
||||
def test_handle_room_started_skips_dispatch_rule_when_telephony_disabled(
|
||||
mock_create_dispatch_rule, service, settings
|
||||
):
|
||||
"""Should skip creating telephony dispatch rule when telephony is disabled during room start."""
|
||||
"""Should skip creating SIP dispatch rule when telephony is disabled during room start."""
|
||||
settings.ROOM_TELEPHONY_ENABLED = False
|
||||
settings.ROOMKIT_ENABLED = False
|
||||
room = RoomFactory()
|
||||
|
||||
+48
-48
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Test telephony service.
|
||||
Test SIP mamagement service.
|
||||
"""
|
||||
|
||||
# pylint: disable=W0212
|
||||
@@ -20,10 +20,10 @@ from livekit.protocol.sip import (
|
||||
|
||||
from core.factories import RoomFactory
|
||||
from core.models import RoomAccessLevel
|
||||
from core.services.telephony import (
|
||||
from core.services.sip_management import (
|
||||
DispatchRuleConflictError,
|
||||
TelephonyException,
|
||||
TelephonyService,
|
||||
SIPException,
|
||||
SIPManagement,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
@@ -39,9 +39,9 @@ def create_mock_livekit_client():
|
||||
|
||||
def test_rule_name():
|
||||
"""Test rule name generation."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
rule_name = telephony_service._rule_name(room.id)
|
||||
rule_name = sip_management._rule_name(room.id)
|
||||
|
||||
assert rule_name == f"SIP_{str(room.id)}"
|
||||
|
||||
@@ -49,14 +49,14 @@ def test_rule_name():
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_create_dispatch_rule_success(mock_client_factory):
|
||||
"""Test successful dispatch rule creation."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
mock_api.sip.create_sip_dispatch_rule = mock.AsyncMock()
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
telephony_service.create_dispatch_rule(room)
|
||||
sip_management.create_dispatch_rule(room)
|
||||
|
||||
mock_api.sip.create_sip_dispatch_rule.assert_called_once()
|
||||
create_request = mock_api.sip.create_sip_dispatch_rule.call_args[1]["create"]
|
||||
@@ -71,7 +71,7 @@ def test_create_dispatch_rule_success(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_create_dispatch_rule_api_failure(mock_client_factory):
|
||||
"""Test dispatch rule creation when API fails."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -80,8 +80,8 @@ def test_create_dispatch_rule_api_failure(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(TelephonyException, match="Could not create dispatch rule"):
|
||||
telephony_service.create_dispatch_rule(room)
|
||||
with pytest.raises(SIPException, match="Could not create dispatch rule"):
|
||||
sip_management.create_dispatch_rule(room)
|
||||
|
||||
mock_api.sip.create_sip_dispatch_rule.assert_called_once()
|
||||
mock_api.aclose.assert_called_once()
|
||||
@@ -90,7 +90,7 @@ def test_create_dispatch_rule_api_failure(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_list_dispatch_rules_ids_success(mock_client_factory):
|
||||
"""Test successful listing of dispatch rule IDs."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_rules = [
|
||||
@@ -115,7 +115,7 @@ def test_list_dispatch_rules_ids_success(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
result = async_to_sync(telephony_service._list_dispatch_rules_ids)(room.id)
|
||||
result = async_to_sync(sip_management._list_dispatch_rules_ids)(room.id)
|
||||
|
||||
assert len(result) == 2
|
||||
assert "rule-1" in result
|
||||
@@ -131,7 +131,7 @@ def test_list_dispatch_rules_ids_success(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_list_dispatch_rules_ids_empty_response(mock_client_factory):
|
||||
"""Test listing dispatch rule IDs when no rules exist."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -140,7 +140,7 @@ def test_list_dispatch_rules_ids_empty_response(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
result = async_to_sync(telephony_service._list_dispatch_rules_ids)(room.id)
|
||||
result = async_to_sync(sip_management._list_dispatch_rules_ids)(room.id)
|
||||
|
||||
assert result == []
|
||||
mock_api.aclose.assert_called_once()
|
||||
@@ -149,7 +149,7 @@ def test_list_dispatch_rules_ids_empty_response(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_list_dispatch_rules_ids_no_matching_rules(mock_client_factory):
|
||||
"""Test listing dispatch rule IDs when no rules match the room."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_rules = [
|
||||
@@ -167,7 +167,7 @@ def test_list_dispatch_rules_ids_no_matching_rules(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
result = async_to_sync(telephony_service._list_dispatch_rules_ids)(room.id)
|
||||
result = async_to_sync(sip_management._list_dispatch_rules_ids)(room.id)
|
||||
|
||||
assert result == []
|
||||
mock_api.aclose.assert_called_once()
|
||||
@@ -176,7 +176,7 @@ def test_list_dispatch_rules_ids_no_matching_rules(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_list_dispatch_rules_ids_api_failure(mock_client_factory):
|
||||
"""Test listing dispatch rule IDs when API fails."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -185,34 +185,34 @@ def test_list_dispatch_rules_ids_api_failure(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(TelephonyException, match="Could not list dispatch rules"):
|
||||
async_to_sync(telephony_service._list_dispatch_rules_ids)(room.id)
|
||||
with pytest.raises(SIPException, match="Could not list dispatch rules"):
|
||||
async_to_sync(sip_management._list_dispatch_rules_ids)(room.id)
|
||||
|
||||
mock_api.sip.list_sip_dispatch_rule.assert_called_once()
|
||||
mock_api.aclose.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch("core.services.telephony.TelephonyService._list_dispatch_rules_ids")
|
||||
@mock.patch("core.services.sip_management.SIPManagement._list_dispatch_rules_ids")
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_delete_dispatch_rule_no_rules(mock_client_factory, mock_list_rules):
|
||||
"""Test deleting dispatch rules when no rules exist."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_list_rules.return_value = []
|
||||
|
||||
result = telephony_service.delete_dispatch_rule(room.id)
|
||||
result = sip_management.delete_dispatch_rule(room.id)
|
||||
|
||||
assert result is False
|
||||
mock_list_rules.assert_called_once_with(room.id)
|
||||
mock_client_factory.assert_not_called()
|
||||
|
||||
|
||||
@mock.patch("core.services.telephony.TelephonyService._list_dispatch_rules_ids")
|
||||
@mock.patch("core.services.sip_management.SIPManagement._list_dispatch_rules_ids")
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_delete_dispatch_rule_single_rule(mock_client_factory, mock_list_rules):
|
||||
"""Test deleting a single dispatch rule."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_list_rules.return_value = ["rule-1"]
|
||||
@@ -220,7 +220,7 @@ def test_delete_dispatch_rule_single_rule(mock_client_factory, mock_list_rules):
|
||||
mock_api.sip.delete_sip_dispatch_rule = mock.AsyncMock()
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
result = telephony_service.delete_dispatch_rule(room.id)
|
||||
result = sip_management.delete_dispatch_rule(room.id)
|
||||
|
||||
assert result is True
|
||||
mock_api.sip.delete_sip_dispatch_rule.assert_called_once()
|
||||
@@ -230,11 +230,11 @@ def test_delete_dispatch_rule_single_rule(mock_client_factory, mock_list_rules):
|
||||
mock_api.aclose.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch("core.services.telephony.TelephonyService._list_dispatch_rules_ids")
|
||||
@mock.patch("core.services.sip_management.SIPManagement._list_dispatch_rules_ids")
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_delete_dispatch_rule_multiple_rules(mock_client_factory, mock_list_rules):
|
||||
"""Test deleting multiple dispatch rules."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_list_rules.return_value = ["rule-1", "rule-2", "rule-3"]
|
||||
@@ -242,7 +242,7 @@ def test_delete_dispatch_rule_multiple_rules(mock_client_factory, mock_list_rule
|
||||
mock_api.sip.delete_sip_dispatch_rule = mock.AsyncMock()
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
result = telephony_service.delete_dispatch_rule(room.id)
|
||||
result = sip_management.delete_dispatch_rule(room.id)
|
||||
|
||||
assert result is True
|
||||
assert mock_api.sip.delete_sip_dispatch_rule.call_count == 3
|
||||
@@ -257,11 +257,11 @@ def test_delete_dispatch_rule_multiple_rules(mock_client_factory, mock_list_rule
|
||||
mock_api.aclose.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch("core.services.telephony.TelephonyService._list_dispatch_rules_ids")
|
||||
@mock.patch("core.services.sip_management.SIPManagement._list_dispatch_rules_ids")
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_delete_dispatch_rule_partial_failure(mock_client_factory, mock_list_rules):
|
||||
"""Test deleting multiple dispatch rules when one deletion fails."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_list_rules.return_value = ["rule-1", "rule-2", "rule-3"]
|
||||
@@ -281,18 +281,18 @@ def test_delete_dispatch_rule_partial_failure(mock_client_factory, mock_list_rul
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(TelephonyException, match="Could not delete dispatch rules"):
|
||||
telephony_service.delete_dispatch_rule(room.id)
|
||||
with pytest.raises(SIPException, match="Could not delete dispatch rules"):
|
||||
sip_management.delete_dispatch_rule(room.id)
|
||||
|
||||
assert mock_api.sip.delete_sip_dispatch_rule.call_count == 2
|
||||
mock_api.aclose.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch("core.services.telephony.TelephonyService._list_dispatch_rules_ids")
|
||||
@mock.patch("core.services.sip_management.SIPManagement._list_dispatch_rules_ids")
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_delete_dispatch_rule_api_failure(mock_client_factory, mock_list_rules):
|
||||
"""Test deleting dispatch rules when API fails immediately."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_list_rules.return_value = ["rule-1"]
|
||||
@@ -302,8 +302,8 @@ def test_delete_dispatch_rule_api_failure(mock_client_factory, mock_list_rules):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(TelephonyException, match="Could not delete dispatch rules"):
|
||||
telephony_service.delete_dispatch_rule(room.id)
|
||||
with pytest.raises(SIPException, match="Could not delete dispatch rules"):
|
||||
sip_management.delete_dispatch_rule(room.id)
|
||||
|
||||
mock_api.sip.delete_sip_dispatch_rule.assert_called_once()
|
||||
mock_api.aclose.assert_called_once()
|
||||
@@ -312,7 +312,7 @@ def test_delete_dispatch_rule_api_failure(mock_client_factory, mock_list_rules):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_create_dispatch_rule_conflict_raises_dedicated_error(mock_client_factory):
|
||||
"""Test that a LiveKit conflict error raises DispatchRuleConflictError."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -329,7 +329,7 @@ def test_create_dispatch_rule_conflict_raises_dedicated_error(mock_client_factor
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(DispatchRuleConflictError):
|
||||
telephony_service.create_dispatch_rule(room)
|
||||
sip_management.create_dispatch_rule(room)
|
||||
|
||||
mock_api.aclose.assert_called_once()
|
||||
|
||||
@@ -337,7 +337,7 @@ def test_create_dispatch_rule_conflict_raises_dedicated_error(mock_client_factor
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_ensure_dispatch_rule_creates_when_missing(mock_client_factory):
|
||||
"""Test that ensure_dispatch_rule creates the rule when none exists."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -347,7 +347,7 @@ def test_ensure_dispatch_rule_creates_when_missing(mock_client_factory):
|
||||
mock_api.sip.create_sip_dispatch_rule = mock.AsyncMock()
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
created = telephony_service.ensure_dispatch_rule(room)
|
||||
created = sip_management.ensure_dispatch_rule(room)
|
||||
|
||||
assert created is True
|
||||
mock_api.sip.create_sip_dispatch_rule.assert_called_once()
|
||||
@@ -362,7 +362,7 @@ def test_ensure_dispatch_rule_creates_when_missing(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_ensure_dispatch_rule_skips_when_existing(mock_client_factory):
|
||||
"""Test that ensure_dispatch_rule is idempotent when the rule already exists."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
existing_rule = SIPDispatchRuleInfo(
|
||||
@@ -375,7 +375,7 @@ def test_ensure_dispatch_rule_skips_when_existing(mock_client_factory):
|
||||
mock_api.sip.create_sip_dispatch_rule = mock.AsyncMock()
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
created = telephony_service.ensure_dispatch_rule(room)
|
||||
created = sip_management.ensure_dispatch_rule(room)
|
||||
|
||||
assert created is False
|
||||
mock_api.sip.create_sip_dispatch_rule.assert_not_called()
|
||||
@@ -389,7 +389,7 @@ def test_ensure_dispatch_rule_returns_false_on_conflict(mock_client_factory):
|
||||
between the existence check and the creation, LiveKit rejects the
|
||||
duplicate and ensure_dispatch_rule reports the rule as already existing.
|
||||
"""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -408,7 +408,7 @@ def test_ensure_dispatch_rule_returns_false_on_conflict(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
created = telephony_service.ensure_dispatch_rule(room)
|
||||
created = sip_management.ensure_dispatch_rule(room)
|
||||
|
||||
assert created is False
|
||||
|
||||
@@ -416,7 +416,7 @@ def test_ensure_dispatch_rule_returns_false_on_conflict(mock_client_factory):
|
||||
@mock.patch("core.utils.create_livekit_client")
|
||||
def test_ensure_dispatch_rule_raises_on_other_failures(mock_client_factory):
|
||||
"""Test that ensure_dispatch_rule propagates unexpected LiveKit failures."""
|
||||
telephony_service = TelephonyService()
|
||||
sip_management = SIPManagement()
|
||||
room = RoomFactory(access_level=RoomAccessLevel.RESTRICTED, pin_code="1234")
|
||||
|
||||
mock_api = create_mock_livekit_client()
|
||||
@@ -428,5 +428,5 @@ def test_ensure_dispatch_rule_raises_on_other_failures(mock_client_factory):
|
||||
)
|
||||
mock_client_factory.return_value = mock_api
|
||||
|
||||
with pytest.raises(TelephonyException, match="Could not create dispatch rule"):
|
||||
telephony_service.ensure_dispatch_rule(room)
|
||||
with pytest.raises(SIPException, match="Could not create dispatch rule"):
|
||||
sip_management.ensure_dispatch_rule(room)
|
||||
Reference in New Issue
Block a user