diff --git a/meet-ce/backend/openapi/components/parameters/room-x-fields-header.yaml b/meet-ce/backend/openapi/components/parameters/room-x-fields-header.yaml
index ff3cefcb..68738127 100644
--- a/meet-ce/backend/openapi/components/parameters/room-x-fields-header.yaml
+++ b/meet-ce/backend/openapi/components/parameters/room-x-fields-header.yaml
@@ -9,5 +9,5 @@ schema:
type: string
examples:
basic:
- value: 'roomId,roomName,accessUrl'
+ value: 'roomId,roomName,status'
summary: Only return basic room information
diff --git a/meet-ce/backend/openapi/components/requestBodies/update-room-access-request.yaml b/meet-ce/backend/openapi/components/requestBodies/update-room-access-request.yaml
new file mode 100644
index 00000000..4d05b3d5
--- /dev/null
+++ b/meet-ce/backend/openapi/components/requestBodies/update-room-access-request.yaml
@@ -0,0 +1,9 @@
+description: Room access configuration update options
+required: true
+content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ access:
+ $ref: '../schemas/meet-room-access-config.yaml'
diff --git a/meet-ce/backend/openapi/components/requestBodies/update-room-anonymous-request.yaml b/meet-ce/backend/openapi/components/requestBodies/update-room-anonymous-request.yaml
deleted file mode 100644
index 03ff3151..00000000
--- a/meet-ce/backend/openapi/components/requestBodies/update-room-anonymous-request.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-description: Room anonymous access configuration update options
-required: true
-content:
- application/json:
- schema:
- type: object
- properties:
- config:
- $ref: '../schemas/meet-room-anonymous-config.yaml'
diff --git a/meet-ce/backend/openapi/components/responses/success-bulk-delete-rooms.yaml b/meet-ce/backend/openapi/components/responses/success-bulk-delete-rooms.yaml
index 9d95f610..795cef37 100644
--- a/meet-ce/backend/openapi/components/responses/success-bulk-delete-rooms.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-bulk-delete-rooms.yaml
@@ -70,14 +70,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: closed
meetingEndAction: none
_extraFields:
@@ -94,14 +100,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: delete
_extraFields:
@@ -118,14 +130,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: close
_extraFields:
@@ -142,14 +160,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: delete
_extraFields:
@@ -166,14 +190,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: close
_extraFields:
diff --git a/meet-ce/backend/openapi/components/responses/success-create-room.yaml b/meet-ce/backend/openapi/components/responses/success-create-room.yaml
index ed804b7c..44956e92 100644
--- a/meet-ce/backend/openapi/components/responses/success-create-room.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-create-room.yaml
@@ -9,7 +9,7 @@ content:
_extraFields:
type: array
description: >
- List of extra fields that can be included in the response based on the `X-ExtraFields` header.
+ List of extra fields that can be included in the response based on the `X-ExtraFields` header.
items:
type: string
example: config
@@ -58,17 +58,23 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: open
meetingEndAction: none
- _extraFields: ["config"]
+ _extraFields: ['config']
headers:
Location:
description: URL of the newly created room
diff --git a/meet-ce/backend/openapi/components/responses/success-delete-room-processed.yaml b/meet-ce/backend/openapi/components/responses/success-delete-room-processed.yaml
index 44f2a4cc..58c73a6a 100644
--- a/meet-ce/backend/openapi/components/responses/success-delete-room-processed.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-delete-room-processed.yaml
@@ -61,14 +61,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: closed
meetingEndAction: none
_extraFields:
@@ -86,14 +92,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: close
_extraFields:
diff --git a/meet-ce/backend/openapi/components/responses/success-delete-room-scheduled.yaml b/meet-ce/backend/openapi/components/responses/success-delete-room-scheduled.yaml
index dfae9ae1..bb031d00 100644
--- a/meet-ce/backend/openapi/components/responses/success-delete-room-scheduled.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-delete-room-scheduled.yaml
@@ -36,14 +36,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: delete
_extraFields:
@@ -57,14 +63,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: delete
_extraFields:
@@ -78,14 +90,20 @@ content:
roomName: room
owner: 'admin'
creationDate: 1620000000000
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: active_meeting
meetingEndAction: close
_extraFields:
diff --git a/meet-ce/backend/openapi/components/responses/success-get-room.yaml b/meet-ce/backend/openapi/components/responses/success-get-room.yaml
index 9bd359a4..ea892dab 100644
--- a/meet-ce/backend/openapi/components/responses/success-get-room.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-get-room.yaml
@@ -15,7 +15,7 @@ content:
example: config
examples:
default_room_details:
- summary: Full room details response
+ summary: Full room details response without extra fields
value:
roomId: 'room-123'
roomName: 'room'
@@ -58,14 +58,20 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: open
meetingEndAction: none
_extraFields:
@@ -73,16 +79,6 @@ content:
fields=roomId,roomName,creationDate,autoDeletionDate,config:
summary: Room details with roomId, roomName, creationDate, autoDeletionDate, and config
- value:
- roomId: 'room-123'
- roomName: 'room'
- creationDate: 1620000000000
- autoDeletionDate: 1900000000000
- _extraFields:
- - config
-
- extraFields=config:
- summary: Room details with expanded config
value:
roomId: 'room-123'
roomName: 'room'
@@ -103,15 +99,98 @@ content:
enabled: true
_extraFields:
- config
- fields=anonymous:
- summary: Response containing only anonymous access configuration
+
+ extraFields=config:
+ summary: Room details with expanded config
value:
- anonymous:
+ roomId: 'room-123'
+ roomName: 'room'
+ owner: 'admin'
+ creationDate: 1620000000000
+ autoDeletionDate: 1900000000000
+ autoDeletionPolicy:
+ withMeeting: when_meeting_ends
+ withRecordings: close
+ config:
+ chat:
+ enabled: true
+ recording:
+ enabled: true
+ layout: grid
+ encoding: H264_720P_30
+ virtualBackground:
+ enabled: true
+ e2ee:
+ enabled: false
+ captions:
+ enabled: true
+ roles:
moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
+ permissions:
+ canRecord: true
+ canRetrieveRecordings: true
+ canDeleteRecordings: true
+ canJoinMeeting: true
+ canShareAccessLinks: true
+ canMakeModerator: true
+ canKickParticipants: true
+ canEndMeeting: true
+ canPublishVideo: true
+ canPublishAudio: true
+ canShareScreen: true
+ canReadChat: true
+ canWriteChat: true
+ canChangeVirtualBackground: true
speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
+ permissions:
+ canRecord: false
+ canRetrieveRecordings: true
+ canDeleteRecordings: false
+ canJoinMeeting: true
+ canShareAccessLinks: false
+ canMakeModerator: false
+ canKickParticipants: false
+ canEndMeeting: false
+ canPublishVideo: true
+ canPublishAudio: true
+ canShareScreen: true
+ canReadChat: true
+ canWriteChat: true
+ canChangeVirtualBackground: true
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
+ status: open
+ meetingEndAction: none
+ _extraFields:
+ - config
+ fields=access:
+ summary: Response containing only access configuration
+ value:
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
_extraFields:
- config
diff --git a/meet-ce/backend/openapi/components/responses/success-get-rooms.yaml b/meet-ce/backend/openapi/components/responses/success-get-rooms.yaml
index e7cd3758..0aeec474 100644
--- a/meet-ce/backend/openapi/components/responses/success-get-rooms.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-get-rooms.yaml
@@ -20,7 +20,7 @@ content:
examples:
default_room_details:
- summary: Full room details response with multiple rooms
+ summary: Full room details without extra fields for multiple rooms
value:
rooms:
- roomId: 'room-123'
@@ -64,14 +64,20 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: open
meetingEndAction: none
- roomId: 'room-456'
@@ -115,14 +121,20 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: false
- accessUrl: 'https://example.com/room/room-456?secret=789012'
- speaker:
+ access:
+ anonymous:
+ moderator:
+ enabled: false
+ url: 'https://example.com/room/room-456?secret=789012'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-456?secret=210987'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-456/recordings?secret=345678'
+ registered:
enabled: true
- accessUrl: 'https://example.com/room/room-456?secret=210987'
- accessUrl: 'https://example.com/room/room-456'
+ url: 'https://example.com/room/room-456'
status: open
meetingEndAction: none
_extraFields:
@@ -199,14 +211,20 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=123456'
- speaker:
- enabled: true
- accessUrl: 'https://example.com/room/room-123?secret=654321'
- accessUrl: 'https://example.com/room/room-123'
+ access:
+ anonymous:
+ moderator:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=123456'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-123?secret=654321'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-123/recordings?secret=987654'
+ registered:
+ enabled: false
+ url: 'https://example.com/room/room-123'
status: open
meetingEndAction: none
- roomId: 'room-456'
@@ -273,14 +291,20 @@ content:
canReadChat: true
canWriteChat: true
canChangeVirtualBackground: true
- anonymous:
- moderator:
- enabled: false
- accessUrl: 'https://example.com/room/room-456?secret=789012'
- speaker:
+ access:
+ anonymous:
+ moderator:
+ enabled: false
+ url: 'https://example.com/room/room-456?secret=789012'
+ speaker:
+ enabled: true
+ url: 'https://example.com/room/room-456?secret=210987'
+ recording:
+ enabled: true
+ url: 'https://example.com/room/room-456/recordings?secret=345678'
+ registered:
enabled: true
- accessUrl: 'https://example.com/room/room-456?secret=210987'
- accessUrl: 'https://example.com/room/room-456'
+ url: 'https://example.com/room/room-456'
status: open
meetingEndAction: none
_extraFields:
diff --git a/meet-ce/backend/openapi/components/responses/success-update-room-anonymous.yaml b/meet-ce/backend/openapi/components/responses/success-update-room-access.yaml
similarity index 50%
rename from meet-ce/backend/openapi/components/responses/success-update-room-anonymous.yaml
rename to meet-ce/backend/openapi/components/responses/success-update-room-access.yaml
index d739418f..0a80aef8 100644
--- a/meet-ce/backend/openapi/components/responses/success-update-room-anonymous.yaml
+++ b/meet-ce/backend/openapi/components/responses/success-update-room-access.yaml
@@ -1,4 +1,4 @@
-description: Success response for updating room anonymous access configuration
+description: Success response for updating room access configuration
content:
application/json:
schema:
@@ -7,4 +7,4 @@ content:
message:
type: string
example:
- message: Anonymous access config for room 'room-123' updated successfully
+ message: Access config for room 'room-123' updated successfully
diff --git a/meet-ce/backend/openapi/components/schemas/meet-room-access-config.yaml b/meet-ce/backend/openapi/components/schemas/meet-room-access-config.yaml
new file mode 100644
index 00000000..ea3feffb
--- /dev/null
+++ b/meet-ce/backend/openapi/components/schemas/meet-room-access-config.yaml
@@ -0,0 +1,46 @@
+type: object
+properties:
+ anonymous:
+ type: object
+ properties:
+ moderator:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ default: true
+ example: true
+ description: |
+ Enables or disables anonymous access for the moderator role.
+ speaker:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ default: true
+ example: true
+ description: |
+ Enables or disables anonymous access for the speaker role.
+ recording:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ default: true
+ example: true
+ description: |
+ Enables or disables anonymous access for recordings in the room. This also controls whether individual anonymous recording URLs can be generated.
+ registered:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ default: true
+ example: true
+ description: |
+ Enables or disables access for registered users.
+ **Note**: admins, owner and members of the room will always have access regardless of this setting.
+description: |
+ Configuration for room access.
+
+ All fields are optional. If not specified, current configuration will be maintained.
diff --git a/meet-ce/backend/openapi/components/schemas/meet-room-anonymous-config.yaml b/meet-ce/backend/openapi/components/schemas/meet-room-anonymous-config.yaml
deleted file mode 100644
index e824804f..00000000
--- a/meet-ce/backend/openapi/components/schemas/meet-room-anonymous-config.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-type: object
-properties:
- moderator:
- type: object
- properties:
- enabled:
- type: boolean
- default: true
- example: true
- description: |
- Enables or disables anonymous access for the moderator role.
- speaker:
- type: object
- properties:
- enabled:
- type: boolean
- default: true
- example: true
- description: |
- Enables or disables anonymous access for the speaker role.
-description: |
- Configuration for anonymous access.
-
- Both moderator and speaker fields are optional. If not specified, current configuration will be maintained.
diff --git a/meet-ce/backend/openapi/components/schemas/meet-room-options.yaml b/meet-ce/backend/openapi/components/schemas/meet-room-options.yaml
index 2b6651a5..9b93808b 100644
--- a/meet-ce/backend/openapi/components/schemas/meet-room-options.yaml
+++ b/meet-ce/backend/openapi/components/schemas/meet-room-options.yaml
@@ -68,12 +68,15 @@ properties:
- Speaker: Permissions to publish audio and video streams.
You can customize this by providing partial permissions for each role (only specify the permissions you want to override).
- anonymous:
- $ref: meet-room-anonymous-config.yaml
+ access:
+ $ref: meet-room-access-config.yaml
description: |
- Configuration for anonymous access to the room.
+ Configuration for room access.
- By default (if not specified), anonymous access is enabled for both moderators and speakers.
- You can customize this behavior by disabling anonymous access for specific roles (moderator/speaker) with per-role `enabled: false`
+ By default (if not specified), anonymous access is enabled for both moderator and speaker roles, and for recording access.
+ However, registered access is disabled by default.
+ You can customize this behavior by disabling access for specific scopes and roles
+ (`registered`, `anonymous.moderator`, `anonymous.speaker`, `anonymous.recording`) using `enabled: false`.
- Permissions for anonymous users are determined by the room's role permissions.
+ Permissions for anonymous users are determined by the room's role permissions. For registered users (who are not admins or members of the room),
+ permissions will be the same as the speaker role.
diff --git a/meet-ce/backend/openapi/components/schemas/meet-room.yaml b/meet-ce/backend/openapi/components/schemas/meet-room.yaml
index 6b0f87ff..2a9f01df 100644
--- a/meet-ce/backend/openapi/components/schemas/meet-room.yaml
+++ b/meet-ce/backend/openapi/components/schemas/meet-room.yaml
@@ -62,7 +62,7 @@ properties:
Policy for automatic deletion when the room has recordings. Options are:
- force: The room and its recordings will be deleted.
- close: The room will be closed instead of deleted, maintaining its recordings.
- config (excluded by default):
+ config:
description: |
Room configuration (chat, recording, virtual background, e2ee, captions).
@@ -70,7 +70,7 @@ properties:
**Excluded from responses by default to reduce payload size.**
To include it in the response:
- **POST requests:** use the `X-ExtraFields: config` header
- - **Other requests:** use either the `extraFields=config` query parameter or the `X-ExtraFields: config` header $ref: meet-room-config.yaml#/MeetRoomConfig
+ - **Other requests:** use either the `extraFields=config` query parameter or the `X-ExtraFields: config` header
$ref: meet-room-config.yaml#/MeetRoomConfig
# maxParticipants:
# type: integer
@@ -97,49 +97,71 @@ properties:
$ref: meet-permissions.yaml
description: >
The complete set of permissions for the speaker role. These define what speakers can do in the meeting.
- anonymous:
+ access:
description: >
- Configuration for anonymous access to the room. Defines which roles have anonymous access enabled and their access URLs.
+ Access configuration and generated access URLs for the room.
type: object
properties:
- moderator:
+ anonymous:
+ type: object
+ properties:
+ moderator:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ example: true
+ description: >
+ Whether anonymous access for the moderator role is enabled.
+ url:
+ type: string
+ format: uri
+ example: 'http://localhost:6080/room/room-123?secret=123456'
+ description: >
+ The URL for anonymous moderators to access the room.
+ speaker:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ example: true
+ description: >
+ Whether anonymous access for the speaker role is enabled.
+ url:
+ type: string
+ format: uri
+ example: 'http://localhost:6080/room/room-123?secret=654321'
+ description: >
+ The URL for anonymous speakers to access the room.
+ recording:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ example: true
+ description: >
+ Whether anonymous access for recordings in the room is enabled.
+ url:
+ type: string
+ format: uri
+ example: 'http://localhost:6080/room/room-123?secret=987654'
+ description: >
+ The URL for anonymous access to the room's recordings.
+ registered:
type: object
properties:
enabled:
type: boolean
example: true
description: >
- Whether anonymous access with moderator role is enabled.
- accessUrl:
+ Whether access for registered users is enabled.
+ **Note**: admins, owner and members of the room will always have access regardless of this setting.
+ url:
type: string
format: uri
- example: 'http://localhost:6080/room/room-123?secret=123456'
+ example: 'http://localhost:6080/room/room-123'
description: >
- The URL for anonymous moderators to access the room.
- speaker:
- type: object
- properties:
- enabled:
- type: boolean
- example: true
- description: >
- Whether anonymous access with speaker role is enabled.
- accessUrl:
- type: string
- format: uri
- example: 'http://localhost:6080/room/room-123?secret=654321'
- description: >
- The URL for anonymous speakers to access the room.
- accessUrl:
- type: string
- format: uri
- example: 'http://localhost:6080/room/room-123'
- description: |
- The general access URL for authenticated users to join the room.
-
- This URL should be used by:
- - The room owner (registered Meet user who created the room)
- - Registered Meet users who are members of the room
+ The URL for registered users to access the room.
status:
type: string
enum:
diff --git a/meet-ce/backend/openapi/openvidu-meet-api.yaml b/meet-ce/backend/openapi/openvidu-meet-api.yaml
index 795406f4..2859118e 100644
--- a/meet-ce/backend/openapi/openvidu-meet-api.yaml
+++ b/meet-ce/backend/openapi/openvidu-meet-api.yaml
@@ -17,8 +17,8 @@ paths:
$ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1config'
/rooms/{roomId}/roles:
$ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1roles'
- /rooms/{roomId}/anonymous:
- $ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1anonymous'
+ /rooms/{roomId}/access:
+ $ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1access'
/rooms/{roomId}/status:
$ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1status'
/rooms/{roomId}/members:
diff --git a/meet-ce/backend/openapi/paths/rooms.yaml b/meet-ce/backend/openapi/paths/rooms.yaml
index 22eb6001..e29e29e6 100644
--- a/meet-ce/backend/openapi/paths/rooms.yaml
+++ b/meet-ce/backend/openapi/paths/rooms.yaml
@@ -290,14 +290,15 @@
$ref: '../components/responses/validation-error.yaml'
'500':
$ref: '../components/responses/internal-server-error.yaml'
-/rooms/{roomId}/anonymous:
+/rooms/{roomId}/access:
put:
- operationId: updateRoomAnonymous
- summary: Update anonymous access config for a room
+ operationId: updateRoomAccess
+ summary: Update access config for a room
description: |
- Updates the anonymous access configuration for the specified room.
+ Updates the access configuration for the specified room.
- This allows you to enable or disable anonymous access for specific roles (moderator/speaker).
+ This allows you to enable or disable access for registered users and anonymous roles
+ (moderator/speaker/recording).
tags:
- OpenVidu Meet - Rooms
security:
@@ -306,10 +307,10 @@
parameters:
- $ref: '../components/parameters/room-id-path.yaml'
requestBody:
- $ref: '../components/requestBodies/update-room-anonymous-request.yaml'
+ $ref: '../components/requestBodies/update-room-access-request.yaml'
responses:
'200':
- $ref: '../components/responses/success-update-room-anonymous.yaml'
+ $ref: '../components/responses/success-update-room-access.yaml'
'401':
$ref: '../components/responses/unauthorized-error.yaml'
'403':
diff --git a/meet-ce/backend/src/controllers/room.controller.ts b/meet-ce/backend/src/controllers/room.controller.ts
index bccc213c..55b7bd2c 100644
--- a/meet-ce/backend/src/controllers/room.controller.ts
+++ b/meet-ce/backend/src/controllers/room.controller.ts
@@ -257,18 +257,18 @@ export const updateRoomRoles = async (req: Request, res: Response) => {
}
};
-export const updateRoomAnonymous = async (req: Request, res: Response) => {
+export const updateRoomAccess = async (req: Request, res: Response) => {
const logger = container.get(LoggerService);
const roomService = container.get(RoomService);
- const { anonymous } = req.body;
+ const { access } = req.body;
const { roomId } = req.params;
- logger.verbose(`Updating anonymous access config for room '${roomId}'`);
+ logger.verbose(`Updating access config for room '${roomId}'`);
try {
- await roomService.updateMeetRoomAnonymous(roomId, anonymous);
- return res.status(200).json({ message: `Anonymous access config for room '${roomId}' updated successfully` });
+ await roomService.updateMeetRoomAccess(roomId, access);
+ return res.status(200).json({ message: `Access config for room '${roomId}' updated successfully` });
} catch (error) {
- handleError(res, error, `updating anonymous access config for room '${roomId}'`);
+ handleError(res, error, `updating access config for room '${roomId}'`);
}
};
diff --git a/meet-ce/backend/src/helpers/room.helper.ts b/meet-ce/backend/src/helpers/room.helper.ts
index b4a52e4f..a777ad81 100644
--- a/meet-ce/backend/src/helpers/room.helper.ts
+++ b/meet-ce/backend/src/helpers/room.helper.ts
@@ -2,7 +2,7 @@ import {
MEET_ROOM_EXTRA_FIELDS,
MEET_ROOM_FIELDS,
MeetRoom,
- MeetRoomAnonymous,
+ MeetRoomAccess,
MeetRoomExtraField,
MeetRoomField,
MeetRoomMemberPermissions,
@@ -77,12 +77,20 @@ export class MeetRoomHelper {
autoDeletionPolicy: room.autoDeletionPolicy,
config: room.config,
roles: room.roles,
- anonymous: {
- moderator: {
- enabled: room.anonymous.moderator.enabled
+ access: {
+ anonymous: {
+ moderator: {
+ enabled: room.access.anonymous.moderator.enabled
+ },
+ speaker: {
+ enabled: room.access.anonymous.speaker.enabled
+ },
+ recording: {
+ enabled: room.access.anonymous.recording.enabled
+ }
},
- speaker: {
- enabled: room.anonymous.speaker.enabled
+ registered: {
+ enabled: room.access.registered.enabled
}
}
// maxParticipants: room.maxParticipants
@@ -90,25 +98,33 @@ export class MeetRoomHelper {
}
/**
- * Extracts speaker and moderator secrets from MeetRoom anonymous access URLs.
+ * Extracts speaker, moderator, and recording secrets from MeetRoom anonymous access URLs.
*
- * This method parses the 'secret' query parameter from both speaker and moderator
+ * This method parses the 'secret' query parameter from speaker, moderator, and recording
* anonymous access URLs associated with the meeting room.
*
- * @param room - The anonymous access configuration of the MeetRoom from which to extract secrets.
+ * @param roomAccess - The access configuration of the MeetRoom from which to extract secrets.
* @returns An object containing the extracted secrets with the following properties:
* - speakerSecret: The secret extracted from the speaker anonymous access URL
* - moderatorSecret: The secret extracted from the moderator anonymous access URL
+ * - recordingSecret: The secret extracted from the recording anonymous access URL
*/
- static extractSecretsFromRoom(anonymous: MeetRoomAnonymous): { speakerSecret: string; moderatorSecret: string } {
- const speakerUrl = anonymous.speaker.accessUrl;
- const moderatorUrl = anonymous.moderator.accessUrl;
+ static extractSecretsFromRoom(roomAccess: MeetRoomAccess): {
+ speakerSecret: string;
+ moderatorSecret: string;
+ recordingSecret: string;
+ } {
+ const speakerUrl = roomAccess.anonymous.speaker.url;
+ const moderatorUrl = roomAccess.anonymous.moderator.url;
+ const recordingUrl = roomAccess.anonymous.recording.url;
const parsedSpeakerUrl = new URL(speakerUrl);
const speakerSecret = parsedSpeakerUrl.searchParams.get('secret') || '';
const parsedModeratorUrl = new URL(moderatorUrl);
const moderatorSecret = parsedModeratorUrl.searchParams.get('secret') || '';
- return { speakerSecret, moderatorSecret };
+ const parsedRecordingUrl = new URL(recordingUrl);
+ const recordingSecret = parsedRecordingUrl.searchParams.get('secret') || '';
+ return { speakerSecret, moderatorSecret, recordingSecret };
}
/**
diff --git a/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts b/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts
index c6837434..81328e15 100644
--- a/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts
+++ b/meet-ce/backend/src/middlewares/request-validators/room-validator.middleware.ts
@@ -8,7 +8,7 @@ import {
RoomFiltersSchema,
RoomOptionsSchema,
RoomQueryFieldsSchema,
- UpdateRoomAnonymousReqSchema,
+ UpdateRoomAccessReqSchema,
UpdateRoomConfigReqSchema,
UpdateRoomRolesReqSchema,
UpdateRoomStatusReqSchema
@@ -152,8 +152,8 @@ export const validateUpdateRoomRolesReq = (req: Request, res: Response, next: Ne
next();
};
-export const validateUpdateRoomAnonymousReq = (req: Request, res: Response, next: NextFunction) => {
- const { success, error, data } = UpdateRoomAnonymousReqSchema.safeParse(req.body);
+export const validateUpdateRoomAccessReq = (req: Request, res: Response, next: NextFunction) => {
+ const { success, error, data } = UpdateRoomAccessReqSchema.safeParse(req.body);
if (!success) {
return rejectUnprocessableRequest(res, error);
diff --git a/meet-ce/backend/src/migrations/room-migrations.ts b/meet-ce/backend/src/migrations/room-migrations.ts
index 4f6096b4..b267989b 100644
--- a/meet-ce/backend/src/migrations/room-migrations.ts
+++ b/meet-ce/backend/src/migrations/room-migrations.ts
@@ -1,4 +1,5 @@
import { MeetRecordingEncodingPreset, MeetRecordingLayout } from '@openvidu-meet/typings';
+import { uid as secureUid } from 'uid/secure';
import { MEET_ENV } from '../environment.js';
import { generateSchemaMigrationName, SchemaMigrationMap, SchemaTransform } from '../models/migration.model.js';
import { meetRoomCollectionName, MeetRoomDocument } from '../models/mongoose-schemas/room.schema.js';
@@ -63,17 +64,26 @@ const roomMigrationV2ToV3Transform: SchemaTransform = (room) =
}
}
};
- room.anonymous = {
- moderator: {
- enabled: true,
- accessUrl: legacyRoom.moderatorUrl!
+ room.access = {
+ anonymous: {
+ moderator: {
+ enabled: true,
+ url: legacyRoom.moderatorUrl!
+ },
+ speaker: {
+ enabled: true,
+ url: legacyRoom.speakerUrl!
+ },
+ recording: {
+ enabled: false,
+ url: `/room/${room.roomId}/recordings?secret=${secureUid(10)}`
+ }
},
- speaker: {
+ registered: {
enabled: true,
- accessUrl: legacyRoom.speakerUrl!
+ url: `/room/${room.roomId}`
}
};
- room.accessUrl = `/room/${room.roomId}`;
room.rolesUpdatedAt = Date.now();
delete legacyRoom.moderatorUrl;
diff --git a/meet-ce/backend/src/models/mongoose-schemas/room.schema.ts b/meet-ce/backend/src/models/mongoose-schemas/room.schema.ts
index 5e226f34..c4392f59 100644
--- a/meet-ce/backend/src/models/mongoose-schemas/room.schema.ts
+++ b/meet-ce/backend/src/models/mongoose-schemas/room.schema.ts
@@ -200,26 +200,48 @@ const MeetRoomRolesSchema = new Schema(
);
/**
- * Sub-schema for anonymous access configuration.
+ * Sub-schema for access configuration.
*/
-const MeetRoomAnonymousSchema = new Schema(
+const MeetRoomAccessSchema = new Schema(
{
- moderator: {
- enabled: {
- type: Boolean,
- required: true
+ anonymous: {
+ moderator: {
+ enabled: {
+ type: Boolean,
+ required: true
+ },
+ url: {
+ type: String,
+ required: true
+ }
},
- accessUrl: {
- type: String,
- required: true
+ speaker: {
+ enabled: {
+ type: Boolean,
+ required: true
+ },
+ url: {
+ type: String,
+ required: true
+ }
+ },
+ recording: {
+ enabled: {
+ type: Boolean,
+ required: true
+ },
+ url: {
+ type: String,
+ required: true
+ }
}
},
- speaker: {
+ registered: {
enabled: {
type: Boolean,
required: true
},
- accessUrl: {
+ url: {
type: String,
required: true
}
@@ -300,12 +322,8 @@ const MeetRoomSchema = new Schema(
type: MeetRoomRolesSchema,
required: true
},
- anonymous: {
- type: MeetRoomAnonymousSchema,
- required: true
- },
- accessUrl: {
- type: String,
+ access: {
+ type: MeetRoomAccessSchema,
required: true
},
status: {
diff --git a/meet-ce/backend/src/models/zod-schemas/room.schema.ts b/meet-ce/backend/src/models/zod-schemas/room.schema.ts
index 9e1dd2e2..2c1ac1af 100644
--- a/meet-ce/backend/src/models/zod-schemas/room.schema.ts
+++ b/meet-ce/backend/src/models/zod-schemas/room.schema.ts
@@ -11,7 +11,7 @@ import {
MeetRecordingEncodingPreset,
MeetRecordingLayout,
MeetRecordingVideoCodec,
- MeetRoomAnonymousConfig,
+ MeetRoomAccessConfig,
MeetRoomAutoDeletionPolicy,
MeetRoomCaptionsConfig,
MeetRoomConfig,
@@ -296,13 +296,27 @@ const RoomRolesConfigSchema: z.ZodType = z.object({
.optional()
});
-const RoomAnonymousConfigSchema: z.ZodType = z.object({
- moderator: z
+const RoomAccessConfigSchema: z.ZodType = z.object({
+ anonymous: z
.object({
- enabled: z.boolean()
+ moderator: z
+ .object({
+ enabled: z.boolean()
+ })
+ .optional(),
+ speaker: z
+ .object({
+ enabled: z.boolean()
+ })
+ .optional(),
+ recording: z
+ .object({
+ enabled: z.boolean()
+ })
+ .optional()
})
.optional(),
- speaker: z
+ registered: z
.object({
enabled: z.boolean()
})
@@ -359,9 +373,13 @@ export const RoomOptionsSchema: z.ZodType = z.object({
captions: { enabled: true }
}),
roles: RoomRolesConfigSchema.optional(),
- anonymous: RoomAnonymousConfigSchema.optional().default({
- moderator: { enabled: true },
- speaker: { enabled: true }
+ access: RoomAccessConfigSchema.optional().default({
+ anonymous: {
+ moderator: { enabled: true },
+ speaker: { enabled: true },
+ recording: { enabled: true }
+ },
+ registered: { enabled: false }
})
// maxParticipants: z
// .number()
@@ -556,8 +574,8 @@ export const UpdateRoomRolesReqSchema = z.object({
roles: RoomRolesConfigSchema
});
-export const UpdateRoomAnonymousReqSchema = z.object({
- anonymous: RoomAnonymousConfigSchema
+export const UpdateRoomAccessReqSchema = z.object({
+ access: RoomAccessConfigSchema
});
export const UpdateRoomStatusReqSchema = z.object({
diff --git a/meet-ce/backend/src/repositories/room.repository.ts b/meet-ce/backend/src/repositories/room.repository.ts
index 8cb9d22f..0a56faa1 100644
--- a/meet-ce/backend/src/repositories/room.repository.ts
+++ b/meet-ce/backend/src/repositories/room.repository.ts
@@ -261,19 +261,25 @@ export class RoomRepository extends BaseRepository {
* @returns Normalized partial room data
*/
private normalizeRoomForStorage(room: Partial): Partial {
- if (room.accessUrl) {
- room.accessUrl = this.extractPathFromUrl(room.accessUrl);
+ const registeredUrl = room.access?.registered.url;
+ const moderatorUrl = room.access?.anonymous.moderator.url;
+ const speakerUrl = room.access?.anonymous.speaker.url;
+ const recordingUrl = room.access?.anonymous.recording.url;
+
+ if (registeredUrl) {
+ room.access!.registered.url = this.extractPathFromUrl(registeredUrl);
}
- const moderatorUrl = room.anonymous?.moderator.accessUrl;
- const speakerUrl = room.anonymous?.speaker.accessUrl;
-
if (moderatorUrl) {
- room.anonymous!.moderator.accessUrl = this.extractPathFromUrl(moderatorUrl);
+ room.access!.anonymous.moderator.url = this.extractPathFromUrl(moderatorUrl);
}
if (speakerUrl) {
- room.anonymous!.speaker.accessUrl = this.extractPathFromUrl(speakerUrl);
+ room.access!.anonymous.speaker.url = this.extractPathFromUrl(speakerUrl);
+ }
+
+ if (recordingUrl) {
+ room.access!.anonymous.recording.url = this.extractPathFromUrl(recordingUrl);
}
return room;
@@ -330,19 +336,25 @@ export class RoomRepository extends BaseRepository {
private enrichRoomWithBaseUrls(room: MeetRoom): MeetRoom {
const baseUrl = getBaseUrl();
- if (room.accessUrl) {
- room.accessUrl = `${baseUrl}${room.accessUrl}`;
+ const registeredUrl = room.access?.registered.url;
+ const moderatorUrl = room.access?.anonymous.moderator.url;
+ const speakerUrl = room.access?.anonymous.speaker.url;
+ const recordingUrl = room.access?.anonymous.recording.url;
+
+ if (registeredUrl) {
+ room.access!.registered.url = `${baseUrl}${registeredUrl}`;
}
- const moderatorUrl = room.anonymous?.moderator.accessUrl;
- const speakerUrl = room.anonymous?.speaker.accessUrl;
-
if (moderatorUrl) {
- room.anonymous!.moderator.accessUrl = `${baseUrl}${moderatorUrl}`;
+ room.access!.anonymous.moderator.url = `${baseUrl}${moderatorUrl}`;
}
if (speakerUrl) {
- room.anonymous!.speaker.accessUrl = `${baseUrl}${speakerUrl}`;
+ room.access!.anonymous.speaker.url = `${baseUrl}${speakerUrl}`;
+ }
+
+ if (recordingUrl) {
+ room.access!.anonymous.recording.url = `${baseUrl}${recordingUrl}`;
}
return room;
diff --git a/meet-ce/backend/src/routes/room.routes.ts b/meet-ce/backend/src/routes/room.routes.ts
index 1994166e..9ebaf417 100644
--- a/meet-ce/backend/src/routes/room.routes.ts
+++ b/meet-ce/backend/src/routes/room.routes.ts
@@ -22,7 +22,7 @@ import {
validateDeleteRoomReq,
validateGetRoomReq,
validateGetRoomsReq,
- validateUpdateRoomAnonymousReq,
+ validateUpdateRoomAccessReq,
validateUpdateRoomConfigReq,
validateUpdateRoomRolesReq,
validateUpdateRoomStatusReq,
@@ -116,12 +116,12 @@ roomRouter.put(
roomCtrl.updateRoomRoles
);
roomRouter.put(
- '/:roomId/anonymous',
+ '/:roomId/access',
withAuth(apiKeyValidator, accessTokenValidator(MeetUserRole.ADMIN, MeetUserRole.USER)),
withValidRoomId,
- validateUpdateRoomAnonymousReq,
+ validateUpdateRoomAccessReq,
authorizeRoomManagement,
- roomCtrl.updateRoomAnonymous
+ roomCtrl.updateRoomAccess
);
// Room Member Routes
diff --git a/meet-ce/backend/src/services/room-member.service.ts b/meet-ce/backend/src/services/room-member.service.ts
index 816dcd60..70885037 100644
--- a/meet-ce/backend/src/services/room-member.service.ts
+++ b/meet-ce/backend/src/services/room-member.service.ts
@@ -418,10 +418,10 @@ export class RoomMemberService {
} else {
// If secret matches anonymous access URL secret, assign role and permissions based on it
baseRole = await this.getRoomMemberRoleBySecret(roomId, secret);
- const { roles, anonymous } = await this.roomService.getMeetRoom(roomId, ['roles', 'anonymous']);
+ const { roles, access } = await this.roomService.getMeetRoom(roomId, ['roles', 'access']);
// Check that anonymous access is enabled for the role
- if (!anonymous[baseRole].enabled) {
+ if (!access.anonymous[baseRole].enabled) {
throw errorAnonymousAccessDisabled(roomId, baseRole);
}
@@ -609,8 +609,8 @@ export class RoomMemberService {
* @throws Error if the provided secret doesn't match any of the room's secrets (unauthorized)
*/
protected async getRoomMemberRoleBySecret(roomId: string, secret: string): Promise {
- const { anonymous } = await this.roomService.getMeetRoom(roomId, ['anonymous']);
- const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(anonymous);
+ const { access } = await this.roomService.getMeetRoom(roomId, ['access']);
+ const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(access);
switch (secret) {
case moderatorSecret:
@@ -778,7 +778,7 @@ export class RoomMemberService {
newRole: MeetRoomMemberRole
): Promise {
try {
- const { roles, anonymous } = await this.roomService.getMeetRoom(roomId, ['roles', 'anonymous']);
+ const { roles, access } = await this.roomService.getMeetRoom(roomId, ['roles', 'access']);
const participant = await this.getParticipantFromMeeting(roomId, participantIdentity);
const metadata: MeetRoomMemberTokenMetadata = this.tokenService.parseRoomMemberTokenMetadata(
participant.metadata
@@ -791,7 +791,7 @@ export class RoomMemberService {
await this.livekitService.updateParticipantMetadata(roomId, participantIdentity, JSON.stringify(metadata));
- const { speakerSecret, moderatorSecret } = MeetRoomHelper.extractSecretsFromRoom(anonymous);
+ const { speakerSecret, moderatorSecret } = MeetRoomHelper.extractSecretsFromRoom(access);
const secret = newRole === MeetRoomMemberRole.MODERATOR ? moderatorSecret : speakerSecret;
await this.frontendEventService.sendParticipantRoleUpdatedSignal(
roomId,
diff --git a/meet-ce/backend/src/services/room.service.ts b/meet-ce/backend/src/services/room.service.ts
index d34eb3d6..74da80f2 100644
--- a/meet-ce/backend/src/services/room.service.ts
+++ b/meet-ce/backend/src/services/room.service.ts
@@ -1,8 +1,8 @@
import {
MeetingEndAction,
MeetRoom,
- MeetRoomAnonymous,
- MeetRoomAnonymousConfig,
+ MeetRoomAccess,
+ MeetRoomAccessConfig,
MeetRoomConfig,
MeetRoomDeletionErrorCode,
MeetRoomDeletionPolicyWithMeeting,
@@ -81,7 +81,7 @@ export class RoomService {
*
*/
async createMeetRoom(roomOptions: MeetRoomOptions): Promise {
- const { roomName, autoDeletionDate, autoDeletionPolicy, config, roles, anonymous } = roomOptions;
+ const { roomName, autoDeletionDate, autoDeletionPolicy, config, roles, access } = roomOptions;
// Generate a unique room ID based on the room name
const roomIdPrefix = MeetRoomHelper.createRoomIdPrefixFromRoomName(roomName!) || 'room';
@@ -135,14 +135,24 @@ export class RoomService {
}
};
- const anonymousConfig: MeetRoomAnonymous = {
- moderator: {
- enabled: anonymous?.moderator?.enabled ?? true,
- accessUrl: `/room/${roomId}?secret=${secureUid(10)}`
+ const accessConfig: MeetRoomAccess = {
+ anonymous: {
+ moderator: {
+ enabled: access?.anonymous?.moderator?.enabled ?? true,
+ url: `/room/${roomId}?secret=${secureUid(10)}`
+ },
+ speaker: {
+ enabled: access?.anonymous?.speaker?.enabled ?? true,
+ url: `/room/${roomId}?secret=${secureUid(10)}`
+ },
+ recording: {
+ enabled: access?.anonymous?.recording?.enabled ?? true,
+ url: `/room/${roomId}/recordings?secret=${secureUid(10)}`
+ }
},
- speaker: {
- enabled: anonymous?.speaker?.enabled ?? true,
- accessUrl: `/room/${roomId}?secret=${secureUid(10)}`
+ registered: {
+ enabled: access?.registered?.enabled ?? false,
+ url: `/room/${roomId}`
}
};
@@ -157,8 +167,7 @@ export class RoomService {
autoDeletionPolicy: autoDeletionDate ? autoDeletionPolicy : undefined,
config: config as MeetRoomConfig,
roles: roomRoles,
- anonymous: anonymousConfig,
- accessUrl: `/room/${roomId}`,
+ access: accessConfig,
status: MeetRoomStatus.OPEN,
rolesUpdatedAt: now,
meetingEndAction: MeetingEndAction.NONE
@@ -284,24 +293,24 @@ export class RoomService {
}
/**
- * Updates the anonymous access configuration of a specific meeting room.
+ * Updates the access configuration of a specific meeting room.
*
* @param roomId - The unique identifier of the meeting room to update
- * @param anonymous - Partial anonymous config with the fields to update
+ * @param access - Partial access config with the fields to update
* @returns A Promise that resolves to the updated MeetRoom object
*/
- async updateMeetRoomAnonymous(roomId: string, anonymous: MeetRoomAnonymousConfig): Promise {
- const room = await this.getMeetRoom(roomId, ['anonymous', 'status']);
+ async updateMeetRoomAccess(roomId: string, access: MeetRoomAccessConfig): Promise {
+ const room = await this.getMeetRoom(roomId, ['access', 'status']);
if (room.status === MeetRoomStatus.ACTIVE_MEETING) {
throw errorRoomActiveMeeting(roomId);
}
- // Merge existing anonymous config with new anonymous config (partial update)
- const updatedAnonymous = merge({}, room.anonymous, anonymous);
+ // Merge existing access config with new access config (partial update)
+ const updatedAccess = merge({}, room.access, access);
return this.roomRepository.updatePartial(roomId, {
- anonymous: updatedAnonymous,
+ access: updatedAccess,
rolesUpdatedAt: Date.now()
});
}
@@ -870,9 +879,10 @@ export class RoomService {
* @throws Error if room not found
*/
async isValidRoomSecret(roomId: string, secret: string): Promise {
- const { anonymous } = await this.getMeetRoom(roomId, ['anonymous']);
- const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(anonymous);
- return secret === moderatorSecret || secret === speakerSecret;
+ const { access } = await this.getMeetRoom(roomId, ['access']);
+ const { moderatorSecret, speakerSecret, recordingSecret } = MeetRoomHelper.extractSecretsFromRoom(access);
+ const allSecrets = [moderatorSecret, speakerSecret, recordingSecret];
+ return allSecrets.includes(secret);
}
/**
diff --git a/meet-ce/backend/tests/helpers/assertion-helpers.ts b/meet-ce/backend/tests/helpers/assertion-helpers.ts
index 80b37c2b..8cd3df8d 100644
--- a/meet-ce/backend/tests/helpers/assertion-helpers.ts
+++ b/meet-ce/backend/tests/helpers/assertion-helpers.ts
@@ -169,18 +169,23 @@ export const expectValidRoom = (
expect(room.owner).toBeDefined();
expect(room.roles).toBeDefined();
- expect(room.anonymous).toBeDefined();
- expect(room.anonymous.moderator).toBeDefined();
- expect(room.anonymous.speaker).toBeDefined();
- expect(room.anonymous.moderator.enabled).toBeDefined();
- expect(room.anonymous.speaker.enabled).toBeDefined();
- expect(room.anonymous.moderator.accessUrl).toBeDefined();
- expect(room.anonymous.speaker.accessUrl).toBeDefined();
- expect(room.anonymous.moderator.accessUrl).toContain(room.roomId);
- expect(room.anonymous.speaker.accessUrl).toContain(room.roomId);
-
- expect(room.accessUrl).toBeDefined();
- expect(room.accessUrl).toContain(room.roomId);
+ expect(room.access).toBeDefined();
+ expect(room.access.anonymous.moderator).toBeDefined();
+ expect(room.access.anonymous.speaker).toBeDefined();
+ expect(room.access.anonymous.recording).toBeDefined();
+ expect(room.access.registered).toBeDefined();
+ expect(room.access.anonymous.moderator.enabled).toBeDefined();
+ expect(room.access.anonymous.speaker.enabled).toBeDefined();
+ expect(room.access.anonymous.recording.enabled).toBeDefined();
+ expect(room.access.registered.enabled).toBeDefined();
+ expect(room.access.anonymous.moderator.url).toBeDefined();
+ expect(room.access.anonymous.speaker.url).toBeDefined();
+ expect(room.access.anonymous.recording.url).toBeDefined();
+ expect(room.access.registered.url).toBeDefined();
+ expect(room.access.anonymous.moderator.url).toContain(room.roomId);
+ expect(room.access.anonymous.speaker.url).toContain(room.roomId);
+ expect(room.access.anonymous.recording.url).toContain(room.roomId);
+ expect(room.access.registered.url).toContain(room.roomId);
expect(room.status).toBeDefined();
expect(room.status).toEqual(status || MeetRoomStatus.OPEN);
diff --git a/meet-ce/backend/tests/helpers/request-helpers.ts b/meet-ce/backend/tests/helpers/request-helpers.ts
index c97f0f83..39ab7f69 100644
--- a/meet-ce/backend/tests/helpers/request-helpers.ts
+++ b/meet-ce/backend/tests/helpers/request-helpers.ts
@@ -6,7 +6,7 @@ import {
MeetRecordingInfo,
MeetRecordingStatus,
MeetRoom,
- MeetRoomAnonymousConfig,
+ MeetRoomAccessConfig,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings,
@@ -547,13 +547,13 @@ export const updateRoomRoles = async (roomId: string, rolesConfig: MeetRoomRoles
.send({ roles: rolesConfig });
};
-export const updateRoomAnonymousConfig = async (roomId: string, anonymousConfig: MeetRoomAnonymousConfig) => {
+export const updateRoomAccessConfig = async (roomId: string, accessConfig: MeetRoomAccessConfig) => {
checkAppIsRunning();
return await request(app)
- .put(getFullPath(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/anonymous`))
+ .put(getFullPath(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/access`))
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_ENV.INITIAL_API_KEY)
- .send({ anonymous: anonymousConfig });
+ .send({ access: accessConfig });
};
export const deleteRoom = async (
diff --git a/meet-ce/backend/tests/helpers/test-scenarios.ts b/meet-ce/backend/tests/helpers/test-scenarios.ts
index a16c1d44..a0f14e4d 100644
--- a/meet-ce/backend/tests/helpers/test-scenarios.ts
+++ b/meet-ce/backend/tests/helpers/test-scenarios.ts
@@ -51,7 +51,7 @@ export const setupSingleRoom = async (
});
// Extract the room secrets and generate room member tokens
- const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room.anonymous);
+ const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room.access);
const [moderatorToken, speakerToken] = await Promise.all([
generateRoomMemberToken(room.roomId, { secret: moderatorSecret, joinMeeting: false }),
generateRoomMemberToken(room.roomId, { secret: speakerSecret, joinMeeting: false })
diff --git a/meet-ce/backend/tests/integration/api/auth/token-validation.test.ts b/meet-ce/backend/tests/integration/api/auth/token-validation.test.ts
index fa5ef44a..0bf574ab 100644
--- a/meet-ce/backend/tests/integration/api/auth/token-validation.test.ts
+++ b/meet-ce/backend/tests/integration/api/auth/token-validation.test.ts
@@ -15,7 +15,7 @@ import {
resetUserPassword,
sleep,
startTestServer,
- updateRoomAnonymousConfig,
+ updateRoomAccessConfig,
updateRoomConfig,
updateRoomMember,
updateRoomRoles
@@ -478,7 +478,7 @@ describe('Token Validation Tests', () => {
expect(response.body.message).toContain('Invalid token');
});
- it('should succeed when room anonymous config is updated after room member token issuance', async () => {
+ it('should succeed when room access config is updated after room member token issuance', async () => {
// Create a room with an external member
const roomData = await setupSingleRoom();
const roomMember = await setupRoomMember(roomData.room.roomId, {
@@ -492,11 +492,13 @@ describe('Token Validation Tests', () => {
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken);
expect(initialResponse.status).toBe(200);
- // Update the room anonymous configuration
+ // Update the room access configuration
await sleep('100ms'); // Small delay to ensure timestamp difference
- await updateRoomAnonymousConfig(roomData.room.roomId, {
- moderator: {
- enabled: false
+ await updateRoomAccessConfig(roomData.room.roomId, {
+ anonymous: {
+ moderator: {
+ enabled: false
+ }
}
});
@@ -507,7 +509,7 @@ describe('Token Validation Tests', () => {
expect(response.status).toBe(200);
});
- it('should fail when room anonymous config is updated after anonymous room member token issuance', async () => {
+ it('should fail when room access config is updated after anonymous room member token issuance', async () => {
// Create a room and generate an anonymous room member token
const roomData = await setupSingleRoom();
@@ -517,11 +519,13 @@ describe('Token Validation Tests', () => {
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.moderatorToken);
expect(initialResponse.status).toBe(200);
- // Update the room's anonymous configuration
+ // Update the room's access configuration
await sleep('100ms'); // Small delay to ensure timestamp difference
- await updateRoomAnonymousConfig(roomData.room.roomId, {
- moderator: {
- enabled: false
+ await updateRoomAccessConfig(roomData.room.roomId, {
+ anonymous: {
+ moderator: {
+ enabled: false
+ }
}
});
@@ -538,7 +542,7 @@ describe('Token Validation Tests', () => {
// Create a room and generate an anonymous room member token
const roomData = await setupSingleRoom();
- // Update room config (not roles/permissions/anonymous)
+ // Update room config (not roles/access)
await sleep('100ms');
await updateRoomConfig(roomData.room.roomId, {
chat: { enabled: false }
diff --git a/meet-ce/backend/tests/integration/api/room-members/generate-room-member-token.test.ts b/meet-ce/backend/tests/integration/api/room-members/generate-room-member-token.test.ts
index 2152a23e..af7dc333 100644
--- a/meet-ce/backend/tests/integration/api/room-members/generate-room-member-token.test.ts
+++ b/meet-ce/backend/tests/integration/api/room-members/generate-room-member-token.test.ts
@@ -18,7 +18,7 @@ import {
generateRoomMemberToken,
generateRoomMemberTokenRequest,
startTestServer,
- updateRoomAnonymousConfig,
+ updateRoomAccessConfig,
updateRoomRoles,
updateRoomStatus
} from '../../../helpers/request-helpers.js';
@@ -63,8 +63,10 @@ describe('Room Members API Tests', () => {
describe('Generate Room Member Token Tests', () => {
it('should generate anonymous moderator token when anonymous.moderator.enabled is true', async () => {
// Enable anonymous moderator access
- await updateRoomAnonymousConfig(roomId, {
- moderator: { enabled: true }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ moderator: { enabled: true }
+ }
});
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret });
@@ -77,23 +79,29 @@ describe('Room Members API Tests', () => {
it('should fail to generate anonymous moderator token when anonymous.moderator.enabled is false', async () => {
// Disable anonymous moderator access
- await updateRoomAnonymousConfig(roomId, {
- moderator: { enabled: false }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ moderator: { enabled: false }
+ }
});
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret });
expect(response.status).toBe(403);
// Enable anonymous moderator access for further tests
- await updateRoomAnonymousConfig(roomId, {
- moderator: { enabled: true }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ moderator: { enabled: true }
+ }
});
});
it('should generate anonymous speaker token when anonymous.speaker.enabled is true', async () => {
// Enable anonymous speaker access
- await updateRoomAnonymousConfig(roomId, {
- speaker: { enabled: true }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ speaker: { enabled: true }
+ }
});
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret });
@@ -106,16 +114,20 @@ describe('Room Members API Tests', () => {
it('should fail to generate anonymous speaker token when anonymous.speaker.enabled is false', async () => {
// Disable anonymous speaker access
- await updateRoomAnonymousConfig(roomId, {
- speaker: { enabled: false }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ speaker: { enabled: false }
+ }
});
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret });
expect(response.status).toBe(403);
// Enable anonymous speaker access for further tests
- await updateRoomAnonymousConfig(roomId, {
- speaker: { enabled: true }
+ await updateRoomAccessConfig(roomId, {
+ anonymous: {
+ speaker: { enabled: true }
+ }
});
});
diff --git a/meet-ce/backend/tests/integration/api/rooms/expired-rooms-gc.test.ts b/meet-ce/backend/tests/integration/api/rooms/expired-rooms-gc.test.ts
index 54c8d28f..86c98e18 100644
--- a/meet-ce/backend/tests/integration/api/rooms/expired-rooms-gc.test.ts
+++ b/meet-ce/backend/tests/integration/api/rooms/expired-rooms-gc.test.ts
@@ -98,7 +98,7 @@ describe('Expired Rooms GC Tests', () => {
expect(response.body).toHaveProperty('meetingEndAction', 'delete');
// End the meeting
- const { moderatorSecret } = MeetRoomHelper.extractSecretsFromRoom(room.anonymous);
+ const { moderatorSecret } = MeetRoomHelper.extractSecretsFromRoom(room.access);
const moderatorToken = await generateRoomMemberToken(room.roomId, { secret: moderatorSecret });
await endMeeting(room.roomId, moderatorToken);
diff --git a/meet-ce/backend/tests/integration/api/rooms/room-migrations.test.ts b/meet-ce/backend/tests/integration/api/rooms/room-migrations.test.ts
index 2151e125..f2037d7c 100644
--- a/meet-ce/backend/tests/integration/api/rooms/room-migrations.test.ts
+++ b/meet-ce/backend/tests/integration/api/rooms/room-migrations.test.ts
@@ -100,17 +100,26 @@ const expectMigratedRoomToCurrentVersion = (migratedRoom: Record {
}
}
},
- anonymous: {
- moderator: {
- enabled: true,
- accessUrl: '/room/room-v2?secret=123456'
+ access: {
+ anonymous: {
+ moderator: {
+ enabled: true,
+ url: '/room/room-v2?secret=123456'
+ },
+ speaker: {
+ enabled: true,
+ url: '/room/room-v2?secret=abcdef'
+ },
+ recording: {
+ enabled: false,
+ url: expect.stringContaining('/room/room-v2/recordings')
+ }
},
- speaker: {
+ registered: {
enabled: true,
- accessUrl: '/room/room-v2?secret=abcdef'
+ url: '/room/room-v2'
}
},
- accessUrl: '/room/room-v2',
rolesUpdatedAt: expect.any(Number),
status: MeetRoomStatus.OPEN,
meetingEndAction: MeetingEndAction.NONE
diff --git a/meet-ce/backend/tests/integration/api/security/room-security.test.ts b/meet-ce/backend/tests/integration/api/security/room-security.test.ts
index 0831acc3..d9d98c92 100644
--- a/meet-ce/backend/tests/integration/api/security/room-security.test.ts
+++ b/meet-ce/backend/tests/integration/api/security/room-security.test.ts
@@ -757,7 +757,7 @@ describe('Room API Security Tests', () => {
});
});
- describe('Update Room Anonymous Config Tests', () => {
+ describe('Update Room Access Config Tests', () => {
let roomData: RoomData;
let roomId: string;
let roomUsers: RoomTestUsers;
@@ -771,70 +771,70 @@ describe('Room API Security Tests', () => {
it('should succeed when request includes API key', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_ENV.INITIAL_API_KEY)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(200);
});
it('should succeed when user is authenticated as ADMIN', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(200);
});
it('should succeed when user is authenticated as USER and is room owner', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, roomUsers.userOwner.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(200);
});
it('should fail when user is authenticated as USER and is room member', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, roomUsers.userMember.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(403);
});
it('should fail when user is authenticated as USER without access to the room', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(403);
});
it('should fail when user is authenticated as ROOM_MEMBER and is room member', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, roomUsers.roomMember.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(403);
});
it('should fail when user is authenticated as ROOM_MEMBER without access to the room', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(403);
});
it('should fail when user is not authenticated', async () => {
- const response = await request(app).put(`${ROOMS_PATH}/${roomId}/anonymous`).send({ anonymous: {} });
+ const response = await request(app).put(`${ROOMS_PATH}/${roomId}/access`).send({ access: {} });
expect(response.status).toBe(401);
});
it('should fail when using room member token', async () => {
const response = await request(app)
- .put(`${ROOMS_PATH}/${roomId}/anonymous`)
+ .put(`${ROOMS_PATH}/${roomId}/access`)
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.moderatorToken)
- .send({ anonymous: {} });
+ .send({ access: {} });
expect(response.status).toBe(401);
});
});
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts
index 308193df..8aaad552 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts
@@ -93,7 +93,7 @@ export class MeetingContextService {
setMeetRoom(room: MeetRoom): void {
this._meetRoom.set(room);
this.setRoomId(room.roomId);
- this.setMeetingUrl(room.accessUrl);
+ this.setMeetingUrl(room.access.registered.url);
}
/**
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts
index f5e4d8b9..79a1f589 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts
@@ -156,7 +156,7 @@ export class MeetingLobbyService {
const [room] = await Promise.all([
this.roomService.getRoom(roomId, {
- fields: ['roomId', 'roomName', 'status', 'config', 'accessUrl', 'anonymous'],
+ fields: ['roomId', 'roomName', 'status', 'config', 'access'],
extraFields: ['config']
}),
this.setBackButtonText(),
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting.service.ts
index b5845768..5344b85a 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting.service.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting.service.ts
@@ -21,7 +21,7 @@ export class MeetingService {
* Copies the meeting speaker link to the clipboard.
*/
copyMeetingSpeakerLink(room: MeetRoom): void {
- const speakerLink = room.anonymous.speaker.accessUrl;
+ const speakerLink = room.access.anonymous.speaker.url;
this.clipboard.copy(speakerLink);
this.notificationService.showSnackbar('Speaker link copied to clipboard');
}
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-detail/room-detail.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-detail/room-detail.component.ts
index 6153a0e7..e7a54846 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-detail/room-detail.component.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-detail/room-detail.component.ts
@@ -201,14 +201,14 @@ export class RoomDetailComponent implements OnInit {
const room = this.room();
if (!room) return;
- window.open(room.accessUrl, '_blank');
+ window.open(room.access.registered.url, '_blank');
}
copyAccessLink() {
const room = this.room();
if (!room) return;
- this.clipboard.copy(room.accessUrl);
+ this.clipboard.copy(room.access.registered.url);
this.notificationService.showSnackbar('Access link copied to clipboard');
}
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/room-wizard.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/room-wizard.component.ts
index 23fd1274..a59bcef1 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/room-wizard.component.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/room-wizard.component.ts
@@ -137,10 +137,10 @@ export class RoomWizardComponent implements OnInit {
async createRoomBasic(roomName?: string) {
try {
// Create room with basic config including e2ee: false (default settings)
- const { accessUrl } = await this.roomService.createRoom({ roomName }, { fields: ['accessUrl'] });
+ const { access } = await this.roomService.createRoom({ roomName }, { fields: ['access'] });
// Extract the path from the access URL and navigate to it
- const url = new URL(accessUrl);
+ const url = new URL(access.registered.url);
const path = url.pathname;
await this.navigationService.redirectTo(path);
} catch (error) {
@@ -168,10 +168,10 @@ export class RoomWizardComponent implements OnInit {
this.notificationService.showSnackbar('Room updated successfully');
} else {
// Create new room
- const { accessUrl } = await this.roomService.createRoom(roomOptions, { fields: ['accessUrl'] });
+ const { access } = await this.roomService.createRoom(roomOptions, { fields: ['access'] });
// Extract the path from the access URL and navigate to it
- const url = new URL(accessUrl);
+ const url = new URL(access.registered.url);
const path = url.pathname;
await this.navigationService.redirectTo(path);
}
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/steps/role-permissions/role-permissions.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/steps/role-permissions/role-permissions.component.ts
index b9fd11de..49c7a562 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/steps/role-permissions/role-permissions.component.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/room-wizard/steps/role-permissions/role-permissions.component.ts
@@ -26,37 +26,102 @@ export const PERMISSION_GROUPS: PermissionGroup[] = [
label: 'Meeting',
icon: 'groups',
permissions: [
- { key: 'canJoinMeeting', label: 'Can join meeting', description: 'Allow joining the meeting', icon: 'login' },
- { key: 'canEndMeeting', label: 'Can end meeting', description: 'Allow ending the meeting for all participants', icon: 'meeting_room' },
- { key: 'canMakeModerator', label: 'Can make moderator', description: 'Allow promoting participants to moderator role', icon: 'manage_accounts' },
- { key: 'canKickParticipants', label: 'Can kick participants', description: 'Allow removing participants from the meeting', icon: 'person_remove' },
- { key: 'canShareAccessLinks', label: 'Can share access links', description: 'Allow sharing invite links with others', icon: 'link' }
+ {
+ key: 'canJoinMeeting',
+ label: 'Can join meeting',
+ description: 'Allow joining the meeting',
+ icon: 'login'
+ },
+ {
+ key: 'canEndMeeting',
+ label: 'Can end meeting',
+ description: 'Allow ending the meeting for all participants',
+ icon: 'meeting_room'
+ },
+ {
+ key: 'canMakeModerator',
+ label: 'Can make moderator',
+ description: 'Allow promoting participants to moderator role',
+ icon: 'manage_accounts'
+ },
+ {
+ key: 'canKickParticipants',
+ label: 'Can kick participants',
+ description: 'Allow removing participants from the meeting',
+ icon: 'person_remove'
+ },
+ {
+ key: 'canShareAccessLinks',
+ label: 'Can share access links',
+ description: 'Allow sharing invite links with others',
+ icon: 'link'
+ }
]
},
{
label: 'Media',
icon: 'perm_media',
permissions: [
- { key: 'canPublishVideo', label: 'Can publish video', description: 'Allow sharing camera video', icon: 'videocam' },
- { key: 'canPublishAudio', label: 'Can publish audio', description: 'Allow sharing microphone audio', icon: 'mic' },
- { key: 'canShareScreen', label: 'Can share screen', description: 'Allow sharing desktop or browser tabs', icon: 'screen_share' },
- { key: 'canChangeVirtualBackground', label: 'Can change virtual background', description: 'Allow changing the virtual background', icon: 'background_replace' }
+ {
+ key: 'canPublishVideo',
+ label: 'Can publish video',
+ description: 'Allow sharing camera video',
+ icon: 'videocam'
+ },
+ {
+ key: 'canPublishAudio',
+ label: 'Can publish audio',
+ description: 'Allow sharing microphone audio',
+ icon: 'mic'
+ },
+ {
+ key: 'canShareScreen',
+ label: 'Can share screen',
+ description: 'Allow sharing desktop or browser tabs',
+ icon: 'screen_share'
+ },
+ {
+ key: 'canChangeVirtualBackground',
+ label: 'Can change virtual background',
+ description: 'Allow changing the virtual background',
+ icon: 'background_replace'
+ }
]
},
{
label: 'Recordings',
icon: 'video_library',
permissions: [
- { key: 'canRecord', label: 'Can record', description: 'Allow starting and stopping recordings', icon: 'fiber_manual_record' },
- { key: 'canRetrieveRecordings', label: 'Can retrieve recordings', description: 'Allow listing and playing recordings', icon: 'play_circle' },
- { key: 'canDeleteRecordings', label: 'Can delete recordings', description: 'Allow deleting recordings', icon: 'delete' }
+ {
+ key: 'canRecord',
+ label: 'Can record',
+ description: 'Allow starting and stopping recordings',
+ icon: 'fiber_manual_record'
+ },
+ {
+ key: 'canRetrieveRecordings',
+ label: 'Can retrieve recordings',
+ description: 'Allow listing and playing recordings',
+ icon: 'play_circle'
+ },
+ {
+ key: 'canDeleteRecordings',
+ label: 'Can delete recordings',
+ description: 'Allow deleting recordings',
+ icon: 'delete'
+ }
]
},
{
label: 'Chat',
icon: 'chat',
permissions: [
- { key: 'canReadChat', label: 'Can read chat', description: 'Allow reading chat messages', icon: 'visibility' },
+ {
+ key: 'canReadChat',
+ label: 'Can read chat',
+ description: 'Allow reading chat messages',
+ icon: 'visibility'
+ },
{ key: 'canWriteChat', label: 'Can write chat', description: 'Allow sending chat messages', icon: 'edit' }
]
}
@@ -107,9 +172,11 @@ export class RolePermissionsComponent implements OnDestroy {
moderator: { permissions: buildPermissions(formValue.moderator) },
speaker: { permissions: buildPermissions(formValue.speaker) }
},
- anonymous: {
- moderator: { enabled: formValue.moderator.anonymousEnabled ?? false },
- speaker: { enabled: formValue.speaker.anonymousEnabled ?? false }
+ access: {
+ anonymous: {
+ moderator: { enabled: formValue.moderator.anonymousEnabled ?? false },
+ speaker: { enabled: formValue.speaker.anonymousEnabled ?? false }
+ }
}
};
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/rooms/rooms.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/rooms/rooms.component.ts
index c40d3ef7..079e0963 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/rooms/rooms.component.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/pages/rooms/rooms.component.ts
@@ -206,8 +206,8 @@ export class RoomsComponent implements OnInit {
}
}
- private openRoom({ accessUrl }: MeetRoom) {
- window.open(accessUrl, '_blank');
+ private openRoom({ access }: MeetRoom) {
+ window.open(access.registered.url, '_blank');
}
private async editRoomConfig(room: MeetRoom) {
@@ -219,13 +219,13 @@ export class RoomsComponent implements OnInit {
}
}
- private copyModeratorLink({ anonymous }: MeetRoom) {
- this.clipboard.copy(anonymous.moderator.accessUrl);
+ private copyModeratorLink({ access }: MeetRoom) {
+ this.clipboard.copy(access.anonymous.moderator.url);
this.notificationService.showSnackbar('Moderator link copied to clipboard');
}
- private copySpeakerLink({ anonymous }: MeetRoom) {
- this.clipboard.copy(anonymous.speaker.accessUrl);
+ private copySpeakerLink({ access }: MeetRoom) {
+ this.clipboard.copy(access.anonymous.speaker.url);
this.notificationService.showSnackbar('Speaker link copied to clipboard');
}
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/room.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/room.service.ts
index 95e2b926..f37cf894 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/room.service.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/room.service.ts
@@ -1,7 +1,7 @@
import { inject, Injectable } from '@angular/core';
import {
MeetRoom,
- MeetRoomAnonymousConfig,
+ MeetRoomAccessConfig,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings,
@@ -167,15 +167,15 @@ export class RoomService {
}
/**
- * Updates the anonymous access configuration of a room.
+ * Updates the access configuration of a room.
*
* @param roomId - The unique identifier of the room
- * @param anonymousConfig - The new anonymous access configuration to be set
- * @returns A promise that resolves when the anonymous access configuration has been updated
+ * @param accessConfig - The new access configuration to be set
+ * @returns A promise that resolves when the access configuration has been updated
*/
- async updateRoomAnonymous(roomId: string, anonymousConfig: MeetRoomAnonymousConfig): Promise {
- const path = `${this.ROOMS_API}/${roomId}/anonymous`;
- return this.httpService.putRequest(path, { anonymous: anonymousConfig });
+ async updateRoomAccess(roomId: string, accessConfig: MeetRoomAccessConfig): Promise {
+ const path = `${this.ROOMS_API}/${roomId}/access`;
+ return this.httpService.putRequest(path, { access: accessConfig });
}
/**
diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/wizard-state.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/wizard-state.service.ts
index ca68d291..f4c08615 100644
--- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/wizard-state.service.ts
+++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/rooms/services/wizard-state.service.ts
@@ -238,13 +238,13 @@ export class RoomWizardStateService {
isVisible: true,
formGroup: this.formBuilder.group({
moderator: this.formBuilder.group({
- anonymousEnabled: initialRoomOptions.anonymous?.moderator?.enabled ?? false,
+ anonymousEnabled: initialRoomOptions.access?.anonymous?.moderator?.enabled ?? false,
...this.buildPermissionsFormConfig(
initialRoomOptions.roles?.moderator?.permissions ?? DEFAULT_MODERATOR_PERMISSIONS
)
}),
speaker: this.formBuilder.group({
- anonymousEnabled: initialRoomOptions.anonymous?.speaker?.enabled ?? false,
+ anonymousEnabled: initialRoomOptions.access?.anonymous?.speaker?.enabled ?? false,
...this.buildPermissionsFormConfig(
initialRoomOptions.roles?.speaker?.permissions ?? DEFAULT_SPEAKER_PERMISSIONS
)
@@ -298,10 +298,7 @@ export class RoomWizardStateService {
}
}
- private mergeRoomDetailsData(
- currentOptions: MeetRoomOptions,
- stepData: Partial
- ): MeetRoomOptions {
+ private mergeRoomDetailsData(currentOptions: MeetRoomOptions, stepData: Partial): MeetRoomOptions {
return {
...currentOptions,
...('roomName' in stepData ? { roomName: stepData.roomName } : {}),
@@ -310,10 +307,7 @@ export class RoomWizardStateService {
};
}
- private mergeRecordingData(
- currentOptions: MeetRoomOptions,
- stepData: Partial
- ): MeetRoomOptions {
+ private mergeRecordingData(currentOptions: MeetRoomOptions, stepData: Partial): MeetRoomOptions {
return {
...currentOptions,
config: this.buildMergedConfig(currentOptions.config, {
@@ -353,16 +347,29 @@ export class RoomWizardStateService {
}
}
},
- anonymous: {
- moderator: {
- enabled:
- stepData.anonymous?.moderator?.enabled ??
- currentOptions.anonymous?.moderator?.enabled ??
- false
+ access: {
+ anonymous: {
+ moderator: {
+ enabled:
+ stepData.access?.anonymous?.moderator?.enabled ??
+ currentOptions.access?.anonymous?.moderator?.enabled ??
+ false
+ },
+ speaker: {
+ enabled:
+ stepData.access?.anonymous?.speaker?.enabled ??
+ currentOptions.access?.anonymous?.speaker?.enabled ??
+ false
+ },
+ recording: {
+ enabled:
+ stepData.access?.anonymous?.recording?.enabled ??
+ currentOptions.access?.anonymous?.recording?.enabled ??
+ false
+ }
},
- speaker: {
- enabled:
- stepData.anonymous?.speaker?.enabled ?? currentOptions.anonymous?.speaker?.enabled ?? false
+ registered: {
+ enabled: stepData.access?.registered?.enabled ?? currentOptions.access?.registered?.enabled ?? true
}
}
};
diff --git a/meet-ce/typings/src/database/room.entity.ts b/meet-ce/typings/src/database/room.entity.ts
index c5586551..52b879dd 100644
--- a/meet-ce/typings/src/database/room.entity.ts
+++ b/meet-ce/typings/src/database/room.entity.ts
@@ -38,13 +38,9 @@ export interface MeetRoom {
*/
roles: MeetRoomRoles;
/**
- * Anonymous access configuration for the room. See {@link MeetRoomAnonymous} for details.
+ * Access configuration for the room. See {@link MeetRoomAccess} for details.
*/
- anonymous: MeetRoomAnonymous;
- /**
- * General access URL for registered users with access to the room.
- */
- accessUrl: string;
+ access: MeetRoomAccess;
/**
* Status of the room. See {@link MeetRoomStatus} for details.
*/
@@ -73,17 +69,63 @@ export interface MeetRoomRoles {
}
/**
- * Anonymous access configuration for a room.
+ * Access configuration for a room.
+ */
+export interface MeetRoomAccess {
+ /**
+ * Anonymous users access configuration for the room. See {@link MeetRoomAnonymousUsers} for details.
+ */
+ anonymous: MeetRoomAnonymousUsers;
+ /**
+ * Registered users access configuration for the room. See {@link MeetRoomRegisteredUsers} for details.
+ */
+ registered: MeetRoomRegisteredUsers;
+}
+
+/**
+ * Access configuration for registered users in a room.
+ */
+export interface MeetRoomRegisteredUsers {
+ /**
+ * Indicates if all registered users can access the room.
+ * When enabled, any registered user can join, including non-members.
+ * Room owners and administrators always have access regardless of this setting.
+ */
+ enabled: boolean;
+ /**
+ * General access URL for registered users with access to the room.
+ */
+ url: string;
+}
+
+/**
+ * Access configuration for anonymous users in a room.
* Defines which roles have anonymous access enabled and their access URLs.
*/
-export interface MeetRoomAnonymous {
+export interface MeetRoomAnonymousUsers {
+ /**
+ * Indicates if anonymous access is enabled for the moderator role in the room.
+ * If true, anonymous users with moderator permissions can access the room using the provided URL.
+ */
moderator: {
enabled: boolean;
- accessUrl: string;
+ url: string;
};
+ /**
+ * Indicates if anonymous access is enabled for the speaker role in the room.
+ * If true, anonymous users with speaker permissions can access the room using the provided URL.
+ */
speaker: {
enabled: boolean;
- accessUrl: string;
+ url: string;
+ };
+ /**
+ * Indicates if anonymous access is enabled for recordings of the room.
+ * If true, anonymous users can access the recordings using the provided URL.
+ */
+ recording: {
+ enabled: boolean;
+ url: string;
};
}
diff --git a/meet-ce/typings/src/request/room-request.ts b/meet-ce/typings/src/request/room-request.ts
index fc912b41..f02fc1b1 100644
--- a/meet-ce/typings/src/request/room-request.ts
+++ b/meet-ce/typings/src/request/room-request.ts
@@ -27,9 +27,9 @@ export interface MeetRoomOptions {
*/
roles?: MeetRoomRolesConfig;
/**
- * Anonymous access configuration for the room. See {@link MeetRoomAnonymousConfig} for details.
+ * Access configuration for the room. See {@link MeetRoomAccessConfig} for details.
*/
- anonymous?: MeetRoomAnonymousConfig;
+ access?: MeetRoomAccessConfig;
}
/**
@@ -46,14 +46,22 @@ export interface MeetRoomRolesConfig {
}
/**
- * Anonymous access configuration for creating/updating a room.
+ * Access configuration for creating/updating a room.
* Only includes enabled flags.
*/
-export interface MeetRoomAnonymousConfig {
- moderator?: {
- enabled: boolean;
+export interface MeetRoomAccessConfig {
+ anonymous?: {
+ moderator?: {
+ enabled: boolean;
+ };
+ speaker?: {
+ enabled: boolean;
+ };
+ recording?: {
+ enabled: boolean;
+ };
};
- speaker?: {
+ registered?: {
enabled: boolean;
};
}
diff --git a/meet-ce/typings/src/response/room-response.ts b/meet-ce/typings/src/response/room-response.ts
index 6eef8f12..d1435574 100644
--- a/meet-ce/typings/src/response/room-response.ts
+++ b/meet-ce/typings/src/response/room-response.ts
@@ -14,8 +14,7 @@ export const MEET_ROOM_FIELDS = [
'creationDate',
'config',
'roles',
- 'anonymous',
- 'accessUrl',
+ 'access',
'status',
'rolesUpdatedAt',
'meetingEndAction',
@@ -57,7 +56,7 @@ export type MeetRoomSortField = (typeof MEET_ROOM_SORT_FIELDS)[number];
* Sensitive fields of a MeetRoom that require specific permissions to be viewed.
*/
export const SENSITIVE_ROOM_FIELDS_BY_PERMISSION: Partial> = {
- canShareAccessLinks: ['anonymous']
+ canShareAccessLinks: ['access']
};
export const SENSITIVE_ROOM_FIELDS_ENTRIES = Object.entries(SENSITIVE_ROOM_FIELDS_BY_PERMISSION) as ReadonlyArray<