diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index bb7c8a93..5382be25 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -1,5 +1,7 @@ """Client serializers for the Meet core app.""" +import uuid + from django.utils.translation import gettext_lazy as _ from rest_framework import serializers @@ -219,6 +221,14 @@ class ParticipantEntrySerializer(serializers.Serializer): participant_id = serializers.CharField(required=True) allow_entry = serializers.BooleanField(required=True) + def validate_participant_id(self, value): + """Validate that the participant_id is a valid UUID hex string.""" + try: + uuid.UUID(hex=value, version=4) + except (ValueError, TypeError) as e: + raise serializers.ValidationError("Invalid UUID hex format") from e + return value + def create(self, validated_data): """Not implemented as this is a validation-only serializer.""" raise NotImplementedError("ParticipantEntrySerializer is validation-only") diff --git a/src/backend/core/tests/rooms/test_api_rooms_lobby.py b/src/backend/core/tests/rooms/test_api_rooms_lobby.py index 25034a4b..51ae97a8 100644 --- a/src/backend/core/tests/rooms/test_api_rooms_lobby.py +++ b/src/backend/core/tests/rooms/test_api_rooms_lobby.py @@ -132,18 +132,18 @@ def test_request_entry_with_existing_participants(settings): # Add two participants already waiting in the lobby cache.set( - f"mocked-cache-prefix_{room.id}_participant1", + f"mocked-cache-prefix_{room.id}_2f7f162fe7d1421b90e702bfbfbf8def", { - "id": "participant1", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "user1", "status": "waiting", "color": "#123456", }, ) cache.set( - f"mocked-cache-prefix_{room.id}_participant2", + f"mocked-cache-prefix_{room.id}_f4ca3ab8a6c04ad88097b8da33f60f10", { - "id": "participant2", + "id": "f4ca3ab8a6c04ad88097b8da33f60f10", "username": "user2", "status": "accepted", "color": "#654321", @@ -257,7 +257,9 @@ def test_request_entry_authenticated_user_public_room(settings): with ( mock.patch.object(LobbyService, "notify_participants", return_value=None), mock.patch.object( - LobbyService, "_get_or_create_participant_id", return_value="123" + LobbyService, + "_get_or_create_participant_id", + return_value="2f7f162fe7d1421b90e702bfbfbf8def", ), mock.patch.object( utils, "generate_livekit_config", return_value={"token": "test-token"} @@ -274,11 +276,11 @@ def test_request_entry_authenticated_user_public_room(settings): # Verify the lobby cookie was set cookie = response.cookies.get("mocked-cookie") assert cookie is not None - assert cookie.value == "123" + assert cookie.value == "2f7f162fe7d1421b90e702bfbfbf8def" # Verify response content matches expected structure and values assert response.json() == { - "id": "123", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "test_user", "status": "accepted", "color": "mocked-color", @@ -300,9 +302,9 @@ def test_request_entry_waiting_participant_public_room(settings): # Add a waiting participant to the room's lobby cache cache.set( - f"mocked-cache-prefix_{room.id}_participant1", + f"mocked-cache-prefix_{room.id}_2f7f162fe7d1421b90e702bfbfbf8def", { - "id": "participant1", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "user1", "status": "waiting", "color": "#123456", @@ -310,7 +312,7 @@ def test_request_entry_waiting_participant_public_room(settings): ) # Simulate a browser with existing participant cookie - client.cookies.load({"mocked-cookie": "participant1"}) + client.cookies.load({"mocked-cookie": "2f7f162fe7d1421b90e702bfbfbf8def"}) with ( mock.patch.object(LobbyService, "notify_participants", return_value=None), @@ -328,11 +330,11 @@ def test_request_entry_waiting_participant_public_room(settings): # Verify the lobby cookie was set cookie = response.cookies.get("mocked-cookie") assert cookie is not None - assert cookie.value == "participant1" + assert cookie.value == "2f7f162fe7d1421b90e702bfbfbf8def" # Verify response content matches expected structure and values assert response.json() == { - "id": "participant1", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "user1", "status": "accepted", "color": "#123456", @@ -379,7 +381,7 @@ def test_allow_participant_to_enter_anonymous(): response = client.post( f"/api/v1.0/rooms/{room.id}/enter/", - {"participant_id": "test-id", "allow_entry": True}, + {"participant_id": "2f7f162fe7d1421b90e702bfbfbf8def", "allow_entry": True}, ) assert response.status_code == 401 @@ -394,7 +396,7 @@ def test_allow_participant_to_enter_non_owner(): response = client.post( f"/api/v1.0/rooms/{room.id}/enter/", - {"participant_id": "test-id", "allow_entry": True}, + {"participant_id": "2f7f162fe7d1421b90e702bfbfbf8def", "allow_entry": True}, ) assert response.status_code == 403 @@ -412,7 +414,7 @@ def test_allow_participant_to_enter_public_room(): response = client.post( f"/api/v1.0/rooms/{room.id}/enter/", - {"participant_id": "test-id", "allow_entry": True}, + {"participant_id": "2f7f162fe7d1421b90e702bfbfbf8def", "allow_entry": True}, ) assert response.status_code == 404 @@ -435,9 +437,9 @@ def test_allow_participant_to_enter_success(settings, allow_entry, updated_statu settings.LOBBY_KEY_PREFIX = "mocked-cache-prefix" cache.set( - f"mocked-cache-prefix_{room.id!s}_participant1", + f"mocked-cache-prefix_{room.id!s}_2f7f162fe7d1421b90e702bfbfbf8def", { - "id": "test-id", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "status": "waiting", "username": "foo", "color": "123", @@ -446,13 +448,18 @@ def test_allow_participant_to_enter_success(settings, allow_entry, updated_statu response = client.post( f"/api/v1.0/rooms/{room.id}/enter/", - {"participant_id": "participant1", "allow_entry": allow_entry}, + { + "participant_id": "2f7f162fe7d1421b90e702bfbfbf8def", + "allow_entry": allow_entry, + }, ) assert response.status_code == 200 assert response.json() == {"message": "Participant was updated."} - participant_data = cache.get(f"mocked-cache-prefix_{room.id!s}_participant1") + participant_data = cache.get( + f"mocked-cache-prefix_{room.id!s}_2f7f162fe7d1421b90e702bfbfbf8def" + ) assert participant_data.get("status") == updated_status @@ -468,12 +475,14 @@ def test_allow_participant_to_enter_participant_not_found(settings): settings.LOBBY_KEY_PREFIX = "mocked-cache-prefix" - participant_data = cache.get(f"mocked-cache-prefix_{room.id!s}_test-id") + participant_data = cache.get( + f"mocked-cache-prefix_{room.id!s}_2f7f162fe7d1421b90e702bfbfbf8def" + ) assert participant_data is None response = client.post( f"/api/v1.0/rooms/{room.id}/enter/", - {"participant_id": "test-id", "allow_entry": True}, + {"participant_id": "2f7f162fe7d1421b90e702bfbfbf8def", "allow_entry": True}, ) assert response.status_code == 404 @@ -563,18 +572,18 @@ def test_list_waiting_participants_success(settings): # Add participants in the lobby cache.set( - f"mocked-cache-prefix_{room.id}_participant1", + f"mocked-cache-prefix_{room.id}_2f7f162fe7d1421b90e702bfbfbf8def", { - "id": "participant1", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "user1", "status": "waiting", "color": "#123456", }, ) cache.set( - f"mocked-cache-prefix_{room.id}_participant2", + f"mocked-cache-prefix_{room.id}_f4ca3ab8a6c04ad88097b8da33f60f10", { - "id": "participant2", + "id": "f4ca3ab8a6c04ad88097b8da33f60f10", "username": "user2", "status": "waiting", "color": "#654321", @@ -588,13 +597,13 @@ def test_list_waiting_participants_success(settings): participants = response.json().get("participants") assert sorted(participants, key=lambda p: p["id"]) == [ { - "id": "participant1", + "id": "2f7f162fe7d1421b90e702bfbfbf8def", "username": "user1", "status": "waiting", "color": "#123456", }, { - "id": "participant2", + "id": "f4ca3ab8a6c04ad88097b8da33f60f10", "username": "user2", "status": "waiting", "color": "#654321",