mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-21 15:47:09 +00:00
✨(backend) add roomkit viewset to start a room without WebRTC join
Introduce a new viewset that lets the roomkit start a room even when no WebRTC participant has joined yet. This is a first entry point that will be extended over time with more actions a roomkit needs to be able to trigger. Known limitations: * The responsibility around SIP rules is currently split between the telephony feature and the roomkit one. This may need a refactor later on to consolidate ownership in a single place. * The default throttle might be too low for production usage and will likely need to be revisited.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
"""Roomkit API endpoints for meeting-room (SIP) device integration."""
|
||||
|
||||
from logging import getLogger
|
||||
|
||||
from rest_framework import decorators, viewsets
|
||||
from rest_framework import (
|
||||
exceptions as drf_exceptions,
|
||||
)
|
||||
from rest_framework import (
|
||||
response as drf_response,
|
||||
)
|
||||
from rest_framework import (
|
||||
status as drf_status,
|
||||
)
|
||||
|
||||
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 . import authentication, serializers
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class RoomKitViewSet(viewsets.ViewSet):
|
||||
"""Server-to-server API endpoints for the roomkit integration.
|
||||
|
||||
Groups all interactions between roomkit (SIP) devices and the backend,
|
||||
brokered by the LiveKit SIP module. All endpoints are authenticated
|
||||
with the roomkit server-to-server tokens.
|
||||
"""
|
||||
|
||||
authentication_classes = [authentication.ServerToServerAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
@decorators.action(
|
||||
detail=False,
|
||||
methods=["post"],
|
||||
url_path="join",
|
||||
throttle_classes=[throttling.RoomKitJoinRateThrottle],
|
||||
)
|
||||
@FeatureFlag.require("roomkit")
|
||||
def join(self, request):
|
||||
"""Prepare a room for a meeting-room (SIP) device joining by PIN code.
|
||||
|
||||
Called by the LiveKit SIP module when a meeting-room device dials in
|
||||
with a PIN code before any WebRTC participant has joined. Resolves the
|
||||
room by PIN and creates its SIP dispatch rule, so the device can enter
|
||||
without waiting for a WebRTC user.
|
||||
|
||||
The webhook-based creation path is kept: both converge on the same rule
|
||||
through the shared TelephonyService.
|
||||
"""
|
||||
|
||||
serializer = serializers.RoomKitJoinSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
try:
|
||||
room = models.Room.objects.get(
|
||||
pin_code=serializer.validated_data["pin_code"]
|
||||
)
|
||||
except models.Room.DoesNotExist as e:
|
||||
raise drf_exceptions.NotFound("No room found for this PIN code.") from e
|
||||
|
||||
try:
|
||||
created = TelephonyService().ensure_dispatch_rule(room)
|
||||
except TelephonyException as e:
|
||||
raise drf_exceptions.APIException("Could not create dispatch rule.") from e
|
||||
|
||||
analytics.capture(
|
||||
request.user,
|
||||
analytics.AnalyticsEvent.ROOMKIT_JOINED,
|
||||
{
|
||||
"room_id": str(room.pk),
|
||||
"dispatch_rule_created": created,
|
||||
},
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Roomkit join requested: room_id=%s, dispatch_rule_created=%s",
|
||||
room.id,
|
||||
created,
|
||||
)
|
||||
|
||||
return drf_response.Response(
|
||||
{"status": "success"},
|
||||
status=drf_status.HTTP_200_OK,
|
||||
)
|
||||
Reference in New Issue
Block a user