diff --git a/backend/README.md b/backend/README.md index 51f9272..49f46a3 100644 --- a/backend/README.md +++ b/backend/README.md @@ -57,51 +57,53 @@ openvidu-appdata/ ### Directory Descriptions #### **Global Preferences** (`global-preferences.json`) + Contains system-wide settings and configurations for the OpenVidu Meet application, such as default recording settings, UI preferences, and feature toggles. #### **Users** (`users/`) + Stores user account information in individual JSON files. Each file is named using the username (e.g., `admin.json`) and contains user-specific data including authentication details, permissions, and preferences. #### **Rooms** (`rooms/`) + Contains room configuration and metadata. Each room is stored in its own directory named after the room ID, containing: + - `room-123.json`: Room configuration, settings, and metadata #### **Recordings** (`recordings/`) + The recordings directory is organized into several subdirectories to manage different aspects of recorded content: - **Recording Files** (`room-123/`): Contains the actual video files with naming convention `room-123--{uid}.mp4` - **Metadata** (`.metadata/room-123/{egressId}/{uid}.json`): Stores recording metadata including: - - Recording duration and timestamps - - Participant information - - Quality settings and technical specifications - - File size and format details + - Recording duration and timestamps + - Participant information + - Quality settings and technical specifications + - File size and format details - **Secrets** (`.secrets/room-123/{egressId}/{uid}.json`): Contains sensitive recording-related data such as: - - Encryption keys - - Access tokens - - Security credentials + - Encryption keys + - Access tokens + - Security credentials - **Room Metadata** (`.room_metadata/room-123/room_metadata.json`): Stores room-level information for recordings including: - - Room name and description - - Recording session details - - Participant list and roles + - Room name and description + - Recording session details + - Participant list and roles ### Recording Identifier Format Recordings use a composite identifier format: `recordingId: room-123--{egressId}--{uid}` Where: + - `room-123`: The room identifier - `{egressId}`: LiveKit egress process identifier - `{uid}`: Unique recording session identifier This naming convention ensures uniqueness and provides traceability between the recording file, its metadata, and the originating room session. - - - - ## Recordings The recording feature is based on the following key concepts: @@ -112,7 +114,6 @@ The recording feature is based on the following key concepts: 2. **Lock lifetime**: The lock has not lifetime. It is not automatically released after a certain period. Instead, it remains active until the recording is manually stopped and an `egress_ended` webhook is received, or when the room meeting ends. This design choice allows for flexibility in managing recordings, as the lock can be held for an extended duration if needed. However, it also means that care must be taken to ensure that the lock is released appropriately to avoid blocking future recording attempts. (see **Failure handling** below). - ```mermaid flowchart TD A["Start New Recording Request"] --> B{"Can room be recorded?"} @@ -165,4 +166,3 @@ graph TD; M -->|No more rooms| N[Process completed] ``` - diff --git a/backend/openapi/components/parameters/internal/x-participant-role.yaml b/backend/openapi/components/parameters/internal/x-participant-role.yaml index 7b381c7..a4dbd5d 100644 --- a/backend/openapi/components/parameters/internal/x-participant-role.yaml +++ b/backend/openapi/components/parameters/internal/x-participant-role.yaml @@ -3,10 +3,10 @@ in: header description: | The role of the participant in the meeting. It can be one of the following values: - `moderator`: Can manage the room and its participants. - - `publisher`: Can publish media streams to the room. - + - `speaker`: Can publish media streams to the room. + This is required to distinguish roles when multiple are present in the participant token required: true schema: type: string - enum: ['moderator', 'publisher'] + enum: ['moderator', 'speaker'] diff --git a/backend/openapi/components/responses/internal/success-get-room-roles.yaml b/backend/openapi/components/responses/internal/success-get-room-roles.yaml index c898c49..dc6211a 100644 --- a/backend/openapi/components/responses/internal/success-get-room-roles.yaml +++ b/backend/openapi/components/responses/internal/success-get-room-roles.yaml @@ -19,7 +19,7 @@ content: canRecord: true canChat: true canChangeVirtualBackground: true - - role: 'publisher' + - role: 'speaker' permissions: livekit: roomJoin: true diff --git a/backend/openapi/components/responses/success-get-room.yaml b/backend/openapi/components/responses/success-get-room.yaml index 8369c97..344b0da 100644 --- a/backend/openapi/components/responses/success-get-room.yaml +++ b/backend/openapi/components/responses/success-get-room.yaml @@ -18,8 +18,8 @@ content: enabled: false virtualBackgroundPreferences: enabled: true - moderatorURL: 'http://localhost:6080/room/room-123?secret=123456' - publisherURL: 'http://localhost:6080/room/room-123?secret=654321' + moderatorRoomURL: 'http://localhost:6080/room/room-123?secret=123456' + speakerRoomURL: 'http://localhost:6080/room/room-123?secret=654321' fields=roomId: summary: Response with only the roomId @@ -41,8 +41,8 @@ content: virtualBackgroundPreferences: enabled: true - fields=moderatorURL,publisherURL: - summary: Response containing only moderator and publisher URLs + fields=moderatorRoomURL,speakerRoomURL: + summary: Response containing only moderator and speaker URLs value: - moderatorURL: 'http://localhost:6080/room/room-123?secret=123456' - publisherURL: 'http://localhost:6080/room/room-123?secret=654321' + moderatorRoomURL: 'http://localhost:6080/room/room-123?secret=123456' + speakerRoomURL: 'http://localhost:6080/room/room-123?secret=654321' diff --git a/backend/openapi/components/responses/success-get-rooms.yaml b/backend/openapi/components/responses/success-get-rooms.yaml index 9c78449..7f2d8ae 100644 --- a/backend/openapi/components/responses/success-get-rooms.yaml +++ b/backend/openapi/components/responses/success-get-rooms.yaml @@ -27,8 +27,8 @@ content: enabled: false virtualBackgroundPreferences: enabled: true - moderatorURL: 'http://localhost:6080/room/room-123?secret=123456' - publisherURL: 'http://localhost:6080/room/room-123?secret=654321' + moderatorRoomURL: 'http://localhost:6080/room/room-123?secret=123456' + speakerRoomURL: 'http://localhost:6080/room/room-123?secret=654321' - roomId: 'room-456' roomName: 'room' creationDate: 1620001000000 @@ -40,8 +40,8 @@ content: enabled: true virtualBackgroundPreferences: enabled: false - moderatorURL: 'http://localhost:6080/room/room-456?secret=789012' - publisherURL: 'http://localhost:6080/room/room-456?secret=210987' + moderatorRoomURL: 'http://localhost:6080/room/room-456?secret=789012' + speakerRoomURL: 'http://localhost:6080/room/room-456?secret=210987' pagination: isTruncated: false maxItems: 10 @@ -86,14 +86,14 @@ content: nextPageToken: 'abc123' maxItems: 10 - fields=moderatorURL,publisherURL: - summary: Response containing only moderator and publisher URLs + fields=moderatorRoomURL,speakerRoomURL: + summary: Response containing only moderator and speaker URLs value: rooms: - - moderatorURL: 'http://localhost:6080/room/room-123?secret=123456' - publisherURL: 'http://localhost:6080/room/room-123?secret=654321' - - moderatorURL: 'http://localhost:6080/room/room-456?secret=789012' - publisherURL: 'http://localhost:6080/room/room-456?secret=210987' + - moderatorRoomURL: 'http://localhost:6080/room/room-123?secret=123456' + speakerRoomURL: 'http://localhost:6080/room/room-123?secret=654321' + - moderatorRoomURL: 'http://localhost:6080/room/room-456?secret=789012' + speakerRoomURL: 'http://localhost:6080/room/room-456?secret=210987' pagination: isTruncated: false maxItems: 10 diff --git a/backend/openapi/components/schemas/internal/meet-room-role-permissions.yaml b/backend/openapi/components/schemas/internal/meet-room-role-permissions.yaml index fcc0a4a..06a47b7 100644 --- a/backend/openapi/components/schemas/internal/meet-room-role-permissions.yaml +++ b/backend/openapi/components/schemas/internal/meet-room-role-permissions.yaml @@ -2,12 +2,12 @@ type: object properties: role: type: string - enum: ['moderator', 'publisher'] + enum: ['moderator', 'speaker'] description: | A role that a participant can have in a room. The role determines the permissions of the participant in the room. - `moderator`: Can manage the room and its participants. - - `publisher`: Can publish media streams to the room. + - `speaker`: Can publish media streams to the room. example: 'moderator' permissions: type: object diff --git a/backend/openapi/components/schemas/meet-room-preferences.yaml b/backend/openapi/components/schemas/meet-room-preferences.yaml index 6ecfecd..0962193 100644 --- a/backend/openapi/components/schemas/meet-room-preferences.yaml +++ b/backend/openapi/components/schemas/meet-room-preferences.yaml @@ -31,14 +31,14 @@ MeetRecordingPreferences: enum: - admin - admin-moderator - - admin-moderator-publisher - default: admin-moderator-publisher - example: admin-moderator-publisher + - admin-moderator-speaker + default: admin-moderator-speaker + example: admin-moderator-speaker description: | Defines who can access the recording. Options are: - `admin`: Only administrators can access the recording. - `admin-moderator`: Administrators and moderators can access the recording. - - `admin-moderator-publisher`: Administrators, moderators and publishers can access the recording. + - `admin-moderator-speaker`: Administrators, moderators and speakers can access the recording. MeetVirtualBackgroundPreferences: type: object properties: diff --git a/backend/openapi/components/schemas/meet-room.yaml b/backend/openapi/components/schemas/meet-room.yaml index 2891f7d..3fa1a90 100644 --- a/backend/openapi/components/schemas/meet-room.yaml +++ b/backend/openapi/components/schemas/meet-room.yaml @@ -39,15 +39,15 @@ properties: # description: > # The maximum number of participants allowed in the room. If the number of participants exceeds # this limit, new participants will not be allowed to join. - moderatorURL: + moderatorRoomURL: type: string example: 'http://localhost:6080/room/room-123?secret=123456' description: > The URL for the moderator participants to join the room. The moderator role has special permissions to manage the room and participants. - publisherURL: + speakerRoomURL: type: string example: 'http://localhost:6080/room/room-123?secret=654321' description: > - The URL for the publisher participants to join the room. The publisher role has permissions to publish audio and + The URL for the speaker participants to join the room. The speaker role has permissions to publish audio and video streams to the room. diff --git a/backend/package-lock.json b/backend/package-lock.json index f8632f7..5f1e1c9 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4087,12 +4087,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", - "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.5.tgz", + "integrity": "sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4125,15 +4125,15 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", - "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.5.tgz", + "integrity": "sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -4141,35 +4141,37 @@ } }, "node_modules/@smithy/core": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.2.tgz", - "integrity": "sha512-JoLw59sT5Bm8SAjFCYZyuCGxK8y3vovmoVbZWLDPTH5XpPEIwpFd9m90jjVMwoypDuB/SdVgje5Y4T7w50lJaw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.8.0.tgz", + "integrity": "sha512-EYqsIYJmkR1VhVE9pccnk353xhs+lB6btdutJEtsp7R055haMJp2yE16eSxw8fv+G0WUY6vqxyYOP8kOqawxYQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.0.8", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.3", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-stream": "^4.2.4", "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", - "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.7.tgz", + "integrity": "sha512-dDzrMXA8d8riFNiPvytxn0mNwR4B3h8lgrQ5UjAGu6T9z/kRg/Xncf4tEQHE/+t25sY8IH3CowcmWi+1U5B1Gw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -4177,13 +4179,13 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", - "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.5.tgz", + "integrity": "sha512-miEUN+nz2UTNoRYRhRqVTJCx7jMeILdAurStT2XoS+mhokkmz1xAPp95DFW9Gxt4iF2VBqpeF9HbTQ3kY1viOA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-hex-encoding": "^4.0.0", "tslib": "^2.6.2" }, @@ -4192,13 +4194,13 @@ } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz", - "integrity": "sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.5.tgz", + "integrity": "sha512-LCUQUVTbM6HFKzImYlSB9w4xafZmpdmZsOh9rIl7riPC3osCgGFVP+wwvYVw6pXda9PPT9TcEZxaq3XE81EdJQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-serde-universal": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4206,12 +4208,12 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz", - "integrity": "sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.3.tgz", + "integrity": "sha512-yTTzw2jZjn/MbHu1pURbHdpjGbCuMHWncNBpJnQAPxOVnFUAbSIUSwafiphVDjNV93TdBJWmeVAds7yl5QCkcA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4219,13 +4221,13 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz", - "integrity": "sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.5.tgz", + "integrity": "sha512-lGS10urI4CNzz6YlTe5EYG0YOpsSp3ra8MXyco4aqSkQDuyZPIw2hcaxDU82OUVtK7UY9hrSvgWtpsW5D4rb4g==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-serde-universal": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4233,13 +4235,13 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz", - "integrity": "sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.5.tgz", + "integrity": "sha512-JFnmu4SU36YYw3DIBVao3FsJh4Uw65vVDIqlWT4LzR6gXA0F3KP0IXFKKJrhaVzCBhAuMsrUUaT5I+/4ZhF7aw==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-codec": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4247,14 +4249,14 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", - "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.1.tgz", + "integrity": "sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/querystring-builder": "^4.0.5", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" }, @@ -4263,14 +4265,14 @@ } }, "node_modules/@smithy/hash-blob-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.4.tgz", - "integrity": "sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.5.tgz", + "integrity": "sha512-F7MmCd3FH/Q2edhcKd+qulWkwfChHbc9nhguBlVjSUE6hVHhec3q6uPQ+0u69S6ppvLtR3eStfCuEKMXBXhvvA==", "license": "Apache-2.0", "dependencies": { "@smithy/chunked-blob-reader": "^5.0.0", "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4278,12 +4280,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", - "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.5.tgz", + "integrity": "sha512-cv1HHkKhpyRb6ahD8Vcfb2Hgz67vNIXEp2vnhzfxLFGRukLCNEA5QdsorbUEzXma1Rco0u3rx5VTqbM06GcZqQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -4293,12 +4295,12 @@ } }, "node_modules/@smithy/hash-stream-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.4.tgz", - "integrity": "sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.5.tgz", + "integrity": "sha512-IJuDS3+VfWB67UC0GU0uYBG/TA30w+PlOaSo0GPm9UHS88A6rCP6uZxNjNYiyRtOcjv7TXn/60cW8ox1yuZsLg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -4307,12 +4309,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", - "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.5.tgz", + "integrity": "sha512-IVnb78Qtf7EJpoEVo7qJ8BEXQwgC4n3igeJNNKEj/MLYtapnx8A67Zt/J3RXAj2xSO1910zk0LdFiygSemuLow==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4332,12 +4334,12 @@ } }, "node_modules/@smithy/md5-js": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.4.tgz", - "integrity": "sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.5.tgz", + "integrity": "sha512-8n2XCwdUbGr8W/XhMTaxILkVlw2QebkVTn5tm3HOcbPbOpWg89zr6dPXsH8xbeTsbTXlJvlJNTQsKAIoqQGbdA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -4346,13 +4348,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", - "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.5.tgz", + "integrity": "sha512-l1jlNZoYzoCC7p0zCtBDE5OBXZ95yMKlRlftooE5jPWQn4YBPLgsp+oeHp7iMHaTGoUdFqmHOPa8c9G3gBsRpQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4360,18 +4362,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.17.tgz", - "integrity": "sha512-S3hSGLKmHG1m35p/MObQCBCdRsrpbPU8B129BVzRqRfDvQqPMQ14iO4LyRw+7LNizYc605COYAcjqgawqi+6jA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.18.tgz", + "integrity": "sha512-ZhvqcVRPZxnZlokcPaTwb+r+h4yOIOCJmx0v2d1bpVlmP465g3qpVSf7wxcq5zZdu4jb0H4yIMxuPwDJSQc3MQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.7.2", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-middleware": "^4.0.4", + "@smithy/core": "^3.8.0", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", + "@smithy/util-middleware": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -4379,18 +4381,19 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.18.tgz", - "integrity": "sha512-bYLZ4DkoxSsPxpdmeapvAKy7rM5+25gR7PGxq2iMiecmbrRGBHj9s75N74Ylg+aBiw9i5jIowC/cLU2NR0qH8w==", + "version": "4.1.19", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.19.tgz", + "integrity": "sha512-X58zx/NVECjeuUB6A8HBu4bhx72EoUz+T5jTMIyeNKx2lf+Gs9TmWPNNkH+5QF0COjpInP/xSpJGJ7xEnAklQQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.9", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/protocol-http": "^5.1.3", + "@smithy/service-error-classification": "^4.0.7", + "@smithy/smithy-client": "^4.4.10", + "@smithy/types": "^4.3.2", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-retry": "^4.0.7", + "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" }, @@ -4399,13 +4402,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", - "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.9.tgz", + "integrity": "sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4413,12 +4416,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", - "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.5.tgz", + "integrity": "sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4426,14 +4429,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", - "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.4.tgz", + "integrity": "sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4441,15 +4444,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", - "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.1.tgz", + "integrity": "sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/abort-controller": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/querystring-builder": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4457,12 +4460,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", - "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.5.tgz", + "integrity": "sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4470,12 +4473,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", - "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.3.tgz", + "integrity": "sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4483,12 +4486,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", - "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.5.tgz", + "integrity": "sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" }, @@ -4497,12 +4500,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", - "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.5.tgz", + "integrity": "sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4510,24 +4513,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", - "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.7.tgz", + "integrity": "sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1" + "@smithy/types": "^4.3.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", - "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.5.tgz", + "integrity": "sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4535,16 +4538,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", - "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.3.tgz", + "integrity": "sha512-mARDSXSEgllNzMw6N+mC+r1AQlEBO3meEAkR/UlfAgnMzJUB3goRBWgip1EAMG99wh36MDqzo86SfIX5Y+VEaw==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -4554,17 +4557,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.9.tgz", - "integrity": "sha512-mbMg8mIUAWwMmb74LoYiArP04zWElPzDoA1jVOp3or0cjlDMgoS6WTC3QXK0Vxoc9I4zdrX0tq6qsOmaIoTWEQ==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.10.tgz", + "integrity": "sha512-iW6HjXqN0oPtRS0NK/zzZ4zZeGESIFcxj2FkWed3mcK8jdSdHzvnCKXSjvewESKAgGKAbJRA+OsaqKhkdYRbQQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.7.2", - "@smithy/middleware-endpoint": "^4.1.17", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.3", + "@smithy/core": "^3.8.0", + "@smithy/middleware-endpoint": "^4.1.18", + "@smithy/middleware-stack": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", + "@smithy/util-stream": "^4.2.4", "tslib": "^2.6.2" }, "engines": { @@ -4572,9 +4575,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", - "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.2.tgz", + "integrity": "sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -4584,13 +4587,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", - "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.5.tgz", + "integrity": "sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/querystring-parser": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4661,14 +4664,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.25", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.25.tgz", - "integrity": "sha512-pxEWsxIsOPLfKNXvpgFHBGFC3pKYKUFhrud1kyooO9CJai6aaKDHfT10Mi5iiipPXN/JhKAu3qX9o75+X85OdQ==", + "version": "4.0.26", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.26.tgz", + "integrity": "sha512-xgl75aHIS/3rrGp7iTxQAOELYeyiwBu+eEgAk4xfKwJJ0L8VUjhO2shsDpeil54BOFsqmk5xfdesiewbUY5tKQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.9", - "@smithy/types": "^4.3.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/smithy-client": "^4.4.10", + "@smithy/types": "^4.3.2", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -4677,17 +4680,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.25", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.25.tgz", - "integrity": "sha512-+w4n4hKFayeCyELZLfsSQG5mCC3TwSkmRHv4+el5CzFU8ToQpYGhpV7mrRzqlwKkntlPilT1HJy1TVeEvEjWOQ==", + "version": "4.0.26", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.26.tgz", + "integrity": "sha512-z81yyIkGiLLYVDetKTUeCZQ8x20EEzvQjrqJtb/mXnevLq2+w3XCEWTJ2pMp401b6BkEkHVfXb/cROBpVauLMQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.1.4", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.9", - "@smithy/types": "^4.3.1", + "@smithy/config-resolver": "^4.1.5", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/property-provider": "^4.0.5", + "@smithy/smithy-client": "^4.4.10", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4695,13 +4698,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", - "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.7.tgz", + "integrity": "sha512-klGBP+RpBp6V5JbrY2C/VKnHXn3d5V2YrifZbmMY8os7M6m8wdYFoO6w/fe5VkP+YVwrEktW3IWYaSQVNZJ8oQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4721,12 +4724,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", - "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.5.tgz", + "integrity": "sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4734,13 +4737,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", - "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.7.tgz", + "integrity": "sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.0.6", - "@smithy/types": "^4.3.1", + "@smithy/service-error-classification": "^4.0.7", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -4748,14 +4751,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", - "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.4.tgz", + "integrity": "sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/types": "^4.3.1", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-hex-encoding": "^4.0.0", @@ -4792,13 +4795,13 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz", - "integrity": "sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.7.tgz", + "integrity": "sha512-mYqtQXPmrwvUljaHyGxYUIIRI3qjBTEb/f5QFi3A6VlxhpmZd5mWXn9W+qUkf2pVE1Hv3SqxefiZOPGdxmO64A==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/abort-controller": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -7481,9 +7484,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.195", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.195.tgz", - "integrity": "sha512-URclP0iIaDUzqcAyV1v2PgduJ9N0IdXmWsnPzPfelvBmjmZzEy6xJcjb1cXj+TbYqXgtLrjHEoaSIdTYhw4ezg==", + "version": "1.5.197", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.197.tgz", + "integrity": "sha512-m1xWB3g7vJ6asIFz+2pBUbq3uGmfmln1M9SSvBe4QIFWYrRHylP73zL/3nMjDmwz8V+1xAXQDfBd6+HPW0WvDQ==", "dev": true, "license": "ISC" }, diff --git a/backend/src/controllers/room.controller.ts b/backend/src/controllers/room.controller.ts index 982b57d..019ac09 100644 --- a/backend/src/controllers/room.controller.ts +++ b/backend/src/controllers/room.controller.ts @@ -173,7 +173,7 @@ export const getRoomRolesAndPermissions = async (req: Request, res: Response) => logger.verbose(`Getting roles and associated permissions for room '${roomId}'`); const moderatorPermissions = participantService.getParticipantPermissions(roomId, ParticipantRole.MODERATOR); - const publisherPermissions = participantService.getParticipantPermissions(roomId, ParticipantRole.PUBLISHER); + const speakerPermissions = participantService.getParticipantPermissions(roomId, ParticipantRole.SPEAKER); const rolesAndPermissions = [ { @@ -181,8 +181,8 @@ export const getRoomRolesAndPermissions = async (req: Request, res: Response) => permissions: moderatorPermissions }, { - role: ParticipantRole.PUBLISHER, - permissions: publisherPermissions + role: ParticipantRole.SPEAKER, + permissions: speakerPermissions } ]; res.status(200).json(rolesAndPermissions); diff --git a/backend/src/helpers/room.helper.ts b/backend/src/helpers/room.helper.ts index fcf729c..1259b88 100644 --- a/backend/src/helpers/room.helper.ts +++ b/backend/src/helpers/room.helper.ts @@ -22,24 +22,24 @@ export class MeetRoomHelper { } /** - * Extracts publisher and moderator secrets from a MeetRoom object's URLs. + * Extracts speaker and moderator secrets from a MeetRoom object's URLs. * - * This method parses the 'secret' query parameter from both publisher and moderator + * This method parses the 'secret' query parameter from both speaker and moderator * room URLs associated with the meeting room. * - * @param room - The MeetRoom object containing publisherRoomUrl and moderatorRoomUrl properties + * @param room - The MeetRoom object containing speakerRoomUrl and moderatorRoomUrl properties * @returns An object containing the extracted secrets with the following properties: - * - publisherSecret: The secret extracted from the publisher room URL + * - speakerSecret: The secret extracted from the speaker room URL * - moderatorSecret: The secret extracted from the moderator room URL */ - static extractSecretsFromRoom(room: MeetRoom): { publisherSecret: string; moderatorSecret: string } { - const { publisherRoomUrl, moderatorRoomUrl } = room; + static extractSecretsFromRoom(room: MeetRoom): { speakerSecret: string; moderatorSecret: string } { + const { speakerRoomUrl, moderatorRoomUrl } = room; - const publisherUrl = new URL(publisherRoomUrl); - const publisherSecret = publisherUrl.searchParams.get('secret') || ''; + const speakerUrl = new URL(speakerRoomUrl); + const speakerSecret = speakerUrl.searchParams.get('secret') || ''; const moderatorUrl = new URL(moderatorRoomUrl); const moderatorSecret = moderatorUrl.searchParams.get('secret') || ''; - return { publisherSecret, moderatorSecret }; + return { speakerSecret, moderatorSecret }; } /** diff --git a/backend/src/middlewares/auth.middleware.ts b/backend/src/middlewares/auth.middleware.ts index 1587104..1cc3655 100644 --- a/backend/src/middlewares/auth.middleware.ts +++ b/backend/src/middlewares/auth.middleware.ts @@ -98,7 +98,7 @@ export const participantTokenValidator = async (req: Request) => { // Check if the participant role is provided in the request headers // This is required to distinguish roles when multiple are present in the token const participantRole = req.headers[INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER]; - const allRoles = [ParticipantRole.MODERATOR, ParticipantRole.PUBLISHER]; + const allRoles = [ParticipantRole.MODERATOR, ParticipantRole.SPEAKER]; if (!participantRole || !allRoles.includes(participantRole as ParticipantRole)) { throw errorWithControl(errorInvalidParticipantRole(), true); diff --git a/backend/src/middlewares/request-validators/room-validator.middleware.ts b/backend/src/middlewares/request-validators/room-validator.middleware.ts index 2b8d881..a70e2f9 100644 --- a/backend/src/middlewares/request-validators/room-validator.middleware.ts +++ b/backend/src/middlewares/request-validators/room-validator.middleware.ts @@ -67,7 +67,7 @@ const validForceQueryParam = () => const RecordingAccessSchema: z.ZodType = z.enum([ MeetRecordingAccess.ADMIN, MeetRecordingAccess.ADMIN_MODERATOR, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ]); const RecordingPreferencesSchema: z.ZodType = z @@ -116,7 +116,7 @@ const RoomRequestOptionsSchema: z.ZodType = z.object({ ) .optional(), preferences: RoomPreferencesSchema.optional().default({ - recordingPreferences: { enabled: true, allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER }, + recordingPreferences: { enabled: true, allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } }) diff --git a/backend/src/services/participant.service.ts b/backend/src/services/participant.service.ts index 27d91cf..4f59e13 100644 --- a/backend/src/services/participant.service.ts +++ b/backend/src/services/participant.service.ts @@ -82,8 +82,8 @@ export class ParticipantService { switch (role) { case ParticipantRole.MODERATOR: return this.generateModeratorPermissions(roomId, addJoinPermission); - case ParticipantRole.PUBLISHER: - return this.generatePublisherPermissions(roomId, addJoinPermission); + case ParticipantRole.SPEAKER: + return this.generateSpeakerPermissions(roomId, addJoinPermission); default: throw new Error(`Role ${role} not supported`); } @@ -107,7 +107,7 @@ export class ParticipantService { }; } - protected generatePublisherPermissions(roomId: string, addJoinPermission = true): ParticipantPermissions { + protected generateSpeakerPermissions(roomId: string, addJoinPermission = true): ParticipantPermissions { return { livekit: { roomJoin: addJoinPermission, diff --git a/backend/src/services/room.service.ts b/backend/src/services/room.service.ts index 2f08f84..a87cbea 100644 --- a/backend/src/services/room.service.ts +++ b/backend/src/services/room.service.ts @@ -81,7 +81,7 @@ export class RoomService { autoDeletionDate, preferences, moderatorRoomUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}`, - publisherRoomUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}` + speakerRoomUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}` }; await this.storageService.saveMeetRoom(meetRoom); @@ -195,8 +195,8 @@ export class RoomService { const filteredRoom = UtilsHelper.filterObjectFields(meetRoom, fields); - // Remove moderatorRoomUrl if the participant is a publisher to prevent access to moderator links - if (participantRole === ParticipantRole.PUBLISHER) { + // Remove moderatorRoomUrl if the participant is a speaker to prevent access to moderator links + if (participantRole === ParticipantRole.SPEAKER) { delete filteredRoom.moderatorRoomUrl; } @@ -244,12 +244,12 @@ export class RoomService { } /** - * Validates a secret against a room's moderator and publisher secrets and returns the corresponding role. + * Validates a secret against a room's moderator and speaker secrets and returns the corresponding role. * * @param roomId - The unique identifier of the room to check - * @param secret - The secret to validate against the room's moderator and publisher secrets - * @returns A promise that resolves to the participant role (MODERATOR or PUBLISHER) if the secret is valid - * @throws Error if the moderator or publisher secrets cannot be extracted from their URLs + * @param secret - The secret to validate against the room's moderator and speaker secrets + * @returns A promise that resolves to the participant role (MODERATOR or SPEAKER) if the secret is valid + * @throws Error if the moderator or speaker secrets cannot be extracted from their URLs * @throws Error if the provided secret doesn't match any of the room's secrets (unauthorized) */ async getRoomRoleBySecret(roomId: string, secret: string): Promise { @@ -258,13 +258,13 @@ export class RoomService { } getRoomRoleBySecretFromRoom(room: MeetRoom, secret: string): ParticipantRole { - const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room); + const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room); switch (secret) { case moderatorSecret: return ParticipantRole.MODERATOR; - case publisherSecret: - return ParticipantRole.PUBLISHER; + case speakerSecret: + return ParticipantRole.SPEAKER; default: throw errorInvalidRoomSecret(room.roomId, secret); } @@ -299,11 +299,11 @@ export class RoomService { /* A participant can retrieve recordings if - they can delete recordings - - they are a publisher and the recording access includes publishers + - they are a speaker and the recording access includes speakers */ const canRetrieveRecordings = canDeleteRecordings || - (role === ParticipantRole.PUBLISHER && recordingAccess === MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER); + (role === ParticipantRole.SPEAKER && recordingAccess === MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER); return { canRetrieveRecordings, diff --git a/backend/src/services/storage/storage.service.ts b/backend/src/services/storage/storage.service.ts index 49d0899..8432f14 100644 --- a/backend/src/services/storage/storage.service.ts +++ b/backend/src/services/storage/storage.service.ts @@ -278,7 +278,7 @@ export class MeetStorageService< /** * Archives room metadata by storing essential room information in both cache and persistent storage. * - * This method retrieves the room data, extracts key metadata (moderator/publisher URLs and + * This method retrieves the room data, extracts key metadata (moderator/speaker URLs and * recording preferences), and saves it to an archived location for future reference. * * If `updateOnlyIfExists` is true, it will only save the archived metadata if it already exists, @@ -311,7 +311,7 @@ export class MeetStorageService< const archivedRoom: Partial = { moderatorRoomUrl: room.moderatorRoomUrl, - publisherRoomUrl: room.publisherRoomUrl, + speakerRoomUrl: room.speakerRoomUrl, preferences: { recordingPreferences: room.preferences?.recordingPreferences } diff --git a/backend/tests/helpers/assertion-helpers.ts b/backend/tests/helpers/assertion-helpers.ts index 86dc27b..0d9a750 100644 --- a/backend/tests/helpers/assertion-helpers.ts +++ b/backend/tests/helpers/assertion-helpers.ts @@ -131,7 +131,7 @@ export const expectValidRoom = ( expect(room.preferences).toEqual({ recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -139,9 +139,9 @@ export const expectValidRoom = ( } expect(room.moderatorRoomUrl).toBeDefined(); - expect(room.publisherRoomUrl).toBeDefined(); + expect(room.speakerRoomUrl).toBeDefined(); expect(room.moderatorRoomUrl).toContain(room.roomId); - expect(room.publisherRoomUrl).toContain(room.roomId); + expect(room.speakerRoomUrl).toContain(room.roomId); if (markedForDeletion !== undefined) { expect(room.autoDeletionDate).toBeDefined(); @@ -473,8 +473,8 @@ export const expectValidRoomRolesAndPermissionsResponse = (response: any, roomId permissions: getPermissions(roomId, ParticipantRole.MODERATOR) }, { - role: ParticipantRole.PUBLISHER, - permissions: getPermissions(roomId, ParticipantRole.PUBLISHER) + role: ParticipantRole.SPEAKER, + permissions: getPermissions(roomId, ParticipantRole.SPEAKER) } ]) ); @@ -510,7 +510,7 @@ const getPermissions = (roomId: string, role: ParticipantRole, addJoinPermission canChangeVirtualBackground: true } }; - case ParticipantRole.PUBLISHER: + case ParticipantRole.SPEAKER: return { livekit: { roomJoin: addJoinPermission, diff --git a/backend/tests/helpers/test-scenarios.ts b/backend/tests/helpers/test-scenarios.ts index 6996f1c..da33cfe 100644 --- a/backend/tests/helpers/test-scenarios.ts +++ b/backend/tests/helpers/test-scenarios.ts @@ -19,8 +19,8 @@ export interface RoomData { room: MeetRoom; moderatorSecret: string; moderatorCookie: string; - publisherSecret: string; - publisherCookie: string; + speakerSecret: string; + speakerCookie: string; recordingId?: string; } @@ -49,10 +49,10 @@ export const setupSingleRoom = async ( }); // Extract the room secrets and generate participant tokens, saved as cookies - const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room); - const [moderatorCookie, publisherCookie] = await Promise.all([ + const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room); + const [moderatorCookie, speakerCookie] = await Promise.all([ generateParticipantTokenCookie(room.roomId, moderatorSecret, 'MODERATOR'), - generateParticipantTokenCookie(room.roomId, publisherSecret, 'PUBLISHER') + generateParticipantTokenCookie(room.roomId, speakerSecret, 'SPEAKER') ]); // Join participant if needed @@ -64,8 +64,8 @@ export const setupSingleRoom = async ( room, moderatorSecret, moderatorCookie, - publisherSecret, - publisherCookie + speakerSecret, + speakerCookie }; }; diff --git a/backend/tests/integration/api/participants/generate-token.test.ts b/backend/tests/integration/api/participants/generate-token.test.ts index 2b02fde..34f051c 100644 --- a/backend/tests/integration/api/participants/generate-token.test.ts +++ b/backend/tests/integration/api/participants/generate-token.test.ts @@ -48,40 +48,40 @@ describe('Participant API Tests', () => { ); }); - it('should generate a participant token with publisher permissions when using the publisher secret', async () => { + it('should generate a participant token with speaker permissions when using the speaker secret', async () => { const response = await generateParticipantToken({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName }); expectValidParticipantTokenResponse( response, roomData.room.roomId, - ParticipantRole.PUBLISHER, + ParticipantRole.SPEAKER, participantName ); }); - it(`should generate a participant token with both publisher and moderator permissions - when using the publisher secret after having a moderator token`, async () => { + it(`should generate a participant token with both speaker and moderator permissions + when using the speaker secret after having a moderator token`, async () => { const moderatorCookie = await generateParticipantTokenCookie( roomData.room.roomId, roomData.moderatorSecret, `${participantName}_MODERATOR` ); - const publisherResponse = await generateParticipantToken( + const speakerResponse = await generateParticipantToken( { roomId: roomData.room.roomId, - secret: roomData.publisherSecret, - participantName: `${participantName}_PUBLISHER` + secret: roomData.speakerSecret, + participantName: `${participantName}_SPEAKER` }, moderatorCookie ); expectValidParticipantTokenResponse( - publisherResponse, + speakerResponse, roomData.room.roomId, - ParticipantRole.PUBLISHER, - `${participantName}_PUBLISHER`, + ParticipantRole.SPEAKER, + `${participantName}_SPEAKER`, [ParticipantRole.MODERATOR] ); }); diff --git a/backend/tests/integration/api/participants/refresh-token.test.ts b/backend/tests/integration/api/participants/refresh-token.test.ts index 2025dd0..160826c 100644 --- a/backend/tests/integration/api/participants/refresh-token.test.ts +++ b/backend/tests/integration/api/participants/refresh-token.test.ts @@ -53,19 +53,19 @@ describe('Participant API Tests', () => { ); }); - it('should refresh participant token with publisher permissions when using the publisher secret', async () => { + it('should refresh participant token with speaker permissions when using the speaker secret', async () => { const response = await refreshParticipantToken( { roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName }, - roomData.publisherCookie + roomData.speakerCookie ); expectValidParticipantTokenResponse( response, roomData.room.roomId, - ParticipantRole.PUBLISHER, + ParticipantRole.SPEAKER, participantName ); }); diff --git a/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts b/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts index 54a34b0..40b4f13 100644 --- a/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts +++ b/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts @@ -182,13 +182,13 @@ describe('Recording API Tests', () => { expect(roomMetadata).toBeDefined(); expect(roomMetadata!.moderatorRoomUrl).toContain(room.roomId); - expect(roomMetadata!.publisherRoomUrl).toContain(room.roomId); + expect(roomMetadata!.speakerRoomUrl).toContain(room.roomId); roomMetadata = await meetStorageService.getArchivedRoomMetadata(room.roomId); expect(roomMetadata).toBeDefined(); expect(roomMetadata!.moderatorRoomUrl).toContain(room.roomId); - expect(roomMetadata!.publisherRoomUrl).toContain(room.roomId); + expect(roomMetadata!.speakerRoomUrl).toContain(room.roomId); const response = await startRecording(room.roomId, moderatorCookie); expectValidStartRecordingResponse(response, room.roomId, room.roomName); diff --git a/backend/tests/integration/api/recordings/delete-recording.test.ts b/backend/tests/integration/api/recordings/delete-recording.test.ts index 41c7623..96dc1ee 100644 --- a/backend/tests/integration/api/recordings/delete-recording.test.ts +++ b/backend/tests/integration/api/recordings/delete-recording.test.ts @@ -74,7 +74,7 @@ describe('Recording API Tests', () => { let roomMetadata = await meetStorageService.getArchivedRoomMetadata(room.roomId); expect(roomMetadata).toBeDefined(); expect(roomMetadata!.moderatorRoomUrl).toContain(room.roomId); - expect(roomMetadata!.publisherRoomUrl).toContain(room.roomId); + expect(roomMetadata!.speakerRoomUrl).toContain(room.roomId); // Generate a new recording const response = await startRecording(room.roomId, moderatorCookie); @@ -91,7 +91,7 @@ describe('Recording API Tests', () => { expect(roomMetadata).toBeDefined(); expect(roomMetadata!.moderatorRoomUrl).toContain(room.roomId); - expect(roomMetadata!.publisherRoomUrl).toContain(room.roomId); + expect(roomMetadata!.speakerRoomUrl).toContain(room.roomId); // Delete the second recording deleteResponse = await deleteRecording(secondRecordingId!); diff --git a/backend/tests/integration/api/recordings/get-recordings.test.ts b/backend/tests/integration/api/recordings/get-recordings.test.ts index 057eadc..6872d09 100644 --- a/backend/tests/integration/api/recordings/get-recordings.test.ts +++ b/backend/tests/integration/api/recordings/get-recordings.test.ts @@ -63,7 +63,7 @@ describe('Recordings API Tests', () => { const roomId = roomData.room.roomId; // Generate a recording token for the room - const recordingCookie = await generateRecordingTokenCookie(roomId, roomData.publisherSecret); + const recordingCookie = await generateRecordingTokenCookie(roomId, roomData.speakerSecret); // Create a new room and start a recording roomData = await setupSingleRoomWithRecording(true); diff --git a/backend/tests/integration/api/recordings/start-recording.test.ts b/backend/tests/integration/api/recordings/start-recording.test.ts index d075086..8b4a956 100644 --- a/backend/tests/integration/api/recordings/start-recording.test.ts +++ b/backend/tests/integration/api/recordings/start-recording.test.ts @@ -72,7 +72,7 @@ describe('Recording API Tests', () => { const archivedRoom = await storageService.getArchivedRoomMetadata(room.roomId); expect(archivedRoom).toBeDefined(); expect(archivedRoom?.moderatorRoomUrl).toBeDefined(); - expect(archivedRoom?.publisherRoomUrl).toBeDefined(); + expect(archivedRoom?.speakerRoomUrl).toBeDefined(); expect(archivedRoom?.preferences).toBeDefined(); const secretsResponse = await stopRecording(recordingId, moderatorCookie); diff --git a/backend/tests/integration/api/rooms/create-room.test.ts b/backend/tests/integration/api/rooms/create-room.test.ts index 722c07d..f905410 100644 --- a/backend/tests/integration/api/rooms/create-room.test.ts +++ b/backend/tests/integration/api/rooms/create-room.test.ts @@ -48,7 +48,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: false }, virtualBackgroundPreferences: { enabled: true } @@ -165,7 +165,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: 'yes', // invalid boolean - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } diff --git a/backend/tests/integration/api/rooms/generate-recording-token.test.ts b/backend/tests/integration/api/rooms/generate-recording-token.test.ts index 55adb52..a294a01 100644 --- a/backend/tests/integration/api/rooms/generate-recording-token.test.ts +++ b/backend/tests/integration/api/rooms/generate-recording-token.test.ts @@ -34,35 +34,38 @@ describe('Room API Tests', () => { expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR, true, true); }); - it('should generate a recording token with canRetrieve and canDelete permissions when using the moderator secret and recording access is admin-moderator-publisher', async () => { + it('should generate a recording token with canRetrieve and canDelete permissions when using the moderator secret and recording access is admin-moderator-speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret); expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR, true, true); }); - it('should generate a recording token without any permissions when using the publisher secret and recording access is admin-moderator', async () => { + it('should generate a recording token without any permissions when using the speaker secret and recording access is admin-moderator', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); - const response = await generateRecordingToken(roomData.room.roomId, roomData.publisherSecret); - expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.PUBLISHER, false, false); + const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret); + expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, false, false); }); - it('should generate a recording token with canRetrieve permission but not canDelete when using the publisher secret and recording access is admin-moderator-publisher', async () => { + it('should generate a recording token with canRetrieve permission but not canDelete when using the speaker secret and recording access is admin-moderator-speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); - const response = await generateRecordingToken(roomData.room.roomId, roomData.publisherSecret); - expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.PUBLISHER, true, false); + const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret); + expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, true, false); }); it('should succeed even if the room is deleted', async () => { - await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER); + await updateRecordingAccessPreferencesInRoom( + roomData.room.roomId, + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + ); await deleteRoom(roomData.room.roomId); const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret); diff --git a/backend/tests/integration/api/rooms/get-room-preferences.test.ts b/backend/tests/integration/api/rooms/get-room-preferences.test.ts index 2c28c69..d94c519 100644 --- a/backend/tests/integration/api/rooms/get-room-preferences.test.ts +++ b/backend/tests/integration/api/rooms/get-room-preferences.test.ts @@ -8,7 +8,7 @@ describe('Room API Tests', () => { const DEFAULT_PREFERENCES = { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -39,7 +39,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: false } diff --git a/backend/tests/integration/api/rooms/get-room-roles.test.ts b/backend/tests/integration/api/rooms/get-room-roles.test.ts index fedf941..4f2813e 100644 --- a/backend/tests/integration/api/rooms/get-room-roles.test.ts +++ b/backend/tests/integration/api/rooms/get-room-roles.test.ts @@ -42,9 +42,9 @@ describe('Room API Tests', () => { expectValidRoomRoleAndPermissionsResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR); }); - it('should retrieve publisher role and associated permissions for a room with a valid publisher secret', async () => { - const response = await getRoomRoleBySecret(roomData.room.roomId, roomData.publisherSecret); - expectValidRoomRoleAndPermissionsResponse(response, roomData.room.roomId, ParticipantRole.PUBLISHER); + it('should retrieve speaker role and associated permissions for a room with a valid speaker secret', async () => { + const response = await getRoomRoleBySecret(roomData.room.roomId, roomData.speakerSecret); + expectValidRoomRoleAndPermissionsResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER); }); it('should return a 404 error if the room does not exist', async () => { diff --git a/backend/tests/integration/api/rooms/get-room.test.ts b/backend/tests/integration/api/rooms/get-room.test.ts index 67c3102..833102b 100644 --- a/backend/tests/integration/api/rooms/get-room.test.ts +++ b/backend/tests/integration/api/rooms/get-room.test.ts @@ -38,7 +38,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: false } @@ -97,13 +97,13 @@ describe('Room API Tests', () => { expectSuccessRoomResponse(response, 'deletion-date', validAutoDeletionDate); }); - it('should retrieve a room without moderatorRoomUrl when participant is publisher', async () => { + it('should retrieve a room without moderatorRoomUrl when participant is speaker', async () => { const roomData = await setupSingleRoom(); const response = await getRoom( roomData.room.roomId, undefined, - roomData.publisherCookie, - ParticipantRole.PUBLISHER + roomData.speakerCookie, + ParticipantRole.SPEAKER ); expect(response.status).toBe(200); expect(response.body.moderatorRoomUrl).toBeUndefined(); diff --git a/backend/tests/integration/api/rooms/update-room.test.ts b/backend/tests/integration/api/rooms/update-room.test.ts index f30b166..f6e80af 100644 --- a/backend/tests/integration/api/rooms/update-room.test.ts +++ b/backend/tests/integration/api/rooms/update-room.test.ts @@ -36,7 +36,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -85,7 +85,7 @@ describe('Room API Tests', () => { preferences: { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -96,7 +96,7 @@ describe('Room API Tests', () => { const partialPreferences = { recordingPreferences: { enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -146,7 +146,7 @@ describe('Room API Tests', () => { const invalidPreferences = { recordingPreferences: { enabled: 'true', // String instead of boolean - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: false }, virtualBackgroundPreferences: { enabled: false } @@ -212,7 +212,7 @@ describe('Room API Tests', () => { const preferences = { recordingPreferences: { enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: false }, virtualBackgroundPreferences: { enabled: false } diff --git a/backend/tests/integration/api/security/meeting-security.test.ts b/backend/tests/integration/api/security/meeting-security.test.ts index bc0f745..e0b927e 100644 --- a/backend/tests/integration/api/security/meeting-security.test.ts +++ b/backend/tests/integration/api/security/meeting-security.test.ts @@ -66,11 +66,11 @@ describe('Meeting API Security Tests', () => { expect(response.status).toBe(403); }); - it('should fail when participant is publisher', async () => { + it('should fail when participant is speaker', async () => { const response = await request(app) .delete(`${MEETINGS_PATH}/${roomData.room.roomId}`) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(403); }); }); @@ -110,11 +110,11 @@ describe('Meeting API Security Tests', () => { expect(response.status).toBe(403); }); - it('should fail when participant is publisher', async () => { + it('should fail when participant is speaker', async () => { const response = await request(app) .delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}`) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(403); }); }); diff --git a/backend/tests/integration/api/security/participant-security.test.ts b/backend/tests/integration/api/security/participant-security.test.ts index 3b73a4a..a884f2d 100644 --- a/backend/tests/integration/api/security/participant-security.test.ts +++ b/backend/tests/integration/api/security/participant-security.test.ts @@ -38,12 +38,12 @@ describe('Participant API Security Tests', () => { roomData = await setupSingleRoom(); }); - it('should succeed when no authentication is required and participant is publisher', async () => { + it('should succeed when no authentication is required and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.NONE); const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); @@ -60,12 +60,12 @@ describe('Participant API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when authentication is required for moderator and participant is publisher', async () => { + it('should succeed when authentication is required for moderator and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.MODERATORS_ONLY); const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); @@ -93,23 +93,23 @@ describe('Participant API Security Tests', () => { expect(response.status).toBe(401); }); - it('should succeed when authentication is required for all users, participant is publisher and authenticated', async () => { + it('should succeed when authentication is required for all users, participant is speaker and authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).set('Cookie', adminCookie).send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); }); - it('should fail when authentication is required for all users and participant is publisher but not authenticated', async () => { + it('should fail when authentication is required for all users and participant is speaker but not authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(401); @@ -153,15 +153,15 @@ describe('Participant API Security Tests', () => { INTERNAL_CONFIG.PARTICIPANT_TOKEN_EXPIRATION = initialTokenExpiration; }); - it('should succeed when no authentication is required and participant is publisher', async () => { + it('should succeed when no authentication is required and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.NONE); const response = await request(app) .post(`${PARTICIPANTS_PATH}/token/refresh`) - .set('Cookie', roomData.publisherCookie) + .set('Cookie', roomData.speakerCookie) .send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); @@ -181,15 +181,15 @@ describe('Participant API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when authentication is required for moderator and participant is publisher', async () => { + it('should succeed when authentication is required for moderator and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.MODERATORS_ONLY); const response = await request(app) .post(`${PARTICIPANTS_PATH}/token/refresh`) - .set('Cookie', roomData.publisherCookie) + .set('Cookie', roomData.speakerCookie) .send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); @@ -223,29 +223,29 @@ describe('Participant API Security Tests', () => { expect(response.status).toBe(401); }); - it('should succeed when authentication is required for all users, participant is publisher and authenticated', async () => { + it('should succeed when authentication is required for all users, participant is speaker and authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app) .post(`${PARTICIPANTS_PATH}/token/refresh`) - .set('Cookie', [adminCookie, roomData.publisherCookie]) + .set('Cookie', [adminCookie, roomData.speakerCookie]) .send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(200); }); - it('should fail when authentication is required for all users and participant is publisher but not authenticated', async () => { + it('should fail when authentication is required for all users and participant is speaker but not authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app) .post(`${PARTICIPANTS_PATH}/token/refresh`) - .set('Cookie', roomData.publisherCookie) + .set('Cookie', roomData.speakerCookie) .send({ roomId: roomData.room.roomId, - secret: roomData.publisherSecret, + secret: roomData.speakerSecret, participantName: PARTICIPANT_NAME }); expect(response.status).toBe(401); diff --git a/backend/tests/integration/api/security/recording-security.test.ts b/backend/tests/integration/api/security/recording-security.test.ts index e9f219f..8e28650 100644 --- a/backend/tests/integration/api/security/recording-security.test.ts +++ b/backend/tests/integration/api/security/recording-security.test.ts @@ -84,12 +84,12 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(403); }); - it('should fail when participant is publisher', async () => { + it('should fail when participant is speaker', async () => { const response = await request(app) .post(INTERNAL_RECORDINGS_PATH) .send({ roomId: roomData.room.roomId }) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(403); }); }); @@ -138,11 +138,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(403); }); - it('should fail when participant is publisher', async () => { + it('should fail when participant is speaker', async () => { const response = await request(app) .post(`${INTERNAL_RECORDINGS_PATH}/${roomData.recordingId}/stop`) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(403); }); }); @@ -169,24 +169,24 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app).get(RECORDINGS_PATH).set('Cookie', recordingCookie); expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -197,11 +197,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app).get(RECORDINGS_PATH).set('Cookie', recordingCookie); @@ -233,14 +233,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -249,10 +249,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -265,11 +265,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -362,14 +362,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(404); }); - it('should fail when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should fail when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -378,10 +378,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(403); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -394,11 +394,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(404); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -449,14 +449,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should fail when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -466,10 +466,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(403); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -483,11 +483,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -527,14 +527,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -543,10 +543,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -559,11 +559,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -651,14 +651,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -667,10 +667,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -683,11 +683,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -727,14 +727,14 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is publisher', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) @@ -744,10 +744,10 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when recording access is admin-moderator-publisher and participant is moderator', async () => { + it('should succeed when recording access is admin-moderator-speaker and participant is moderator', async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, @@ -761,11 +761,11 @@ describe('Recording API Security Tests', () => { expect(response.status).toBe(200); }); - it('should fail when recording access is admin-moderator and participant is publisher', async () => { + it('should fail when recording access is admin-moderator and participant is speaker', async () => { await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); const recordingCookie = await generateRecordingTokenCookie( roomData.room.roomId, - roomData.publisherSecret + roomData.speakerSecret ); const response = await request(app) diff --git a/backend/tests/integration/api/security/room-security.test.ts b/backend/tests/integration/api/security/room-security.test.ts index 293a3fa..b213819 100644 --- a/backend/tests/integration/api/security/room-security.test.ts +++ b/backend/tests/integration/api/security/room-security.test.ts @@ -142,11 +142,11 @@ describe('Room API Security Tests', () => { expect(response.status).toBe(403); }); - it('should succeed when participant is publisher', async () => { + it('should succeed when participant is speaker', async () => { const response = await request(app) .get(`${ROOMS_PATH}/${roomData.room.roomId}`) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(200); }); }); @@ -181,7 +181,7 @@ describe('Room API Security Tests', () => { const roomPreferences = { recordingPreferences: { enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -260,21 +260,21 @@ describe('Room API Security Tests', () => { expect(response.status).toBe(403); }); - it('should succeed when participant is publisher', async () => { + it('should succeed when participant is speaker', async () => { const response = await request(app) .get(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/preferences`) - .set('Cookie', roomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', roomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(200); }); - it('should fail when participant is publisher of a different room', async () => { + it('should fail when participant is speaker of a different room', async () => { const newRoomData = await setupSingleRoom(); const response = await request(app) .get(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/preferences`) - .set('Cookie', newRoomData.publisherCookie) - .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.PUBLISHER); + .set('Cookie', newRoomData.speakerCookie) + .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); expect(response.status).toBe(403); }); }); @@ -289,16 +289,16 @@ describe('Room API Security Tests', () => { beforeEach(async () => { await updateRecordingAccessPreferencesInRoom( roomData.room.roomId, - MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER ); }); - it('should succeed when no authentication is required and participant is publisher', async () => { + it('should succeed when no authentication is required and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.NONE); const response = await request(app) .post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`) - .send({ secret: roomData.publisherSecret }); + .send({ secret: roomData.speakerSecret }); expect(response.status).toBe(200); }); @@ -311,12 +311,12 @@ describe('Room API Security Tests', () => { expect(response.status).toBe(200); }); - it('should succeed when authentication is required for moderator and participant is publisher', async () => { + it('should succeed when authentication is required for moderator and participant is speaker', async () => { await changeSecurityPreferences(AuthMode.MODERATORS_ONLY); const response = await request(app) .post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`) - .send({ secret: roomData.publisherSecret }); + .send({ secret: roomData.speakerSecret }); expect(response.status).toBe(200); }); @@ -339,22 +339,22 @@ describe('Room API Security Tests', () => { expect(response.status).toBe(401); }); - it('should succeed when authentication is required for all users, participant is publisher and authenticated', async () => { + it('should succeed when authentication is required for all users, participant is speaker and authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app) .post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`) .set('Cookie', adminCookie) - .send({ secret: roomData.publisherSecret }); + .send({ secret: roomData.speakerSecret }); expect(response.status).toBe(200); }); - it('should fail when authentication is required for all users and participant is publisher but not authenticated', async () => { + it('should fail when authentication is required for all users and participant is speaker but not authenticated', async () => { await changeSecurityPreferences(AuthMode.ALL_USERS); const response = await request(app) .post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`) - .send({ secret: roomData.publisherSecret }); + .send({ secret: roomData.speakerSecret }); expect(response.status).toBe(401); }); diff --git a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.html b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.html index 484f670..bf33db5 100644 --- a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.html +++ b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.html @@ -11,12 +11,7 @@
Search rooms - + search
@@ -285,11 +280,11 @@ diff --git a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.spec.ts b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.spec.ts index 37dd3bc..d0c0016 100644 --- a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.spec.ts +++ b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.spec.ts @@ -6,217 +6,213 @@ import { RoomsListsComponent } from './rooms-lists.component'; import { MeetRoom } from '../../typings/ce'; describe('RoomsListsComponent', () => { - let component: RoomsListsComponent; - let fixture: ComponentFixture; + let component: RoomsListsComponent; + let fixture: ComponentFixture; - const mockRooms: MeetRoom[] = [ - { - roomId: 'test-room-1', - creationDate: 1642248000000, // 2024-01-15T10:00:00Z - markedForDeletion: false, - autoDeletionDate: undefined, - roomIdPrefix: 'test', - moderatorRoomUrl: 'http://localhost/room/test-room-1?secret=mod-123', - publisherRoomUrl: 'http://localhost/room/test-room-1?secret=pub-123', - preferences: { - chatPreferences: { enabled: true }, - recordingPreferences: { enabled: false }, - virtualBackgroundPreferences: { enabled: true } - } - }, - { - roomId: 'test-room-2', - creationDate: 1642334400000, // 2024-01-16T14:30:00Z - markedForDeletion: true, - autoDeletionDate: 1643673600000, // 2024-02-01T00:00:00Z - roomIdPrefix: 'test', - moderatorRoomUrl: 'http://localhost/room/test-room-2?secret=mod-456', - publisherRoomUrl: 'http://localhost/room/test-room-2?secret=pub-456', - preferences: { - chatPreferences: { enabled: true }, - recordingPreferences: { enabled: false }, - virtualBackgroundPreferences: { enabled: true } - } - } - ]; + const mockRooms: MeetRoom[] = [ + { + roomId: 'test-room-1', + creationDate: 1642248000000, // 2024-01-15T10:00:00Z + markedForDeletion: false, + autoDeletionDate: undefined, + roomIdPrefix: 'test', + moderatorRoomUrl: 'http://localhost/room/test-room-1?secret=mod-123', + speakerRoomUrl: 'http://localhost/room/test-room-1?secret=pub-123', + preferences: { + chatPreferences: { enabled: true }, + recordingPreferences: { enabled: false }, + virtualBackgroundPreferences: { enabled: true } + } + }, + { + roomId: 'test-room-2', + creationDate: 1642334400000, // 2024-01-16T14:30:00Z + markedForDeletion: true, + autoDeletionDate: 1643673600000, // 2024-02-01T00:00:00Z + roomIdPrefix: 'test', + moderatorRoomUrl: 'http://localhost/room/test-room-2?secret=mod-456', + speakerRoomUrl: 'http://localhost/room/test-room-2?secret=pub-456', + preferences: { + chatPreferences: { enabled: true }, + recordingPreferences: { enabled: false }, + virtualBackgroundPreferences: { enabled: true } + } + } + ]; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RoomsListsComponent, - NoopAnimationsModule, - MatSnackBarModule - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RoomsListsComponent, NoopAnimationsModule, MatSnackBarModule] + }).compileComponents(); - fixture = TestBed.createComponent(RoomsListsComponent); - component = fixture.componentInstance; + fixture = TestBed.createComponent(RoomsListsComponent); + component = fixture.componentInstance; - // Set up test data - component.rooms = mockRooms; - component.loading = false; - component.canDeleteRooms = true; + // Set up test data + component.rooms = mockRooms; + component.loading = false; + component.canDeleteRooms = true; - fixture.detectChanges(); - }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should initialize with correct default values', () => { - expect(component.rooms).toEqual(mockRooms); - expect(component.canDeleteRooms).toBe(true); - expect(component.loading).toBe(false); - expect(component.showFilters).toBe(false); - expect(component.showSelection).toBe(true); - expect(component.emptyMessage).toBe('No rooms found'); - }); + it('should initialize with correct default values', () => { + expect(component.rooms).toEqual(mockRooms); + expect(component.canDeleteRooms).toBe(true); + expect(component.loading).toBe(false); + expect(component.showFilters).toBe(false); + expect(component.showSelection).toBe(true); + expect(component.emptyMessage).toBe('No rooms found'); + }); - it('should update displayed columns based on showSelection', () => { - component.showSelection = false; - component.ngOnInit(); - expect(component.displayedColumns).not.toContain('select'); + it('should update displayed columns based on showSelection', () => { + component.showSelection = false; + component.ngOnInit(); + expect(component.displayedColumns).not.toContain('select'); - component.showSelection = true; - component.ngOnInit(); - expect(component.displayedColumns).toContain('select'); - }); + component.showSelection = true; + component.ngOnInit(); + expect(component.displayedColumns).toContain('select'); + }); - it('should determine room status correctly', () => { - expect(component.isRoomActive(mockRooms[0])).toBe(true); - expect(component.isRoomActive(mockRooms[1])).toBe(false); - expect(component.isRoomInactive(mockRooms[0])).toBe(false); - expect(component.isRoomInactive(mockRooms[1])).toBe(true); - }); + it('should determine room status correctly', () => { + expect(component.isRoomActive(mockRooms[0])).toBe(true); + expect(component.isRoomActive(mockRooms[1])).toBe(false); + expect(component.isRoomInactive(mockRooms[0])).toBe(false); + expect(component.isRoomInactive(mockRooms[1])).toBe(true); + }); - it('should return correct status information', () => { - expect(component.getRoomStatus(mockRooms[0])).toBe('Active'); - expect(component.getRoomStatus(mockRooms[1])).toBe('Inactive'); + it('should return correct status information', () => { + expect(component.getRoomStatus(mockRooms[0])).toBe('Active'); + expect(component.getRoomStatus(mockRooms[1])).toBe('Inactive'); - expect(component.getStatusIcon(mockRooms[0])).toBe('check_circle'); - expect(component.getStatusIcon(mockRooms[1])).toBe('delete_outline'); + expect(component.getStatusIcon(mockRooms[0])).toBe('check_circle'); + expect(component.getStatusIcon(mockRooms[1])).toBe('delete_outline'); - expect(component.getStatusColor(mockRooms[0])).toBe('var(--ov-meet-color-success)'); - expect(component.getStatusColor(mockRooms[1])).toBe('var(--ov-meet-color-error)'); - }); + expect(component.getStatusColor(mockRooms[0])).toBe('var(--ov-meet-color-success)'); + expect(component.getStatusColor(mockRooms[1])).toBe('var(--ov-meet-color-error)'); + }); - it('should handle auto-deletion information correctly', () => { - expect(component.hasAutoDeletion(mockRooms[0])).toBe(false); - expect(component.hasAutoDeletion(mockRooms[1])).toBe(true); + it('should handle auto-deletion information correctly', () => { + expect(component.hasAutoDeletion(mockRooms[0])).toBe(false); + expect(component.hasAutoDeletion(mockRooms[1])).toBe(true); - expect(component.getAutoDeletionStatus(mockRooms[0])).toBe('Not scheduled'); - expect(component.getAutoDeletionStatus(mockRooms[1])).toBe('Scheduled'); + expect(component.getAutoDeletionStatus(mockRooms[0])).toBe('Not scheduled'); + expect(component.getAutoDeletionStatus(mockRooms[1])).toBe('Scheduled'); - expect(component.getAutoDeletionIcon(mockRooms[0])).toBe('close'); - expect(component.getAutoDeletionIcon(mockRooms[1])).toBe('auto_delete'); - }); + expect(component.getAutoDeletionIcon(mockRooms[0])).toBe('close'); + expect(component.getAutoDeletionIcon(mockRooms[1])).toBe('auto_delete'); + }); - it('should handle room selection correctly', () => { - const room = mockRooms[0]; + it('should handle room selection correctly', () => { + const room = mockRooms[0]; - expect(component.isRoomSelected(room)).toBe(false); + expect(component.isRoomSelected(room)).toBe(false); - component.toggleRoomSelection(room); - expect(component.isRoomSelected(room)).toBe(true); + component.toggleRoomSelection(room); + expect(component.isRoomSelected(room)).toBe(true); - component.toggleRoomSelection(room); - expect(component.isRoomSelected(room)).toBe(false); - }); + component.toggleRoomSelection(room); + expect(component.isRoomSelected(room)).toBe(false); + }); - it('should determine if room can be selected', () => { - expect(component.canSelectRoom(mockRooms[0])).toBe(true); // Active room - expect(component.canSelectRoom(mockRooms[1])).toBe(false); // Marked for deletion - }); + it('should determine if room can be selected', () => { + expect(component.canSelectRoom(mockRooms[0])).toBe(true); // Active room + expect(component.canSelectRoom(mockRooms[1])).toBe(false); // Marked for deletion + }); - it('should determine room permissions correctly', () => { - expect(component.canOpenRoom(mockRooms[0])).toBe(true); - expect(component.canOpenRoom(mockRooms[1])).toBe(false); + it('should determine room permissions correctly', () => { + expect(component.canOpenRoom(mockRooms[0])).toBe(true); + expect(component.canOpenRoom(mockRooms[1])).toBe(false); - expect(component.canEditRoom(mockRooms[0])).toBe(true); - expect(component.canEditRoom(mockRooms[1])).toBe(false); + expect(component.canEditRoom(mockRooms[0])).toBe(true); + expect(component.canEditRoom(mockRooms[1])).toBe(false); - expect(component.canDeleteRoom(mockRooms[0])).toBe(true); - expect(component.canDeleteRoom(mockRooms[1])).toBe(false); - }); + expect(component.canDeleteRoom(mockRooms[0])).toBe(true); + expect(component.canDeleteRoom(mockRooms[1])).toBe(false); + }); - it('should emit room actions correctly', () => { - spyOn(component.roomAction, 'emit'); + it('should emit room actions correctly', () => { + spyOn(component.roomAction, 'emit'); - component.openRoom(mockRooms[0]); - expect(component.roomAction.emit).toHaveBeenCalledWith({ - rooms: [mockRooms[0]], - action: 'open' - }); + component.openRoom(mockRooms[0]); + expect(component.roomAction.emit).toHaveBeenCalledWith({ + rooms: [mockRooms[0]], + action: 'open' + }); - component.deleteRoom(mockRooms[0]); - expect(component.roomAction.emit).toHaveBeenCalledWith({ - rooms: [mockRooms[0]], - action: 'delete' - }); + component.deleteRoom(mockRooms[0]); + expect(component.roomAction.emit).toHaveBeenCalledWith({ + rooms: [mockRooms[0]], + action: 'delete' + }); - component.viewSettings(mockRooms[0]); - expect(component.roomAction.emit).toHaveBeenCalledWith({ - rooms: [mockRooms[0]], - action: 'settings' - }); - }); + component.viewSettings(mockRooms[0]); + expect(component.roomAction.emit).toHaveBeenCalledWith({ + rooms: [mockRooms[0]], + action: 'settings' + }); + }); - it('should handle batch delete correctly', () => { - spyOn(component.roomAction, 'emit'); + it('should handle batch delete correctly', () => { + spyOn(component.roomAction, 'emit'); - // Select some rooms - component.toggleRoomSelection(mockRooms[0]); - component.bulkDeleteSelected(); + // Select some rooms + component.toggleRoomSelection(mockRooms[0]); + component.bulkDeleteSelected(); - expect(component.roomAction.emit).toHaveBeenCalledWith({ - rooms: [mockRooms[0]], - action: 'bulkDelete' - }); - }); + expect(component.roomAction.emit).toHaveBeenCalledWith({ + rooms: [mockRooms[0]], + action: 'bulkDelete' + }); + }); - it('should emit filter changes', () => { - spyOn(component.filterChange, 'emit'); + it('should emit filter changes', () => { + spyOn(component.filterChange, 'emit'); - component.nameFilterControl.setValue('test'); + component.nameFilterControl.setValue('test'); - // Trigger change detection to simulate the valueChanges observable - fixture.detectChanges(); + // Trigger change detection to simulate the valueChanges observable + fixture.detectChanges(); - // The filter change should be emitted through the form control subscription - expect(component.filterChange.emit).toHaveBeenCalled(); - }); + // The filter change should be emitted through the form control subscription + expect(component.filterChange.emit).toHaveBeenCalled(); + }); - it('should show empty state when no rooms', () => { - component.rooms = []; - fixture.detectChanges(); + it('should show empty state when no rooms', () => { + component.rooms = []; + fixture.detectChanges(); - const emptyState = fixture.nativeElement.querySelector('.no-rooms-state'); - expect(emptyState).toBeTruthy(); - }); + const emptyState = fixture.nativeElement.querySelector('.no-rooms-state'); + expect(emptyState).toBeTruthy(); + }); - it('should show loading state', () => { - component.loading = true; - fixture.detectChanges(); + it('should show loading state', () => { + component.loading = true; + fixture.detectChanges(); - const loadingContainer = fixture.nativeElement.querySelector('.loading-container'); - expect(loadingContainer).toBeTruthy(); - }); + const loadingContainer = fixture.nativeElement.querySelector('.loading-container'); + expect(loadingContainer).toBeTruthy(); + }); - it('should clear selection correctly', () => { - // Select a room first - component.toggleRoomSelection(mockRooms[0]); - expect(component.selectedRooms().size).toBe(1); + it('should clear selection correctly', () => { + // Select a room first + component.toggleRoomSelection(mockRooms[0]); + expect(component.selectedRooms().size).toBe(1); - // Clear selection - component.clearSelection(); - expect(component.selectedRooms().size).toBe(0); - }); + // Clear selection + component.clearSelection(); + expect(component.selectedRooms().size).toBe(0); + }); - it('should get selected rooms correctly', () => { - component.toggleRoomSelection(mockRooms[0]); - const selectedRooms = component.getSelectedRooms(); + it('should get selected rooms correctly', () => { + component.toggleRoomSelection(mockRooms[0]); + const selectedRooms = component.getSelectedRooms(); - expect(selectedRooms).toEqual([mockRooms[0]]); - }); + expect(selectedRooms).toEqual([mockRooms[0]]); + }); }); diff --git a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.ts b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.ts index 8915373..d71ff8f 100644 --- a/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/components/rooms-lists/rooms-lists.component.ts @@ -34,7 +34,7 @@ export interface RoomTableAction { | 'open' | 'edit' | 'copyModeratorLink' - | 'copyPublisherLink' + | 'copySpeakerLink' | 'viewRecordings' | 'delete' | 'bulkDelete'; @@ -242,8 +242,8 @@ export class RoomsListsComponent implements OnInit, OnChanges { this.roomAction.emit({ rooms: [room], action: 'copyModeratorLink' }); } - copyPublisherLink(room: MeetRoom) { - this.roomAction.emit({ rooms: [room], action: 'copyPublisherLink' }); + copySpeakerLink(room: MeetRoom) { + this.roomAction.emit({ rooms: [room], action: 'copySpeakerLink' }); } viewRecordings(room: MeetRoom) { diff --git a/frontend/projects/shared-meet-components/src/lib/models/auth.model.ts b/frontend/projects/shared-meet-components/src/lib/models/auth.model.ts index b50858e..aae2c6d 100644 --- a/frontend/projects/shared-meet-components/src/lib/models/auth.model.ts +++ b/frontend/projects/shared-meet-components/src/lib/models/auth.model.ts @@ -2,6 +2,6 @@ import { ParticipantPermissions, ParticipantRole } from '../typings/ce'; export interface ParticipantTokenInfo { token: string; // The generated participant token - role: ParticipantRole; // Role of the participant (e.g., 'moderator', 'publisher') + role: ParticipantRole; // Role of the participant (e.g., 'moderator', 'speaker') permissions: ParticipantPermissions; // List of permissions granted to the participant } diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/recording-preferences/recording-preferences.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/recording-preferences/recording-preferences.component.ts index f7a8c4f..98a9f6c 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/recording-preferences/recording-preferences.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/room-wizard/steps/recording-preferences/recording-preferences.component.ts @@ -44,7 +44,7 @@ export class RecordingPreferencesComponent implements OnDestroy { title: 'Allow Recording', description: 'Enable recording capabilities for this room. Recordings can be started manually or automatically.', - icon: 'video_library', + icon: 'video_library' // recommended: true }, { @@ -64,8 +64,8 @@ export class RecordingPreferencesComponent implements OnDestroy { label: 'Admin and Moderators' }, { - value: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER, - label: 'Admin, Moderators and Publishers' + value: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER, + label: 'Admin, Moderators and Speakers' } ]; diff --git a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/rooms.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/rooms.component.ts index 65afc49..feee62d 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/rooms.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/console/rooms/rooms.component.ts @@ -86,8 +86,8 @@ export class RoomsComponent implements OnInit { case 'copyModeratorLink': this.copyModeratorLink(action.rooms[0]); break; - case 'copyPublisherLink': - this.copyPublisherLink(action.rooms[0]); + case 'copySpeakerLink': + this.copySpeakerLink(action.rooms[0]); break; case 'viewRecordings': await this.viewRecordings(action.rooms[0]); @@ -236,9 +236,9 @@ export class RoomsComponent implements OnInit { this.notificationService.showSnackbar('Moderator link copied to clipboard'); } - private copyPublisherLink(room: MeetRoom) { - this.clipboard.copy(room.publisherRoomUrl); - this.notificationService.showSnackbar('Publisher link copied to clipboard'); + private copySpeakerLink(room: MeetRoom) { + this.clipboard.copy(room.speakerRoomUrl); + this.notificationService.showSnackbar('Speaker link copied to clipboard'); } private async viewRecordings(room: MeetRoom) { diff --git a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts index f67c96d..7fe0f68 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts @@ -52,7 +52,7 @@ export class ErrorComponent implements OnInit { const reasonMap: { [key in ErrorReason]: { title: string; message: string } } = { [ErrorReason.MISSING_ROOM_SECRET]: { title: 'Missing secret', - message: 'You need to provide a secret to join the room as a moderator or publisher' + message: 'You need to provide a secret to join the room as a moderator or speaker' }, [ErrorReason.MISSING_RECORDING_SECRET]: { title: 'Missing secret', @@ -60,7 +60,7 @@ export class ErrorComponent implements OnInit { }, [ErrorReason.INVALID_ROOM_SECRET]: { title: 'Invalid secret', - message: 'The secret provided to join the room is neither valid for moderators nor publishers' + message: 'The secret provided to join the room is neither valid for moderators nor speakers' }, [ErrorReason.INVALID_RECORDING_SECRET]: { title: 'Invalid secret', diff --git a/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.html b/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.html index 5f546d6..70dd790 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.html +++ b/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.html @@ -44,9 +44,9 @@
@@ -110,7 +110,7 @@ [titleSize]="'xl'" [titleWeight]="'bold'" [meetingUrl]="hostname + '/' + roomId" - (copyClicked)="copyPublisherLink()" + (copyClicked)="copySpeakerLink()" > } @@ -218,7 +218,7 @@ @if (features().canModerateRoom) { } diff --git a/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.ts index e4deb60..ff56a3c 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/meeting/meeting.component.ts @@ -90,7 +90,7 @@ export class MeetingComponent implements OnInit { roomSecret = ''; participantName = ''; participantToken = ''; - participantRole: ParticipantRole = ParticipantRole.PUBLISHER; + participantRole: ParticipantRole = ParticipantRole.SPEAKER; remoteParticipants: ParticipantModel[] = []; showMeeting = false; @@ -406,9 +406,9 @@ export class MeetingComponent implements OnInit { this.notificationService.showSnackbar('Moderator link copied to clipboard'); } - async copyPublisherLink() { - this.clipboard.copy(this.room!.publisherRoomUrl); - this.notificationService.showSnackbar('Publisher link copied to clipboard'); + async copySpeakerLink() { + this.clipboard.copy(this.room!.speakerRoomUrl); + this.notificationService.showSnackbar('Speaker link copied to clipboard'); } async onRecordingStartRequested(event: RecordingStartRequestedEvent) { diff --git a/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts b/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts index 5066fd1..dfaced0 100644 --- a/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts +++ b/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts @@ -12,7 +12,7 @@ export class ParticipantTokenService { protected readonly PARTICIPANTS_API = `${HttpService.INTERNAL_API_PATH_PREFIX}/participants`; protected participantName?: string; - protected participantRole: ParticipantRole = ParticipantRole.PUBLISHER; + protected participantRole: ParticipantRole = ParticipantRole.SPEAKER; protected currentTokenInfo?: ParticipantTokenInfo; protected log; diff --git a/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts b/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts index 32e853a..5e8fa47 100644 --- a/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts +++ b/frontend/projects/shared-meet-components/src/lib/services/wizard-state.service.ts @@ -7,7 +7,7 @@ import { MeetRecordingAccess, MeetRoomOptions, MeetRoomPreferences } from '@lib/ const DEFAULT_PREFERENCES: MeetRoomPreferences = { recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } diff --git a/frontend/webcomponent/tests/e2e/core/events.test.ts b/frontend/webcomponent/tests/e2e/core/events.test.ts index b3d35cc..6b5ed45 100644 --- a/frontend/webcomponent/tests/e2e/core/events.test.ts +++ b/frontend/webcomponent/tests/e2e/core/events.test.ts @@ -56,8 +56,8 @@ test.describe('Web Component E2E Tests', () => { expect(joinElements.length).toBe(1); }); - test('should successfully join as publisher and receive JOINED event', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + test('should successfully join as speaker and receive JOINED event', async ({ page }) => { + await joinRoomAs('speaker', participantName, page); await page.waitForSelector('.event-JOINED'); const joinElements = await page.locator('.event-JOINED').all(); expect(joinElements.length).toBe(1); diff --git a/frontend/webcomponent/tests/e2e/core/room.test.ts b/frontend/webcomponent/tests/e2e/core/room.test.ts index c0e5e70..03031de 100644 --- a/frontend/webcomponent/tests/e2e/core/room.test.ts +++ b/frontend/webcomponent/tests/e2e/core/room.test.ts @@ -91,7 +91,7 @@ test.describe('Room Functionality Tests', () => { test.describe('Basic Room Features', () => { test('should show the toolbar and media buttons', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); await waitForElementInIframe(page, '#toolbar'); // Check media buttons are present @@ -102,8 +102,8 @@ test.describe('Room Functionality Tests', () => { }); test('should start a videoconference and display video elements', async ({ page, browser }) => { - // First participant (publisher) joins - await joinRoomAs('publisher', participantName, page); + // First participant (speaker) joins + await joinRoomAs('speaker', participantName, page); // Check local video element const localVideo = await waitForElementInIframe(page, '.OV_stream.local'); @@ -132,7 +132,7 @@ test.describe('Room Functionality Tests', () => { test.describe('Screen Sharing', () => { test('should be able to share and stop screen sharing', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); await waitForElementInIframe(page, '#toolbar'); @@ -169,7 +169,7 @@ test.describe('Room Functionality Tests', () => { test.describe('UI Panels and Components', () => { test('should show and interact with chat panel', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Open chat panel await waitForElementInIframe(page, '#chat-panel-btn'); @@ -205,7 +205,7 @@ test.describe('Room Functionality Tests', () => { }); test('should show participants panel', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Open participants panel await waitForElementInIframe(page, '#participants-panel-btn'); @@ -219,7 +219,7 @@ test.describe('Room Functionality Tests', () => { }); test('should show settings panel', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); await openMoreOptionsMenu(page); @@ -240,7 +240,7 @@ test.describe('Room Functionality Tests', () => { test.describe('Advanced Features', () => { test('should apply virtual background and detect visual changes', async ({ page }) => { - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Wait for video element to be ready await waitForElementInIframe(page, '.OV_video-element'); diff --git a/frontend/webcomponent/tests/e2e/recording-access.test.ts b/frontend/webcomponent/tests/e2e/recording-access.test.ts index 954545e..8d22a2e 100644 --- a/frontend/webcomponent/tests/e2e/recording-access.test.ts +++ b/frontend/webcomponent/tests/e2e/recording-access.test.ts @@ -92,7 +92,7 @@ test.describe('Recording Access Tests', () => { await waitForElementInIframe(page, '#view-recordings-btn', { state: 'hidden' }); }); - test('should publisher not be able to access recording when access level is set to admin', async ({ page }) => { + test('should speaker not be able to access recording when access level is set to admin', async ({ page }) => { await updateRoomPreferences( roomId, { @@ -108,7 +108,7 @@ test.describe('Recording Access Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await accessRoomAs('publisher', page); + await accessRoomAs('speaker', page); await waitForElementInIframe(page, '#view-recordings-btn', { state: 'hidden' }); }); @@ -134,7 +134,7 @@ test.describe('Recording Access Tests', () => { await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); }); - test('should publisher not be able to access recording when access level is set to moderator', async ({ page }) => { + test('should speaker not be able to access recording when access level is set to moderator', async ({ page }) => { await updateRoomPreferences( roomId, { @@ -150,12 +150,12 @@ test.describe('Recording Access Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await accessRoomAs('publisher', page); + await accessRoomAs('speaker', page); await waitForElementInIframe(page, '#view-recordings-btn', { state: 'hidden' }); }); - test('should allow moderators to access recording when access level is set to publisher', async ({ page }) => { + test('should allow moderators to access recording when access level is set to speaker', async ({ page }) => { await updateRoomPreferences( roomId, { @@ -176,14 +176,14 @@ test.describe('Recording Access Tests', () => { await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); }); - test('should allow publisher to access recording when access level is set to publisher', async ({ page }) => { + test('should allow speaker to access recording when access level is set to speaker', async ({ page }) => { await updateRoomPreferences( roomId, { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -192,7 +192,7 @@ test.describe('Recording Access Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await viewRecordingsAs('publisher', page); + await viewRecordingsAs('speaker', page); await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); }); diff --git a/frontend/webcomponent/tests/e2e/ui-feature-preferences.test.ts b/frontend/webcomponent/tests/e2e/ui-feature-preferences.test.ts index 0971d15..1d70382 100644 --- a/frontend/webcomponent/tests/e2e/ui-feature-preferences.test.ts +++ b/frontend/webcomponent/tests/e2e/ui-feature-preferences.test.ts @@ -79,7 +79,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -88,7 +88,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Check that chat button is visible const chatButton = await waitForElementInIframe(page, '#chat-panel-btn', { state: 'visible' }); @@ -103,7 +103,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: false }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -112,7 +112,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Check that chat button is not visible const chatButton = await waitForElementInIframe(page, '#chat-panel-btn', { state: 'hidden' }); @@ -132,7 +132,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -159,14 +159,14 @@ test.describe('UI Feature Preferences Tests', () => { await leaveRoom(page, 'moderator'); }); - test('should not show recording button for publisher', async ({ page }) => { + test('should not show recording button for speaker', async ({ page }) => { await updateRoomPreferences( roomId, { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -175,9 +175,9 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); - // Check that recording button is not visible for publisher + // Check that recording button is not visible for speaker const recordingButton = await waitForElementInIframe(page, '#recording-btn', { state: 'hidden' }); await expect(recordingButton).toBeHidden(); await leaveRoom(page); @@ -191,7 +191,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -232,7 +232,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -241,7 +241,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Click more options to reveal virtual background button await openMoreOptionsMenu(page); @@ -261,7 +261,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: false } }, @@ -270,7 +270,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); // Click more options to reveal virtual background button await openMoreOptionsMenu(page); @@ -290,7 +290,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: true } }, @@ -299,7 +299,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.goto(MEET_TESTAPP_URL); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); await applyVirtualBackground(page, '2'); await waitForVirtualBackgroundToApply(page); @@ -311,7 +311,7 @@ test.describe('UI Feature Preferences Tests', () => { chatPreferences: { enabled: true }, recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, virtualBackgroundPreferences: { enabled: false } }, @@ -323,7 +323,7 @@ test.describe('UI Feature Preferences Tests', () => { await page.reload(); await prepareForJoiningRoom(page, MEET_TESTAPP_URL, roomId); - await joinRoomAs('publisher', participantName, page); + await joinRoomAs('speaker', participantName, page); await page.waitForTimeout(2000); const isVBApplied = await isVirtualBackgroundApplied(page); diff --git a/frontend/webcomponent/tests/helpers/function-helpers.ts b/frontend/webcomponent/tests/helpers/function-helpers.ts index 08ba9b1..8db9931 100644 --- a/frontend/webcomponent/tests/helpers/function-helpers.ts +++ b/frontend/webcomponent/tests/helpers/function-helpers.ts @@ -92,7 +92,7 @@ export async function interactWithElementInIframe( const getDefaultRoomPreferences = (): MeetRoomPreferences => ({ recordingPreferences: { enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, chatPreferences: { enabled: true }, virtualBackgroundPreferences: { enabled: true } @@ -222,10 +222,10 @@ export const prepareForJoiningRoom = async (page: Page, url: string, roomId: str await page.waitForSelector(`#${roomId}`); await page.click('.dropdown-button'); await page.waitForSelector('#join-as-moderator'); - await page.waitForSelector('#join-as-publisher'); + await page.waitForSelector('#join-as-speaker'); }; -export const joinRoomAs = async (role: 'moderator' | 'publisher', pName: string, page: Page) => { +export const joinRoomAs = async (role: 'moderator' | 'speaker', pName: string, page: Page) => { await page.click('#join-as-' + role); const component = page.locator('openvidu-meet'); await expect(component).toBeVisible(); @@ -244,13 +244,13 @@ export const joinRoomAs = async (role: 'moderator' | 'publisher', pName: string, await waitForElementInIframe(page, 'ov-session', { state: 'visible' }); }; -export const accessRoomAs = async (role: 'moderator' | 'publisher', page: Page) => { +export const accessRoomAs = async (role: 'moderator' | 'speaker', page: Page) => { await page.click('#join-as-' + role); const component = page.locator('openvidu-meet'); await expect(component).toBeVisible(); }; -export const viewRecordingsAs = async (role: 'moderator' | 'publisher', page: Page) => { +export const viewRecordingsAs = async (role: 'moderator' | 'speaker', page: Page) => { await page.click('#join-as-' + role); const component = page.locator('openvidu-meet'); await expect(component).toBeVisible(); @@ -258,7 +258,7 @@ export const viewRecordingsAs = async (role: 'moderator' | 'publisher', page: Pa await interactWithElementInIframe(page, '#view-recordings-btn', { action: 'click' }); }; -export const leaveRoom = async (page: Page, role: 'moderator' | 'publisher' = 'publisher') => { +export const leaveRoom = async (page: Page, role: 'moderator' | 'speaker' = 'speaker') => { const button = await waitForElementInIframe(page, '#leave-btn'); await button.click(); diff --git a/frontend/webcomponent/tests/unit/lifecycle.test.ts b/frontend/webcomponent/tests/unit/lifecycle.test.ts index eead60d..704c309 100644 --- a/frontend/webcomponent/tests/unit/lifecycle.test.ts +++ b/frontend/webcomponent/tests/unit/lifecycle.test.ts @@ -113,9 +113,7 @@ describe('OpenViduMeet Event Handling', () => { // Set attributes const roomUrl = 'https://example.com/room/testRoom-123?secret=123456'; component.setAttribute('room-url', roomUrl); - component.setAttribute('user', 'testUser'); - component.setAttribute('role', 'publisher'); - component.setAttribute('token', 'test-token'); + component.setAttribute('participant-name', 'testUser'); // Trigger update (component as any).updateIframeSrc(); @@ -125,8 +123,6 @@ describe('OpenViduMeet Event Handling', () => { const src = iframe?.src; expect(src).toContain(roomUrl); - expect(src).toContain('user=testUser'); - expect(src).toContain('role=publisher'); - expect(src).toContain('token=test-token'); + expect(src).toContain('participant-name=testUser'); }); }); diff --git a/testapp/public/views/index.mustache b/testapp/public/views/index.mustache index a2a024d..7daabd8 100644 --- a/testapp/public/views/index.mustache +++ b/testapp/public/views/index.mustache @@ -91,21 +91,21 @@ @@ -271,8 +271,8 @@ - diff --git a/testapp/src/controllers/homeController.ts b/testapp/src/controllers/homeController.ts index b3ca306..68fd3f6 100644 --- a/testapp/src/controllers/homeController.ts +++ b/testapp/src/controllers/homeController.ts @@ -26,7 +26,10 @@ export const getHome = async (_req: Request, res: Response) => { apiUrl: process.env.MEET_API_URL || 'http://localhost:6080/api/v1', apiKey: process.env.MEET_API_KEY || 'meet-api-key' }); - res.status(500).send('Internal Server Error - Failed to fetch rooms: ' + (error instanceof Error ? error.message : 'Unknown error')); + res.status(500).send( + 'Internal Server Error - Failed to fetch rooms: ' + + (error instanceof Error ? error.message : 'Unknown error') + ); return; } }; @@ -50,7 +53,10 @@ export const postCreateRoom = async (req: Request, res: Response) => { stack: error instanceof Error ? error.stack : 'No stack trace', requestBody: req.body }); - res.status(500).send('Internal Server Error - Failed to create room: ' + (error instanceof Error ? error.message : 'Unknown error')); + res.status(500).send( + 'Internal Server Error - Failed to create room: ' + + (error instanceof Error ? error.message : 'Unknown error') + ); return; } }; @@ -77,7 +83,10 @@ export const deleteRoomCtrl = async (req: Request, res: Response) => { stack: error instanceof Error ? error.stack : 'No stack trace', requestBody: req.body }); - res.status(500).send('Internal Server Error - Failed to delete room: ' + (error instanceof Error ? error.message : 'Unknown error')); + res.status(500).send( + 'Internal Server Error - Failed to delete room: ' + + (error instanceof Error ? error.message : 'Unknown error') + ); return; } }; @@ -105,7 +114,10 @@ export const deleteAllRoomsCtrl = async (_req: Request, res: Response) => { message: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : 'No stack trace' }); - res.status(500).send('Internal Server Error - Failed to delete all rooms: ' + (error instanceof Error ? error.message : 'Unknown error')); + res.status(500).send( + 'Internal Server Error - Failed to delete all rooms: ' + + (error instanceof Error ? error.message : 'Unknown error') + ); return; } }; @@ -133,7 +145,10 @@ export const deleteAllRecordingsCtrl = async (_req: Request, res: Response) => { message: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : 'No stack trace' }); - res.status(500).send('Internal Server Error - Failed to delete all recordings: ' + (error instanceof Error ? error.message : 'Unknown error')); + res.status(500).send( + 'Internal Server Error - Failed to delete all recordings: ' + + (error instanceof Error ? error.message : 'Unknown error') + ); return; } }; @@ -150,7 +165,7 @@ const processFormPreferences = (body: any): any => { enabled: body['preferences.recordingPreferences.enabled'] === 'on', // Only include allowAccessTo if recording is enabled ...(body['preferences.recordingPreferences.enabled'] === 'on' && { - allowAccessTo: body['preferences.recordingPreferences.allowAccessTo'] || 'admin-moderator-publisher' + allowAccessTo: body['preferences.recordingPreferences.allowAccessTo'] || 'admin-moderator-speaker' }) }, virtualBackgroundPreferences: { diff --git a/typings/src/participant.ts b/typings/src/participant.ts index ff44864..c12e844 100644 --- a/typings/src/participant.ts +++ b/typings/src/participant.ts @@ -32,5 +32,5 @@ export interface ParticipantPermissions { */ export const enum ParticipantRole { MODERATOR = 'moderator', - PUBLISHER = 'publisher' + SPEAKER = 'speaker' } diff --git a/typings/src/room-preferences.ts b/typings/src/room-preferences.ts index 7218c91..9fb0d1b 100644 --- a/typings/src/room-preferences.ts +++ b/typings/src/room-preferences.ts @@ -2,29 +2,29 @@ * Interface representing the preferences for a room. */ export interface MeetRoomPreferences { - chatPreferences: MeetChatPreferences; - recordingPreferences: MeetRecordingPreferences; - virtualBackgroundPreferences: MeetVirtualBackgroundPreferences; + chatPreferences: MeetChatPreferences; + recordingPreferences: MeetRecordingPreferences; + virtualBackgroundPreferences: MeetVirtualBackgroundPreferences; } /** * Interface representing the preferences for recording. */ export interface MeetRecordingPreferences { - enabled: boolean; - allowAccessTo?: MeetRecordingAccess; + enabled: boolean; + allowAccessTo?: MeetRecordingAccess; } export const enum MeetRecordingAccess { - ADMIN = 'admin', // Only admins can access the recording - ADMIN_MODERATOR = 'admin-moderator', // Admins and moderators can access - ADMIN_MODERATOR_PUBLISHER = 'admin-moderator-publisher', // Admins, moderators and publishers can access + ADMIN = 'admin', // Only admins can access the recording + ADMIN_MODERATOR = 'admin-moderator', // Admins and moderators can access + ADMIN_MODERATOR_SPEAKER = 'admin-moderator-speaker' // Admins, moderators and speakers can access } export interface MeetChatPreferences { - enabled: boolean; + enabled: boolean; } export interface MeetVirtualBackgroundPreferences { - enabled: boolean; + enabled: boolean; } diff --git a/typings/src/room.ts b/typings/src/room.ts index 792875d..d707081 100644 --- a/typings/src/room.ts +++ b/typings/src/room.ts @@ -21,7 +21,7 @@ export interface MeetRoom extends BaseRoomOptions { roomName: string; creationDate: number; moderatorRoomUrl: string; - publisherRoomUrl: string; + speakerRoomUrl: string; markedForDeletion?: boolean; } diff --git a/typings/src/webcomponent/properties.model.ts b/typings/src/webcomponent/properties.model.ts index bf7afec..7b39c89 100644 --- a/typings/src/webcomponent/properties.model.ts +++ b/typings/src/webcomponent/properties.model.ts @@ -1,27 +1,26 @@ export enum WebComponentProperty { + /** + * The OpenVidu Meet room URL to connect to (moderator or speaker url) + * @required This attribute is required unless `recording-url` is provided. + */ + ROOM_URL = 'room-url', + /** + * The URL of a recording to view. + * @required This attribute is required unless `room-url` is provided. + */ + RECORDING_URL = 'recording-url', + /** + * Display name for the local participant. + */ + PARTICIPANT_NAME = 'participant-name', - /** - * The OpenVidu Meet room URL to connect to (moderator or publisher url) - * @required This attribute is required unless `recording-url` is provided. - */ - ROOM_URL = 'room-url', - /** - * The URL of a recording to view. - * @required This attribute is required unless `room-url` is provided. - */ - RECORDING_URL = 'recording-url', - /** - * Display name for the local participant. - */ - PARTICIPANT_NAME = 'participant-name', - - /** - * URL to redirect to when leaving the meeting. - * Redirection occurs after the **`CLOSED` event** fires. - */ - LEAVE_REDIRECT_URL = 'leave-redirect-url', - /** - * Whether to show only recordings instead of live meetings. - */ - SHOW_ONLY_RECORDINGS = 'show-only-recordings' + /** + * URL to redirect to when leaving the meeting. + * Redirection occurs after the **`CLOSED` event** fires. + */ + LEAVE_REDIRECT_URL = 'leave-redirect-url', + /** + * Whether to show only recordings instead of live meetings. + */ + SHOW_ONLY_RECORDINGS = 'show-only-recordings' }