backend: update participant handling to make participantName optional and adjust related logic

This commit is contained in:
juancarmore 2025-08-05 17:52:13 +02:00
parent 5637c56f44
commit 6e9c1743a1
12 changed files with 165 additions and 183 deletions

View File

@ -1,18 +1,17 @@
type: object
required:
- roomId
- participantName
- secret
properties:
roomId:
type: string
description: The unique identifier of the room where the participant will join.
example: 'room-123'
participantName:
type: string
description: The name of the participant.
example: 'Alice'
secret:
type: string
description: The secret token from the room Url
example: 'abc123456'
participantName:
type: string
description: The name of the participant.
example: 'Alice'

View File

@ -40,9 +40,13 @@ export const generateParticipantToken = async (req: Request, res: Response) => {
try {
logger.verbose(`Generating participant token for room '${roomId}'`);
await roomService.createLivekitRoom(roomId);
const token = await participantService.generateOrRefreshParticipantToken(participantOptions, currentRoles);
// If participantName is provided, create the Livekit room if it doesn't exist
if (participantOptions.participantName) {
await roomService.createLivekitRoom(roomId);
}
const token = await participantService.generateOrRefreshParticipantToken(participantOptions, currentRoles);
res.cookie(INTERNAL_CONFIG.PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/'));
return res.status(200).json({ token });
} catch (error) {

View File

@ -6,8 +6,8 @@ import { nonEmptySanitizedRoomId } from './room-validator.middleware.js';
const ParticipantTokenRequestSchema: z.ZodType<ParticipantOptions> = z.object({
roomId: nonEmptySanitizedRoomId('roomId'),
participantName: z.string().nonempty('Participant name is required'),
secret: z.string().nonempty('Secret is required')
secret: z.string().nonempty('Secret is required'),
participantName: z.string().optional()
});
export const validateParticipantTokenRequest = (req: Request, res: Response, next: NextFunction) => {

View File

@ -20,17 +20,19 @@ export class ParticipantService {
): Promise<string> {
const { roomId, participantName, secret } = participantOptions;
// Check if participant with same participantName exists in the room
const participantExists = await this.participantExists(roomId, participantName);
if (participantName) {
// Check if participant with same participantName exists in the room
const participantExists = await this.participantExists(roomId, participantName);
if (!refresh && participantExists) {
this.logger.verbose(`Participant '${participantName}' already exists in room '${roomId}'`);
throw errorParticipantAlreadyExists(participantName, roomId);
}
if (!refresh && participantExists) {
this.logger.verbose(`Participant '${participantName}' already exists in room '${roomId}'`);
throw errorParticipantAlreadyExists(participantName, roomId);
}
if (refresh && !participantExists) {
this.logger.verbose(`Participant '${participantName}' does not exist in room '${roomId}'`);
throw errorParticipantNotFound(participantName, roomId);
if (refresh && !participantExists) {
this.logger.verbose(`Participant '${participantName}' does not exist in room '${roomId}'`);
throw errorParticipantNotFound(participantName, roomId);
}
}
const role = await this.roomService.getRoomRoleBySecret(roomId, secret);
@ -44,7 +46,8 @@ export class ParticipantService {
role: ParticipantRole,
currentRoles: { role: ParticipantRole; permissions: OpenViduMeetPermissions }[]
): Promise<string> {
const permissions = this.getParticipantPermissions(participantOptions.roomId, role);
const { roomId, participantName } = participantOptions;
const permissions = this.getParticipantPermissions(roomId, role, !!participantName);
if (!currentRoles.some((r) => r.role === role)) {
currentRoles.push({ role, permissions: permissions.openvidu });
@ -75,21 +78,21 @@ export class ParticipantService {
return this.livekitService.deleteParticipant(participantName, roomId);
}
getParticipantPermissions(roomId: string, role: ParticipantRole): ParticipantPermissions {
getParticipantPermissions(roomId: string, role: ParticipantRole, addJoinPermission = true): ParticipantPermissions {
switch (role) {
case ParticipantRole.MODERATOR:
return this.generateModeratorPermissions(roomId);
return this.generateModeratorPermissions(roomId, addJoinPermission);
case ParticipantRole.PUBLISHER:
return this.generatePublisherPermissions(roomId);
return this.generatePublisherPermissions(roomId, addJoinPermission);
default:
throw new Error(`Role ${role} not supported`);
}
}
protected generateModeratorPermissions(roomId: string): ParticipantPermissions {
protected generateModeratorPermissions(roomId: string, addJoinPermission = true): ParticipantPermissions {
return {
livekit: {
roomJoin: true,
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,
@ -104,10 +107,10 @@ export class ParticipantService {
};
}
protected generatePublisherPermissions(roomId: string): ParticipantPermissions {
protected generatePublisherPermissions(roomId: string, addJoinPermission = true): ParticipantPermissions {
return {
livekit: {
roomJoin: true,
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,

View File

@ -45,7 +45,7 @@ export class TokenService {
roles: { role: ParticipantRole; permissions: OpenViduMeetPermissions }[]
): Promise<string> {
const { roomId, participantName } = participantOptions;
this.logger.info(`Generating token for ${participantName} in room ${roomId}`);
this.logger.info(`Generating token for room '${roomId}'`);
const tokenOptions: AccessTokenOptions = {
identity: participantName,

View File

@ -480,12 +480,12 @@ export const expectValidRoomRoleAndPermissionsResponse = (
});
};
const getPermissions = (roomId: string, role: ParticipantRole): ParticipantPermissions => {
const getPermissions = (roomId: string, role: ParticipantRole, addJoinPermission = true): ParticipantPermissions => {
switch (role) {
case ParticipantRole.MODERATOR:
return {
livekit: {
roomJoin: true,
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,
@ -501,7 +501,7 @@ const getPermissions = (roomId: string, role: ParticipantRole): ParticipantPermi
case ParticipantRole.PUBLISHER:
return {
livekit: {
roomJoin: true,
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,
@ -522,8 +522,8 @@ const getPermissions = (roomId: string, role: ParticipantRole): ParticipantPermi
export const expectValidParticipantTokenResponse = (
response: any,
roomId: string,
participantName: string,
participantRole: ParticipantRole,
participantName?: string,
otherRoles: ParticipantRole[] = []
) => {
expect(response.status).toBe(200);
@ -532,10 +532,10 @@ export const expectValidParticipantTokenResponse = (
const token = response.body.token;
const decodedToken = decodeJWTToken(token);
const permissions = getPermissions(roomId, participantRole);
const permissions = getPermissions(roomId, participantRole, !!participantName);
const rolesAndPermissions = otherRoles.map((role) => ({
role,
permissions: getPermissions(roomId, role).openvidu
permissions: getPermissions(roomId, role, !!participantName).openvidu
}));
if (!rolesAndPermissions.some((r) => r.role === participantRole)) {
@ -545,7 +545,12 @@ export const expectValidParticipantTokenResponse = (
});
}
expect(decodedToken).toHaveProperty('sub', participantName);
if (participantName) {
expect(decodedToken).toHaveProperty('sub', participantName);
} else {
expect(decodedToken).not.toHaveProperty('sub');
}
expect(decodedToken).toHaveProperty('video', permissions.livekit);
expect(decodedToken).toHaveProperty('metadata');
const metadata = JSON.parse(decodedToken.metadata || '{}');

View File

@ -227,13 +227,18 @@ export const getRooms = async (query: Record<string, any> = {}) => {
* @returns A Promise that resolves to the room data
* @throws Error if the app instance is not defined
*/
export const getRoom = async (roomId: string, fields?: string) => {
export const getRoom = async (roomId: string, fields?: string, cookie?: string, role?: ParticipantRole) => {
checkAppIsRunning();
return await request(app)
.get(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_API_KEY)
.query({ fields });
const req = request(app).get(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/rooms/${roomId}`).query({ fields });
if (cookie && role) {
req.set('Cookie', cookie).set(INTERNAL_CONFIG.PARTICIPANT_ROLE_HEADER, role);
} else {
req.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_API_KEY);
}
return await req;
};
export const getRoomPreferences = async (roomId: string, cookie: string, role: ParticipantRole) => {
@ -380,16 +385,16 @@ export const generateParticipantToken = async (participantOptions: any, cookie?:
*/
export const generateParticipantTokenCookie = async (
roomId: string,
participantName: string,
secret: string,
participantName: string,
cookie?: string
): Promise<string> => {
// Generate the participant token
const response = await generateParticipantToken(
{
roomId,
participantName,
secret
secret,
participantName
},
cookie
);

View File

@ -51,8 +51,8 @@ export const setupSingleRoom = async (
// Extract the room secrets and generate participant tokens, saved as cookies
const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room);
const [moderatorCookie, publisherCookie] = await Promise.all([
generateParticipantTokenCookie(room.roomId, 'MODERATOR', moderatorSecret),
generateParticipantTokenCookie(room.roomId, 'PUBLISHER', publisherSecret)
generateParticipantTokenCookie(room.roomId, moderatorSecret, 'MODERATOR'),
generateParticipantTokenCookie(room.roomId, publisherSecret, 'PUBLISHER')
]);
// Join participant if needed

View File

@ -26,31 +26,39 @@ describe('Participant API Tests', () => {
});
describe('Generate Participant Token Tests', () => {
it('should generate a participant token without join permissions when not specifying participant name', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
secret: roomData.moderatorSecret
});
expectValidParticipantTokenResponse(response, roomData.room.roomId, ParticipantRole.MODERATOR);
});
it('should generate a participant token with moderator permissions when using the moderator secret', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
});
expectValidParticipantTokenResponse(
response,
roomData.room.roomId,
participantName,
ParticipantRole.MODERATOR
ParticipantRole.MODERATOR,
participantName
);
});
it('should generate a participant token with publisher permissions when using the publisher secret', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName
});
expectValidParticipantTokenResponse(
response,
roomData.room.roomId,
participantName,
ParticipantRole.PUBLISHER
ParticipantRole.PUBLISHER,
participantName
);
});
@ -58,22 +66,22 @@ describe('Participant API Tests', () => {
when using the publisher secret after having a moderator token`, async () => {
const moderatorCookie = await generateParticipantTokenCookie(
roomData.room.roomId,
`${participantName}_MODERATOR`,
roomData.moderatorSecret
roomData.moderatorSecret,
`${participantName}_MODERATOR`
);
const publisherResponse = await generateParticipantToken(
{
roomId: roomData.room.roomId,
participantName: `${participantName}_PUBLISHER`,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: `${participantName}_PUBLISHER`
},
moderatorCookie
);
expectValidParticipantTokenResponse(
publisherResponse,
roomData.room.roomId,
`${participantName}_PUBLISHER`,
ParticipantRole.PUBLISHER,
`${participantName}_PUBLISHER`,
[ParticipantRole.MODERATOR]
);
});
@ -82,8 +90,8 @@ describe('Participant API Tests', () => {
roomData = await setupSingleRoom(true);
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
});
expect(response.status).toBe(409);
@ -94,8 +102,8 @@ describe('Participant API Tests', () => {
it('should fail with 404 when room does not exist', async () => {
const response = await generateParticipantToken({
roomId: 'non_existent_room',
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
});
expect(response.status).toBe(404);
});
@ -103,8 +111,8 @@ describe('Participant API Tests', () => {
it('should fail with 400 when secret is invalid', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName,
secret: 'invalid_secret'
secret: 'invalid_secret',
participantName
});
expect(response.status).toBe(400);
});
@ -113,20 +121,12 @@ describe('Participant API Tests', () => {
describe('Generate Participant Token Validation Tests', () => {
it('should fail when roomId is not provided', async () => {
const response = await generateParticipantToken({
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
});
expectValidationError(response, 'roomId', 'Required');
});
it('should fail when participantName is not provided', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
secret: roomData.moderatorSecret
});
expectValidationError(response, 'participantName', 'Required');
});
it('should fail when secret is not provided', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
@ -135,20 +135,11 @@ describe('Participant API Tests', () => {
expectValidationError(response, 'secret', 'Required');
});
it('should fail when participantName is empty', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName: '',
secret: roomData.moderatorSecret
});
expectValidationError(response, 'participantName', 'Participant name is required');
});
it('should fail when secret is empty', async () => {
const response = await generateParticipantToken({
roomId: roomData.room.roomId,
participantName,
secret: ''
secret: '',
participantName
});
expectValidationError(response, 'secret', 'Secret is required');
});

View File

@ -40,16 +40,16 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
},
roomData.moderatorCookie
);
expectValidParticipantTokenResponse(
response,
roomData.room.roomId,
participantName,
ParticipantRole.MODERATOR
ParticipantRole.MODERATOR,
participantName
);
});
@ -57,16 +57,16 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName
},
roomData.publisherCookie
);
expectValidParticipantTokenResponse(
response,
roomData.room.roomId,
participantName,
ParticipantRole.PUBLISHER
ParticipantRole.PUBLISHER,
participantName
);
});
@ -74,8 +74,8 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName,
secret: 'invalid_secret'
secret: 'invalid_secret',
participantName
},
roomData.moderatorCookie
);
@ -86,8 +86,8 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
},
''
);
@ -100,8 +100,8 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: newRoomData.room.roomId,
participantName,
secret: newRoomData.moderatorSecret
secret: newRoomData.moderatorSecret,
participantName
},
roomData.moderatorCookie
);
@ -112,8 +112,8 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: 'non_existent_room',
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
},
roomData.moderatorCookie
);
@ -125,8 +125,8 @@ describe('Participant API Tests', () => {
const response = await refreshParticipantToken(
{
roomId: newRoomData.room.roomId,
participantName,
secret: newRoomData.moderatorSecret
secret: newRoomData.moderatorSecret,
participantName
},
newRoomData.moderatorCookie
);
@ -139,25 +139,14 @@ describe('Participant API Tests', () => {
it('should fail when roomId is not provided', async () => {
const response = await refreshParticipantToken(
{
participantName,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName
},
roomData.moderatorCookie
);
expectValidationError(response, 'roomId', 'Required');
});
it('should fail when participantName is not provided', async () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
secret: roomData.moderatorSecret
},
roomData.moderatorCookie
);
expectValidationError(response, 'participantName', 'Required');
});
it('should fail when secret is not provided', async () => {
const response = await refreshParticipantToken(
{
@ -169,24 +158,12 @@ describe('Participant API Tests', () => {
expectValidationError(response, 'secret', 'Required');
});
it('should fail when participantName is empty', async () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName: '',
secret: roomData.moderatorSecret
},
roomData.moderatorCookie
);
expectValidationError(response, 'participantName', 'Participant name is required');
});
it('should fail when secret is empty', async () => {
const response = await refreshParticipantToken(
{
roomId: roomData.room.roomId,
participantName,
secret: ''
secret: '',
participantName
},
roomData.moderatorCookie
);

View File

@ -43,8 +43,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -54,8 +54,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -65,8 +65,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -76,8 +76,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).set('Cookie', adminCookie).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -87,8 +87,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});
@ -98,8 +98,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).set('Cookie', adminCookie).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -109,8 +109,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});
@ -120,8 +120,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).set('Cookie', adminCookie).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -131,8 +131,8 @@ describe('Participant API Security Tests', () => {
const response = await request(app).post(`${PARTICIPANTS_PATH}/token`).send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});
@ -161,8 +161,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.publisherCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -175,8 +175,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.moderatorCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -189,8 +189,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.publisherCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -203,8 +203,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', [adminCookie, roomData.moderatorCookie])
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -217,8 +217,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.moderatorCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});
@ -231,8 +231,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', [adminCookie, roomData.publisherCookie])
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -245,8 +245,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.publisherCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.publisherSecret
secret: roomData.publisherSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});
@ -259,8 +259,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', [adminCookie, roomData.moderatorCookie])
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(200);
});
@ -273,8 +273,8 @@ describe('Participant API Security Tests', () => {
.set('Cookie', roomData.moderatorCookie)
.send({
roomId: roomData.room.roomId,
participantName: PARTICIPANT_NAME,
secret: roomData.moderatorSecret
secret: roomData.moderatorSecret,
participantName: PARTICIPANT_NAME
});
expect(response.status).toBe(401);
});

View File

@ -5,34 +5,32 @@ import { OpenViduMeetPermissions } from './permissions/openvidu-permissions.js';
* Options for a participant to join a room.
*/
export interface ParticipantOptions {
/**
* The unique identifier for the room.
*/
roomId: string;
/**
* The name of the participant.
*/
participantName: string;
/**
* A secret key for room access.
*/
secret: string;
/**
* The unique identifier for the room.
*/
roomId: string;
/**
* A secret key for room access.
*/
secret: string;
/**
* The name of the participant.
*/
participantName?: string;
}
/**
* Represents the permissions for an individual participant.
*/
export interface ParticipantPermissions {
livekit: LiveKitPermissions;
openvidu: OpenViduMeetPermissions;
livekit: LiveKitPermissions;
openvidu: OpenViduMeetPermissions;
}
/**
* Represents the role of a participant in a room.
*/
export const enum ParticipantRole {
MODERATOR = 'moderator',
PUBLISHER = 'publisher',
MODERATOR = 'moderator',
PUBLISHER = 'publisher'
}