test: enhance analytics, API key, global config, meeting, and user API security tests with user role and permissions validations
This commit is contained in:
parent
0a5852d89a
commit
6a350b07a5
@ -55,7 +55,7 @@ export const startTestServer = async (): Promise<Express> => {
|
||||
export const generateApiKey = async (): Promise<string> => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -68,7 +68,7 @@ export const generateApiKey = async (): Promise<string> => {
|
||||
export const getApiKeys = async () => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -79,7 +79,7 @@ export const getApiKeys = async () => {
|
||||
export const deleteApiKeys = async () => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.delete(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -114,7 +114,7 @@ export const getRoomsAppearanceConfig = async () => {
|
||||
export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppearanceConfig }) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/rooms/appearance`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -125,7 +125,7 @@ export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppe
|
||||
export const getWebbhookConfig = async () => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -136,7 +136,7 @@ export const getWebbhookConfig = async () => {
|
||||
export const updateWebbhookConfig = async (config: WebhookConfig) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -164,7 +164,7 @@ export const getSecurityConfig = async () => {
|
||||
export const updateSecurityConfig = async (config: SecurityConfig) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/security`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -199,9 +199,9 @@ export const loginUser = async (userId: string, password: string): Promise<strin
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs in admin user and returns the access token in the format "Bearer <token>"
|
||||
* Logs in the root admin user and returns the access token in the format "Bearer <token>"
|
||||
*/
|
||||
export const loginAdminUser = async (): Promise<string> => {
|
||||
export const loginRootAdmin = async (): Promise<string> => {
|
||||
return loginUser(MEET_ENV.INITIAL_ADMIN_USER, MEET_ENV.INITIAL_ADMIN_PASSWORD);
|
||||
};
|
||||
|
||||
@ -210,7 +210,7 @@ export const loginAdminUser = async (): Promise<string> => {
|
||||
export const createUser = async (options: MeetUserOptions) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -220,7 +220,7 @@ export const createUser = async (options: MeetUserOptions) => {
|
||||
export const getUsers = async (query: Record<string, unknown> = {}) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -230,7 +230,7 @@ export const getUsers = async (query: Record<string, unknown> = {}) => {
|
||||
export const getUser = async (userId: string) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/${userId}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -274,7 +274,7 @@ export const changePasswordAfterFirstLogin = async (
|
||||
export const resetUserPassword = async (userId: string, newPassword: string) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/${userId}/password`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -284,7 +284,7 @@ export const resetUserPassword = async (userId: string, newPassword: string) =>
|
||||
export const updateUserRole = async (userId: string, role: string) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/${userId}/role`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -294,7 +294,7 @@ export const updateUserRole = async (userId: string, role: string) => {
|
||||
export const deleteUser = async (userId: string) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.delete(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/${userId}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -304,7 +304,7 @@ export const deleteUser = async (userId: string) => {
|
||||
export const bulkDeleteUsers = async (userIds: string[]) => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
return await request(app)
|
||||
.delete(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
@ -905,7 +905,7 @@ export const runReleaseActiveRecordingLock = async (roomId: string) => {
|
||||
export const getAnalytics = async () => {
|
||||
checkAppIsRunning();
|
||||
|
||||
const accessToken = await loginAdminUser();
|
||||
const accessToken = await loginRootAdmin();
|
||||
const response = await request(app)
|
||||
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
|
||||
|
||||
@ -3,17 +3,23 @@ import { Express } from 'express';
|
||||
import request from 'supertest';
|
||||
import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js';
|
||||
import { MEET_ENV } from '../../../../src/environment.js';
|
||||
import { loginAdminUser, startTestServer } from '../../../helpers/request-helpers.js';
|
||||
import { deleteAllUsers, startTestServer } from '../../../helpers/request-helpers.js';
|
||||
import { setupTestUsers } from '../../../helpers/test-scenarios.js';
|
||||
import { TestUsers } from '../../../interfaces/scenarios.js';
|
||||
|
||||
const ANALYTICS_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`;
|
||||
|
||||
describe('Analytics API Security Tests', () => {
|
||||
let app: Express;
|
||||
let adminAccessToken: string;
|
||||
let testUsers: TestUsers;
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await startTestServer();
|
||||
adminAccessToken = await loginAdminUser();
|
||||
testUsers = await setupTestUsers();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteAllUsers();
|
||||
});
|
||||
|
||||
describe('Get Analytics Tests', () => {
|
||||
@ -24,13 +30,27 @@ describe('Analytics API Security Tests', () => {
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
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)
|
||||
.get(ANALYTICS_PATH)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.get(ANALYTICS_PATH)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.get(ANALYTICS_PATH)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).get(ANALYTICS_PATH);
|
||||
expect(response.status).toBe(401);
|
||||
|
||||
@ -2,36 +2,48 @@ import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
|
||||
import { Express } from 'express';
|
||||
import request from 'supertest';
|
||||
import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js';
|
||||
import {
|
||||
generateApiKey,
|
||||
loginAdminUser,
|
||||
restoreDefaultApiKeys,
|
||||
startTestServer
|
||||
} from '../../../helpers/request-helpers.js';
|
||||
import { deleteAllUsers, generateApiKey, restoreDefaultApiKeys, startTestServer } from '../../../helpers/request-helpers.js';
|
||||
import { setupTestUsers } from '../../../helpers/test-scenarios.js';
|
||||
import { TestUsers } from '../../../interfaces/scenarios.js';
|
||||
|
||||
const API_KEYS_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`;
|
||||
|
||||
describe('API Keys API Security Tests', () => {
|
||||
let app: Express;
|
||||
let adminAccessToken: string;
|
||||
let testUsers: TestUsers;
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await startTestServer();
|
||||
adminAccessToken = await loginAdminUser();
|
||||
testUsers = await setupTestUsers();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await restoreDefaultApiKeys();
|
||||
await deleteAllUsers();
|
||||
});
|
||||
|
||||
describe('Create API Key', () => {
|
||||
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)
|
||||
.post(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken);
|
||||
expect(response.status).toBe(201);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.post(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.post(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).post(`${API_KEYS_PATH}`);
|
||||
expect(response.status).toBe(401);
|
||||
@ -39,13 +51,27 @@ describe('API Keys API Security Tests', () => {
|
||||
});
|
||||
|
||||
describe('Get API Keys', () => {
|
||||
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)
|
||||
.get(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.get(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.get(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).get(`${API_KEYS_PATH}`);
|
||||
expect(response.status).toBe(401);
|
||||
@ -58,13 +84,27 @@ describe('API Keys API Security Tests', () => {
|
||||
await generateApiKey();
|
||||
});
|
||||
|
||||
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)
|
||||
.delete(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${API_KEYS_PATH}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).delete(`${API_KEYS_PATH}`);
|
||||
expect(response.status).toBe(401);
|
||||
|
||||
@ -4,17 +4,23 @@ import { Express } from 'express';
|
||||
import request from 'supertest';
|
||||
import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js';
|
||||
import { MEET_ENV } from '../../../../src/environment.js';
|
||||
import { loginAdminUser, restoreDefaultGlobalConfig, startTestServer } from '../../../helpers/request-helpers.js';
|
||||
import { deleteAllUsers, restoreDefaultGlobalConfig, startTestServer } from '../../../helpers/request-helpers.js';
|
||||
import { setupTestUsers } from '../../../helpers/test-scenarios.js';
|
||||
import { TestUsers } from '../../../interfaces/scenarios.js';
|
||||
|
||||
const CONFIG_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config`;
|
||||
|
||||
describe('Global Config API Security Tests', () => {
|
||||
let app: Express;
|
||||
let adminAccessToken: string;
|
||||
let testUsers: TestUsers;
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await startTestServer();
|
||||
adminAccessToken = await loginAdminUser();
|
||||
testUsers = await setupTestUsers();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteAllUsers();
|
||||
});
|
||||
|
||||
describe('Update Webhook Config Tests', () => {
|
||||
@ -31,16 +37,32 @@ describe('Global Config API Security Tests', () => {
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
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)
|
||||
.put(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken)
|
||||
.send(webhookConfig);
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
await restoreDefaultGlobalConfig();
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken)
|
||||
.send(webhookConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken)
|
||||
.send(webhookConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).put(`${CONFIG_PATH}/webhooks`).send(webhookConfig);
|
||||
expect(response.status).toBe(401);
|
||||
@ -55,13 +77,27 @@ describe('Global Config API Security Tests', () => {
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
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)
|
||||
.get(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.get(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.get(`${CONFIG_PATH}/webhooks`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).get(`${CONFIG_PATH}/webhooks`);
|
||||
expect(response.status).toBe(401);
|
||||
@ -84,16 +120,32 @@ describe('Global Config API Security Tests', () => {
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
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)
|
||||
.put(`${CONFIG_PATH}/security`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken)
|
||||
.send(securityConfig);
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
await restoreDefaultGlobalConfig();
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/security`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken)
|
||||
.send(securityConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/security`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken)
|
||||
.send(securityConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).put(`${CONFIG_PATH}/security`).send(securityConfig);
|
||||
expect(response.status).toBe(401);
|
||||
@ -128,16 +180,32 @@ describe('Global Config API Security Tests', () => {
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
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)
|
||||
.put(`${CONFIG_PATH}/rooms/appearance`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.admin.accessToken)
|
||||
.send(appearanceConfig);
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
await restoreDefaultGlobalConfig();
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as USER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/rooms/appearance`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.user.accessToken)
|
||||
.send(appearanceConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as ROOM_MEMBER', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${CONFIG_PATH}/rooms/appearance`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, testUsers.roomMember.accessToken)
|
||||
.send(appearanceConfig);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when user is not authenticated', async () => {
|
||||
const response = await request(app).put(`${CONFIG_PATH}/rooms/appearance`).send(appearanceConfig);
|
||||
expect(response.status).toBe(401);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from '@jest/globals';
|
||||
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
|
||||
import { MeetRoomMemberRole, MeetRoomMemberTokenMetadata } from '@openvidu-meet/typings';
|
||||
import { Express } from 'express';
|
||||
import request from 'supertest';
|
||||
@ -8,27 +8,36 @@ import { getPermissions } from '../../../helpers/assertion-helpers.js';
|
||||
import {
|
||||
deleteAllRooms,
|
||||
disconnectFakeParticipants,
|
||||
loginAdminUser,
|
||||
joinFakeParticipant,
|
||||
loginRootAdmin,
|
||||
startTestServer,
|
||||
updateParticipantMetadata
|
||||
} from '../../../helpers/request-helpers.js';
|
||||
import { setupSingleRoom } from '../../../helpers/test-scenarios.js';
|
||||
import { RoomData } from '../../../interfaces/scenarios.js';
|
||||
import { setupRoomMember, setupSingleRoom, updateRoomMemberPermissions } from '../../../helpers/test-scenarios.js';
|
||||
import { RoomData, RoomMemberData } from '../../../interfaces/scenarios.js';
|
||||
|
||||
const MEETINGS_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/meetings`;
|
||||
|
||||
describe('Meeting API Security Tests', () => {
|
||||
const participantIdentity = 'TEST_PARTICIPANT';
|
||||
|
||||
let app: Express;
|
||||
let adminAccessToken: string;
|
||||
let rootAdminAccessToken: string;
|
||||
|
||||
let roomData: RoomData;
|
||||
let roomId: string;
|
||||
let roomMember: RoomMemberData;
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await startTestServer();
|
||||
adminAccessToken = await loginAdminUser();
|
||||
});
|
||||
rootAdminAccessToken = await loginRootAdmin();
|
||||
|
||||
beforeEach(async () => {
|
||||
roomData = await setupSingleRoom(true);
|
||||
roomData = await setupSingleRoom();
|
||||
roomId = roomData.room.roomId;
|
||||
roomMember = await setupRoomMember(roomId, {
|
||||
name: 'External Member',
|
||||
baseRole: MeetRoomMemberRole.MODERATOR
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@ -39,136 +48,176 @@ describe('Meeting API Security Tests', () => {
|
||||
describe('End Meeting Tests', () => {
|
||||
it('should fail when request includes API key', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}`)
|
||||
.delete(`${MEETINGS_PATH}/${roomId}`)
|
||||
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_ENV.INITIAL_API_KEY);
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as admin', async () => {
|
||||
it('should fail when using access token', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, rootAdminAccessToken);
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should succeed when participant is moderator', async () => {
|
||||
it('should succeed when using room member token with canEndMeeting permission', async () => {
|
||||
// Update room member to have canEndMeeting permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, { canEndMeeting: true });
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.moderatorToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken);
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
// Re-join participant for further tests
|
||||
await joinFakeParticipant(roomId, participantIdentity);
|
||||
});
|
||||
|
||||
it('should fail when participant is moderator of a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
it('should fail when using room member token without canEndMeeting permission', async () => {
|
||||
// Update room member to not have canEndMeeting permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, {
|
||||
canEndMeeting: false
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when participant is speaker', async () => {
|
||||
it('should fail when using room member token from a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.speakerToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Update Participant in Meeting Tests', () => {
|
||||
const PARTICIPANT_NAME = 'TEST_PARTICIPANT';
|
||||
const role = MeetRoomMemberRole.MODERATOR;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setParticipantMetadata = async () => {
|
||||
const metadata: MeetRoomMemberTokenMetadata = {
|
||||
livekitUrl: MEET_ENV.LIVEKIT_URL,
|
||||
roomId: roomData.room.roomId,
|
||||
roomId,
|
||||
baseRole: MeetRoomMemberRole.SPEAKER,
|
||||
effectivePermissions: getPermissions(MeetRoomMemberRole.SPEAKER)
|
||||
};
|
||||
await updateParticipantMetadata(roomData.room.roomId, PARTICIPANT_NAME, metadata);
|
||||
await updateParticipantMetadata(roomId, participantIdentity, metadata);
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
// Ensure participant has the correct metadata before tests
|
||||
await setParticipantMetadata();
|
||||
});
|
||||
|
||||
it('should fail when request includes API key', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}/role`)
|
||||
.put(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}/role`)
|
||||
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_ENV.INITIAL_API_KEY)
|
||||
.send({ role });
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as admin', async () => {
|
||||
it('should fail when using access token', async () => {
|
||||
const response = await request(app)
|
||||
.put(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}/role`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken)
|
||||
.put(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}/role`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, rootAdminAccessToken)
|
||||
.send({ role });
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should succeed when participant is moderator', async () => {
|
||||
it('should succeed when using room member token with canMakeModerator permission', async () => {
|
||||
// Update room member to have canMakeModerator permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, {
|
||||
canMakeModerator: true
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.put(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.moderatorToken)
|
||||
.put(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken)
|
||||
.send({ role });
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
// Re-join participant for further tests
|
||||
await joinFakeParticipant(roomId, participantIdentity);
|
||||
await setParticipantMetadata();
|
||||
});
|
||||
|
||||
it('should fail when participant is moderator of a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
it('should fail when using room member token without canMakeModerator permission', async () => {
|
||||
// Update room member to not have canMakeModerator permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, {
|
||||
canMakeModerator: false
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.put(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken)
|
||||
.put(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken)
|
||||
.send({ role });
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when participant is speaker', async () => {
|
||||
it('should fail when using room member token from a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
|
||||
const response = await request(app)
|
||||
.put(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_NAME}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.speakerToken)
|
||||
.put(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}/role`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken)
|
||||
.send({ role });
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Kick Participant from Meeting Tests', () => {
|
||||
const PARTICIPANT_IDENTITY = 'TEST_PARTICIPANT';
|
||||
|
||||
it('should fail when request includes API key', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_IDENTITY}`)
|
||||
.delete(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}`)
|
||||
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_ENV.INITIAL_API_KEY);
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should fail when user is authenticated as admin', async () => {
|
||||
it('should fail when using access token', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_IDENTITY}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, adminAccessToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}`)
|
||||
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, rootAdminAccessToken);
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
it('should succeed when participant is moderator', async () => {
|
||||
it('should succeed when using room member token with canKickParticipants permission', async () => {
|
||||
// Update room member to have canKickParticipants permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, {
|
||||
canKickParticipants: true
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_IDENTITY}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.moderatorToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken);
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
// Re-join participant for further tests
|
||||
await joinFakeParticipant(roomId, participantIdentity);
|
||||
});
|
||||
|
||||
it('should fail when participant is moderator of a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
it('should fail when using room member token without canKickParticipants permission', async () => {
|
||||
// Update room member to not have canKickParticipants permission
|
||||
roomMember = await updateRoomMemberPermissions(roomId, roomMember.member.memberId, {
|
||||
canKickParticipants: false
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_IDENTITY}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomMember.memberToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
|
||||
it('should fail when participant is speaker', async () => {
|
||||
it('should fail when using room member token from a different room', async () => {
|
||||
const newRoomData = await setupSingleRoom();
|
||||
|
||||
const response = await request(app)
|
||||
.delete(`${MEETINGS_PATH}/${roomData.room.roomId}/participants/${PARTICIPANT_IDENTITY}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, roomData.speakerToken);
|
||||
.delete(`${MEETINGS_PATH}/${roomId}/participants/${participantIdentity}`)
|
||||
.set(INTERNAL_CONFIG.ROOM_MEMBER_TOKEN_HEADER, newRoomData.moderatorToken);
|
||||
expect(response.status).toBe(403);
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user