diff --git a/meet-ce/backend/tests/helpers/assertion-helpers.ts b/meet-ce/backend/tests/helpers/assertion-helpers.ts index 0547f9e1..d9647e68 100644 --- a/meet-ce/backend/tests/helpers/assertion-helpers.ts +++ b/meet-ce/backend/tests/helpers/assertion-helpers.ts @@ -1,18 +1,17 @@ import { expect } from '@jest/globals'; import { + LiveKitPermissions, MeetingEndAction, - MeetRecordingAccess, MeetRecordingInfo, MeetRecordingLayout, MeetRecordingStatus, MeetRoom, MeetRoomAutoDeletionPolicy, MeetRoomConfig, - MeetRoomDeletionPolicyWithMeeting, - MeetRoomDeletionPolicyWithRecordings, MeetRoomMemberPermissions, MeetRoomMemberRole, - MeetRoomStatus + MeetRoomStatus, + TrackSource } from '@openvidu-meet/typings'; import { Response } from 'supertest'; import { container } from '../../src/config/dependency-injector.config'; @@ -136,16 +135,12 @@ export const expectValidRoom = ( expect(room.autoDeletionDate).toBe(autoDeletionDate); } else { expect(room.autoDeletionDate).toBeUndefined(); + expect(room.autoDeletionPolicy).toBeUndefined(); } if (autoDeletionPolicy !== undefined) { expect(room.autoDeletionPolicy).toBeDefined(); expect(room.autoDeletionPolicy).toEqual(autoDeletionPolicy); - } else { - expect(room.autoDeletionPolicy).toEqual({ - withMeeting: MeetRoomDeletionPolicyWithMeeting.WHEN_MEETING_ENDS, - withRecordings: MeetRoomDeletionPolicyWithRecordings.CLOSE - }); } expect(room.config).toBeDefined(); @@ -156,8 +151,7 @@ export const expectValidRoom = ( expect(room.config).toEqual({ recording: { enabled: true, - layout: MeetRecordingLayout.GRID, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.GRID }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -165,10 +159,21 @@ export const expectValidRoom = ( }); } - expect(room.moderatorUrl).toBeDefined(); - expect(room.speakerUrl).toBeDefined(); - expect(room.moderatorUrl).toContain(room.roomId); - expect(room.speakerUrl).toContain(room.roomId); + expect(room.owner).toBeDefined(); + expect(room.roles).toBeDefined(); + + expect(room.anonymous).toBeDefined(); + expect(room.anonymous.moderator).toBeDefined(); + expect(room.anonymous.speaker).toBeDefined(); + expect(room.anonymous.moderator.enabled).toBeDefined(); + expect(room.anonymous.speaker.enabled).toBeDefined(); + expect(room.anonymous.moderator.accessUrl).toBeDefined(); + expect(room.anonymous.speaker.accessUrl).toBeDefined(); + expect(room.anonymous.moderator.accessUrl).toContain(room.roomId); + expect(room.anonymous.speaker.accessUrl).toContain(room.roomId); + + expect(room.accessUrl).toBeDefined(); + expect(room.accessUrl).toContain(room.roomId); expect(room.status).toBeDefined(); expect(room.status).toEqual(status || MeetRoomStatus.OPEN); @@ -518,90 +523,13 @@ export const expectValidGetRecordingUrlResponse = (response: Response, recording expect(parsedUrl.searchParams.get('secret')).toBeDefined(); }; -export const expectValidRoomMemberRolesAndPermissionsResponse = (response: Response, roomId: string) => { - expect(response.status).toBe(200); - expect(response.body).toEqual( - expect.arrayContaining([ - { - role: MeetRoomMemberRole.MODERATOR, - permissions: getPermissions(roomId, MeetRoomMemberRole.MODERATOR, true, true) - }, - { - role: MeetRoomMemberRole.SPEAKER, - permissions: getPermissions(roomId, MeetRoomMemberRole.SPEAKER, true, false) - } - ]) - ); -}; - -export const expectValidRoomMemberRoleAndPermissionsResponse = ( - response: Response, - roomId: string, - role: MeetRoomMemberRole -) => { - expect(response.status).toBe(200); - expect(response.body).toEqual({ - role: role, - permissions: getPermissions(roomId, role, true, role === MeetRoomMemberRole.MODERATOR) - }); -}; - -export const getPermissions = ( - roomId: string, - role: MeetRoomMemberRole, - canRetrieveRecordings: boolean, - canDeleteRecordings: boolean, - addJoinPermission = true -): MeetRoomMemberPermissions => { - switch (role) { - case MeetRoomMemberRole.MODERATOR: - return { - livekit: { - roomJoin: addJoinPermission, - room: roomId, - canPublish: true, - canSubscribe: true, - canPublishData: true, - canUpdateOwnMetadata: true - }, - meet: { - canRecord: true, - canRetrieveRecordings, - canDeleteRecordings, - canChat: true, - canChangeVirtualBackground: true - } - }; - case MeetRoomMemberRole.SPEAKER: - return { - livekit: { - roomJoin: addJoinPermission, - room: roomId, - canPublish: true, - canSubscribe: true, - canPublishData: true, - canUpdateOwnMetadata: true - }, - meet: { - canRecord: false, - canRetrieveRecordings, - canDeleteRecordings, - canChat: true, - canChangeVirtualBackground: true - } - }; - } -}; - export const expectValidRoomMemberTokenResponse = ( response: Response, roomId: string, - role: MeetRoomMemberRole, - addJoinPermission = false, + baseRole: MeetRoomMemberRole, + joinMeeting = false, participantName?: string, - participantIdentityPrefix?: string, - canRetrieveRecordings?: boolean, - canDeleteRecordings?: boolean + participantIdentityPrefix?: string ) => { expect(response.status).toBe(200); expect(response.body).toHaveProperty('token'); @@ -609,11 +537,7 @@ export const expectValidRoomMemberTokenResponse = ( const token = response.body.token; const decodedToken = decodeJWTToken(token); - canRetrieveRecordings = canRetrieveRecordings ?? true; - canDeleteRecordings = canDeleteRecordings ?? role === MeetRoomMemberRole.MODERATOR; - const permissions = getPermissions(roomId, role, canRetrieveRecordings, canDeleteRecordings, addJoinPermission); - - if (addJoinPermission) { + if (joinMeeting) { expect(participantName).toBeDefined(); expect(decodedToken).toHaveProperty('name', participantName); expect(decodedToken).toHaveProperty('sub'); @@ -621,17 +545,88 @@ export const expectValidRoomMemberTokenResponse = ( if (participantIdentityPrefix) { expect(decodedToken.sub?.startsWith(participantIdentityPrefix)).toBe(true); } + + // const livekitPermissions = getLiveKitPermissions(roomId, getPermissions(baseRole)); + expect(decodedToken).toHaveProperty('video'); } else { expect(decodedToken).not.toHaveProperty('name'); expect(decodedToken).not.toHaveProperty('sub'); + expect(decodedToken).not.toHaveProperty('video'); } - expect(decodedToken).toHaveProperty('video', permissions.livekit); expect(decodedToken).toHaveProperty('metadata'); const metadata = JSON.parse(decodedToken.metadata || '{}'); expect(metadata).toHaveProperty('livekitUrl'); - expect(metadata).toHaveProperty('role', role); - expect(metadata).toHaveProperty('permissions', permissions.meet); + expect(metadata).toHaveProperty('baseRole', baseRole); + const permissions = getPermissions(baseRole); + expect(metadata).toHaveProperty('effectivePermissions', permissions); +}; + +export const getPermissions = (role: MeetRoomMemberRole): MeetRoomMemberPermissions => { + switch (role) { + case MeetRoomMemberRole.MODERATOR: + return { + canRecord: true, + canRetrieveRecordings: true, + canDeleteRecordings: true, + canJoinMeeting: true, + canShareAccessLinks: true, + canMakeModerator: true, + canKickParticipants: true, + canEndMeeting: true, + canPublishVideo: true, + canPublishAudio: true, + canShareScreen: true, + canReadChat: true, + canWriteChat: true, + canChangeVirtualBackground: true + }; + case MeetRoomMemberRole.SPEAKER: + return { + canRecord: false, + canRetrieveRecordings: true, + canDeleteRecordings: false, + canJoinMeeting: true, + canShareAccessLinks: false, + canMakeModerator: false, + canKickParticipants: false, + canEndMeeting: false, + canPublishVideo: true, + canPublishAudio: true, + canShareScreen: true, + canReadChat: true, + canWriteChat: true, + canChangeVirtualBackground: true + }; + } +}; + +const getLiveKitPermissions = (roomId: string, permissions: MeetRoomMemberPermissions): LiveKitPermissions => { + const canPublishSources: TrackSource[] = []; + + if (permissions.canPublishAudio) { + canPublishSources.push(TrackSource.MICROPHONE); + } + + if (permissions.canPublishVideo) { + canPublishSources.push(TrackSource.CAMERA); + } + + if (permissions.canShareScreen) { + canPublishSources.push(TrackSource.SCREEN_SHARE); + canPublishSources.push(TrackSource.SCREEN_SHARE_AUDIO); + } + + const livekitPermissions: LiveKitPermissions = { + room: roomId, + roomJoin: true, + canPublish: permissions.canPublishAudio || permissions.canPublishVideo || permissions.canShareScreen, + canPublishSources, + canSubscribe: true, + canPublishData: true, + canUpdateOwnMetadata: true + }; + return livekitPermissions; }; const decodeJWTToken = (token: string) => { diff --git a/meet-ce/backend/tests/helpers/request-helpers.ts b/meet-ce/backend/tests/helpers/request-helpers.ts index 94845776..39fbf7d1 100644 --- a/meet-ce/backend/tests/helpers/request-helpers.ts +++ b/meet-ce/backend/tests/helpers/request-helpers.ts @@ -1,8 +1,6 @@ import { expect } from '@jest/globals'; import { - AuthMode, MeetAppearanceConfig, - MeetRecordingAccess, MeetRecordingInfo, MeetRecordingStatus, MeetRoom, @@ -30,13 +28,6 @@ import { GlobalConfigService } from '../../src/services/global-config.service.js import { RecordingService } from '../../src/services/recording.service.js'; import { RoomScheduledTasksService } from '../../src/services/room-scheduled-tasks.service.js'; -const CREDENTIALS = { - admin: { - username: MEET_ENV.INITIAL_ADMIN_USER, - password: MEET_ENV.INITIAL_ADMIN_PASSWORD - } -}; - let app: Express; const fakeParticipantsProcesses = new Map(); @@ -58,7 +49,7 @@ export const startTestServer = async (): Promise => { export const generateApiKey = async (): Promise => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -71,7 +62,7 @@ export const generateApiKey = async (): Promise => { export const getApiKeys = async () => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -82,7 +73,7 @@ export const getApiKeys = async () => { export const deleteApiKeys = async () => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .delete(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -115,7 +106,7 @@ export const getRoomsAppearanceConfig = async () => { export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppearanceConfig }) => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/rooms/appearance`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -126,7 +117,7 @@ export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppe export const getWebbhookConfig = async () => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -137,7 +128,7 @@ export const getWebbhookConfig = async () => { export const updateWebbhookConfig = async (config: WebhookConfig) => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -165,7 +156,7 @@ export const getSecurityConfig = async () => { export const updateSecurityConfig = async (config: SecurityConfig) => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/security`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) @@ -173,17 +164,6 @@ export const updateSecurityConfig = async (config: SecurityConfig) => { return response; }; -export const changeSecurityConfig = async (authMode: AuthMode) => { - // Get current config to avoid overwriting other properties - let response = await getSecurityConfig(); - expect(response.status).toBe(200); - const currentConfig = response.body; - - currentConfig.authentication.authModeToAccessRoom = authMode; - response = await updateSecurityConfig(currentConfig); - expect(response.status).toBe(200); -}; - export const restoreDefaultGlobalConfig = async () => { const configService = container.get(GlobalConfigService); const defaultGlobalConfig = configService['getDefaultConfig'](); @@ -191,25 +171,28 @@ export const restoreDefaultGlobalConfig = async () => { }; /** - * Logs in a user and returns the access token in the format "Bearer " + * Logs in admin user and returns the access token in the format "Bearer " */ -export const loginUser = async (): Promise => { +export const loginAdminUser = async (): Promise => { checkAppIsRunning(); const response = await request(app) .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth/login`) - .send(CREDENTIALS.admin) + .send({ + username: MEET_ENV.INITIAL_ADMIN_USER, + password: MEET_ENV.INITIAL_ADMIN_PASSWORD + }) .expect(200); expect(response.body).toHaveProperty('accessToken'); return `Bearer ${response.body.accessToken}`; }; -export const getProfile = async (accessToken: string) => { +export const getMe = async (accessToken: string) => { checkAppIsRunning(); return await request(app) - .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/profile`) + .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/me`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) .send(); }; @@ -284,16 +267,6 @@ export const updateRoomConfig = async (roomId: string, config: Partial { - const response = await updateRoomConfig(roomId, { - recording: { - enabled: true, - allowAccessTo: recordingAccess - } - }); - expect(response.status).toBe(200); -}; - export const updateRoomStatus = async (roomId: string, status: MeetRoomStatus) => { checkAppIsRunning(); @@ -368,14 +341,14 @@ export const runExpiredRoomsGC = async () => { * Runs the inconsistent rooms garbage collector. * * This function retrieves the RoomScheduledTasksService from the dependency injection container - * and calls its checkInconsistentRooms method to clean up inconsistent rooms. + * and calls its validateRoomsStatusGC method to clean up inconsistent rooms. * It then waits for 1 second before completing. */ export const executeRoomStatusValidationGC = async () => { checkAppIsRunning(); const roomTaskScheduler = container.get(RoomScheduledTasksService); - await (roomTaskScheduler as any)['validateRoomsStatusGC'](); + await (roomTaskScheduler)['validateRoomsStatusGC'](); await sleep('1s'); }; @@ -386,33 +359,11 @@ export const runReleaseActiveRecordingLock = async (roomId: string) => { await recordingService.releaseRecordingLockIfNoEgress(roomId); }; -export const getRoomMemberRoles = async (roomId: string) => { - checkAppIsRunning(); - - const response = await request(app) - .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/roles`) - .send(); - return response; -}; - -export const getRoomMemberRoleBySecret = async (roomId: string, secret: string) => { - checkAppIsRunning(); - - const response = await request(app) - .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/roles/${secret}`) - .send(); - return response; -}; - export const generateRoomMemberTokenRequest = async (roomId: string, tokenOptions: MeetRoomMemberTokenOptions) => { checkAppIsRunning(); - // Disable authentication to generate the token - await changeSecurityConfig(AuthMode.NONE); - - // Generate the room member token const response = await request(app) - .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/token`) + .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/members/token`) .send(tokenOptions); return response; }; @@ -760,7 +711,7 @@ export const deleteAllRecordings = async () => { export const getAnalytics = async () => { checkAppIsRunning(); - const accessToken = await loginUser(); + const accessToken = await loginAdminUser(); const response = await request(app) .get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) diff --git a/meet-ce/backend/tests/helpers/test-scenarios.ts b/meet-ce/backend/tests/helpers/test-scenarios.ts index 58986716..85d8f302 100644 --- a/meet-ce/backend/tests/helpers/test-scenarios.ts +++ b/meet-ce/backend/tests/helpers/test-scenarios.ts @@ -37,8 +37,8 @@ export const setupSingleRoom = async ( // Extract the room secrets and generate room member tokens const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room); const [moderatorToken, speakerToken] = await Promise.all([ - generateRoomMemberToken(room.roomId, { secret: moderatorSecret, grantJoinMeetingPermission: false }), - generateRoomMemberToken(room.roomId, { secret: speakerSecret, grantJoinMeetingPermission: false }) + generateRoomMemberToken(room.roomId, { secret: moderatorSecret, joinMeeting: false }), + generateRoomMemberToken(room.roomId, { secret: speakerSecret, joinMeeting: false }) ]); // Join participant if needed diff --git a/meet-ce/backend/tests/integration/api/api-keys/create-api-key.test.ts b/meet-ce/backend/tests/integration/api/api-keys/create-api-key.test.ts index 6628a88e..3129312c 100644 --- a/meet-ce/backend/tests/integration/api/api-keys/create-api-key.test.ts +++ b/meet-ce/backend/tests/integration/api/api-keys/create-api-key.test.ts @@ -5,7 +5,7 @@ import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js'; import { generateApiKey, getApiKeys, - loginUser, + loginAdminUser, restoreDefaultApiKeys, startTestServer } from '../../../helpers/request-helpers.js'; @@ -18,7 +18,7 @@ describe('API Keys API Tests', () => { beforeAll(async () => { app = await startTestServer(); - adminAccessToken = await loginUser(); + adminAccessToken = await loginAdminUser(); }); afterAll(async () => { diff --git a/meet-ce/backend/tests/integration/api/auth/login.test.ts b/meet-ce/backend/tests/integration/api/auth/login.test.ts index 6485a8cb..9a634430 100644 --- a/meet-ce/backend/tests/integration/api/auth/login.test.ts +++ b/meet-ce/backend/tests/integration/api/auth/login.test.ts @@ -15,7 +15,7 @@ describe('Authentication API Tests', () => { }); describe('Login Tests', () => { - it('should successfully login with valid credentials', async () => { + it('should successfully login with valid root admin credentials', async () => { const response = await request(app) .post(`${AUTH_PATH}/login`) .send({ diff --git a/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts b/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts index a1d76b3c..6ac678c6 100644 --- a/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts +++ b/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts @@ -14,7 +14,7 @@ describe('Authentication API Tests', () => { }); describe('Refresh Token Tests', () => { - it('should successfully refresh token with valid refresh token', async () => { + it('should successfully refresh access token with valid refresh token', async () => { // First, login to get a valid refresh token const loginResponse = await request(app) .post(`${AUTH_PATH}/login`) diff --git a/meet-ce/backend/tests/integration/api/global-config/security.test.ts b/meet-ce/backend/tests/integration/api/global-config/security.test.ts index f55765d4..80d06f4c 100644 --- a/meet-ce/backend/tests/integration/api/global-config/security.test.ts +++ b/meet-ce/backend/tests/integration/api/global-config/security.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeAll, describe, expect, it } from '@jest/globals'; -import { AuthMode, AuthType, SecurityConfig } from '@openvidu-meet/typings'; +import { SecurityConfig } from '@openvidu-meet/typings'; import { expectValidationError } from '../../../helpers/assertion-helpers.js'; import { getSecurityConfig, @@ -19,12 +19,10 @@ describe('Security Config API Tests', () => { describe('Update security config', () => { it('should update security config with valid complete data', async () => { - const validConfig = { + const validConfig: SecurityConfig = { authentication: { - authMethod: { - type: AuthType.SINGLE_USER - }, - authModeToAccessRoom: AuthMode.ALL_USERS + allowUserCreation: true, + oauthProviders: [] } }; let response = await updateSecurityConfig(validConfig); @@ -39,75 +37,57 @@ describe('Security Config API Tests', () => { }); describe('Update security config validation', () => { - it('should reject when authModeToAccessRoom is not a valid enum value', async () => { + it('should reject when allowUserCreation is not a boolean', async () => { const response = await updateSecurityConfig({ authentication: { - authMethod: { - type: AuthType.SINGLE_USER - }, - authModeToAccessRoom: 'invalid' + allowUserCreation: 'invalid' } } as unknown as SecurityConfig); - - expectValidationError( - response, - 'authentication.authModeToAccessRoom', - "Invalid enum value. Expected 'none' | 'moderators_only' | 'all_users', received 'invalid'" - ); + expectValidationError(response, 'authentication.allowUserCreation', 'Expected boolean, received string'); }); - it('should reject when authType is not a valid enum value', async () => { + it('should reject when oauthProviders is not an array', async () => { const response = await updateSecurityConfig({ authentication: { - authMethod: { - type: 'invalid' - }, - authModeToAccessRoom: AuthMode.ALL_USERS + allowUserCreation: true, + oauthProviders: 'invalid' } } as unknown as SecurityConfig); - - expectValidationError( - response, - 'authentication.authMethod.type', - "Invalid enum value. Expected 'single_user', received 'invalid'" - ); + expectValidationError(response, 'authentication.oauthProviders', 'Expected array, received string'); }); - it('should reject when authModeToAccessRoom or authMethod are not provided', async () => { - let response = await updateSecurityConfig({ + it('should reject when allowUserCreation is not provided', async () => { + const response = await updateSecurityConfig({ authentication: { - authModeToAccessRoom: AuthMode.NONE + oauthProviders: [] } } as unknown as SecurityConfig); - expectValidationError(response, 'authentication.authMethod', 'Required'); + expectValidationError(response, 'authentication.allowUserCreation', 'Required'); + }); - response = await updateSecurityConfig({ + it('should reject when oauthProviders is not provided', async () => { + const response = await updateSecurityConfig({ authentication: { - authMethod: { - type: AuthType.SINGLE_USER - } + allowUserCreation: true } - } as unknown as SecurityConfig); - expectValidationError(response, 'authentication.authModeToAccessRoom', 'Required'); + } as SecurityConfig); + expectValidationError(response, 'authentication.oauthProviders', 'Required'); }); it('should reject when authentication is not an object', async () => { const response = await updateSecurityConfig({ authentication: 'invalid' } as unknown as SecurityConfig); - expectValidationError(response, 'authentication', 'Expected object, received string'); }); }); describe('Get security config', () => { it('should return security config when authenticated as admin', async () => { - const defaultConfig = { + const defaultConfig: SecurityConfig = { authentication: { - authMethod: { - type: AuthType.SINGLE_USER - }, - authModeToAccessRoom: AuthMode.NONE + allowUserCreation: true, + oauthProviders: [] } }; diff --git a/meet-ce/backend/tests/integration/api/meetings/update-participant.test.ts b/meet-ce/backend/tests/integration/api/meetings/update-participant.test.ts index 3ed62ad6..36bc0fee 100644 --- a/meet-ce/backend/tests/integration/api/meetings/update-participant.test.ts +++ b/meet-ce/backend/tests/integration/api/meetings/update-participant.test.ts @@ -33,11 +33,12 @@ describe('Meetings API Tests', () => { }); describe('Update Participant Tests', () => { - const setParticipantMetadata = async (roomId: string, role: MeetRoomMemberRole) => { + const setParticipantMetadata = async (roomId: string, baseRole: MeetRoomMemberRole) => { const metadata: MeetRoomMemberTokenMetadata = { livekitUrl: MEET_ENV.LIVEKIT_URL, - role, - permissions: getPermissions(roomId, role, true, true).meet + roomId, + baseRole, + effectivePermissions: getPermissions(baseRole) }; await updateParticipantMetadata(roomId, participantIdentity, metadata); }; @@ -65,7 +66,10 @@ describe('Meetings API Tests', () => { expect(participant).toBeDefined(); expect(participant).toHaveProperty('metadata'); const metadata = JSON.parse(participant.metadata || '{}'); - expect(metadata).toHaveProperty('role', MeetRoomMemberRole.MODERATOR); + expect(metadata).toHaveProperty('roomId', roomData.room.roomId); + expect(metadata).toHaveProperty('baseRole', MeetRoomMemberRole.MODERATOR); + const permissions = getPermissions(MeetRoomMemberRole.MODERATOR); + expect(metadata).toHaveProperty('effectivePermissions', permissions); // Verify sendSignal method has been called twice expect(sendSignalSpy).toHaveBeenCalledTimes(2); @@ -119,7 +123,10 @@ describe('Meetings API Tests', () => { expect(participant).toBeDefined(); expect(participant).toHaveProperty('metadata'); const metadata = JSON.parse(participant.metadata || '{}'); - expect(metadata).toHaveProperty('role', MeetRoomMemberRole.SPEAKER); + expect(metadata).toHaveProperty('roomId', roomData.room.roomId); + expect(metadata).toHaveProperty('baseRole', MeetRoomMemberRole.SPEAKER); + const permissions = getPermissions(MeetRoomMemberRole.SPEAKER); + expect(metadata).toHaveProperty('effectivePermissions', permissions); }); it('should fail with 404 if participant does not exist', async () => { diff --git a/meet-ce/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts b/meet-ce/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts index ecba9eb9..a4ef160a 100644 --- a/meet-ce/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts +++ b/meet-ce/backend/tests/integration/api/recordings/bulk-delete-recording.test.ts @@ -164,7 +164,7 @@ describe('Recording API Tests', () => { it('should handle empty recordingIds array gracefully', async () => { const response = await bulkDeleteRecordings([]); - expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item'); + expectValidationError(response, 'recordingIds', 'At least one recordingId is required'); }); it('should reject a CSV string with invalid format', async () => { @@ -178,7 +178,7 @@ describe('Recording API Tests', () => { const invalidRecordingIds = ['', ' ']; const response = await bulkDeleteRecordings(invalidRecordingIds); - expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item'); + expectValidationError(response, 'recordingIds', 'At least one recordingId is required'); }); it('should reject an array with mixed valid and totally invalid IDs', async () => { diff --git a/meet-ce/backend/tests/integration/api/recordings/download-recordings.test.ts b/meet-ce/backend/tests/integration/api/recordings/download-recordings.test.ts index a2f6d31b..f8274d42 100644 --- a/meet-ce/backend/tests/integration/api/recordings/download-recordings.test.ts +++ b/meet-ce/backend/tests/integration/api/recordings/download-recordings.test.ts @@ -92,7 +92,7 @@ describe('Recording API Tests', () => { it('should handle empty recordingIds array gracefully', async () => { const response = await downloadRecordings([], false); - expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item'); + expectValidationError(response, 'recordingIds', 'At least one recordingId is required'); }); it('should reject an array with mixed valid and totally invalid IDs', async () => { @@ -106,7 +106,7 @@ describe('Recording API Tests', () => { const invalidRecordingIds = ['', ' ']; const response = await downloadRecordings(invalidRecordingIds, false); - expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item'); + expectValidationError(response, 'recordingIds', 'At least one recordingId is required'); }); }); }); diff --git a/meet-ce/backend/tests/integration/api/rooms/create-room.test.ts b/meet-ce/backend/tests/integration/api/rooms/create-room.test.ts index de9e2997..c16cfe01 100644 --- a/meet-ce/backend/tests/integration/api/rooms/create-room.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/create-room.test.ts @@ -1,6 +1,5 @@ import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; import { - MeetRecordingAccess, MeetRecordingLayout, MeetRoomDeletionPolicyWithMeeting, MeetRoomDeletionPolicyWithRecordings @@ -61,8 +60,7 @@ describe('Room API Tests', () => { config: { recording: { enabled: false, - layout: MeetRecordingLayout.GRID, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.GRID }, chat: { enabled: false }, virtualBackground: { enabled: true }, @@ -98,8 +96,7 @@ describe('Room API Tests', () => { const expectedConfig = { recording: { enabled: false, - layout: MeetRecordingLayout.GRID, // Default value - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER // Default value + layout: MeetRecordingLayout.GRID // Default value }, chat: { enabled: true }, // Default value virtualBackground: { enabled: true }, // Default value @@ -127,8 +124,7 @@ describe('Room API Tests', () => { const expectedConfig = { recording: { enabled: true, // Default value - layout: MeetRecordingLayout.GRID, // Default value - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER // Default value + layout: MeetRecordingLayout.GRID // Default value }, chat: { enabled: false }, virtualBackground: { enabled: false }, @@ -492,8 +488,7 @@ describe('Room API Tests', () => { autoDeletionDate: validAutoDeletionDate, config: { recording: { - enabled: 'yes', // invalid boolean - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: 'yes' // invalid boolean }, chat: { enabled: true }, virtualBackground: { enabled: true } diff --git a/meet-ce/backend/tests/integration/api/rooms/e2ee-room-config.test.ts b/meet-ce/backend/tests/integration/api/rooms/e2ee-room-config.test.ts index a1f2b6af..65ece15a 100644 --- a/meet-ce/backend/tests/integration/api/rooms/e2ee-room-config.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/e2ee-room-config.test.ts @@ -1,5 +1,5 @@ import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; -import { MeetRecordingAccess, MeetRoom } from '@openvidu-meet/typings'; +import { MeetRoom } from '@openvidu-meet/typings'; import { Express } from 'express'; import request from 'supertest'; import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js'; @@ -48,8 +48,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'Test E2EE Enabled', config: { recording: { - enabled: true, // This should be automatically disabled - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true // This should be automatically disabled }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -87,8 +86,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'Test E2EE Update', config: { recording: { - enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -122,8 +120,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'Test Invalid E2EE', config: { recording: { - enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -145,8 +142,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'Test Invalid E2EE Enabled', config: { recording: { - enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -174,8 +170,7 @@ describe('E2EE Room Configuration Tests', () => { const { status, body } = await updateRoomConfig(room.roomId, { recording: { - enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: false }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -201,8 +196,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'E2EE Enabled Room', config: { recording: { - enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: false }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -214,8 +208,7 @@ describe('E2EE Room Configuration Tests', () => { roomName: 'E2EE Disabled Room', config: { recording: { - enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true }, chat: { enabled: true }, virtualBackground: { enabled: true }, diff --git a/meet-ce/backend/tests/integration/api/rooms/generate-room-member-token.test.ts b/meet-ce/backend/tests/integration/api/rooms/generate-room-member-token.test.ts index bad1e60c..99e5a2e6 100644 --- a/meet-ce/backend/tests/integration/api/rooms/generate-room-member-token.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/generate-room-member-token.test.ts @@ -1,10 +1,5 @@ import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; -import { - MeetRecordingAccess, - MeetRoomMemberRole, - MeetRoomMemberTokenOptions, - MeetRoomStatus -} from '@openvidu-meet/typings'; +import { MeetRoomMemberRole, MeetRoomStatus } from '@openvidu-meet/typings'; import { expectValidationError, expectValidRoomMemberTokenResponse } from '../../../helpers/assertion-helpers.js'; import { deleteAllRooms, @@ -12,7 +7,6 @@ import { endMeeting, generateRoomMemberTokenRequest, startTestServer, - updateRecordingAccessConfigInRoom, updateRoomStatus } from '../../../helpers/request-helpers.js'; import { setupSingleRoom } from '../../../helpers/test-scenarios.js'; @@ -48,18 +42,18 @@ describe('Room API Tests', () => { expectValidRoomMemberTokenResponse(response, roomId, MeetRoomMemberRole.SPEAKER); }); - it('should generate a room member token without join meeting permission when not specifying grantJoinMeetingPermission', async () => { + it('should generate a room member token without join meeting permission when not specifying joinMeeting', async () => { const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret }); expectValidRoomMemberTokenResponse(response, roomId, MeetRoomMemberRole.MODERATOR, false); }); - it('should generate a room member token with join meeting permission when specifying grantJoinMeetingPermission true and participantName', async () => { + it('should generate a room member token to join meeting when specifying joinMeeting true and participantName', async () => { const participantName = 'TEST_PARTICIPANT'; const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName }); expectValidRoomMemberTokenResponse( @@ -75,13 +69,13 @@ describe('Room API Tests', () => { await endMeeting(roomId, roomData.moderatorToken); }); - it('should success when when specifying grantJoinMeetingPermission true and participant already exists in the room', async () => { + it('should success when specifying joinMeeting true and participant already exists in the room', async () => { const participantName = 'TEST_PARTICIPANT'; // Create token for the first participant let response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName }); expectValidRoomMemberTokenResponse( @@ -96,7 +90,7 @@ describe('Room API Tests', () => { // Create token for the second participant with the same name response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName }); expectValidRoomMemberTokenResponse( @@ -112,7 +106,7 @@ describe('Room API Tests', () => { await endMeeting(roomId, roomData.moderatorToken); }); - it('should refresh a room member token with join meeting permission for an existing participant', async () => { + it('should refresh a room member token to join meeting for an existing participant', async () => { const participantName = 'TEST_PARTICIPANT'; // Create room with initial participant @@ -121,7 +115,7 @@ describe('Room API Tests', () => { // Refresh token for the participant by specifying participantIdentity const response = await generateRoomMemberTokenRequest(roomWithParticipant.room.roomId, { secret: roomWithParticipant.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName, participantIdentity: participantName }); @@ -135,13 +129,13 @@ describe('Room API Tests', () => { ); }); - it('should fail with 409 when generating a room member token with join meeting permission and room is closed', async () => { + it('should fail with 409 when generating a room member token to join meeting and room is closed', async () => { // Close the room await updateRoomStatus(roomId, MeetRoomStatus.CLOSED); const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName: 'TEST_PARTICIPANT' }); expect(response.status).toBe(409); @@ -161,7 +155,7 @@ describe('Room API Tests', () => { const participantName = 'NON_EXISTENT_PARTICIPANT'; const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true, + joinMeeting: true, participantName, participantIdentity: participantName }); @@ -176,149 +170,21 @@ describe('Room API Tests', () => { }); }); - describe('Generate Room Member Token Recording Permissions Tests', () => { - afterAll(async () => { - // Reset recording access to default for other tests - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER); - }); - - it(`should generate a room member token with canRetrieve and canDelete permissions - when using the moderator secret and recording access is admin_moderator_speaker`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.MODERATOR, - false, - undefined, - undefined, - true, // canRetrieveRecordings - true // canDeleteRecordings - ); - }); - - it(`should generate a room member token with canRetrieve permission but not canDelete - when using the speaker secret and recording access is admin_moderator_speaker`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.SPEAKER, - false, - undefined, - undefined, - true, // canRetrieveRecordings - false // canDeleteRecordings - ); - }); - - it(`should generate a room member token with canRetrieve and canDelete permissions - when using the moderator secret and recording access is admin_moderator`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.MODERATOR, - false, - undefined, - undefined, - true, // canRetrieveRecordings - true // canDeleteRecordings - ); - }); - - it(`should generate a room member token without any permissions - when using the speaker secret and recording access is admin_moderator`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.SPEAKER, - false, - undefined, - undefined, - false, // canRetrieveRecordings - false // canDeleteRecordings - ); - }); - - it(`should generate a room member token without any permissions - when using the moderator secret and recording access is admin`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.MODERATOR, - false, - undefined, - undefined, - false, // canRetrieveRecordings - false // canDeleteRecordings - ); - }); - - it(`should generate a room member token without any permissions - when using the speaker secret and recording access is admin`, async () => { - await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN); - - const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret }); - expectValidRoomMemberTokenResponse( - response, - roomId, - MeetRoomMemberRole.SPEAKER, - false, - undefined, - undefined, - false, // canRetrieveRecordings - false // canDeleteRecordings - ); - }); - }); - describe('Generate Room Member Token Validation Tests', () => { - it('should fail when secret is not provided', async () => { - const response = await generateRoomMemberTokenRequest( - roomData.room.roomId, - {} as unknown as MeetRoomMemberTokenOptions - ); - expectValidationError(response, 'secret', 'Required'); - }); - - it('should fail when secret is empty', async () => { - const response = await generateRoomMemberTokenRequest(roomData.room.roomId, { - secret: '' - }); - expectValidationError(response, 'secret', 'Secret is required'); - }); - - it('should fail when grantJoinMeetingPermission is not a boolean', async () => { + it('should fail when joinMeeting is not a boolean', async () => { const response = await generateRoomMemberTokenRequest(roomData.room.roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: 'not-a-boolean' as unknown as boolean + joinMeeting: 'not-a-boolean' as unknown as boolean }); - expectValidationError(response, 'grantJoinMeetingPermission', 'Expected boolean'); + expectValidationError(response, 'joinMeeting', 'Expected boolean'); }); - it('should fail when grantJoinMeetingPermission is true but participantName is not provided', async () => { + it('should fail when joinMeeting is true but participantName is not provided', async () => { const response = await generateRoomMemberTokenRequest(roomData.room.roomId, { secret: roomData.moderatorSecret, - grantJoinMeetingPermission: true + joinMeeting: true }); - expectValidationError( - response, - 'participantName', - 'participantName is required when grantJoinMeetingPermission is true' - ); + expectValidationError(response, 'participantName', 'participantName is required when joinMeeting is true'); }); }); }); diff --git a/meet-ce/backend/tests/integration/api/rooms/get-room-config.test.ts b/meet-ce/backend/tests/integration/api/rooms/get-room-config.test.ts index 2a9b38a1..0edcd9d4 100644 --- a/meet-ce/backend/tests/integration/api/rooms/get-room-config.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/get-room-config.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeAll, describe, it } from '@jest/globals'; -import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings'; +import { MeetRecordingLayout } from '@openvidu-meet/typings'; import { Response } from 'supertest'; import { expectSuccessRoomConfigResponse } from '../../../helpers/assertion-helpers.js'; import { deleteAllRooms, getRoomConfig, startTestServer } from '../../../helpers/request-helpers.js'; @@ -9,8 +9,7 @@ describe('Room API Tests', () => { const DEFAULT_CONFIG = { recording: { enabled: true, - layout: MeetRecordingLayout.GRID, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.GRID }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -41,8 +40,7 @@ describe('Room API Tests', () => { config: { recording: { enabled: true, - layout: MeetRecordingLayout.SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.SPEAKER }, chat: { enabled: true }, virtualBackground: { enabled: false }, diff --git a/meet-ce/backend/tests/integration/api/rooms/get-room-member-roles.test.ts b/meet-ce/backend/tests/integration/api/rooms/get-room-member-roles.test.ts deleted file mode 100644 index 9cd4f7f1..00000000 --- a/meet-ce/backend/tests/integration/api/rooms/get-room-member-roles.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; -import { MeetRoomMemberRole } from '@openvidu-meet/typings'; -import { - expectValidRoomMemberRoleAndPermissionsResponse, - expectValidRoomMemberRolesAndPermissionsResponse -} from '../../../helpers/assertion-helpers.js'; -import { - deleteAllRooms, - getRoomMemberRoleBySecret, - getRoomMemberRoles, - startTestServer -} from '../../../helpers/request-helpers.js'; -import { setupSingleRoom } from '../../../helpers/test-scenarios.js'; -import { RoomData } from '../../../interfaces/scenarios.js'; - -describe('Room API Tests', () => { - let roomData: RoomData; - - beforeAll(async () => { - await startTestServer(); - roomData = await setupSingleRoom(); - }); - - afterAll(async () => { - await deleteAllRooms(); - }); - - describe('Get Room Member Roles Tests', () => { - it('should retrieve all roles and associated permissions for a room', async () => { - const response = await getRoomMemberRoles(roomData.room.roomId); - expectValidRoomMemberRolesAndPermissionsResponse(response, roomData.room.roomId); - }); - - it('should return a 404 error if the room does not exist', async () => { - const response = await getRoomMemberRoles('non-existent-room-id'); - expect(response.status).toBe(404); - }); - }); - - describe('Get Room Member Role Tests', () => { - it('should retrieve moderator role and associated permissions for a room with a valid moderator secret', async () => { - const response = await getRoomMemberRoleBySecret(roomData.room.roomId, roomData.moderatorSecret); - expectValidRoomMemberRoleAndPermissionsResponse( - response, - roomData.room.roomId, - MeetRoomMemberRole.MODERATOR - ); - }); - - it('should retrieve speaker role and associated permissions for a room with a valid speaker secret', async () => { - const response = await getRoomMemberRoleBySecret(roomData.room.roomId, roomData.speakerSecret); - expectValidRoomMemberRoleAndPermissionsResponse(response, roomData.room.roomId, MeetRoomMemberRole.SPEAKER); - }); - - it('should return a 404 error if the room does not exist', async () => { - const response = await getRoomMemberRoleBySecret('non-existent-room-id', roomData.moderatorSecret); - expect(response.status).toBe(404); - }); - - it('should return a 400 error if the secret is invalid', async () => { - const response = await getRoomMemberRoleBySecret(roomData.room.roomId, 'invalid-secret'); - expect(response.status).toBe(400); - }); - }); -}); diff --git a/meet-ce/backend/tests/integration/api/rooms/get-room.test.ts b/meet-ce/backend/tests/integration/api/rooms/get-room.test.ts index a00271c1..5aaafc07 100644 --- a/meet-ce/backend/tests/integration/api/rooms/get-room.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/get-room.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeAll, describe, expect, it } from '@jest/globals'; -import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings'; +import { MeetRecordingLayout } from '@openvidu-meet/typings'; import ms from 'ms'; import { expectSuccessRoomResponse, @@ -38,8 +38,7 @@ describe('Room API Tests', () => { config: { recording: { enabled: true, - layout: MeetRecordingLayout.SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.SPEAKER }, chat: { enabled: true }, virtualBackground: { enabled: false }, diff --git a/meet-ce/backend/tests/integration/api/rooms/recording-layout-room-config.test.ts b/meet-ce/backend/tests/integration/api/rooms/recording-layout-room-config.test.ts index 91684c31..6621909c 100644 --- a/meet-ce/backend/tests/integration/api/rooms/recording-layout-room-config.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/recording-layout-room-config.test.ts @@ -1,5 +1,5 @@ import { afterAll, beforeAll, describe, it } from '@jest/globals'; -import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings'; +import { MeetRecordingLayout } from '@openvidu-meet/typings'; import { expectValidRoom } from '../../../helpers/assertion-helpers.js'; import { createRoom, deleteAllRooms, startTestServer } from '../../../helpers/request-helpers.js'; @@ -27,8 +27,7 @@ describe('Room API Tests', () => { const expectedConfig = { recording: { enabled: true, - layout: MeetRecordingLayout.GRID, // Default value - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.GRID // Default value }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -43,8 +42,7 @@ describe('Room API Tests', () => { config: { recording: { enabled: true, - layout: MeetRecordingLayout.SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.SPEAKER } } }; @@ -54,8 +52,7 @@ describe('Room API Tests', () => { const expectedConfig = { recording: { enabled: true, - layout: MeetRecordingLayout.SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.SPEAKER }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -70,8 +67,7 @@ describe('Room API Tests', () => { config: { recording: { enabled: true, - layout: MeetRecordingLayout.SINGLE_SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN + layout: MeetRecordingLayout.SINGLE_SPEAKER } } }; @@ -81,8 +77,7 @@ describe('Room API Tests', () => { const expectedConfig = { recording: { enabled: true, - layout: MeetRecordingLayout.SINGLE_SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN + layout: MeetRecordingLayout.SINGLE_SPEAKER }, chat: { enabled: true }, virtualBackground: { enabled: true }, diff --git a/meet-ce/backend/tests/integration/api/rooms/update-room-config.test.ts b/meet-ce/backend/tests/integration/api/rooms/update-room-config.test.ts index 04d7e378..c3688ca2 100644 --- a/meet-ce/backend/tests/integration/api/rooms/update-room-config.test.ts +++ b/meet-ce/backend/tests/integration/api/rooms/update-room-config.test.ts @@ -1,7 +1,5 @@ -import { afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals'; -import { MeetRecordingAccess, MeetRecordingLayout, MeetRoomConfig, MeetSignalType } from '@openvidu-meet/typings'; -import { container } from '../../../../src/config/dependency-injector.config.js'; -import { FrontendEventService } from '../../../../src/services/frontend-event.service.js'; +import { afterEach, beforeAll, describe, expect, it } from '@jest/globals'; +import { MeetRecordingLayout, MeetRoomConfig } from '@openvidu-meet/typings'; import { createRoom, deleteAllRooms, @@ -22,21 +20,12 @@ describe('Room API Tests', () => { }); describe('Update Room Config Tests', () => { - let frontendEventService: FrontendEventService; - - beforeAll(() => { - // Ensure the FrontendEventService is registered - frontendEventService = container.get(FrontendEventService); - }); - it('should successfully update room config', async () => { - const sendSignalSpy = jest.spyOn(frontendEventService as any, 'sendSignal'); const createdRoom = await createRoom({ roomName: 'update-test', config: { recording: { - enabled: true, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: true }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -47,8 +36,7 @@ describe('Room API Tests', () => { // Update the room config const updatedConfig = { recording: { - enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN + enabled: false }, chat: { enabled: false }, virtualBackground: { enabled: false }, @@ -56,22 +44,6 @@ describe('Room API Tests', () => { }; const updateResponse = await updateRoomConfig(createdRoom.roomId, updatedConfig); - // Verify a method of frontend event service is called - expect(sendSignalSpy).toHaveBeenCalledWith( - createdRoom.roomId, - { - roomId: createdRoom.roomId, - config: { - ...updatedConfig, - recording: { ...updatedConfig.recording, layout: MeetRecordingLayout.GRID } - }, - timestamp: expect.any(Number) - }, - { - topic: MeetSignalType.MEET_ROOM_CONFIG_UPDATED - } - ); - // Verify update response expect(updateResponse.status).toBe(200); expect(updateResponse.body).toHaveProperty('message'); @@ -120,8 +92,7 @@ describe('Room API Tests', () => { const expectedConfig: MeetRoomConfig = { recording: { enabled: false, - layout: MeetRecordingLayout.SPEAKER, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + layout: MeetRecordingLayout.SPEAKER }, chat: { enabled: true }, virtualBackground: { enabled: true }, @@ -161,8 +132,7 @@ describe('Room API Tests', () => { const config = { recording: { - enabled: false, - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: false }, chat: { enabled: false }, virtualBackground: { enabled: false } @@ -183,8 +153,7 @@ describe('Room API Tests', () => { // Invalid config (wrong types) const invalidConfig = { recording: { - enabled: 'true', // String instead of boolean - allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER + enabled: 'true' // String instead of boolean }, chat: { enabled: false }, virtualBackground: { enabled: false } diff --git a/meet-ce/backend/tests/integration/api/users/change-password.test.ts b/meet-ce/backend/tests/integration/api/users/change-password.test.ts index 2952c674..fb51b9d6 100644 --- a/meet-ce/backend/tests/integration/api/users/change-password.test.ts +++ b/meet-ce/backend/tests/integration/api/users/change-password.test.ts @@ -1,14 +1,14 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import { MEET_ENV } from '../../../../src/environment.js'; import { expectValidationError } from '../../../helpers/assertion-helpers.js'; -import { changePassword, loginUser, startTestServer } from '../../../helpers/request-helpers.js'; +import { changePassword, loginAdminUser, startTestServer } from '../../../helpers/request-helpers.js'; describe('Users API Tests', () => { let adminAccessToken: string; beforeAll(async () => { await startTestServer(); - adminAccessToken = await loginUser(); + adminAccessToken = await loginAdminUser(); }); describe('Change Password Tests', () => { diff --git a/meet-ce/backend/tests/integration/api/users/get-profile.test.ts b/meet-ce/backend/tests/integration/api/users/get-profile.test.ts index af6ba404..7ca1c4bf 100644 --- a/meet-ce/backend/tests/integration/api/users/get-profile.test.ts +++ b/meet-ce/backend/tests/integration/api/users/get-profile.test.ts @@ -1,22 +1,22 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; -import { getProfile, loginUser, startTestServer } from '../../../helpers/request-helpers.js'; +import { getMe, loginAdminUser, startTestServer } from '../../../helpers/request-helpers.js'; describe('Users API Tests', () => { let adminAccessToken: string; beforeAll(async () => { await startTestServer(); - adminAccessToken = await loginUser(); + adminAccessToken = await loginAdminUser(); }); describe('Profile Tests', () => { it('should return 200 and admin profile', async () => { - const response = await getProfile(adminAccessToken); + const response = await getMe(adminAccessToken); expect(response.status).toBe(200); - expect(response.body).toHaveProperty('username'); - expect(response.body.username).toBe('admin'); - expect(response.body).toHaveProperty('roles'); - expect(response.body.roles).toEqual(expect.arrayContaining(['admin', 'user'])); + expect(response.body).toHaveProperty('userId', 'admin'); + expect(response.body).toHaveProperty('name', 'Admin'); + expect(response.body).toHaveProperty('role', 'admin'); + expect(response.body).toHaveProperty('registrationDate'); }); }); });