openvidu/meet-ce/backend/src/controllers/participant.controller.ts
Carlos Santos faa5934a17 backend: Exports internal config as a constant
Refactors the internal configuration to be exported as a constant,
improving code modularity and preventing accidental modifications.

Updates all files that use the internal config to import the constant
instead of the default export.
2025-10-16 17:33:55 +02:00

152 lines
5.6 KiB
TypeScript

import {
AuthTransportMode,
OpenViduMeetPermissions,
ParticipantOptions,
ParticipantRole
} from '@openvidu-meet/typings';
import { Request, Response } from 'express';
import { container } from '../config/index.js';
import { INTERNAL_CONFIG } from '../config/internal-config.js';
import {
errorInvalidParticipantToken,
errorParticipantTokenNotPresent,
handleError,
rejectRequestFromMeetError
} from '../models/error.model.js';
import { LoggerService, ParticipantService, RoomService, TokenService } from '../services/index.js';
import { getAuthTransportMode, getCookieOptions, getParticipantToken } from '../utils/index.js';
export const generateParticipantToken = async (req: Request, res: Response) => {
const logger = container.get(LoggerService);
const participantService = container.get(ParticipantService);
const tokenService = container.get(TokenService);
const participantOptions: ParticipantOptions = req.body;
const { roomId } = participantOptions;
// Check if there is a previous token (only for cookie mode)
const previousToken = req.cookies[INTERNAL_CONFIG.PARTICIPANT_TOKEN_COOKIE_NAME];
let currentRoles: { role: ParticipantRole; permissions: OpenViduMeetPermissions }[] = [];
if (previousToken) {
// If there is a previous token, extract the roles from it
// and use them to generate the new token, aggregating the new role to the current ones
// This logic is only used in cookie mode to allow multiple roles across tabs
logger.verbose('Previous participant token found. Extracting roles');
try {
const claims = tokenService.getClaimsIgnoringExpiration(previousToken);
const metadata = participantService.parseMetadata(claims.metadata || '{}');
currentRoles = metadata.roles;
} catch (error) {
logger.verbose('Error extracting roles from previous token:', error);
}
}
try {
logger.verbose(`Generating participant token for room '${roomId}'`);
const token = await participantService.generateOrRefreshParticipantToken(participantOptions, currentRoles);
const authTransportMode = await getAuthTransportMode();
// Send participant token as cookie for cookie mode
if (authTransportMode === AuthTransportMode.COOKIE) {
res.cookie(INTERNAL_CONFIG.PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/'));
}
return res.status(200).json({ token });
} catch (error) {
handleError(res, error, `generating participant token for room '${roomId}'`);
}
};
export const refreshParticipantToken = async (req: Request, res: Response) => {
const logger = container.get(LoggerService);
const tokenService = container.get(TokenService);
const participantService = container.get(ParticipantService);
// Check if there is a previous token
const previousToken = await getParticipantToken(req);
if (!previousToken) {
logger.verbose('No previous participant token found. Cannot refresh.');
const error = errorParticipantTokenNotPresent();
return rejectRequestFromMeetError(res, error);
}
// Extract roles from the previous token
let currentRoles: { role: ParticipantRole; permissions: OpenViduMeetPermissions }[] = [];
try {
const claims = tokenService.getClaimsIgnoringExpiration(previousToken);
const metadata = participantService.parseMetadata(claims.metadata || '{}');
currentRoles = metadata.roles;
} catch (err) {
logger.verbose('Error extracting roles from previous token:', err);
const error = errorInvalidParticipantToken();
return rejectRequestFromMeetError(res, error);
}
const participantOptions: ParticipantOptions = req.body;
const { roomId } = participantOptions;
try {
logger.verbose(`Refreshing participant token for room '${roomId}'`);
const token = await participantService.generateOrRefreshParticipantToken(
participantOptions,
currentRoles,
true
);
const authTransportMode = await getAuthTransportMode();
// Send participant token as cookie for cookie mode
if (authTransportMode === AuthTransportMode.COOKIE) {
res.cookie(INTERNAL_CONFIG.PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/'));
}
return res.status(200).json({ token });
} catch (error) {
handleError(res, error, `refreshing participant token for room '${roomId}'`);
}
};
export const updateParticipantRole = async (req: Request, res: Response) => {
const logger = container.get(LoggerService);
const participantService = container.get(ParticipantService);
const { roomId, participantIdentity } = req.params;
const { role } = req.body;
try {
logger.verbose(`Changing role of participant '${participantIdentity}' in room '${roomId}' to '${role}'`);
await participantService.updateParticipantRole(roomId, participantIdentity, role);
res.status(200).json({ message: `Participant '${participantIdentity}' role updated to '${role}'` });
} catch (error) {
handleError(res, error, `changing role for participant '${participantIdentity}' in room '${roomId}'`);
}
};
export const kickParticipant = async (req: Request, res: Response) => {
const logger = container.get(LoggerService);
const roomService = container.get(RoomService);
const participantService = container.get(ParticipantService);
const { roomId, participantIdentity } = req.params;
// Check if the room exists
try {
await roomService.getMeetRoom(roomId);
} catch (error) {
return handleError(res, error, `getting room '${roomId}'`);
}
try {
logger.verbose(`Kicking participant '${participantIdentity}' from room '${roomId}'`);
await participantService.kickParticipant(roomId, participantIdentity);
res.status(200).json({
message: `Participant '${participantIdentity}' kicked successfully from room '${roomId}'`
});
} catch (error) {
handleError(res, error, `kicking participant '${participantIdentity}' from room '${roomId}'`);
}
};