Rename room preferences to room config

This commit is contained in:
juancarmore 2025-09-10 00:22:11 +02:00
parent 686af46102
commit 40742d22f8
61 changed files with 745 additions and 773 deletions

View File

@ -0,0 +1,16 @@
description: New room config
content:
application/json:
schema:
type: object
properties:
config:
$ref: '../schemas/meet-room-config.yaml#/MeetRoomConfig'
example:
config:
chatConfig:
enabled: true
recordingConfig:
enabled: false
virtualBackgroundConfig:
enabled: true

View File

@ -1,16 +0,0 @@
description: New room preferences
content:
application/json:
schema:
type: object
properties:
preferences:
$ref: '../schemas/meet-room-preferences.yaml#/MeetRoomPreferences'
example:
preferences:
chatPreferences:
enabled: true
recordingPreferences:
enabled: false
virtualBackgroundPreferences:
enabled: true

View File

@ -0,0 +1,5 @@
description: Success response for retrieving the room config
content:
application/json:
schema:
$ref: '../schemas/meet-room-config.yaml#/MeetRoomConfig'

View File

@ -1,5 +0,0 @@
description: Success response for retrieving the room preferences
content:
application/json:
schema:
$ref: '../schemas/meet-room-preferences.yaml#/MeetRoomPreferences'

View File

@ -14,12 +14,12 @@ content:
autoDeletionPolicy: autoDeletionPolicy:
withMeeting: when_meeting_ends withMeeting: when_meeting_ends
withRecordings: close withRecordings: close
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'
@ -31,19 +31,19 @@ content:
value: value:
roomId: 'room-123' roomId: 'room-123'
fields=roomId,roomName,creationDate,autoDeletionDate,preferences: fields=roomId,roomName,creationDate,autoDeletionDate,config:
summary: Room details with roomId, roomName, creationDate, autoDeletionDate, and preferences summary: Room details with roomId, roomName, creationDate, autoDeletionDate, and config
value: value:
roomId: 'room-123' roomId: 'room-123'
roomName: 'room' roomName: 'room'
creationDate: 1620000000000 creationDate: 1620000000000
autoDeletionDate: 1900000000000 autoDeletionDate: 1900000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
fields=moderatorUrl,speakerUrl: fields=moderatorUrl,speakerUrl:

View File

@ -23,12 +23,12 @@ content:
autoDeletionPolicy: autoDeletionPolicy:
withMeeting: when_meeting_ends withMeeting: when_meeting_ends
withRecordings: close withRecordings: close
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'
@ -41,12 +41,12 @@ content:
autoDeletionPolicy: autoDeletionPolicy:
withMeeting: when_meeting_ends withMeeting: when_meeting_ends
withRecordings: close withRecordings: close
preferences: config:
chatPreferences: chatConfig:
enabled: false enabled: false
recordingPreferences: recordingConfig:
enabled: true enabled: true
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: false enabled: false
moderatorUrl: 'http://localhost:6080/room/room-456?secret=789012' moderatorUrl: 'http://localhost:6080/room/room-456?secret=789012'
speakerUrl: 'http://localhost:6080/room/room-456?secret=210987' speakerUrl: 'http://localhost:6080/room/room-456?secret=210987'
@ -65,31 +65,31 @@ content:
isTruncated: false isTruncated: false
maxItems: 10 maxItems: 10
fields=roomId,roomName,creationDate,autoDeletionDate,preferences: fields=roomId,roomName,creationDate,autoDeletionDate,config:
summary: Room details including preferences but no URLs summary: Room details including config but no URLs
value: value:
rooms: rooms:
- roomId: 'room-123' - roomId: 'room-123'
roomName: 'room' roomName: 'room'
creationDate: 1620000000000 creationDate: 1620000000000
autoDeletionDate: 1900000000000 autoDeletionDate: 1900000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
- roomId: 'room-456' - roomId: 'room-456'
roomName: 'room' roomName: 'room'
creationDate: 1620001000000 creationDate: 1620001000000
autoDeletionDate: 1900000000000 autoDeletionDate: 1900000000000
preferences: config:
chatPreferences: chatConfig:
enabled: false enabled: false
recordingPreferences: recordingConfig:
enabled: true enabled: true
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: false enabled: false
pagination: pagination:
isTruncated: true isTruncated: true

View File

@ -40,12 +40,12 @@ content:
roomId: room-123 roomId: room-123
roomName: room roomName: room
creationDate: 1620000000000 creationDate: 1620000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'
@ -63,12 +63,12 @@ content:
roomId: room-123 roomId: room-123
roomName: room roomName: room
creationDate: 1620000000000 creationDate: 1620000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'

View File

@ -25,12 +25,12 @@ content:
roomId: room-123 roomId: room-123
roomName: room roomName: room
creationDate: 1620000000000 creationDate: 1620000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'
@ -44,12 +44,12 @@ content:
roomId: room-123 roomId: room-123
roomName: room roomName: room
creationDate: 1620000000000 creationDate: 1620000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'
@ -63,12 +63,12 @@ content:
roomId: room-123 roomId: room-123
roomName: room roomName: room
creationDate: 1620000000000 creationDate: 1620000000000
preferences: config:
chatPreferences: chatConfig:
enabled: true enabled: true
recordingPreferences: recordingConfig:
enabled: false enabled: false
virtualBackgroundPreferences: virtualBackgroundConfig:
enabled: true enabled: true
moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456' moderatorUrl: 'http://localhost:6080/room/room-123?secret=123456'
speakerUrl: 'http://localhost:6080/room/room-123?secret=654321' speakerUrl: 'http://localhost:6080/room/room-123?secret=654321'

View File

@ -1,4 +1,4 @@
description: Success response for updating room preferences description: Success response for updating room config
content: content:
application/json: application/json:
schema: schema:
@ -7,4 +7,4 @@ content:
message: message:
type: string type: string
example: example:
message: Room preferences for room 'room-123' updated successfully message: Room config for room 'room-123' updated successfully

View File

@ -1,16 +1,16 @@
MeetRoomPreferences: MeetRoomConfig:
type: object type: object
properties: properties:
chatPreferences: chatConfig:
$ref: '#/MeetChatPreferences' $ref: '#/MeetChatConfig'
description: Preferences for the chat feature in the room. description: Config for the chat feature in the room.
recordingPreferences: recordingConfig:
$ref: '#/MeetRecordingPreferences' $ref: '#/MeetRecordingConfig'
description: Preferences for recording the room. description: Config for recording the room.
virtualBackgroundPreferences: virtualBackgroundConfig:
$ref: '#/MeetVirtualBackgroundPreferences' $ref: '#/MeetVirtualBackgroundConfig'
description: Preferences for virtual background in the room. description: Config for virtual background in the room.
MeetChatPreferences: MeetChatConfig:
type: object type: object
properties: properties:
enabled: enabled:
@ -18,7 +18,7 @@ MeetChatPreferences:
default: true default: true
example: true example: true
description: If true, the room will be allowed to send and receive chat messages. description: If true, the room will be allowed to send and receive chat messages.
MeetRecordingPreferences: MeetRecordingConfig:
type: object type: object
properties: properties:
enabled: enabled:
@ -39,7 +39,7 @@ MeetRecordingPreferences:
- `admin`: Only administrators can access the recording. - `admin`: Only administrators can access the recording.
- `admin_moderator`: Administrators and moderators can access the recording. - `admin_moderator`: Administrators and moderators can access the recording.
- `admin_moderator_speaker`: Administrators, moderators and speakers can access the recording. - `admin_moderator_speaker`: Administrators, moderators and speakers can access the recording.
MeetVirtualBackgroundPreferences: MeetVirtualBackgroundConfig:
type: object type: object
properties: properties:
enabled: enabled:

View File

@ -54,7 +54,7 @@ properties:
# description: > # description: >
# The maximum number of participants allowed in the room. If the number of participants exceeds # 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. # this limit, new participants will not be allowed to join.
preferences: config:
$ref: './meet-room-preferences.yaml#/MeetRoomPreferences' $ref: './meet-room-config.yaml#/MeetRoomConfig'
description: > description: >
The preferences for the room. These preferences will be used to configure the room's settings. The config for the room. These config will be used to configure the room's settings.

View File

@ -58,9 +58,9 @@ properties:
Policy for automatic deletion when the room has recordings. Options are: Policy for automatic deletion when the room has recordings. Options are:
- force: The room and its recordings will be deleted. - force: The room and its recordings will be deleted.
- close: The room will be closed instead of deleted, maintaining its recordings. - close: The room will be closed instead of deleted, maintaining its recordings.
preferences: config:
$ref: meet-room-preferences.yaml#/MeetRoomPreferences $ref: meet-room-config.yaml#/MeetRoomConfig
description: The preferences for the room. description: The config for the room.
# maxParticipants: # maxParticipants:
# type: integer # type: integer
# example: 10 # example: 10

View File

@ -13,8 +13,8 @@ paths:
$ref: './paths/rooms.yaml#/~1rooms' $ref: './paths/rooms.yaml#/~1rooms'
/rooms/{roomId}: /rooms/{roomId}:
$ref: './paths/rooms.yaml#/~1rooms~1{roomId}' $ref: './paths/rooms.yaml#/~1rooms~1{roomId}'
/rooms/{roomId}/preferences: /rooms/{roomId}/config:
$ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1preferences' $ref: './paths/rooms.yaml#/~1rooms~1{roomId}~1config'
/recordings: /recordings:
$ref: './paths/recordings.yaml#/~1recordings' $ref: './paths/recordings.yaml#/~1recordings'
/recordings/download: /recordings/download:
@ -33,8 +33,8 @@ components:
$ref: components/schemas/meet-room.yaml $ref: components/schemas/meet-room.yaml
MeetRoomOptions: MeetRoomOptions:
$ref: components/schemas/meet-room-options.yaml $ref: components/schemas/meet-room-options.yaml
MeetRoomPreferences: MeetRoomConfig:
$ref: './components/schemas/meet-room-preferences.yaml#/MeetRoomPreferences' $ref: './components/schemas/meet-room-config.yaml#/MeetRoomConfig'
MeetRecording: MeetRecording:
$ref: components/schemas/meet-recording.yaml $ref: components/schemas/meet-recording.yaml
Error: Error:

View File

@ -63,8 +63,8 @@ components:
$ref: components/schemas/meet-room.yaml $ref: components/schemas/meet-room.yaml
MeetRoomOptions: MeetRoomOptions:
$ref: components/schemas/meet-room-options.yaml $ref: components/schemas/meet-room-options.yaml
MeetRoomPreferences: MeetRoomConfig:
$ref: components/schemas/meet-room-preferences.yaml#/MeetRoomPreferences $ref: components/schemas/meet-room-config.yaml#/MeetRoomConfig
MeetRoomRoleAndPermissions: MeetRoomRoleAndPermissions:
$ref: components/schemas/internal/meet-room-role-permissions.yaml $ref: components/schemas/internal/meet-room-role-permissions.yaml
MeetRecording: MeetRecording:

View File

@ -151,12 +151,12 @@
$ref: '../components/responses/validation-error.yaml' $ref: '../components/responses/validation-error.yaml'
'500': '500':
$ref: '../components/responses/internal-server-error.yaml' $ref: '../components/responses/internal-server-error.yaml'
/rooms/{roomId}/preferences: /rooms/{roomId}/config:
get: get:
operationId: getRoomPreferences operationId: getRoomConfig
summary: Get room preferences summary: Get room config
description: > description: >
Retrieves the preferences of an OpenVidu Meet room with the specified room ID. Retrieves the config of an OpenVidu Meet room with the specified room ID.
tags: tags:
- OpenVidu Meet - Rooms - OpenVidu Meet - Rooms
security: security:
@ -168,7 +168,7 @@
- $ref: '../components/parameters/internal/x-participant-role.yaml' - $ref: '../components/parameters/internal/x-participant-role.yaml'
responses: responses:
'200': '200':
$ref: '../components/responses/success-get-room-preferences.yaml' $ref: '../components/responses/success-get-room-config.yaml'
'400': '400':
$ref: '../components/responses/internal/error-invalid-participant-role.yaml' $ref: '../components/responses/internal/error-invalid-participant-role.yaml'
'401': '401':
@ -182,10 +182,10 @@
'500': '500':
$ref: '../components/responses/internal-server-error.yaml' $ref: '../components/responses/internal-server-error.yaml'
put: put:
operationId: updateRoomPreferences operationId: updateRoomConfig
summary: Update room preferences summary: Update room config
description: > description: >
Updates the preferences of an OpenVidu Meet room with the specified room ID. Updates the config of an OpenVidu Meet room with the specified room ID.
tags: tags:
- OpenVidu Meet - Rooms - OpenVidu Meet - Rooms
security: security:
@ -194,10 +194,10 @@
parameters: parameters:
- $ref: '../components/parameters/room-id-path.yaml' - $ref: '../components/parameters/room-id-path.yaml'
requestBody: requestBody:
$ref: '../components/requestBodies/update-room-preferences-request.yaml' $ref: '../components/requestBodies/update-room-config-request.yaml'
responses: responses:
'200': '200':
$ref: '../components/responses/success-update-room-preferences.yaml' $ref: '../components/responses/success-update-room-config.yaml'
'401': '401':
$ref: '../components/responses/unauthorized-error.yaml' $ref: '../components/responses/unauthorized-error.yaml'
'403': '403':

View File

@ -128,34 +128,34 @@ export const bulkDeleteRooms = async (req: Request, res: Response) => {
} }
}; };
export const getRoomPreferences = async (req: Request, res: Response) => { export const getRoomConfig = async (req: Request, res: Response) => {
const logger = container.get(LoggerService); const logger = container.get(LoggerService);
const roomService = container.get(RoomService); const roomService = container.get(RoomService);
const { roomId } = req.params; const { roomId } = req.params;
logger.verbose(`Getting room preferences for room '${roomId}'`); logger.verbose(`Getting room config for room '${roomId}'`);
try { try {
const { preferences } = await roomService.getMeetRoom(roomId); const { config } = await roomService.getMeetRoom(roomId);
return res.status(200).json(preferences); return res.status(200).json(config);
} catch (error) { } catch (error) {
handleError(res, error, `getting room preferences for room '${roomId}'`); handleError(res, error, `getting room config for room '${roomId}'`);
} }
}; };
export const updateRoomPreferences = async (req: Request, res: Response) => { export const updateRoomConfig = async (req: Request, res: Response) => {
const logger = container.get(LoggerService); const logger = container.get(LoggerService);
const roomService = container.get(RoomService); const roomService = container.get(RoomService);
const { preferences } = req.body; const { config } = req.body;
const { roomId } = req.params; const { roomId } = req.params;
logger.verbose(`Updating room preferences for room '${roomId}'`); logger.verbose(`Updating room config for room '${roomId}'`);
try { try {
await roomService.updateMeetRoomPreferences(roomId, preferences); await roomService.updateMeetRoomConfig(roomId, config);
return res.status(200).json({ message: `Room preferences for room '${roomId}' updated successfully` }); return res.status(200).json({ message: `Room config for room '${roomId}' updated successfully` });
} catch (error) { } catch (error) {
handleError(res, error, `updating room preferences for room '${roomId}'`); handleError(res, error, `updating room config for room '${roomId}'`);
} }
}; };

