From 2bc1d0262076b3b80c23317e39ff705873bbdc9c Mon Sep 17 00:00:00 2001 From: juancarmore Date: Wed, 21 Jan 2026 19:38:25 +0100 Subject: [PATCH] backend: enhance error handling and validation in room and recording access middleware --- .../src/middlewares/recording.middleware.ts | 30 ++--- .../src/middlewares/room-member.middleware.ts | 104 +++++++++++++----- .../src/middlewares/room.middleware.ts | 55 ++++++--- 3 files changed, 133 insertions(+), 56 deletions(-) diff --git a/meet-ce/backend/src/middlewares/recording.middleware.ts b/meet-ce/backend/src/middlewares/recording.middleware.ts index f65b5204..46ea1d40 100644 --- a/meet-ce/backend/src/middlewares/recording.middleware.ts +++ b/meet-ce/backend/src/middlewares/recording.middleware.ts @@ -158,21 +158,25 @@ export const authorizeRecordingAccess = (permission: keyof MeetRoomMemberPermiss return next(); } - // Check if owner - const isOwner = await roomService.isRoomOwner(roomId, user.userId); + try { + // Check if owner + const isOwner = await roomService.isRoomOwner(roomId, user.userId); - if (isOwner) { - return next(); + if (isOwner) { + return next(); + } + + // Check if member with permissions + const member = await roomMemberService.getRoomMember(roomId, user.userId); + + if (member && member.effectivePermissions[permission]) { + return next(); + } + + return rejectRequestFromMeetError(res, forbiddenError); + } catch (error) { + return handleError(res, error, 'checking user access to room'); } - - // Check if member with permissions - const member = await roomMemberService.getRoomMember(roomId, user.userId); - - if (member && member.effectivePermissions[permission]) { - return next(); - } - - return rejectRequestFromMeetError(res, forbiddenError); } // Otherwise, reject the request diff --git a/meet-ce/backend/src/middlewares/room-member.middleware.ts b/meet-ce/backend/src/middlewares/room-member.middleware.ts index 706d9468..d025c8b8 100644 --- a/meet-ce/backend/src/middlewares/room-member.middleware.ts +++ b/meet-ce/backend/src/middlewares/room-member.middleware.ts @@ -5,6 +5,9 @@ import { MeetRoomHelper } from '../helpers/room.helper.js'; import { errorInsufficientPermissions, errorInvalidRoomSecret, + errorRoomMemberNotFound, + errorRoomNotFound, + handleError, rejectRequestFromMeetError } from '../models/error.model.js'; import { RequestSessionService } from '../services/request-session.service.js'; @@ -23,6 +26,19 @@ export const authorizeRoomMemberAccess = async (req: Request, res: Response, nex const roomId = req.params.roomId as string; const memberId = req.params.memberId as string; + // Fail fast if room or member does not exist + try { + const roomMemberService = container.get(RoomMemberService); + const isMember = await roomMemberService.isRoomMember(roomId, memberId); + + if (!isMember) { + const error = errorRoomMemberNotFound(roomId, memberId); + return rejectRequestFromMeetError(res, error); + } + } catch (error) { + return handleError(res, error, 'checking if member exists in room'); + } + const requestSessionService = container.get(RequestSessionService); const user = requestSessionService.getAuthenticatedUser(); const memberRoomId = requestSessionService.getRoomIdFromMember(); @@ -50,17 +66,21 @@ export const authorizeRoomMemberAccess = async (req: Request, res: Response, nex return next(); } - // Allow if user is room owner - const roomService = container.get(RoomService); - const isOwner = await roomService.isRoomOwner(roomId, user.userId); + try { + // Allow if user is room owner + const roomService = container.get(RoomService); + const isOwner = await roomService.isRoomOwner(roomId, user.userId); - if (isOwner) { - return next(); - } + if (isOwner) { + return next(); + } - if (user.userId === memberId) { - // If the user is trying to access their own member info, allow it - return next(); + // Allow if user is accessing their own member info + if (user.userId === memberId) { + return next(); + } + } catch (error) { + return handleError(res, error, 'checking room ownership'); } } @@ -96,43 +116,58 @@ export const authorizeRoomMemberTokenGeneration = async (req: Request, res: Resp const { roomId } = req.params; const { secret } = req.body as MeetRoomMemberTokenOptions; - const requestSessionService = container.get(RequestSessionService); const roomService = container.get(RoomService); - const roomMemberService = container.get(RoomMemberService); + const roomExists = await roomService.meetRoomExists(roomId); + // Fail fast if room does not exist + if (!roomExists) { + const error = errorRoomNotFound(roomId); + return rejectRequestFromMeetError(res, error); + } + + const requestSessionService = container.get(RequestSessionService); const user = requestSessionService.getAuthenticatedUser(); const forbiddenError = errorInsufficientPermissions(); // Scenario 1: Secret provided (Anonymous access or Member ID) if (secret) { - // Check if secret matches any room access URL secret - const isValidSecret = await roomService.isValidRoomSecret(roomId, secret); + try { + // Check if secret matches any room access URL secret + const isValidSecret = await roomService.isValidRoomSecret(roomId, secret); - if (isValidSecret) { - return next(); + if (isValidSecret) { + return next(); + } + + // Check if secret is a memberId + const roomMemberService = container.get(RoomMemberService); + const isMember = await roomMemberService.isRoomMember(roomId, secret); + + if (isMember) { + return next(); + } + + const error = errorInvalidRoomSecret(roomId, secret); + return rejectRequestFromMeetError(res, error); + } catch (error) { + return handleError(res, error, 'checking room secret'); } - - // Check if secret is a memberId - const isMember = await roomMemberService.isRoomMember(roomId, secret); - - if (isMember) { - return next(); - } - - const error = errorInvalidRoomSecret(roomId, secret); - return rejectRequestFromMeetError(res, error); } // Scenario 2: No secret provided (Authenticated User) if (user) { - const canAccess = await roomService.canUserAccessRoom(roomId, user); + try { + const canAccess = await roomService.canUserAccessRoom(roomId, user); - if (!canAccess) { - return rejectRequestFromMeetError(res, forbiddenError); + if (!canAccess) { + return rejectRequestFromMeetError(res, forbiddenError); + } + + return next(); + } catch (error) { + return handleError(res, error, 'checking user access to room'); } - - return next(); } return rejectRequestFromMeetError(res, forbiddenError); @@ -147,6 +182,15 @@ export const withRoomMemberPermission = (permission: keyof MeetRoomMemberPermiss return async (req: Request, res: Response, next: NextFunction) => { const roomId = MeetRoomHelper.getRoomIdFromRequest(req); + const roomService = container.get(RoomService); + const roomExists = await roomService.meetRoomExists(roomId!); + + // Fail fast if room does not exist + if (!roomExists) { + const error = errorRoomNotFound(roomId!); + return rejectRequestFromMeetError(res, error); + } + const requestSessionService = container.get(RequestSessionService); const memberRoomId = requestSessionService.getRoomIdFromMember(); const permissions = requestSessionService.getRoomMemberPermissions(); diff --git a/meet-ce/backend/src/middlewares/room.middleware.ts b/meet-ce/backend/src/middlewares/room.middleware.ts index e215af23..72cfdc91 100644 --- a/meet-ce/backend/src/middlewares/room.middleware.ts +++ b/meet-ce/backend/src/middlewares/room.middleware.ts @@ -1,7 +1,12 @@ import { MeetUserRole } from '@openvidu-meet/typings'; import { NextFunction, Request, Response } from 'express'; import { container } from '../config/dependency-injector.config.js'; -import { errorInsufficientPermissions, rejectRequestFromMeetError } from '../models/error.model.js'; +import { + errorInsufficientPermissions, + errorRoomNotFound, + handleError, + rejectRequestFromMeetError +} from '../models/error.model.js'; import { RequestSessionService } from '../services/request-session.service.js'; import { RoomService } from '../services/room.service.js'; @@ -15,6 +20,15 @@ import { RoomService } from '../services/room.service.js'; export const authorizeRoomAccess = async (req: Request, res: Response, next: NextFunction) => { const roomId = req.params.roomId as string; + const roomService = container.get(RoomService); + const roomExists = await roomService.meetRoomExists(roomId); + + // Fail fast if room does not exist + if (!roomExists) { + const error = errorRoomNotFound(roomId); + return rejectRequestFromMeetError(res, error); + } + const requestSessionService = container.get(RequestSessionService); const memberRoomId = requestSessionService.getRoomIdFromMember(); const user = requestSessionService.getAuthenticatedUser(); @@ -33,14 +47,17 @@ export const authorizeRoomAccess = async (req: Request, res: Response, next: Nex // Registered User if (user) { - const roomService = container.get(RoomService); - const canAccess = await roomService.canUserAccessRoom(roomId, user); + try { + const canAccess = await roomService.canUserAccessRoom(roomId, user); - if (!canAccess) { - return rejectRequestFromMeetError(res, forbiddenError); + if (!canAccess) { + return rejectRequestFromMeetError(res, forbiddenError); + } + + return next(); + } catch (error) { + return handleError(res, error, 'checking user access to room'); } - - return next(); } // If there is no token and no user, reject the request @@ -55,6 +72,15 @@ export const authorizeRoomAccess = async (req: Request, res: Response, next: Nex export const authorizeRoomManagement = async (req: Request, res: Response, next: NextFunction) => { const roomId = req.params.roomId as string; + const roomService = container.get(RoomService); + const roomExists = await roomService.meetRoomExists(roomId); + + // Fail fast if room does not exist + if (!roomExists) { + const error = errorRoomNotFound(roomId); + return rejectRequestFromMeetError(res, error); + } + const requestSessionService = container.get(RequestSessionService); const user = requestSessionService.getAuthenticatedUser(); @@ -68,12 +94,15 @@ export const authorizeRoomManagement = async (req: Request, res: Response, next: return next(); } - const roomService = container.get(RoomService); - const isOwner = await roomService.isRoomOwner(roomId, user.userId); + try { + const isOwner = await roomService.isRoomOwner(roomId, user.userId); - if (isOwner) { - return next(); + if (isOwner) { + return next(); + } + + return rejectRequestFromMeetError(res, forbiddenError); + } catch (error) { + return handleError(res, error, 'checking room ownership'); } - - return rejectRequestFromMeetError(res, forbiddenError); };