backend: Implement configureRecordingTokenAuth middleware and update room route
This commit is contained in:
parent
8bbbee731b
commit
66f2a10406
@ -1,7 +1,12 @@
|
|||||||
import { AuthMode, ParticipantRole, UserRole } from '@typings-ce';
|
import { AuthMode, MeetRecordingAccess, MeetRoom, ParticipantRole, UserRole } from '@typings-ce';
|
||||||
import { NextFunction, Request, Response } from 'express';
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import { container } from '../config/index.js';
|
import { container } from '../config/index.js';
|
||||||
import { LoggerService, MeetStorageService } from '../services/index.js';
|
import {
|
||||||
|
errorInsufficientPermissions,
|
||||||
|
errorRoomNotFoundOrEmptyRecordings,
|
||||||
|
OpenViduMeetError
|
||||||
|
} from '../models/error.model.js';
|
||||||
|
import { LoggerService, MeetStorageService, RoomService } from '../services/index.js';
|
||||||
import { allowAnonymous, apiKeyValidator, tokenAndRoleValidator, withAuth } from './auth.middleware.js';
|
import { allowAnonymous, apiKeyValidator, tokenAndRoleValidator, withAuth } from './auth.middleware.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,3 +98,77 @@ export const configureRoomAuthorization = async (req: Request, res: Response, ne
|
|||||||
// If the user is not a moderator, it is not allowed to access the resource
|
// If the user is not a moderator, it is not allowed to access the resource
|
||||||
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware to configure authentication based on participant role and authentication mode
|
||||||
|
* for generating a token for retrieving/deleting recordings.
|
||||||
|
*
|
||||||
|
* - If the authentication mode is MODERATORS_ONLY and the participant role is MODERATOR, configure user authentication.
|
||||||
|
* - If the authentication mode is ALL_USERS, configure user authentication.
|
||||||
|
* - Otherwise, allow anonymous access.
|
||||||
|
*/
|
||||||
|
export const configureRecordingTokenAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger = container.get(LoggerService);
|
||||||
|
const storageService = container.get(MeetStorageService);
|
||||||
|
const roomService = container.get(RoomService);
|
||||||
|
|
||||||
|
let role: ParticipantRole;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const roomId = req.params.roomId;
|
||||||
|
const { secret } = req.body;
|
||||||
|
const room = await storageService.getArchivedRoomMetadata(roomId);
|
||||||
|
|
||||||
|
if (!room) {
|
||||||
|
// If the room is not found, it means that there are no recordings for that room or the room doesn't exist
|
||||||
|
throw errorRoomNotFoundOrEmptyRecordings(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const recordingAccess = room.preferences!.recordingPreferences.allowAccessTo;
|
||||||
|
|
||||||
|
if (recordingAccess === MeetRecordingAccess.ADMIN) {
|
||||||
|
// Deny request if the room is configured to allow access to recordings only for admins
|
||||||
|
throw errorInsufficientPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
role = roomService.getRoomRoleBySecretFromRoom(room as MeetRoom, secret);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error getting room role by secret', error);
|
||||||
|
|
||||||
|
if (error instanceof OpenViduMeetError) {
|
||||||
|
return res.status(error.statusCode).json({ name: error.name, message: error.message });
|
||||||
|
} else {
|
||||||
|
return res.status(500).json({
|
||||||
|
name: 'Room Error',
|
||||||
|
message: 'Internal server error. Room operation failed'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let authMode: AuthMode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { securityPreferences } = await storageService.getGlobalPreferences();
|
||||||
|
authMode = securityPreferences.authentication.authMode;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error checking authentication preferences', error);
|
||||||
|
return res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const authValidators = [];
|
||||||
|
|
||||||
|
if (authMode === AuthMode.NONE) {
|
||||||
|
authValidators.push(allowAnonymous);
|
||||||
|
} else {
|
||||||
|
const isModeratorsOnlyMode = authMode === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR;
|
||||||
|
const isAllUsersMode = authMode === AuthMode.ALL_USERS;
|
||||||
|
|
||||||
|
if (isModeratorsOnlyMode || isAllUsersMode) {
|
||||||
|
authValidators.push(tokenAndRoleValidator(UserRole.USER));
|
||||||
|
} else {
|
||||||
|
authValidators.push(allowAnonymous);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return withAuth(...authValidators)(req, res, next);
|
||||||
|
};
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import * as roomCtrl from '../controllers/room.controller.js';
|
|||||||
import {
|
import {
|
||||||
apiKeyValidator,
|
apiKeyValidator,
|
||||||
configureCreateRoomAuth,
|
configureCreateRoomAuth,
|
||||||
|
configureRecordingTokenAuth,
|
||||||
configureRoomAuthorization,
|
configureRoomAuthorization,
|
||||||
participantTokenValidator,
|
participantTokenValidator,
|
||||||
tokenAndRoleValidator,
|
tokenAndRoleValidator,
|
||||||
@ -66,7 +67,7 @@ internalRoomRouter.put(
|
|||||||
|
|
||||||
internalRoomRouter.post(
|
internalRoomRouter.post(
|
||||||
'/:roomId/recording-token',
|
'/:roomId/recording-token',
|
||||||
configureCreateRoomAuth,
|
configureRecordingTokenAuth,
|
||||||
withValidRoomSecret,
|
withValidRoomSecret,
|
||||||
roomCtrl.generateRecordingToken
|
roomCtrl.generateRecordingToken
|
||||||
);
|
);
|
||||||
|
|||||||
@ -249,7 +249,7 @@ export class RoomService {
|
|||||||
return this.getRoomRoleBySecretFromRoom(room, secret);
|
return this.getRoomRoleBySecretFromRoom(room, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getRoomRoleBySecretFromRoom(room: MeetRoom, secret: string): ParticipantRole {
|
getRoomRoleBySecretFromRoom(room: MeetRoom, secret: string): ParticipantRole {
|
||||||
const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room);
|
const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room);
|
||||||
|
|
||||||
switch (secret) {
|
switch (secret) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user