View File

@ -17,7 +17,7 @@ export class MeetRoomHelper {
roomName: room.roomName, roomName: room.roomName,
autoDeletionDate: room.autoDeletionDate, autoDeletionDate: room.autoDeletionDate,
autoDeletionPolicy: room.autoDeletionPolicy, autoDeletionPolicy: room.autoDeletionPolicy,
preferences: room.preferences config: room.config
// maxParticipants: room.maxParticipants // maxParticipants: room.maxParticipants
}; };
} }

View File

@ -27,7 +27,7 @@ export const withRecordingEnabled = async (req: Request, res: Response, next: Ne
const roomId = extractRoomIdFromRequest(req); const roomId = extractRoomIdFromRequest(req);
const room: MeetRoom = await roomService.getMeetRoom(roomId!); const room: MeetRoom = await roomService.getMeetRoom(roomId!);
if (!room.preferences?.recordingPreferences?.enabled) { if (!room.config?.recordingConfig?.enabled) {
logger.debug(`Recording is disabled for room '${roomId}'`); logger.debug(`Recording is disabled for room '${roomId}'`);
const error = errorRecordingDisabled(roomId!); const error = errorRecordingDisabled(roomId!);
return rejectRequestFromMeetError(res, error); return rejectRequestFromMeetError(res, error);
@ -35,7 +35,7 @@ export const withRecordingEnabled = async (req: Request, res: Response, next: Ne
return next(); return next();
} catch (error) { } catch (error) {
handleError(res, error, 'checking recording preferences'); handleError(res, error, 'checking recording config');
} }
}; };

View File

