From 0a2c4ce0fbd91d35e9e38fc7c033a9bcfef6b1fc Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 8 Jul 2026 00:29:09 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20derive=20is=5Fad?= =?UTF-8?q?ministrable=20from=20participant=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The is_administrable flag was previously read from the room API response through the room serializer, giving the frontend static information about the user's rights. Refactor the frontend so it derives this flag from the participant role carried in the participant metadata instead. Two benefits: * The flag now updates live along with the participant attributes/metadata, so role changes are reflected immediately. * It removes the duplication between the API response and the metadata, which both used to determine the user's capabilities. --- src/backend/core/api/serializers.py | 2 -- .../core/tests/rooms/test_api_rooms_retrieve.py | 11 ----------- .../rooms/livekit/hooks/useIsAdminOrOwner.ts | 17 ++++++++++++++--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index 1537b805..371daa15 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -189,8 +189,6 @@ class RoomSerializer(serializers.ModelSerializer): else: del output["pin_code"] - output["is_administrable"] = is_admin_or_owner - return output diff --git a/src/backend/core/tests/rooms/test_api_rooms_retrieve.py b/src/backend/core/tests/rooms/test_api_rooms_retrieve.py index ff746062..06401b39 100644 --- a/src/backend/core/tests/rooms/test_api_rooms_retrieve.py +++ b/src/backend/core/tests/rooms/test_api_rooms_retrieve.py @@ -31,7 +31,6 @@ def test_api_rooms_retrieve_anonymous_private_pk(): "configuration": {}, "access_level": "restricted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -51,7 +50,6 @@ def test_api_rooms_retrieve_anonymous_trusted_pk(): "configuration": {}, "access_level": "trusted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -70,7 +68,6 @@ def test_api_rooms_retrieve_anonymous_private_pk_no_dashes(): "configuration": {}, "access_level": "restricted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -87,7 +84,6 @@ def test_api_rooms_retrieve_anonymous_private_slug(): "configuration": {}, "access_level": "restricted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -104,7 +100,6 @@ def test_api_rooms_retrieve_anonymous_private_slug_not_normalized(): "configuration": {}, "access_level": "restricted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -214,7 +209,6 @@ def test_api_rooms_retrieve_anonymous_public(mock_token): "configuration": {}, "access_level": str(room.access_level), "id": str(room.id), - "is_administrable": False, "livekit": { "url": "test_url_value", "room": expected_name, @@ -261,7 +255,6 @@ def test_api_rooms_retrieve_authenticated_public(mock_token): "configuration": {"can_publish_sources": ["camera"]}, "access_level": str(room.access_level), "id": str(room.id), - "is_administrable": False, "livekit": { "url": "test_url_value", "room": expected_name, @@ -314,7 +307,6 @@ def test_api_rooms_retrieve_authenticated_trusted(mock_token): "configuration": {}, "access_level": str(room.access_level), "id": str(room.id), - "is_administrable": False, "livekit": { "url": "test_url_value", "room": expected_name, @@ -357,7 +349,6 @@ def test_api_rooms_retrieve_authenticated(): "configuration": {}, "access_level": "restricted", "id": str(room.id), - "is_administrable": False, "name": room.name, "slug": room.slug, } @@ -403,7 +394,6 @@ def test_api_rooms_retrieve_members(mock_token, django_assert_num_queries, setti "configuration": {"can_publish_sources": ["camera"]}, "access_level": str(room.access_level), "id": str(room.id), - "is_administrable": False, "livekit": { "url": "test_url_value", "room": expected_name, @@ -496,7 +486,6 @@ def test_api_rooms_retrieve_administrators( assert content_dict == { "access_level": str(room.access_level), "id": str(room.id), - "is_administrable": True, "configuration": {}, "livekit": { "url": "test_url_value", diff --git a/src/frontend/src/features/rooms/livekit/hooks/useIsAdminOrOwner.ts b/src/frontend/src/features/rooms/livekit/hooks/useIsAdminOrOwner.ts index e583a2cd..9dd87ecc 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useIsAdminOrOwner.ts +++ b/src/frontend/src/features/rooms/livekit/hooks/useIsAdminOrOwner.ts @@ -1,6 +1,17 @@ -import { useRoomData } from './useRoomData' +import { + useParticipantAttribute, + useRoomContext, +} from '@livekit/components-react' +import { ParticipantRole } from '@/features/rooms/api/ApiRoom' export const useIsAdminOrOwner = () => { - const apiRoomData = useRoomData() - return apiRoomData?.is_administrable + const room = useRoomContext() + const localParticipant = room.localParticipant + const role = useParticipantAttribute('room_role', { + participant: localParticipant, + }) + return ( + role !== undefined && + ['administrator', 'owner'].includes(role as ParticipantRole) + ) }