@ -1,15 +1,15 @@
import { import {
MeetChatPreferences, MeetChatConfig,
MeetRecordingAccess, MeetRecordingAccess,
MeetRecordingPreferences, MeetRecordingConfig,
MeetRoomAutoDeletionPolicy, MeetRoomAutoDeletionPolicy,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings, MeetRoomDeletionPolicyWithRecordings,
MeetRoomFilters, MeetRoomFilters,
MeetRoomOptions, MeetRoomOptions,
MeetRoomPreferences,
MeetRoomStatus, MeetRoomStatus,
MeetVirtualBackgroundPreferences, MeetVirtualBackgroundConfig,
ParticipantRole, ParticipantRole,
RecordingPermissions RecordingPermissions
} from '@typings-ce'; } from '@typings-ce';
@ -65,7 +65,7 @@ const RecordingAccessSchema: z.ZodType<MeetRecordingAccess> = z.enum([
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
]); ]);
const RecordingPreferencesSchema: z.ZodType<MeetRecordingPreferences> = z const RecordingConfigSchema: z.ZodType<MeetRecordingConfig> = z
.object({ .object({
enabled: z.boolean(), enabled: z.boolean(),
allowAccessTo: RecordingAccessSchema.optional() allowAccessTo: RecordingAccessSchema.optional()
@ -81,18 +81,18 @@ const RecordingPreferencesSchema: z.ZodType<MeetRecordingPreferences> = z
} }
); );
const ChatPreferencesSchema: z.ZodType<MeetChatPreferences> = z.object({ const ChatConfigSchema: z.ZodType<MeetChatConfig> = z.object({
enabled: z.boolean() enabled: z.boolean()
}); });
const VirtualBackgroundPreferencesSchema: z.ZodType<MeetVirtualBackgroundPreferences> = z.object({ const VirtualBackgroundConfigSchema: z.ZodType<MeetVirtualBackgroundConfig> = z.object({
enabled: z.boolean() enabled: z.boolean()
}); });
const RoomPreferencesSchema: z.ZodType<MeetRoomPreferences> = z.object({ const RoomConfigSchema: z.ZodType<MeetRoomConfig> = z.object({
recordingPreferences: RecordingPreferencesSchema, recordingConfig: RecordingConfigSchema,
chatPreferences: ChatPreferencesSchema, chatConfig: ChatConfigSchema,
virtualBackgroundPreferences: VirtualBackgroundPreferencesSchema virtualBackgroundConfig: VirtualBackgroundConfigSchema
}); });
const RoomDeletionPolicyWithMeetingSchema: z.ZodType<MeetRoomDeletionPolicyWithMeeting> = z.enum([ const RoomDeletionPolicyWithMeetingSchema: z.ZodType<MeetRoomDeletionPolicyWithMeeting> = z.enum([
@ -150,10 +150,10 @@ const RoomRequestOptionsSchema: z.ZodType<MeetRoomOptions> = z.object({
path: ['withRecordings'] path: ['withRecordings']
} }
), ),
preferences: RoomPreferencesSchema.optional().default({ config: RoomConfigSchema.optional().default({
recordingPreferences: { enabled: true, allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER }, recordingConfig: { enabled: true, allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}) })
// maxParticipants: z // maxParticipants: z
// .number() // .number()
@ -223,8 +223,8 @@ const BulkDeleteRoomsSchema = z.object({
withRecordings: RoomDeletionPolicyWithRecordingsSchema.optional().default(MeetRoomDeletionPolicyWithRecordings.FAIL) withRecordings: RoomDeletionPolicyWithRecordingsSchema.optional().default(MeetRoomDeletionPolicyWithRecordings.FAIL)
}); });
const UpdateRoomPreferencesSchema = z.object({ const UpdateRoomConfigSchema = z.object({
preferences: RoomPreferencesSchema config: RoomConfigSchema
}); });
const UpdateRoomStatusSchema = z.object({ const UpdateRoomStatusSchema = z.object({
@ -270,8 +270,8 @@ export const withValidRoomFiltersRequest = (req: Request, res: Response, next: N
next(); next();
}; };
export const withValidRoomPreferences = (req: Request, res: Response, next: NextFunction) => { export const withValidRoomConfig = (req: Request, res: Response, next: NextFunction) => {
const { success, error, data } = UpdateRoomPreferencesSchema.safeParse(req.body); const { success, error, data } = UpdateRoomConfigSchema.safeParse(req.body);
if (!success) { if (!success) {
return rejectUnprocessableRequest(res, error); return rejectUnprocessableRequest(res, error);

View File

@ -62,7 +62,7 @@ export const configureRecordingTokenAuth = async (req: Request, res: Response, n
throw errorRoomMetadataNotFound(roomId); throw errorRoomMetadataNotFound(roomId);
} }
const recordingAccess = room.preferences!.recordingPreferences.allowAccessTo; const recordingAccess = room.config!.recordingConfig.allowAccessTo;
if (!recordingAccess || recordingAccess === MeetRecordingAccess.ADMIN) { if (!recordingAccess || recordingAccess === MeetRecordingAccess.ADMIN) {
// Deny request if the room is configured to allow access to recordings only for admins // Deny request if the room is configured to allow access to recordings only for admins

View File

@ -11,11 +11,11 @@ import {
tokenAndRoleValidator, tokenAndRoleValidator,
withAuth, withAuth,
withValidRoomBulkDeleteRequest, withValidRoomBulkDeleteRequest,
withValidRoomConfig,
withValidRoomDeleteRequest, withValidRoomDeleteRequest,
withValidRoomFiltersRequest, withValidRoomFiltersRequest,
withValidRoomId, withValidRoomId,
withValidRoomOptions, withValidRoomOptions,
withValidRoomPreferences,
withValidRoomSecret, withValidRoomSecret,
withValidRoomStatus withValidRoomStatus
} from '../middlewares/index.js'; } from '../middlewares/index.js';
@ -59,18 +59,18 @@ roomRouter.delete(
); );
roomRouter.get( roomRouter.get(
'/:roomId/preferences', '/:roomId/config',
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN), participantTokenValidator), withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN), participantTokenValidator),
withValidRoomId, withValidRoomId,
configureRoomAuthorization, configureRoomAuthorization,
roomCtrl.getRoomPreferences roomCtrl.getRoomConfig
); );
roomRouter.put( roomRouter.put(
'/:roomId/preferences', '/:roomId/config',
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
withValidRoomId, withValidRoomId,
withValidRoomPreferences, withValidRoomConfig,
roomCtrl.updateRoomPreferences roomCtrl.updateRoomConfig
); );
roomRouter.put( roomRouter.put(

View File

@ -1,14 +1,14 @@
import { MeetRoom, MeetRecordingInfo, ParticipantRole } from '@typings-ce'; import { MeetRecordingInfo, MeetRoom, ParticipantRole } from '@typings-ce';
import { inject, injectable } from 'inversify'; import { inject, injectable } from 'inversify';
import { SendDataOptions } from 'livekit-server-sdk'; import { SendDataOptions } from 'livekit-server-sdk';
import { OpenViduComponentsAdapterHelper, OpenViduComponentsSignalPayload } from '../helpers/index.js'; import { OpenViduComponentsAdapterHelper, OpenViduComponentsSignalPayload } from '../helpers/index.js';
import { LiveKitService, LoggerService } from './index.js';
import { import {
MeetParticipantRoleUpdatedPayload, MeetParticipantRoleUpdatedPayload,
MeetRoomPreferencesUpdatedPayload, MeetRoomConfigUpdatedPayload,
MeetSignalPayload, MeetSignalPayload,
MeetSignalType MeetSignalType
} from '../typings/ce/event.model.js'; } from '../typings/ce/event.model.js';
import { LiveKitService, LoggerService } from './index.js';
/** /**
* Service responsible for all communication with the frontend * Service responsible for all communication with the frontend
@ -67,25 +67,25 @@ export class FrontendEventService {
} }
/** /**
* Sends a signal to notify participants in a room about updated room preferences. * Sends a signal to notify participants in a room about updated room config.
*/ */
async sendRoomPreferencesUpdatedSignal(roomId: string, updatedRoom: MeetRoom): Promise<void> { async sendRoomConfigUpdatedSignal(roomId: string, updatedRoom: MeetRoom): Promise<void> {
this.logger.debug(`Sending room preferences updated signal for room ${roomId}`); this.logger.debug(`Sending room config updated signal for room ${roomId}`);
try { try {
const payload: MeetRoomPreferencesUpdatedPayload = { const payload: MeetRoomConfigUpdatedPayload = {
roomId, roomId,
preferences: updatedRoom.preferences!, config: updatedRoom.config!,
timestamp: Date.now() timestamp: Date.now()
}; };
const options: SendDataOptions = { const options: SendDataOptions = {
topic: MeetSignalType.MEET_ROOM_PREFERENCES_UPDATED topic: MeetSignalType.MEET_ROOM_CONFIG_UPDATED
}; };
await this.sendSignal(roomId, payload, options); await this.sendSignal(roomId, payload, options);
} catch (error) { } catch (error) {
this.logger.error(`Error sending room preferences updated signal for room ${roomId}:`, error); this.logger.error(`Error sending room config updated signal for room ${roomId}:`, error);
} }
} }

View File

@ -2,13 +2,13 @@ import {
MeetingEndAction, MeetingEndAction,
MeetRecordingAccess, MeetRecordingAccess,
MeetRoom, MeetRoom,
MeetRoomConfig,
MeetRoomDeletionErrorCode, MeetRoomDeletionErrorCode,
MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings, MeetRoomDeletionPolicyWithRecordings,
MeetRoomDeletionSuccessCode, MeetRoomDeletionSuccessCode,
MeetRoomFilters, MeetRoomFilters,
MeetRoomOptions, MeetRoomOptions,
MeetRoomPreferences,
MeetRoomStatus, MeetRoomStatus,
ParticipantRole, ParticipantRole,
RecordingPermissions RecordingPermissions
@ -80,7 +80,7 @@ export class RoomService {
* *
*/ */
async createMeetRoom(baseUrl: string, roomOptions: MeetRoomOptions): Promise<MeetRoom> { async createMeetRoom(baseUrl: string, roomOptions: MeetRoomOptions): Promise<MeetRoom> {
const { roomName, autoDeletionDate, autoDeletionPolicy, preferences } = roomOptions; const { roomName, autoDeletionDate, autoDeletionPolicy, config } = roomOptions;
const roomIdPrefix = roomName!.replace(/\s+/g, ''); // Remove all spaces const roomIdPrefix = roomName!.replace(/\s+/g, ''); // Remove all spaces
const roomId = `${roomIdPrefix}-${uid(15)}`; // Generate a unique room ID based on the room name const roomId = `${roomIdPrefix}-${uid(15)}`; // Generate a unique room ID based on the room name
@ -91,7 +91,7 @@ export class RoomService {
// maxParticipants, // maxParticipants,
autoDeletionDate, autoDeletionDate,
autoDeletionPolicy, autoDeletionPolicy,
preferences: preferences!, config: config!,
moderatorUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}`, moderatorUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}`,
speakerUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}`, speakerUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}`,
status: MeetRoomStatus.OPEN, status: MeetRoomStatus.OPEN,
@ -135,21 +135,21 @@ export class RoomService {
} }
/** /**
* Updates the preferences of a specific meeting room. * Updates the config of a specific meeting room.
* *
* @param roomId - The unique identifier of the meeting room to update * @param roomId - The unique identifier of the meeting room to update
* @param preferences - The new preferences to apply to the meeting room * @param config - The new config to apply to the meeting room
* @returns A Promise that resolves to the updated MeetRoom object * @returns A Promise that resolves to the updated MeetRoom object
*/ */
async updateMeetRoomPreferences(roomId: string, preferences: MeetRoomPreferences): Promise<MeetRoom> { async updateMeetRoomConfig(roomId: string, config: MeetRoomConfig): Promise<MeetRoom> {
const room = await this.getMeetRoom(roomId); const room = await this.getMeetRoom(roomId);
room.preferences = preferences; room.config = config;
await this.storageService.saveMeetRoom(room); await this.storageService.saveMeetRoom(room);
// Update the archived room metadata if it exists // Update the archived room metadata if it exists
await Promise.all([ await Promise.all([
this.storageService.archiveRoomMetadata(roomId, true), this.storageService.archiveRoomMetadata(roomId, true),
this.frontendEventService.sendRoomPreferencesUpdatedSignal(roomId, room) this.frontendEventService.sendRoomConfigUpdatedSignal(roomId, room)
]); ]);
return room; return room;
} }
@ -684,7 +684,7 @@ export class RoomService {
} }
protected getRecordingPermissions(room: Partial<MeetRoom>, role: ParticipantRole): RecordingPermissions { protected getRecordingPermissions(room: Partial<MeetRoom>, role: ParticipantRole): RecordingPermissions {
const recordingAccess = room.preferences!.recordingPreferences.allowAccessTo; const recordingAccess = room.config!.recordingConfig.allowAccessTo;
// A participant can delete recordings if they are a moderator and the recording access is not set to admin // A participant can delete recordings if they are a moderator and the recording access is not set to admin
const canDeleteRecordings = role === ParticipantRole.MODERATOR && recordingAccess !== MeetRecordingAccess.ADMIN; const canDeleteRecordings = role === ParticipantRole.MODERATOR && recordingAccess !== MeetRecordingAccess.ADMIN;

View File

@ -269,7 +269,7 @@ export class MeetStorageService<
* Archives room metadata by storing essential room information in both cache and persistent storage. * Archives room metadata by storing essential room information in both cache and persistent storage.
* *
* This method retrieves the room data, extracts key metadata (moderator/speaker 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. * recording config), 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, * If `updateOnlyIfExists` is true, it will only save the archived metadata if it already exists,
* updating the existing entry. * updating the existing entry.
@ -302,8 +302,8 @@ export class MeetStorageService<
const archivedRoom: Partial<MRoom> = { const archivedRoom: Partial<MRoom> = {
moderatorUrl: room.moderatorUrl, moderatorUrl: room.moderatorUrl,
speakerUrl: room.speakerUrl, speakerUrl: room.speakerUrl,
preferences: { config: {
recordingPreferences: room.preferences?.recordingPreferences recordingConfig: room.config?.recordingConfig
} }
} as Partial<MRoom>; } as Partial<MRoom>;

View File

@ -9,9 +9,9 @@ import {
MeetRecordingStatus, MeetRecordingStatus,
MeetRoom, MeetRoom,
MeetRoomAutoDeletionPolicy, MeetRoomAutoDeletionPolicy,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings, MeetRoomDeletionPolicyWithRecordings,
MeetRoomPreferences,
MeetRoomStatus, MeetRoomStatus,
ParticipantPermissions, ParticipantPermissions,
ParticipantRole ParticipantRole
@ -93,22 +93,22 @@ export const expectSuccessRoomResponse = (
response: any, response: any,
roomName: string, roomName: string,
autoDeletionDate?: number, autoDeletionDate?: number,
preferences?: MeetRoomPreferences config?: MeetRoomConfig
) => { ) => {
expect(response.status).toBe(200); expect(response.status).toBe(200);
expectValidRoom(response.body, roomName, preferences, autoDeletionDate); expectValidRoom(response.body, roomName, config, autoDeletionDate);
}; };
export const expectSuccessRoomPreferencesResponse = (response: any, preferences: MeetRoomPreferences) => { export const expectSuccessRoomConfigResponse = (response: any, config: MeetRoomConfig) => {
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.body).toBeDefined(); expect(response.body).toBeDefined();
expect(response.body).toEqual(preferences); expect(response.body).toEqual(config);
}; };
export const expectValidRoom = ( export const expectValidRoom = (
room: MeetRoom, room: MeetRoom,
name: string, name: string,
preferences?: MeetRoomPreferences, config?: MeetRoomConfig,
autoDeletionDate?: number, autoDeletionDate?: number,
autoDeletionPolicy?: MeetRoomAutoDeletionPolicy, autoDeletionPolicy?: MeetRoomAutoDeletionPolicy,
status?: MeetRoomStatus, status?: MeetRoomStatus,
@ -140,18 +140,18 @@ export const expectValidRoom = (
}); });
} }
expect(room.preferences).toBeDefined(); expect(room.config).toBeDefined();
if (preferences !== undefined) { if (config !== undefined) {
expect(room.preferences).toEqual(preferences); expect(room.config).toEqual(config);
} else { } else {
expect(room.preferences).toEqual({ expect(room.config).toEqual({
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}); });
} }

View File

@ -243,34 +243,34 @@ export const getRoom = async (roomId: string, fields?: string, cookie?: string,
return await req; return await req;
}; };
export const getRoomPreferences = async (roomId: string) => { export const getRoomConfig = async (roomId: string) => {
checkAppIsRunning(); checkAppIsRunning();
return await request(app) return await request(app)
.get(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/preferences`) .get(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/config`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY) .set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY)
.send(); .send();
}; };
export const updateRoomPreferences = async (roomId: string, preferences: any) => { export const updateRoomConfig = async (roomId: string, config: any) => {
checkAppIsRunning(); checkAppIsRunning();
return await request(app) return await request(app)
.put(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/preferences`) .put(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}/config`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY) .set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY)
.send({ preferences }); .send({ config });
}; };
export const updateRecordingAccessPreferencesInRoom = async (roomId: string, recordingAccess: MeetRecordingAccess) => { export const updateRecordingAccessConfigInRoom = async (roomId: string, recordingAccess: MeetRecordingAccess) => {
const response = await updateRoomPreferences(roomId, { const response = await updateRoomConfig(roomId, {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: recordingAccess allowAccessTo: recordingAccess
}, },
chatPreferences: { chatConfig: {
enabled: true enabled: true
}, },
virtualBackgroundPreferences: { virtualBackgroundConfig: {
enabled: true enabled: true
} }
}); });
@ -297,11 +297,7 @@ export const deleteRoom = async (roomId: string, query: Record<string, any> = {}
return result; return result;
}; };
export const bulkDeleteRooms = async ( export const bulkDeleteRooms = async (roomIds: any[], withMeeting?: string, withRecordings?: string) => {
roomIds: any[],
withMeeting?: string,
withRecordings?: string
) => {
checkAppIsRunning(); checkAppIsRunning();
const result = await request(app) const result = await request(app)

View File

@ -2,7 +2,7 @@ import express, { Request, Response } from 'express';
import http from 'http'; import http from 'http';
import { StringValue } from 'ms'; import { StringValue } from 'ms';
import { MeetRoomHelper } from '../../src/helpers'; import { MeetRoomHelper } from '../../src/helpers';
import { MeetRoom, MeetRoomPreferences } from '../../src/typings/ce'; import { MeetRoom, MeetRoomConfig } from '../../src/typings/ce';
import { expectValidStartRecordingResponse } from './assertion-helpers'; import { expectValidStartRecordingResponse } from './assertion-helpers';
import { import {
createRoom, createRoom,
@ -35,17 +35,17 @@ export interface TestContext {
* *
* @param withParticipant Whether to join a fake participant in the room. * @param withParticipant Whether to join a fake participant in the room.
* @param roomName Name of the room to create. * @param roomName Name of the room to create.
* @param preferences Optional room preferences. * @param config Optional room config.
* @returns Room data including secrets and cookies. * @returns Room data including secrets and cookies.
*/ */
export const setupSingleRoom = async ( export const setupSingleRoom = async (
withParticipant = false, withParticipant = false,
roomName = 'TEST_ROOM', roomName = 'TEST_ROOM',
preferences?: MeetRoomPreferences config?: MeetRoomConfig
): Promise<RoomData> => { ): Promise<RoomData> => {
const room = await createRoom({ const room = await createRoom({
roomName, roomName,
preferences config
}); });
// Extract the room secrets and generate participant tokens, saved as cookies // Extract the room secrets and generate participant tokens, saved as cookies

View File

@ -73,7 +73,7 @@ describe('Recording API Tests', () => {
expect(archivedRoom).toBeDefined(); expect(archivedRoom).toBeDefined();
expect(archivedRoom?.moderatorUrl).toBeDefined(); expect(archivedRoom?.moderatorUrl).toBeDefined();
expect(archivedRoom?.speakerUrl).toBeDefined(); expect(archivedRoom?.speakerUrl).toBeDefined();
expect(archivedRoom?.preferences).toBeDefined(); expect(archivedRoom?.config).toBeDefined();
const secretsResponse = await stopRecording(recordingId, moderatorCookie); const secretsResponse = await stopRecording(recordingId, moderatorCookie);
expectValidStopRecordingResponse(secretsResponse, recordingId, room.roomId, room.roomName); expectValidStopRecordingResponse(secretsResponse, recordingId, room.roomId, room.roomName);

View File

@ -58,25 +58,19 @@ describe('Room API Tests', () => {
withMeeting: MeetRoomDeletionPolicyWithMeeting.FORCE, withMeeting: MeetRoomDeletionPolicyWithMeeting.FORCE,
withRecordings: MeetRoomDeletionPolicyWithRecordings.FORCE withRecordings: MeetRoomDeletionPolicyWithRecordings.FORCE
}, },
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
} }
}; };
const room = await createRoom(payload); const room = await createRoom(payload);
expectValidRoom( expectValidRoom(room, 'Example Room', payload.config, validAutoDeletionDate, payload.autoDeletionPolicy);
room,
'Example Room',
payload.preferences,
validAutoDeletionDate,
payload.autoDeletionPolicy
);
}); });
}); });
@ -180,7 +174,9 @@ describe('Room API Tests', () => {
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422); const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
expect(JSON.stringify(response.body.details)).toContain('FAIL policy is not allowed for withMeeting auto-deletion policy'); expect(JSON.stringify(response.body.details)).toContain(
'FAIL policy is not allowed for withMeeting auto-deletion policy'
);
}); });
it('should fail when autoDeletionPolicy.withRecordings has FAIL policy', async () => { it('should fail when autoDeletionPolicy.withRecordings has FAIL policy', async () => {
@ -195,7 +191,9 @@ describe('Room API Tests', () => {
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422); const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
expect(JSON.stringify(response.body.details)).toContain('FAIL policy is not allowed for withRecordings auto-deletion policy'); expect(JSON.stringify(response.body.details)).toContain(
'FAIL policy is not allowed for withRecordings auto-deletion policy'
);
}); });
it('should fail when roomName is not a string (number provided)', async () => { it('should fail when roomName is not a string (number provided)', async () => {
@ -220,11 +218,11 @@ describe('Room API Tests', () => {
expect(JSON.stringify(response.body.details)).toContain('Expected string'); expect(JSON.stringify(response.body.details)).toContain('Expected string');
}); });
it('should fail when preferences is not an object (string provided)', async () => { it('should fail when config is not an object (string provided)', async () => {
const payload = { const payload = {
roomName: 'TestRoom', roomName: 'TestRoom',
autoDeletionDate: validAutoDeletionDate, autoDeletionDate: validAutoDeletionDate,
preferences: 'invalid-preferences' config: 'invalid-config'
}; };
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422); const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
@ -232,19 +230,19 @@ describe('Room API Tests', () => {
expect(JSON.stringify(response.body.details)).toContain('Expected object'); expect(JSON.stringify(response.body.details)).toContain('Expected object');
}); });
it('should fail when preferences has an invalid structure', async () => { it('should fail when config has an invalid structure', async () => {
// Assuming preferences expects each sub-property to be an object with a boolean "enabled", // Assuming config expects each sub-property to be an object with a boolean "enabled",
// here we deliberately use an invalid structure. // here we deliberately use an invalid structure.
const payload = { const payload = {
roomName: 'TestRoom', roomName: 'TestRoom',
autoDeletionDate: validAutoDeletionDate, autoDeletionDate: validAutoDeletionDate,
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: 'yes', // invalid boolean enabled: 'yes', // invalid boolean
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
} }
}; };

View File

@ -1,6 +1,6 @@
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
import { ParticipantRole } from '../../../../src/typings/ce/participant.js'; import { ParticipantRole } from '../../../../src/typings/ce/participant.js';
import { MeetRecordingAccess } from '../../../../src/typings/ce/room-preferences.js'; import { MeetRecordingAccess } from '../../../../src/typings/ce/room-config.js';
import { expectValidRecordingTokenResponse } from '../../../helpers/assertion-helpers.js'; import { expectValidRecordingTokenResponse } from '../../../helpers/assertion-helpers.js';
import { import {
deleteAllRecordings, deleteAllRecordings,
@ -9,7 +9,7 @@ import {
disconnectFakeParticipants, disconnectFakeParticipants,
generateRecordingToken, generateRecordingToken,
startTestServer, startTestServer,
updateRecordingAccessPreferencesInRoom updateRecordingAccessConfigInRoom
} from '../../../helpers/request-helpers.js'; } from '../../../helpers/request-helpers.js';
import { RoomData, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js'; import { RoomData, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js';
@ -28,44 +28,35 @@ describe('Room API Tests', () => {
describe('Generate Recording Token Tests', () => { describe('Generate Recording Token Tests', () => {
it('should generate a recording token with canRetrieve and canDelete permissions when using the moderator secret and recording access is admin_moderator', async () => { it('should generate a recording token with canRetrieve and canDelete permissions when using the moderator secret and recording access is admin_moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret); const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret);
expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR, true, true); 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_speaker', 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( await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
);
const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret); const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret);
expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR, true, true); expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR, true, true);
}); });
it('should generate a recording token without any permissions when using the speaker 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); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret); const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret);
expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, false, false); expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, false, false);
}); });
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 () => { 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( await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
);
const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret); const response = await generateRecordingToken(roomData.room.roomId, roomData.speakerSecret);
expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, true, false); expectValidRecordingTokenResponse(response, roomData.room.roomId, ParticipantRole.SPEAKER, true, false);
}); });
it('should succeed even if the room is deleted', async () => { it('should succeed even if the room is deleted', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
);
await deleteRoom(roomData.room.roomId); await deleteRoom(roomData.room.roomId);
const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret); const response = await generateRecordingToken(roomData.room.roomId, roomData.moderatorSecret);

View File

@ -1,17 +1,17 @@
import { afterEach, beforeAll, describe, it } from '@jest/globals'; import { afterEach, beforeAll, describe, it } from '@jest/globals';
import { MeetRecordingAccess } from '../../../../src/typings/ce/index.js'; import { MeetRecordingAccess } from '../../../../src/typings/ce/index.js';
import { expectSuccessRoomPreferencesResponse } from '../../../helpers/assertion-helpers.js'; import { expectSuccessRoomConfigResponse } from '../../../helpers/assertion-helpers.js';
import { deleteAllRooms, getRoomPreferences, startTestServer } from '../../../helpers/request-helpers.js'; import { deleteAllRooms, getRoomConfig, startTestServer } from '../../../helpers/request-helpers.js';
import { setupSingleRoom } from '../../../helpers/test-scenarios.js'; import { setupSingleRoom } from '../../../helpers/test-scenarios.js';
describe('Room API Tests', () => { describe('Room API Tests', () => {
const DEFAULT_PREFERENCES = { const DEFAULT_CONFIG = {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}; };
beforeAll(() => { beforeAll(() => {
@ -23,33 +23,33 @@ describe('Room API Tests', () => {
await deleteAllRooms(); await deleteAllRooms();
}); });
describe('Get Room Preferences Tests', () => { describe('Get Room Config Tests', () => {
it('should successfully retrieve a room by its ID', async () => { it('should successfully retrieve a room by its ID', async () => {
const roomData = await setupSingleRoom(); const roomData = await setupSingleRoom();
const roomId = roomData.room.roomId; const roomId = roomData.room.roomId;
const response = await getRoomPreferences(roomId); const response = await getRoomConfig(roomId);
expectSuccessRoomPreferencesResponse(response, DEFAULT_PREFERENCES); expectSuccessRoomConfigResponse(response, DEFAULT_CONFIG);
}); });
it('should retrieve custom room preferences', async () => { it('should retrieve custom room config', async () => {
const payload = { const payload = {
roomName: 'custom-prefs', roomName: 'custom-prefs',
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
} }
}; };
const roomData = await setupSingleRoom(false, payload.roomName, payload.preferences); const roomData = await setupSingleRoom(false, payload.roomName, payload.config);
const roomId = roomData.room.roomId; const roomId = roomData.room.roomId;
const response = await getRoomPreferences(roomId); const response = await getRoomConfig(roomId);
expectSuccessRoomPreferencesResponse(response, payload.preferences); expectSuccessRoomConfigResponse(response, payload.config);
}); });
}); });
}); });

View File

@ -32,25 +32,25 @@ describe('Room API Tests', () => {
expectSuccessRoomResponse(response, 'test-room'); expectSuccessRoomResponse(response, 'test-room');
}); });
it('should retrieve a room with custom preferences', async () => { it('should retrieve a room with custom config', async () => {
const payload = { const payload = {
roomName: 'custom-prefs', roomName: 'custom-prefs',
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
} }
}; };
// Create a room with custom preferences // Create a room with custom config
const { roomId } = await createRoom(payload); const { roomId } = await createRoom(payload);
// Retrieve the room by its ID // Retrieve the room by its ID
const response = await getRoom(roomId); const response = await getRoom(roomId);
expectSuccessRoomResponse(response, 'custom-prefs', undefined, payload.preferences); expectSuccessRoomResponse(response, 'custom-prefs', undefined, payload.config);
}); });
it('should retrieve only specified fields when using fields parameter', async () => { it('should retrieve only specified fields when using fields parameter', async () => {

View File

@ -1,15 +1,15 @@
import { afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals'; import { afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals';
import { container } from '../../../../src/config/index.js';
import { FrontendEventService } from '../../../../src/services/index.js';
import { MeetSignalType } from '../../../../src/typings/ce/event.model.js';
import { MeetRecordingAccess } from '../../../../src/typings/ce/index.js'; import { MeetRecordingAccess } from '../../../../src/typings/ce/index.js';
import { import {
createRoom, createRoom,
deleteAllRooms, deleteAllRooms,
getRoom, getRoom,
startTestServer, startTestServer,
updateRoomPreferences updateRoomConfig
} from '../../../helpers/request-helpers.js'; } from '../../../helpers/request-helpers.js';
import { FrontendEventService } from '../../../../src/services/index.js';
import { container } from '../../../../src/config/index.js';
import { MeetSignalType } from '../../../../src/typings/ce/event.model.js';
describe('Room API Tests', () => { describe('Room API Tests', () => {
beforeAll(() => { beforeAll(() => {
@ -21,7 +21,7 @@ describe('Room API Tests', () => {
await deleteAllRooms(); await deleteAllRooms();
}); });
describe('Update Room Preferences Tests', () => { describe('Update Room Config Tests', () => {
let frontendEventService: FrontendEventService; let frontendEventService: FrontendEventService;
beforeAll(() => { beforeAll(() => {
@ -29,41 +29,41 @@ describe('Room API Tests', () => {
frontendEventService = container.get(FrontendEventService); frontendEventService = container.get(FrontendEventService);
}); });
it('should successfully update room preferences', async () => { it('should successfully update room config', async () => {
const sendSignalSpy = jest.spyOn(frontendEventService as any, 'sendSignal'); const sendSignalSpy = jest.spyOn(frontendEventService as any, 'sendSignal');
const createdRoom = await createRoom({ const createdRoom = await createRoom({
roomName: 'update-test', roomName: 'update-test',
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
} }
}); });
// Update the room preferences // Update the room config
const updatedPreferences = { const updatedConfig = {
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN allowAccessTo: MeetRecordingAccess.ADMIN
}, },
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}; };
const updateResponse = await updateRoomPreferences(createdRoom.roomId, updatedPreferences); const updateResponse = await updateRoomConfig(createdRoom.roomId, updatedConfig);
// Verify a method of frontend event service is called // Verify a method of frontend event service is called
expect(sendSignalSpy).toHaveBeenCalledWith( expect(sendSignalSpy).toHaveBeenCalledWith(
createdRoom.roomId, createdRoom.roomId,
{ {
roomId: createdRoom.roomId, roomId: createdRoom.roomId,
preferences: updatedPreferences, config: updatedConfig,
timestamp: expect.any(Number) timestamp: expect.any(Number)
}, },
{ {
topic: MeetSignalType.MEET_ROOM_PREFERENCES_UPDATED topic: MeetSignalType.MEET_ROOM_CONFIG_UPDATED
} }
); );
@ -74,33 +74,33 @@ describe('Room API Tests', () => {
// Verify with a get request // Verify with a get request
const getResponse = await getRoom(createdRoom.roomId); const getResponse = await getRoom(createdRoom.roomId);
expect(getResponse.status).toBe(200); expect(getResponse.status).toBe(200);
expect(getResponse.body.preferences).toEqual(updatedPreferences); expect(getResponse.body.config).toEqual(updatedConfig);
}); });
it('should allow partial preference updates', async () => { it('should allow partial preference updates', async () => {
// Create a room first with all preferences enabled // Create a room first with all config enabled
const createdRoom = await createRoom({ const createdRoom = await createRoom({
roomName: 'partial-update', roomName: 'partial-update',
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
} }
}); });
// Update only one preference // Update only one preference
const partialPreferences = { const partialConfig = {
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}; };
const updateResponse = await updateRoomPreferences(createdRoom.roomId, partialPreferences); const updateResponse = await updateRoomConfig(createdRoom.roomId, partialConfig);
// Verify update response // Verify update response
expect(updateResponse.status).toBe(200); expect(updateResponse.status).toBe(200);
@ -109,59 +109,59 @@ describe('Room API Tests', () => {
// Verify with a get request // Verify with a get request
const getResponse = await getRoom(createdRoom.roomId); const getResponse = await getRoom(createdRoom.roomId);
expect(getResponse.status).toBe(200); expect(getResponse.status).toBe(200);
expect(getResponse.body.preferences).toEqual(partialPreferences); expect(getResponse.body.config).toEqual(partialConfig);
}); });
}); });
describe('Update Room Preferences Validation failures', () => { describe('Update Room Config Validation failures', () => {
it('should fail when preferences have incorrect structure', async () => { it('should fail when config has incorrect structure', async () => {
const { roomId } = await createRoom({ const { roomId } = await createRoom({
roomName: 'validation-test' roomName: 'validation-test'
}); });
// Invalid preferences (missing required fields) // Invalid config (missing required fields)
const invalidPreferences = { const invalidConfig = {
recordingPreferences: { recordingConfig: {
enabled: false enabled: false
}, },
// Missing chatPreferences // Missing chatConfig
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}; };
const response = await updateRoomPreferences(roomId, invalidPreferences); const response = await updateRoomConfig(roomId, invalidConfig);
expect(response.status).toBe(422); expect(response.status).toBe(422);
expect(response.body.error).toContain('Unprocessable Entity'); expect(response.body.error).toContain('Unprocessable Entity');
expect(JSON.stringify(response.body.details)).toContain('chatPreferences'); expect(JSON.stringify(response.body.details)).toContain('chatConfig');
}); });
it('should fail when preferences have incorrect types', async () => { it('should fail when config has incorrect types', async () => {
const createdRoom = await createRoom({ const createdRoom = await createRoom({
roomName: 'type-test' roomName: 'type-test'
}); });
// Invalid preferences (wrong types) // Invalid config (wrong types)
const invalidPreferences = { const invalidConfig = {
recordingPreferences: { recordingConfig: {
enabled: 'true', // String instead of boolean enabled: 'true', // String instead of boolean
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}; };
const response = await updateRoomPreferences(createdRoom.roomId, invalidPreferences); const response = await updateRoomConfig(createdRoom.roomId, invalidConfig);
expect(response.status).toBe(422); expect(response.status).toBe(422);
expect(response.body.error).toContain('Unprocessable Entity'); expect(response.body.error).toContain('Unprocessable Entity');
expect(JSON.stringify(response.body.details)).toContain('recordingPreferences.enabled'); expect(JSON.stringify(response.body.details)).toContain('recordingConfig.enabled');
}); });
it('should fail when preferences are missing required properties', async () => { it('should fail when config is missing required properties', async () => {
const createdRoom = await createRoom({ const createdRoom = await createRoom({
roomName: 'missing-props' roomName: 'missing-props'
}); });
const emptyPreferences = {}; const emptyConfig = {};
const response = await updateRoomPreferences(createdRoom.roomId, emptyPreferences); const response = await updateRoomConfig(createdRoom.roomId, emptyConfig);
expect(response.status).toBe(422); expect(response.status).toBe(422);
expect(response.body.error).toContain('Unprocessable Entity'); expect(response.body.error).toContain('Unprocessable Entity');
@ -172,32 +172,32 @@ describe('Room API Tests', () => {
roomName: 'missing-access' roomName: 'missing-access'
}); });
const invalidPreferences = { const invalidConfig = {
recordingPreferences: { recordingConfig: {
enabled: true // Missing allowAccessTo enabled: true // Missing allowAccessTo
}, },
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}; };
const response = await updateRoomPreferences(createdRoom.roomId, invalidPreferences); const response = await updateRoomConfig(createdRoom.roomId, invalidConfig);
expect(response.status).toBe(422); expect(response.status).toBe(422);
expect(response.body.error).toContain('Unprocessable Entity'); expect(response.body.error).toContain('Unprocessable Entity');
expect(JSON.stringify(response.body.details)).toContain('recordingPreferences.allowAccessTo'); expect(JSON.stringify(response.body.details)).toContain('recordingConfig.allowAccessTo');
}); });
it('should return 404 when updating non-existent room', async () => { it('should return 404 when updating non-existent room', async () => {
const nonExistentRoomId = 'non-existent-room'; const nonExistentRoomId = 'non-existent-room';
const preferences = { const config = {
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}; };
const response = await updateRoomPreferences(nonExistentRoomId, preferences); const response = await updateRoomConfig(nonExistentRoomId, config);
expect(response.status).toBe(404); expect(response.status).toBe(404);
expect(response.body.message).toContain(`'${nonExistentRoomId}' does not exist`); expect(response.body.message).toContain(`'${nonExistentRoomId}' does not exist`);

View File

@ -15,7 +15,7 @@ import {
startTestServer, startTestServer,
stopAllRecordings, stopAllRecordings,
stopRecording, stopRecording,
updateRecordingAccessPreferencesInRoom updateRecordingAccessConfigInRoom
} from '../../../helpers/request-helpers.js'; } from '../../../helpers/request-helpers.js';
import { RoomData, setupSingleRoom, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js'; import { RoomData, setupSingleRoom, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js';
@ -170,7 +170,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -184,7 +184,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -198,7 +198,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -209,7 +209,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -234,7 +234,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -250,7 +250,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -266,7 +266,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -279,7 +279,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -363,7 +363,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should fail when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -379,7 +379,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -395,7 +395,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -408,7 +408,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -450,7 +450,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should fail when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -467,7 +467,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -484,7 +484,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -498,7 +498,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -528,7 +528,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -544,7 +544,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -560,7 +560,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -573,7 +573,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -652,7 +652,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -668,7 +668,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -684,7 +684,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -697,7 +697,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret
@ -728,7 +728,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -745,7 +745,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => { it('should succeed when recording access is admin_moderator_speaker and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(
roomData.room.roomId, roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
); );
@ -762,7 +762,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should fail when recording access is admin_moderator and participant is speaker', async () => { it('should fail when recording access is admin_moderator and participant is speaker', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.speakerSecret roomData.speakerSecret
@ -776,7 +776,7 @@ describe('Recording API Security Tests', () => {
}); });
it('should succeed when recording access is admin_moderator and participant is moderator', async () => { it('should succeed when recording access is admin_moderator and participant is moderator', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const recordingCookie = await generateRecordingTokenCookie( const recordingCookie = await generateRecordingTokenCookie(
roomData.room.roomId, roomData.room.roomId,
roomData.moderatorSecret roomData.moderatorSecret

View File

@ -12,7 +12,7 @@ import {
disconnectFakeParticipants, disconnectFakeParticipants,
loginUser, loginUser,
startTestServer, startTestServer,
updateRecordingAccessPreferencesInRoom updateRecordingAccessConfigInRoom
} from '../../../helpers/request-helpers.js'; } from '../../../helpers/request-helpers.js';
import { RoomData, setupSingleRoom, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js'; import { RoomData, setupSingleRoom, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js';
@ -179,7 +179,7 @@ describe('Room API Security Tests', () => {
}); });
}); });
describe('Get Room Preferences Tests', () => { describe('Get Room Config Tests', () => {
let roomData: RoomData; let roomData: RoomData;
beforeAll(async () => { beforeAll(async () => {
@ -188,26 +188,26 @@ describe('Room API Security Tests', () => {
it('should succeed when request includes API key', async () => { it('should succeed when request includes API key', async () => {
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY); .set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY);
expect(response.status).toBe(200); expect(response.status).toBe(200);
}); });
it('should succeed when user is authenticated as admin', async () => { it('should succeed when user is authenticated as admin', async () => {
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set('Cookie', adminCookie); .set('Cookie', adminCookie);
expect(response.status).toBe(200); expect(response.status).toBe(200);
}); });
it('should fail when user is not authenticated', async () => { it('should fail when user is not authenticated', async () => {
const response = await request(app).get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`); const response = await request(app).get(`${ROOMS_PATH}/${roomData.room.roomId}/config`);
expect(response.status).toBe(401); expect(response.status).toBe(401);
}); });
it('should succeed when participant is moderator', async () => { it('should succeed when participant is moderator', async () => {
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set('Cookie', roomData.moderatorCookie) .set('Cookie', roomData.moderatorCookie)
.set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.MODERATOR); .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.MODERATOR);
expect(response.status).toBe(200); expect(response.status).toBe(200);
@ -217,7 +217,7 @@ describe('Room API Security Tests', () => {
const newRoomData = await setupSingleRoom(); const newRoomData = await setupSingleRoom();
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set('Cookie', newRoomData.moderatorCookie) .set('Cookie', newRoomData.moderatorCookie)
.set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.MODERATOR); .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.MODERATOR);
expect(response.status).toBe(403); expect(response.status).toBe(403);
@ -225,7 +225,7 @@ describe('Room API Security Tests', () => {
it('should succeed when participant is speaker', async () => { it('should succeed when participant is speaker', async () => {
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set('Cookie', roomData.speakerCookie) .set('Cookie', roomData.speakerCookie)
.set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER);
expect(response.status).toBe(200); expect(response.status).toBe(200);
@ -235,21 +235,21 @@ describe('Room API Security Tests', () => {
const newRoomData = await setupSingleRoom(); const newRoomData = await setupSingleRoom();
const response = await request(app) const response = await request(app)
.get(`${ROOMS_PATH}/${roomData.room.roomId}/preferences`) .get(`${ROOMS_PATH}/${roomData.room.roomId}/config`)
.set('Cookie', newRoomData.speakerCookie) .set('Cookie', newRoomData.speakerCookie)
.set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER); .set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, ParticipantRole.SPEAKER);
expect(response.status).toBe(403); expect(response.status).toBe(403);
}); });
}); });
describe('Update Room Preferences Tests', () => { describe('Update Room Config Tests', () => {
const roomPreferences = { const roomConfig = {
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}; };
let roomId: string; let roomId: string;
@ -261,24 +261,22 @@ describe('Room API Security Tests', () => {
it('should succeed when request includes API key', async () => { it('should succeed when request includes API key', async () => {
const response = await request(app) const response = await request(app)
.put(`${ROOMS_PATH}/${roomId}/preferences`) .put(`${ROOMS_PATH}/${roomId}/config`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY) .set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_INITIAL_API_KEY)
.send({ preferences: roomPreferences }); .send({ config: roomConfig });
expect(response.status).toBe(200); expect(response.status).toBe(200);
}); });
it('should succeed when user is authenticated as admin', async () => { it('should succeed when user is authenticated as admin', async () => {
const response = await request(app) const response = await request(app)
.put(`${ROOMS_PATH}/${roomId}/preferences`) .put(`${ROOMS_PATH}/${roomId}/config`)
.set('Cookie', adminCookie) .set('Cookie', adminCookie)
.send({ preferences: roomPreferences }); .send({ config: roomConfig });
expect(response.status).toBe(200); expect(response.status).toBe(200);
}); });
it('should fail when user is not authenticated', async () => { it('should fail when user is not authenticated', async () => {
const response = await request(app) const response = await request(app).put(`${ROOMS_PATH}/${roomId}/config`).send({ config: roomConfig });
.put(`${ROOMS_PATH}/${roomId}/preferences`)
.send({ preferences: roomPreferences });
expect(response.status).toBe(401); expect(response.status).toBe(401);
}); });
}); });
@ -308,9 +306,7 @@ describe('Room API Security Tests', () => {
}); });
it('should fail when user is not authenticated', async () => { it('should fail when user is not authenticated', async () => {
const response = await request(app) const response = await request(app).put(`${ROOMS_PATH}/${roomId}/status`).send({ status: 'open' });
.put(`${ROOMS_PATH}/${roomId}/status`)
.send({ status: 'open' });
expect(response.status).toBe(401); expect(response.status).toBe(401);
}); });
}); });
@ -323,10 +319,7 @@ describe('Room API Security Tests', () => {
}); });
beforeEach(async () => { beforeEach(async () => {
await updateRecordingAccessPreferencesInRoom( await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
roomData.room.roomId,
MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
);
}); });
it('should succeed when no authentication is required and participant is speaker', async () => { it('should succeed when no authentication is required and participant is speaker', async () => {
@ -414,7 +407,7 @@ describe('Room API Security Tests', () => {
}); });
it('should fail when recording access is set to admin only', async () => { it('should fail when recording access is set to admin only', async () => {
await updateRecordingAccessPreferencesInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN); await updateRecordingAccessConfigInRoom(roomData.room.roomId, MeetRecordingAccess.ADMIN);
const response = await request(app) const response = await request(app)
.post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`) .post(`${INTERNAL_ROOMS_PATH}/${roomData.room.roomId}/recording-token`)

View File

@ -240,7 +240,7 @@
color: var(--ov-meet-color-primary); color: var(--ov-meet-color-primary);
} }
&.room-preferences-btn { &.room-config-btn {
color: var(--ov-meet-icon-settings); color: var(--ov-meet-icon-settings);
} }

View File

@ -56,7 +56,7 @@
<ov-room-wizard-room-details></ov-room-wizard-room-details> <ov-room-wizard-room-details></ov-room-wizard-room-details>
} }
@case ('recording') { @case ('recording') {
<ov-recording-preferences></ov-recording-preferences> <ov-recording-config></ov-recording-config>
} }
@case ('recordingTrigger') { @case ('recordingTrigger') {
<ov-recording-trigger></ov-recording-trigger> <ov-recording-trigger></ov-recording-trigger>
@ -64,8 +64,8 @@
@case ('recordingLayout') { @case ('recordingLayout') {
<ov-recording-layout></ov-recording-layout> <ov-recording-layout></ov-recording-layout>
} }
@case ('preferences') { @case ('config') {
<ov-room-preferences></ov-room-preferences> <ov-room-config></ov-room-config>
} }
} }
} }

View File

@ -10,11 +10,11 @@ import { WizardNavigationConfig, WizardStep } from '@lib/models';
import { NavigationService, NotificationService, RoomService, RoomWizardStateService } from '@lib/services'; import { NavigationService, NotificationService, RoomService, RoomWizardStateService } from '@lib/services';
import { MeetRoomOptions } from '@lib/typings/ce'; import { MeetRoomOptions } from '@lib/typings/ce';
import { RoomBasicCreationComponent } from '../room-basic-creation/room-basic-creation.component'; import { RoomBasicCreationComponent } from '../room-basic-creation/room-basic-creation.component';
import { RecordingConfigComponent } from './steps/recording-config/recording-config.component';
import { RecordingLayoutComponent } from './steps/recording-layout/recording-layout.component'; import { RecordingLayoutComponent } from './steps/recording-layout/recording-layout.component';
import { RecordingPreferencesComponent } from './steps/recording-preferences/recording-preferences.component';
import { RecordingTriggerComponent } from './steps/recording-trigger/recording-trigger.component'; import { RecordingTriggerComponent } from './steps/recording-trigger/recording-trigger.component';
import { RoomConfigComponent } from './steps/room-config/room-config.component';
import { RoomWizardRoomDetailsComponent } from './steps/room-details/room-details.component'; import { RoomWizardRoomDetailsComponent } from './steps/room-details/room-details.component';
import { RoomPreferencesComponent } from './steps/room-preferences/room-preferences.component';
@Component({ @Component({
selector: 'ov-room-wizard', selector: 'ov-room-wizard',
@ -29,10 +29,10 @@ import { RoomPreferencesComponent } from './steps/room-preferences/room-preferen
MatSlideToggleModule, MatSlideToggleModule,
RoomBasicCreationComponent, RoomBasicCreationComponent,
RoomWizardRoomDetailsComponent, RoomWizardRoomDetailsComponent,
RecordingPreferencesComponent, RecordingConfigComponent,
RecordingTriggerComponent, RecordingTriggerComponent,
RecordingLayoutComponent, RecordingLayoutComponent,
RoomPreferencesComponent RoomConfigComponent
], ],
templateUrl: './room-wizard.component.html', templateUrl: './room-wizard.component.html',
styleUrl: './room-wizard.component.scss' styleUrl: './room-wizard.component.scss'
@ -89,8 +89,8 @@ export class RoomWizardComponent implements OnInit {
if (!this.roomId) return; if (!this.roomId) return;
try { try {
const { roomName, autoDeletionDate, preferences } = await this.roomService.getRoom(this.roomId); const { roomName, autoDeletionDate, config } = await this.roomService.getRoom(this.roomId);
this.existingRoomData = { roomName, autoDeletionDate, preferences }; this.existingRoomData = { roomName, autoDeletionDate, config };
if (this.existingRoomData) { if (this.existingRoomData) {
this.isBasicCreation.set(false); this.isBasicCreation.set(false);
} }
@ -154,8 +154,8 @@ export class RoomWizardComponent implements OnInit {
this.isCreatingRoom.set(true); this.isCreatingRoom.set(true);
try { try {
if (this.editMode && this.roomId && roomOptions.preferences) { if (this.editMode && this.roomId && roomOptions.config) {
await this.roomService.updateRoomPreferences(this.roomId, roomOptions.preferences); await this.roomService.updateRoomConfig(this.roomId, roomOptions.config);
await this.navigationService.navigateTo('rooms', undefined, true); await this.navigationService.navigateTo('rooms', undefined, true);
this.notificationService.showSnackbar('Room updated successfully'); this.notificationService.showSnackbar('Room updated successfully');
} else { } else {

View File

@ -1,9 +1,9 @@
<div class="recording-preferences-step fade-in"> <div class="recording-config-step fade-in">
<!-- Header Section --> <!-- Header Section -->
<header class="step-header"> <header class="step-header">
<mat-icon class="ov-recording-icon step-icon">video_library</mat-icon> <mat-icon class="ov-recording-icon step-icon">video_library</mat-icon>
<div class="step-title-group"> <div class="step-title-group">
<h3 class="step-title">Recording Preferences</h3> <h3 class="step-title">Recording Config</h3>
<p class="step-description">Choose whether to enable recording capabilities for this room</p> <p class="step-description">Choose whether to enable recording capabilities for this room</p>
</div> </div>
</header> </header>

View File

@ -1,6 +1,6 @@
@import '../../../../../../../../../../src/assets/styles/design-tokens'; @import '../../../../../../../../../../src/assets/styles/design-tokens';
.recording-preferences-step { .recording-config-step {
@include ov-page-content; @include ov-page-content;
@include ov-container; @include ov-container;
@ -50,7 +50,6 @@
padding: var(--ov-meet-spacing-lg) var(--ov-meet-spacing-lg) 0 var(--ov-meet-spacing-lg); padding: var(--ov-meet-spacing-lg) var(--ov-meet-spacing-lg) 0 var(--ov-meet-spacing-lg);
overflow: hidden; overflow: hidden;
.access-header { .access-header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;

View File

@ -18,7 +18,7 @@ interface RecordingAccessOption {
} }
@Component({ @Component({
selector: 'ov-recording-preferences', selector: 'ov-recording-config',
standalone: true, standalone: true,
imports: [ imports: [
CommonModule, CommonModule,
@ -31,10 +31,10 @@ interface RecordingAccessOption {
MatFormFieldModule, MatFormFieldModule,
SelectableCardComponent SelectableCardComponent
], ],
templateUrl: './recording-preferences.component.html', templateUrl: './recording-config.component.html',
styleUrl: './recording-preferences.component.scss' styleUrl: './recording-config.component.scss'
}) })
export class RecordingPreferencesComponent implements OnDestroy { export class RecordingConfigComponent implements OnDestroy {
recordingForm: FormGroup; recordingForm: FormGroup;
isAnimatingOut = false; isAnimatingOut = false;
@ -89,8 +89,8 @@ export class RecordingPreferencesComponent implements OnDestroy {
const enabled = formValue.recordingEnabled === 'enabled'; const enabled = formValue.recordingEnabled === 'enabled';
const stepData: any = { const stepData: any = {
preferences: { config: {
recordingPreferences: { recordingConfig: {
enabled, enabled,
...(enabled && { allowAccessTo: formValue.allowAccessTo }) ...(enabled && { allowAccessTo: formValue.allowAccessTo })
} }

View File

@ -1,18 +1,18 @@
<div class="room-preferences-step fade-in"> <div class="room-config-step fade-in">
<!-- Header Section --> <!-- Header Section -->
<header class="step-header"> <header class="step-header">
<mat-icon class="ov-room-icon step-icon">video_chat</mat-icon> <mat-icon class="ov-room-icon step-icon">video_chat</mat-icon>
<div class="step-title-group"> <div class="step-title-group">
<h3 class="step-title">Room Preferences</h3> <h3 class="step-title">Room Config</h3>
<p class="step-description">Configure additional features and functionality for your room</p> <p class="step-description">Configure additional features and functionality for your room</p>
</div> </div>
</header> </header>
<!-- Form Section --> <!-- Form Section -->
<main class="step-content"> <main class="step-content">
<form [formGroup]="preferencesForm" class="preferences-form"> <form [formGroup]="configForm" class="config-form">
<!-- Preferences Cards Grid --> <!-- Config Cards Grid -->
<div class="preferences-grid"> <div class="config-grid">
<!-- Chat Settings Card --> <!-- Chat Settings Card -->
<mat-card class="preference-card"> <mat-card class="preference-card">
<mat-card-content> <mat-card-content>

View File

@ -1,6 +1,6 @@
@import '../../../../../../../../../../src/assets/styles/design-tokens'; @import '../../../../../../../../../../src/assets/styles/design-tokens';
.room-preferences-step { .room-config-step {
@include ov-page-content; @include ov-page-content;
@include ov-container; @include ov-container;
@ -41,13 +41,13 @@
.step-content { .step-content {
margin-bottom: var(--ov-meet-spacing-md); margin-bottom: var(--ov-meet-spacing-md);
.preferences-form { .config-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
} }
.preferences-grid { .config-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: var(--ov-meet-spacing-md); gap: var(--ov-meet-spacing-md);
@ -123,7 +123,7 @@
// Responsive design // Responsive design
@media (max-width: 1024px) { @media (max-width: 1024px) {
.room-preferences-step { .room-config-step {
// padding: var(--ov-meet-spacing-xs); // padding: var(--ov-meet-spacing-xs);
.step-header { .step-header {
@ -131,14 +131,14 @@
margin-bottom: var(--ov-meet-spacing-md); margin-bottom: var(--ov-meet-spacing-md);
} }
.preferences-grid { .config-grid {
gap: var(--ov-meet-spacing-sm); gap: var(--ov-meet-spacing-sm);
} }
} }
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.room-preferences-step { .room-config-step {
.step-header { .step-header {
.step-title-group { .step-title-group {
.step-title { .step-title {
@ -151,7 +151,7 @@
} }
} }
.preferences-grid { .config-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
@ -170,7 +170,7 @@
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.room-preferences-step { .room-config-step {
.preference-card { .preference-card {
.card-header { .card-header {
.icon-title-group { .icon-title-group {

View File

@ -7,22 +7,22 @@ import { RoomWizardStateService } from '@lib/services';
import { Subject, takeUntil } from 'rxjs'; import { Subject, takeUntil } from 'rxjs';
@Component({ @Component({
selector: 'ov-room-preferences', selector: 'ov-room-config',
standalone: true, standalone: true,
imports: [ReactiveFormsModule, MatCardModule, MatIconModule, MatSlideToggleModule], imports: [ReactiveFormsModule, MatCardModule, MatIconModule, MatSlideToggleModule],
templateUrl: './room-preferences.component.html', templateUrl: './room-config.component.html',
styleUrl: './room-preferences.component.scss' styleUrl: './room-config.component.scss'
}) })
export class RoomPreferencesComponent implements OnDestroy { export class RoomConfigComponent implements OnDestroy {
preferencesForm: FormGroup; configForm: FormGroup;
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
constructor(private wizardService: RoomWizardStateService) { constructor(private wizardService: RoomWizardStateService) {
const currentStep = this.wizardService.currentStep(); const currentStep = this.wizardService.currentStep();
this.preferencesForm = currentStep!.formGroup; this.configForm = currentStep!.formGroup;
this.preferencesForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => { this.configForm.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
this.saveFormData(value); this.saveFormData(value);
}); });
} }
@ -34,34 +34,34 @@ export class RoomPreferencesComponent implements OnDestroy {
private saveFormData(formValue: any): void { private saveFormData(formValue: any): void {
const stepData: any = { const stepData: any = {
preferences: { config: {
chatPreferences: { chatConfig: {
enabled: formValue.chatEnabled enabled: formValue.chatEnabled
}, },
virtualBackgroundPreferences: { virtualBackgroundConfig: {
enabled: formValue.virtualBackgroundsEnabled enabled: formValue.virtualBackgroundsEnabled
} }
} }
}; };
this.wizardService.updateStepData('preferences', stepData); this.wizardService.updateStepData('config', stepData);
} }
onChatToggleChange(event: any): void { onChatToggleChange(event: any): void {
const isEnabled = event.checked; const isEnabled = event.checked;
this.preferencesForm.patchValue({ chatEnabled: isEnabled }); this.configForm.patchValue({ chatEnabled: isEnabled });
} }
onVirtualBackgroundToggleChange(event: any): void { onVirtualBackgroundToggleChange(event: any): void {
const isEnabled = event.checked; const isEnabled = event.checked;
this.preferencesForm.patchValue({ virtualBackgroundsEnabled: isEnabled }); this.configForm.patchValue({ virtualBackgroundsEnabled: isEnabled });
} }
get chatEnabled(): boolean { get chatEnabled(): boolean {
return this.preferencesForm.value.chatEnabled || false; return this.configForm.value.chatEnabled || false;
} }
get virtualBackgroundsEnabled(): boolean { get virtualBackgroundsEnabled(): boolean {
return this.preferencesForm.value.virtualBackgroundsEnabled || false; return this.configForm.value.virtualBackgroundsEnabled || false;
} }
} }

View File

@ -31,7 +31,7 @@ import {
import { ILogger, LoggerService } from 'openvidu-components-angular'; import { ILogger, LoggerService } from 'openvidu-components-angular';
@Component({ @Component({
selector: 'ov-room-preferences', selector: 'ov-room-config',
standalone: true, standalone: true,
imports: [ imports: [
MatListModule, MatListModule,
@ -109,7 +109,7 @@ export class RoomsComponent implements OnInit {
this.openRoom(action.rooms[0]); this.openRoom(action.rooms[0]);
break; break;
case 'edit': case 'edit':
await this.editRoomPreferences(action.rooms[0]); await this.editRoomConfig(action.rooms[0]);
break; break;
case 'copyModeratorLink': case 'copyModeratorLink':
this.copyModeratorLink(action.rooms[0]); this.copyModeratorLink(action.rooms[0]);
@ -254,12 +254,12 @@ export class RoomsComponent implements OnInit {
window.open(room.moderatorUrl, '_blank'); window.open(room.moderatorUrl, '_blank');
} }
private async editRoomPreferences(room: MeetRoom) { private async editRoomConfig(room: MeetRoom) {
try { try {
await this.navigationService.navigateTo(`rooms/${room.roomId}/edit`); await this.navigationService.navigateTo(`rooms/${room.roomId}/edit`);
} catch (error) { } catch (error) {
this.notificationService.showSnackbar('Error navigating to room preferences'); this.notificationService.showSnackbar('Error navigating to room config');
this.log.e('Error navigating to room preferences:', error); this.log.e('Error navigating to room config:', error);
} }
} }

View File

@ -39,7 +39,7 @@ import {
} from '@lib/typings/ce'; } from '@lib/typings/ce';
import { import {
MeetParticipantRoleUpdatedPayload, MeetParticipantRoleUpdatedPayload,
MeetRoomPreferencesUpdatedPayload, MeetRoomConfigUpdatedPayload,
MeetSignalType MeetSignalType
} from '@lib/typings/ce/event.model'; } from '@lib/typings/ce/event.model';
import { import {
@ -270,7 +270,7 @@ export class MeetingComponent implements OnInit {
try { try {
await this.generateParticipantToken(); await this.generateParticipantToken();
await this.addParticipantNameToUrl(); await this.addParticipantNameToUrl();
await this.roomService.loadRoomPreferences(this.roomId); await this.roomService.loadRoomConfig(this.roomId);
this.showMeeting = true; this.showMeeting = true;
// Subscribe to remote participants updates // Subscribe to remote participants updates
@ -357,13 +357,13 @@ export class MeetingComponent implements OnInit {
break; break;
} }
case MeetSignalType.MEET_ROOM_PREFERENCES_UPDATED: { case MeetSignalType.MEET_ROOM_CONFIG_UPDATED: {
// Update room preferences // Update room config
const { preferences } = event as MeetRoomPreferencesUpdatedPayload; const { config } = event as MeetRoomConfigUpdatedPayload;
this.featureConfService.setRoomPreferences(preferences); this.featureConfService.setRoomConfig(config);
// Refresh recording token if recording is enabled // Refresh recording token if recording is enabled
if (preferences.recordingPreferences.enabled) { if (config.recordingConfig.enabled) {
try { try {
await this.recordingService.generateRecordingToken(this.roomId, this.roomSecret); await this.recordingService.generateRecordingToken(this.roomId, this.roomSecret);
} catch (error) { } catch (error) {

View File

@ -1,6 +1,6 @@
import { computed, Injectable, signal } from '@angular/core'; import { computed, Injectable, signal } from '@angular/core';
import { import {
MeetRoomPreferences, MeetRoomConfig,
ParticipantPermissions, ParticipantPermissions,
ParticipantRole, ParticipantRole,
RecordingPermissions, RecordingPermissions,
@ -57,7 +57,7 @@ const DEFAULT_FEATURES: ApplicationFeatures = {
/** /**
* Centralized service to manage feature configuration * Centralized service to manage feature configuration
* based on room preferences and participant permissions * based on room config and participant permissions
*/ */
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -66,7 +66,7 @@ export class FeatureConfigurationService {
protected log; protected log;
// Signals to handle reactive // Signals to handle reactive
protected roomPreferences = signal<MeetRoomPreferences | undefined>(undefined); protected roomConfig = signal<MeetRoomConfig | undefined>(undefined);
protected participantPermissions = signal<ParticipantPermissions | undefined>(undefined); protected participantPermissions = signal<ParticipantPermissions | undefined>(undefined);
protected participantRole = signal<ParticipantRole | undefined>(undefined); protected participantRole = signal<ParticipantRole | undefined>(undefined);
protected recordingPermissions = signal<RecordingPermissions | undefined>(undefined); protected recordingPermissions = signal<RecordingPermissions | undefined>(undefined);
@ -74,7 +74,7 @@ export class FeatureConfigurationService {
// Computed signal to derive features based on current configurations // Computed signal to derive features based on current configurations
public readonly features = computed<ApplicationFeatures>(() => public readonly features = computed<ApplicationFeatures>(() =>
this.calculateFeatures( this.calculateFeatures(
this.roomPreferences(), this.roomConfig(),
this.participantPermissions(), this.participantPermissions(),
this.participantRole(), this.participantRole(),
this.recordingPermissions() this.recordingPermissions()
@ -86,11 +86,11 @@ export class FeatureConfigurationService {
} }
/** /**
* Updates room preferences * Updates room config
*/ */
setRoomPreferences(preferences: MeetRoomPreferences): void { setRoomConfig(config: MeetRoomConfig): void {
this.log.d('Updating room preferences', preferences); this.log.d('Updating room config', config);
this.roomPreferences.set(preferences); this.roomConfig.set(config);
} }
/** /**
@ -128,7 +128,7 @@ export class FeatureConfigurationService {
* Core logic to calculate features based on all configurations * Core logic to calculate features based on all configurations
*/ */
protected calculateFeatures( protected calculateFeatures(
roomPrefs?: MeetRoomPreferences, roomPrefs?: MeetRoomConfig,
participantPerms?: ParticipantPermissions, participantPerms?: ParticipantPermissions,
role?: ParticipantRole, role?: ParticipantRole,
recordingPerms?: RecordingPermissions recordingPerms?: RecordingPermissions
@ -138,9 +138,9 @@ export class FeatureConfigurationService {
// Apply room configurations // Apply room configurations
if (roomPrefs) { if (roomPrefs) {
features.showRecordingPanel = roomPrefs.recordingPreferences.enabled; features.showRecordingPanel = roomPrefs.recordingConfig.enabled;
features.showChat = roomPrefs.chatPreferences.enabled; features.showChat = roomPrefs.chatConfig.enabled;
features.showBackgrounds = roomPrefs.virtualBackgroundPreferences.enabled; features.showBackgrounds = roomPrefs.virtualBackgroundConfig.enabled;
} }
// Apply participant permissions (these can restrict enabled features) // Apply participant permissions (these can restrict enabled features)
@ -184,7 +184,7 @@ export class FeatureConfigurationService {
* Resets all configurations to their initial values * Resets all configurations to their initial values
*/ */
reset(): void { reset(): void {
this.roomPreferences.set(undefined); this.roomConfig.set(undefined);
this.participantPermissions.set(undefined); this.participantPermissions.set(undefined);
this.participantRole.set(undefined); this.participantRole.set(undefined);
} }

View File

@ -2,12 +2,12 @@ import { Injectable } from '@angular/core';
import { FeatureConfigurationService, HttpService, ParticipantService, SessionStorageService } from '@lib/services'; import { FeatureConfigurationService, HttpService, ParticipantService, SessionStorageService } from '@lib/services';
import { import {
MeetRoom, MeetRoom,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings, MeetRoomDeletionPolicyWithRecordings,
MeetRoomDeletionSuccessCode, MeetRoomDeletionSuccessCode,
MeetRoomFilters, MeetRoomFilters,
MeetRoomOptions, MeetRoomOptions,
MeetRoomPreferences,
MeetRoomRoleAndPermissions, MeetRoomRoleAndPermissions,
MeetRoomStatus MeetRoomStatus
} from '@lib/typings/ce'; } from '@lib/typings/ce';
@ -176,52 +176,52 @@ export class RoomService {
} }
/** /**
* Retrieves the preferences for a specific room. * Retrieves the config for a specific room.
* *
* @param roomId - The unique identifier of the room * @param roomId - The unique identifier of the room
* @return A promise that resolves to the MeetRoomPreferences object * @return A promise that resolves to the MeetRoomConfig object
*/ */
async getRoomPreferences(roomId: string): Promise<MeetRoomPreferences> { async getRoomConfig(roomId: string): Promise<MeetRoomConfig> {
this.log.d('Fetching room preferences for roomId:', roomId); this.log.d('Fetching room config for roomId:', roomId);
try { try {
const path = `${this.ROOMS_API}/${roomId}/preferences`; const path = `${this.ROOMS_API}/${roomId}/config`;
const headers = this.participantService.getParticipantRoleHeader(); const headers = this.participantService.getParticipantRoleHeader();
const preferences = await this.httpService.getRequest<MeetRoomPreferences>(path, headers); const config = await this.httpService.getRequest<MeetRoomConfig>(path, headers);
return preferences; return config;
} catch (error) { } catch (error) {
this.log.e('Error fetching room preferences', error); this.log.e('Error fetching room config', error);
throw new Error(`Failed to fetch room preferences for roomId: ${roomId}`); throw new Error(`Failed to fetch room config for roomId: ${roomId}`);
} }
} }
/** /**
* Loads the room preferences and updates the feature configuration service. * Loads the room config and updates the feature configuration service.
* *
* @param roomId - The unique identifier of the room * @param roomId - The unique identifier of the room
*/ */
async loadRoomPreferences(roomId: string): Promise<void> { async loadRoomConfig(roomId: string): Promise<void> {
try { try {
const preferences = await this.getRoomPreferences(roomId); const config = await this.getRoomConfig(roomId);
this.featureConfService.setRoomPreferences(preferences); this.featureConfService.setRoomConfig(config);
console.log('Room preferences loaded:', preferences); console.log('Room config loaded:', config);
} catch (error) { } catch (error) {
this.log.e('Error loading room preferences', error); this.log.e('Error loading room config', error);
throw new Error('Failed to load room preferences'); throw new Error('Failed to load room config');
} }
} }
/** /**
* Saves new room preferences. * Saves new room config.
* *
* @param roomId - The unique identifier of the room * @param roomId - The unique identifier of the room
* @param preferences - The room preferences to be saved. * @param config - The room config to be saved.
* @returns A promise that resolves when the preferences have been saved. * @returns A promise that resolves when the config have been saved.
*/ */
async updateRoomPreferences(roomId: string, preferences: MeetRoomPreferences): Promise<void> { async updateRoomConfig(roomId: string, config: MeetRoomConfig): Promise<void> {
this.log.d('Saving room preferences', preferences); this.log.d('Saving room config', config);
const path = `${this.ROOMS_API}/${roomId}/preferences`; const path = `${this.ROOMS_API}/${roomId}/config`;
await this.httpService.putRequest(path, { preferences }); await this.httpService.putRequest(path, { config });
} }
/** /**

View File

@ -3,20 +3,20 @@ import { AbstractControl, FormBuilder, ValidationErrors, Validators } from '@ang
import { WizardNavigationConfig, WizardStep } from '@lib/models'; import { WizardNavigationConfig, WizardStep } from '@lib/models';
import { import {
MeetRecordingAccess, MeetRecordingAccess,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings, MeetRoomDeletionPolicyWithRecordings,
MeetRoomOptions, MeetRoomOptions
MeetRoomPreferences
} from '@lib/typings/ce'; } from '@lib/typings/ce';
// Default room preferences following the app's defaults // Default room config following the app's defaults
const DEFAULT_PREFERENCES: MeetRoomPreferences = { const DEFAULT_CONFIG: MeetRoomConfig = {
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}; };
/** /**
@ -32,7 +32,7 @@ export class RoomWizardStateService {
private _visibleSteps = computed(() => this._steps().filter((step) => step.isVisible)); private _visibleSteps = computed(() => this._steps().filter((step) => step.isVisible));
private _currentStepIndex = signal<number>(0); private _currentStepIndex = signal<number>(0);
private _roomOptions = signal<MeetRoomOptions>({ private _roomOptions = signal<MeetRoomOptions>({
preferences: DEFAULT_PREFERENCES config: DEFAULT_CONFIG
}); });
public readonly steps = computed(() => this._steps()); public readonly steps = computed(() => this._steps());
@ -60,9 +60,9 @@ export class RoomWizardStateService {
// Initialize room options with defaults merged with existing data // Initialize room options with defaults merged with existing data
const initialRoomOptions: MeetRoomOptions = { const initialRoomOptions: MeetRoomOptions = {
...existingData, ...existingData,
preferences: { config: {
...DEFAULT_PREFERENCES, ...DEFAULT_CONFIG,
...(existingData?.preferences || {}) ...(existingData?.config || {})
} }
}; };
@ -156,10 +156,8 @@ export class RoomWizardStateService {
isActive: editMode, // Only active in edit mode isActive: editMode, // Only active in edit mode
isVisible: true, isVisible: true,
formGroup: this.formBuilder.group({ formGroup: this.formBuilder.group({
recordingEnabled: initialRoomOptions.preferences!.recordingPreferences.enabled recordingEnabled: initialRoomOptions.config!.recordingConfig.enabled ? 'enabled' : 'disabled',
? 'enabled' allowAccessTo: initialRoomOptions.config!.recordingConfig.allowAccessTo
: 'disabled',
allowAccessTo: initialRoomOptions.preferences!.recordingPreferences.allowAccessTo
}) })
}, },
{ {
@ -183,14 +181,14 @@ export class RoomWizardStateService {
}) })
}, },
{ {
id: 'preferences', id: 'config',
label: 'Room Features', label: 'Room Features',
isCompleted: editMode, // In edit mode, all editable steps are completed isCompleted: editMode, // In edit mode, all editable steps are completed
isActive: false, isActive: false,
isVisible: true, isVisible: true,
formGroup: this.formBuilder.group({ formGroup: this.formBuilder.group({
chatEnabled: initialRoomOptions.preferences!.chatPreferences.enabled, chatEnabled: initialRoomOptions.config!.chatConfig.enabled,
virtualBackgroundsEnabled: initialRoomOptions.preferences!.virtualBackgroundPreferences.enabled virtualBackgroundsEnabled: initialRoomOptions.config!.virtualBackgroundConfig.enabled
}) })
} }
]; ];
@ -234,13 +232,13 @@ export class RoomWizardStateService {
case 'recording': case 'recording':
updatedOptions = { updatedOptions = {
...currentOptions, ...currentOptions,
preferences: { config: {
...currentOptions.preferences, ...currentOptions.config,
recordingPreferences: { recordingConfig: {
...currentOptions.preferences?.recordingPreferences, ...currentOptions.config?.recordingConfig,
...stepData.preferences?.recordingPreferences ...stepData.config?.recordingConfig
} }
} as MeetRoomPreferences } as MeetRoomConfig
}; };
break; break;
case 'recordingTrigger': case 'recordingTrigger':
@ -248,24 +246,24 @@ export class RoomWizardStateService {
// These steps don't update room options // These steps don't update room options
updatedOptions = { ...currentOptions }; updatedOptions = { ...currentOptions };
break; break;
case 'preferences': case 'config':
updatedOptions = { updatedOptions = {
...currentOptions, ...currentOptions,
preferences: { config: {
...currentOptions.preferences, ...currentOptions.config,
chatPreferences: { chatConfig: {
...currentOptions.preferences?.chatPreferences, ...currentOptions.config?.chatConfig,
...stepData.preferences?.chatPreferences ...stepData.config?.chatConfig
}, },
virtualBackgroundPreferences: { virtualBackgroundConfig: {
...currentOptions.preferences?.virtualBackgroundPreferences, ...currentOptions.config?.virtualBackgroundConfig,
...stepData.preferences?.virtualBackgroundPreferences ...stepData.config?.virtualBackgroundConfig
}, },
recordingPreferences: { recordingConfig: {
...currentOptions.preferences?.recordingPreferences, ...currentOptions.config?.recordingConfig,
...stepData.preferences?.recordingPreferences ...stepData.config?.recordingConfig
} }
} as MeetRoomPreferences } as MeetRoomConfig
}; };
break; break;
default: default:
@ -284,8 +282,8 @@ export class RoomWizardStateService {
private updateStepsVisibility(): void { private updateStepsVisibility(): void {
const currentSteps = this._steps(); const currentSteps = this._steps();
const currentOptions = this._roomOptions(); const currentOptions = this._roomOptions();
// TODO: Uncomment when recording preferences are implemented // TODO: Uncomment when recording config is fully implemented
const recordingEnabled = false; // currentOptions.preferences?.recordingPreferences.enabled ?? false; const recordingEnabled = false; // currentOptions.config?.recordingConfig.enabled ?? false;
// Update recording steps visibility based on recordingEnabled // Update recording steps visibility based on recordingEnabled
const updatedSteps = currentSteps.map((step) => { const updatedSteps = currentSteps.map((step) => {
@ -414,7 +412,7 @@ export class RoomWizardStateService {
*/ */
resetWizard(): void { resetWizard(): void {
const defaultOptions: MeetRoomOptions = { const defaultOptions: MeetRoomOptions = {
preferences: DEFAULT_PREFERENCES config: DEFAULT_CONFIG
}; };
this._roomOptions.set(defaultOptions); this._roomOptions.set(defaultOptions);
this._steps.set([]); this._steps.set([]);

View File

@ -11,7 +11,7 @@
"test:e2e-core-room": "playwright test tests/e2e/core/room.test.ts", "test:e2e-core-room": "playwright test tests/e2e/core/room.test.ts",
"test:e2e-core-events": "playwright test tests/e2e/core/events.test.ts", "test:e2e-core-events": "playwright test tests/e2e/core/events.test.ts",
"test:e2e-core-webhooks": "playwright test tests/e2e/core/webhooks.test.ts", "test:e2e-core-webhooks": "playwright test tests/e2e/core/webhooks.test.ts",
"test:e2e-ui-features": "playwright test tests/e2e/ui-feature-preferences.test.ts", "test:e2e-ui-features": "playwright test tests/e2e/ui-feature-config.test.ts",
"test:e2e-recording-access": "playwright test tests/e2e/recording-access.test.ts", "test:e2e-recording-access": "playwright test tests/e2e/recording-access.test.ts",
"lint": "eslint 'src/**/*.ts'" "lint": "eslint 'src/**/*.ts'"
}, },

View File

@ -1,5 +1,5 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { MeetRecordingAccess } from '../../../../typings/src/room-preferences'; import { MeetRecordingAccess } from '../../../../typings/src/room-config';
import { MEET_TESTAPP_URL } from '../config'; import { MEET_TESTAPP_URL } from '../config';
import { import {
accessRoomAs, accessRoomAs,
@ -11,7 +11,7 @@ import {
loginAsAdmin, loginAsAdmin,
prepareForJoiningRoom, prepareForJoiningRoom,
startStopRecording, startStopRecording,
updateRoomPreferences, updateRoomConfig,
viewRecordingsAs, viewRecordingsAs,
waitForElementInIframe waitForElementInIframe
} from '../helpers/function-helpers'; } from '../helpers/function-helpers';
@ -72,15 +72,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should moderator not be able to access recording when access level is set to admin', async ({ page }) => { test('should moderator not be able to access recording when access level is set to admin', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN allowAccessTo: MeetRecordingAccess.ADMIN
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -93,15 +93,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should speaker 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( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN allowAccessTo: MeetRecordingAccess.ADMIN
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -114,15 +114,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should allow moderator to access recording when access level is set to moderator', async ({ page }) => { test('should allow moderator to access recording when access level is set to moderator', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -135,15 +135,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should speaker 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( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -156,15 +156,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should allow moderators to access recording when access level is set to speaker', async ({ page }) => { test('should allow moderators to access recording when access level is set to speaker', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -177,15 +177,15 @@ test.describe('Recording Access Tests', () => {
}); });
test('should allow speaker to access recording when access level is set to speaker', async ({ page }) => { test('should allow speaker to access recording when access level is set to speaker', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );

View File

@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test'; import { expect, test } from '@playwright/test';
import { MeetRecordingAccess } from '../../../../typings/src/room-preferences'; import { MeetRecordingAccess } from '../../../../typings/src/room-config';
import { MEET_TESTAPP_URL } from '../config'; import { MEET_TESTAPP_URL } from '../config';
import { import {
applyVirtualBackground, applyVirtualBackground,
@ -14,14 +14,14 @@ import {
loginAsAdmin, loginAsAdmin,
openMoreOptionsMenu, openMoreOptionsMenu,
prepareForJoiningRoom, prepareForJoiningRoom,
updateRoomPreferences, updateRoomConfig,
waitForElementInIframe, waitForElementInIframe,
waitForVirtualBackgroundToApply waitForVirtualBackgroundToApply
} from '../helpers/function-helpers'; } from '../helpers/function-helpers';
let subscribedToAppErrors = false; let subscribedToAppErrors = false;
test.describe('UI Feature Preferences Tests', () => { test.describe('UI Feature Config Tests', () => {
let roomId: string; let roomId: string;
let participantName: string; let participantName: string;
let adminCookie: string; let adminCookie: string;
@ -73,15 +73,15 @@ test.describe('UI Feature Preferences Tests', () => {
}); });
test('should show chat button when chat is enabled', async ({ page }) => { test('should show chat button when chat is enabled', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -97,15 +97,15 @@ test.describe('UI Feature Preferences Tests', () => {
test('should hide chat button when chat is disabled', async ({ page }) => { test('should hide chat button when chat is disabled', async ({ page }) => {
// Disable chat via API // Disable chat via API
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: false }, chatConfig: { enabled: false },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -126,15 +126,15 @@ test.describe('UI Feature Preferences Tests', () => {
test.describe('Recording Feature', () => { test.describe('Recording Feature', () => {
test('should show recording button for moderators', async ({ page }) => { test('should show recording button for moderators', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -160,15 +160,15 @@ test.describe('UI Feature Preferences Tests', () => {
}); });
test('should not show recording button for speaker', async ({ page }) => { test('should not show recording button for speaker', async ({ page }) => {
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -185,15 +185,15 @@ test.describe('UI Feature Preferences Tests', () => {
test('should not show recording button for moderators when recording is disabled', async ({ page }) => { test('should not show recording button for moderators when recording is disabled', async ({ page }) => {
// Disable recording via API // Disable recording via API
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: false, enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -226,15 +226,15 @@ test.describe('UI Feature Preferences Tests', () => {
}); });
test('should show virtual background button when enabled', async ({ page }) => { test('should show virtual background button when enabled', async ({ page }) => {
// Ensure virtual backgrounds are enabled // Ensure virtual backgrounds are enabled
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -255,15 +255,15 @@ test.describe('UI Feature Preferences Tests', () => {
test('should hide virtual background button when disabled', async ({ page }) => { test('should hide virtual background button when disabled', async ({ page }) => {
// Disable virtual backgrounds via API // Disable virtual backgrounds via API
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}, },
adminCookie adminCookie
); );
@ -284,15 +284,15 @@ test.describe('UI Feature Preferences Tests', () => {
page page
}) => { }) => {
// Ensure virtual backgrounds are enabled // Ensure virtual backgrounds are enabled
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}, },
adminCookie adminCookie
); );
@ -305,15 +305,15 @@ test.describe('UI Feature Preferences Tests', () => {
await waitForVirtualBackgroundToApply(page); await waitForVirtualBackgroundToApply(page);
// Now disable virtual backgrounds // Now disable virtual backgrounds
await updateRoomPreferences( await updateRoomConfig(
roomId, roomId,
{ {
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
virtualBackgroundPreferences: { enabled: false } virtualBackgroundConfig: { enabled: false }
}, },
adminCookie adminCookie
); );

View File

@ -1,7 +1,7 @@
import { expect, FrameLocator, Locator, Page } from '@playwright/test'; import { expect, FrameLocator, Locator, Page } from '@playwright/test';
import * as fs from 'fs'; import * as fs from 'fs';
import { PNG } from 'pngjs'; import { PNG } from 'pngjs';
import { MeetRecordingAccess, MeetRoomPreferences } from '../../../../typings/src/room-preferences'; import { MeetRecordingAccess, MeetRoomConfig } from '../../../../typings/src/room-config';
import { MEET_ADMIN_PASSWORD, MEET_ADMIN_USER, MEET_API_KEY, MEET_API_URL, MEET_TESTAPP_URL } from '../config'; import { MEET_ADMIN_PASSWORD, MEET_ADMIN_USER, MEET_API_KEY, MEET_API_URL, MEET_TESTAPP_URL } from '../config';
/** /**
@ -88,21 +88,18 @@ export async function interactWithElementInIframe(
} }
} }
// Helper function to get default room preferences // Helper function to get default room config
const getDefaultRoomPreferences = (): MeetRoomPreferences => ({ const getDefaultRoomConfig = (): MeetRoomConfig => ({
recordingPreferences: { recordingConfig: {
enabled: true, enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
}, },
chatPreferences: { enabled: true }, chatConfig: { enabled: true },
virtualBackgroundPreferences: { enabled: true } virtualBackgroundConfig: { enabled: true }
}); });
// Helper function to create a room for testing // Helper function to create a room for testing
export const createTestRoom = async ( export const createTestRoom = async (roomName: string, config: MeetRoomConfig = getDefaultRoomConfig()) => {
roomName: string,
preferences: MeetRoomPreferences = getDefaultRoomPreferences()
) => {
const response = await fetch(`${MEET_API_URL}/api/v1/rooms`, { const response = await fetch(`${MEET_API_URL}/api/v1/rooms`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -112,7 +109,7 @@ export const createTestRoom = async (
body: JSON.stringify({ body: JSON.stringify({
roomName, roomName,
autoDeletionDate: new Date(Date.now() + 61 * 60 * 1000).getTime(), // 1 hour from now autoDeletionDate: new Date(Date.now() + 61 * 60 * 1000).getTime(), // 1 hour from now
preferences config
}) })
}); });
@ -126,19 +123,19 @@ export const createTestRoom = async (
return room.roomId; return room.roomId;
}; };
// Helper function to update room preferences via REST API // Helper function to update room config via REST API
export const updateRoomPreferences = async (roomId: string, preferences: any, adminCookie: string) => { export const updateRoomConfig = async (roomId: string, config: any, adminCookie: string) => {
const response = await fetch(`${MEET_API_URL}/api/v1/rooms/${roomId}/preferences`, { const response = await fetch(`${MEET_API_URL}/api/v1/rooms/${roomId}/config`, {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Cookie: adminCookie Cookie: adminCookie
}, },
body: JSON.stringify({ preferences }) body: JSON.stringify({ config })
}); });
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to update room preferences: ${response.status} ${await response.text()}`); throw new Error(`Failed to update room config: ${response.status} ${await response.text()}`);
} }
return response.json(); return response.json();

View File

@ -62,7 +62,7 @@ html {
} }
/* Collapsible sections for room creation form */ /* Collapsible sections for room creation form */
.preferences-accordion { .config-accordion {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
} }

View File

@ -181,10 +181,10 @@
</div> </div>
</div> </div>
<!-- Preferences Accordion --> <!-- Config Accordion -->
<div class="preferences-accordion"> <div class="config-accordion">
<div class="accordion" id="preferencesAccordion"> <div class="accordion" id="configAccordion">
<!-- Chat Preferences --> <!-- Chat Config -->
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header"> <h2 class="accordion-header">
<button <button
@ -194,7 +194,7 @@
data-bs-target="#chatCollapse" data-bs-target="#chatCollapse"
aria-expanded="true" aria-expanded="true"
aria-controls="chatCollapse" aria-controls="chatCollapse"
data-testid="chat-preferences-toggle" data-testid="chat-config-toggle"
> >
Chat Settings Chat Settings
</button> </button>
@ -202,13 +202,13 @@
<div <div
id="chatCollapse" id="chatCollapse"
class="accordion-collapse collapse show" class="accordion-collapse collapse show"
data-bs-parent="#preferencesAccordion" data-bs-parent="#configAccordion"
> >
<div class="accordion-body"> <div class="accordion-body">
<div class="form-check"> <div class="form-check">
<input <input
type="checkbox" type="checkbox"
name="preferences.chatPreferences.enabled" name="config.chatConfig.enabled"
id="chat-enabled" id="chat-enabled"
class="form-check-input" class="form-check-input"
checked checked
@ -222,7 +222,7 @@
</div> </div>
</div> </div>
<!-- Recording Preferences --> <!-- Recording Config -->
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header"> <h2 class="accordion-header">
<button <button
@ -232,7 +232,7 @@
data-bs-target="#recordingCollapse" data-bs-target="#recordingCollapse"
aria-expanded="false" aria-expanded="false"
aria-controls="recordingCollapse" aria-controls="recordingCollapse"
data-testid="recording-preferences-toggle" data-testid="recording-config-toggle"
> >
Recording Settings Recording Settings
</button> </button>
@ -240,13 +240,13 @@
<div <div
id="recordingCollapse" id="recordingCollapse"
class="accordion-collapse collapse" class="accordion-collapse collapse"
data-bs-parent="#preferencesAccordion" data-bs-parent="#configAccordion"
> >
<div class="accordion-body"> <div class="accordion-body">
<div class="form-check mb-2"> <div class="form-check mb-2">
<input <input
type="checkbox" type="checkbox"
name="preferences.recordingPreferences.enabled" name="config.recordingConfig.enabled"
id="recording-enabled" id="recording-enabled"
class="form-check-input" class="form-check-input"
checked checked
@ -262,7 +262,7 @@
>Recording Access Level</label >Recording Access Level</label
> >
<select <select
name="preferences.recordingPreferences.allowAccessTo" name="config.recordingConfig.allowAccessTo"
id="recording-access" id="recording-access"
class="form-select" class="form-select"
data-testid="recording-access-select" data-testid="recording-access-select"
@ -280,7 +280,7 @@
</div> </div>
</div> </div>
<!-- Virtual Background Preferences --> <!-- Virtual Background Config -->
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header"> <h2 class="accordion-header">
<button <button
@ -290,7 +290,7 @@
data-bs-target="#backgroundCollapse" data-bs-target="#backgroundCollapse"
aria-expanded="false" aria-expanded="false"
aria-controls="backgroundCollapse" aria-controls="backgroundCollapse"
data-testid="background-preferences-toggle" data-testid="background-config-toggle"
> >
Virtual Background Settings Virtual Background Settings
</button> </button>
@ -298,13 +298,13 @@
<div <div
id="backgroundCollapse" id="backgroundCollapse"
class="accordion-collapse collapse" class="accordion-collapse collapse"
data-bs-parent="#preferencesAccordion" data-bs-parent="#configAccordion"
> >
<div class="accordion-body"> <div class="accordion-body">
<div class="form-check"> <div class="form-check">
<input <input
type="checkbox" type="checkbox"
name="preferences.virtualBackgroundPreferences.enabled" name="config.virtualBackgroundConfig.enabled"
id="virtual-background-enabled" id="virtual-background-enabled"
class="form-check-input" class="form-check-input"
checked checked

View File

@ -1,6 +1,6 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { getAllRooms, createRoom, deleteRoom, deleteAllRooms } from '../services/roomService';
import { deleteAllRecordings, getAllRecordings } from '../services/recordingService'; import { deleteAllRecordings, getAllRecordings } from '../services/recordingService';
import { createRoom, deleteAllRooms, deleteRoom, getAllRooms } from '../services/roomService';
export const getHome = async (_req: Request, res: Response) => { export const getHome = async (_req: Request, res: Response) => {
try { try {
@ -38,12 +38,12 @@ export const postCreateRoom = async (req: Request, res: Response) => {
try { try {
console.log('Creating room with body:', JSON.stringify(req.body, null, 2)); console.log('Creating room with body:', JSON.stringify(req.body, null, 2));
const { roomName, autoDeletionDate } = req.body; const { roomName, autoDeletionDate } = req.body;
const preferences = processFormPreferences(req.body); const config = processFormConfig(req.body);
console.log('Processed preferences:', JSON.stringify(preferences, null, 2)); console.log('Processed config:', JSON.stringify(config, null, 2));
console.log('Room creation parameters:', { roomName, autoDeletionDate }); console.log('Room creation parameters:', { roomName, autoDeletionDate });
const result = await createRoom({ roomName, autoDeletionDate, preferences }); const result = await createRoom({ roomName, autoDeletionDate, config });
console.log('Room created successfully:', result); console.log('Room created successfully:', result);
res.redirect('/'); res.redirect('/');
} catch (error) { } catch (error) {
@ -154,24 +154,24 @@ export const deleteAllRecordingsCtrl = async (_req: Request, res: Response) => {
}; };
/** /**
* Converts flat form data to nested MeetRoomPreferences object * Converts flat form data to nested MeetRoomConfig object
*/ */
const processFormPreferences = (body: any): any => { const processFormConfig = (body: any): any => {
const preferences = { const config = {
chatPreferences: { chatConfig: {
enabled: body['preferences.chatPreferences.enabled'] === 'on' enabled: body['config.chatConfig.enabled'] === 'on'
}, },
recordingPreferences: { recordingConfig: {
enabled: body['preferences.recordingPreferences.enabled'] === 'on', enabled: body['config.recordingConfig.enabled'] === 'on',
// Only include allowAccessTo if recording is enabled // Only include allowAccessTo if recording is enabled
...(body['preferences.recordingPreferences.enabled'] === 'on' && { ...(body['config.recordingConfig.enabled'] === 'on' && {
allowAccessTo: body['preferences.recordingPreferences.allowAccessTo'] || 'admin_moderator_speaker' allowAccessTo: body['config.recordingConfig.allowAccessTo'] || 'admin_moderator_speaker'
}) })
}, },
virtualBackgroundPreferences: { virtualBackgroundConfig: {
enabled: body['preferences.virtualBackgroundPreferences.enabled'] === 'on' enabled: body['config.virtualBackgroundConfig.enabled'] === 'on'
} }
}; };
return preferences; return config;
}; };

View File

@ -1,14 +1,14 @@
import { ParticipantRole } from './participant.js'; import { ParticipantRole } from './participant.js';
import { MeetRoomPreferences } from './room-preferences.js'; import { MeetRoomConfig } from './room-config.js';
export enum MeetSignalType { export enum MeetSignalType {
MEET_ROOM_PREFERENCES_UPDATED = 'meet_room_preferences_updated', MEET_ROOM_CONFIG_UPDATED = 'meet_room_config_updated',
MEET_PARTICIPANT_ROLE_UPDATED = 'meet_participant_role_updated' MEET_PARTICIPANT_ROLE_UPDATED = 'meet_participant_role_updated'
} }
export interface MeetRoomPreferencesUpdatedPayload { export interface MeetRoomConfigUpdatedPayload {
roomId: string; roomId: string;
preferences: MeetRoomPreferences; config: MeetRoomConfig;
timestamp: number; timestamp: number;
} }
@ -20,4 +20,4 @@ export interface MeetParticipantRoleUpdatedPayload {
timestamp: number; timestamp: number;
} }
export type MeetSignalPayload = MeetRoomPreferencesUpdatedPayload | MeetParticipantRoleUpdatedPayload; export type MeetSignalPayload = MeetRoomConfigUpdatedPayload | MeetParticipantRoleUpdatedPayload;

View File

@ -7,7 +7,7 @@ export * from './permissions/openvidu-permissions.js';
export * from './participant.js'; export * from './participant.js';
export * from './user.js'; export * from './user.js';
export * from './room-preferences.js'; export * from './room-config.js';
export * from './room.js'; export * from './room.js';
export * from './recording.model.js'; export * from './recording.model.js';
export * from './webhook.model.js'; export * from './webhook.model.js';

View File

@ -0,0 +1,30 @@
/**
* Interface representing the config for a room.
*/
export interface MeetRoomConfig {
chatConfig: MeetChatConfig;
recordingConfig: MeetRecordingConfig;
virtualBackgroundConfig: MeetVirtualBackgroundConfig;
}
/**
* Interface representing the config for recordings in a room.
*/
export interface MeetRecordingConfig {
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_SPEAKER = 'admin_moderator_speaker' // Admins, moderators and speakers can access
}
export interface MeetChatConfig {
enabled: boolean;
}
export interface MeetVirtualBackgroundConfig {
enabled: boolean;
}

View File

@ -1,30 +0,0 @@
/**
* Interface representing the preferences for a room.
*/
export interface MeetRoomPreferences {
chatPreferences: MeetChatPreferences;
recordingPreferences: MeetRecordingPreferences;
virtualBackgroundPreferences: MeetVirtualBackgroundPreferences;
}
/**
* Interface representing the preferences for recording.
*/
export interface MeetRecordingPreferences {
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_SPEAKER = 'admin_moderator_speaker' // Admins, moderators and speakers can access
}
export interface MeetChatPreferences {
enabled: boolean;
}
export interface MeetVirtualBackgroundPreferences {
enabled: boolean;
}

View File

@ -1,11 +1,11 @@
import { ParticipantPermissions, ParticipantRole } from './participant.js'; import { ParticipantPermissions, ParticipantRole } from './participant.js';
import { MeetRoomPreferences } from './room-preferences.js'; import { MeetRoomConfig } from './room-config.js';
interface BaseRoomOptions { interface BaseRoomOptions {
roomName?: string; roomName?: string;
autoDeletionDate?: number; autoDeletionDate?: number;
autoDeletionPolicy?: MeetRoomAutoDeletionPolicy; autoDeletionPolicy?: MeetRoomAutoDeletionPolicy;
preferences?: MeetRoomPreferences; config?: MeetRoomConfig;
// maxParticipants?: number | null; // maxParticipants?: number | null;
} }
@ -21,7 +21,7 @@ export interface MeetRoom extends BaseRoomOptions {
roomId: string; roomId: string;
roomName: string; roomName: string;
creationDate: number; creationDate: number;
preferences: MeetRoomPreferences; config: MeetRoomConfig;
moderatorUrl: string; moderatorUrl: string;
speakerUrl: string; speakerUrl: string;
status: MeetRoomStatus; status: MeetRoomStatus;