From bc33e9c5d9647332888f7ce3170e369e4b3475b7 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Fri, 28 Mar 2025 12:12:33 +0100 Subject: [PATCH] backend: Add endpoint to retrieve participant role by room secret --- backend/src/controllers/room.controller.ts | 18 +++++++++++++ .../room-validator.middleware.ts | 26 ++++++++++++++++++- backend/src/routes/room.routes.ts | 8 ++++++ backend/src/server.ts | 7 ++++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/room.controller.ts b/backend/src/controllers/room.controller.ts index 8c0ccad..62213c1 100644 --- a/backend/src/controllers/room.controller.ts +++ b/backend/src/controllers/room.controller.ts @@ -94,6 +94,24 @@ export const deleteRooms = async (req: Request, res: Response) => { } }; +export const getParticipantRole = async (req: Request, res: Response) => { + const logger = container.get(LoggerService); + const roomService = container.get(RoomService); + + const { roomName } = req.params; + const { secret } = req.query as { secret: string }; + + try { + logger.verbose(`Getting participant role for room '${roomName}'`); + + const role = await roomService.getRoomSecretRole(roomName, secret); + return res.status(200).json(role); + } catch (error) { + logger.error(`Error getting participant role for room '${roomName}'`); + handleError(res, error); + } +}; + export const updateRoomPreferences = async (req: Request, res: Response) => { const logger = container.get(LoggerService); diff --git a/backend/src/middlewares/request-validators/room-validator.middleware.ts b/backend/src/middlewares/request-validators/room-validator.middleware.ts index efbd1dc..6865c10 100644 --- a/backend/src/middlewares/request-validators/room-validator.middleware.ts +++ b/backend/src/middlewares/request-validators/room-validator.middleware.ts @@ -49,6 +49,10 @@ const RoomRequestOptionsSchema: z.ZodType = z.object({ .default(null) }); +const GetParticipantRoleSchema = z.object({ + secret: z.string() +}); + export const validateRoomRequest = (req: Request, res: Response, next: NextFunction) => { const { success, error, data } = RoomRequestOptionsSchema.safeParse(req.body); @@ -80,4 +84,24 @@ export const validateGetRoomQueryParams = (req: Request, res: Response, next: Ne } next(); -} +}; + +export const validateGetParticipantRoleRequest = (req: Request, res: Response, next: NextFunction) => { + const { success, error, data } = GetParticipantRoleSchema.safeParse(req.query); + + if (!success) { + const errors = error.errors.map((error) => ({ + field: error.path.join('.'), + message: error.message + })); + + return res.status(422).json({ + error: 'Unprocessable Entity', + message: 'Invalid request query', + details: errors + }); + } + + req.query = data; + next(); +}; diff --git a/backend/src/routes/room.routes.ts b/backend/src/routes/room.routes.ts index 434dfa3..fb5116a 100644 --- a/backend/src/routes/room.routes.ts +++ b/backend/src/routes/room.routes.ts @@ -8,6 +8,7 @@ import { participantTokenValidator } from '../middlewares/auth.middleware.js'; import { + validateGetParticipantRoleRequest, validateGetRoomQueryParams, validateRoomRequest } from '../middlewares/request-validators/room-validator.middleware.js'; @@ -38,3 +39,10 @@ roomRouter.delete('/:roomName', withAuth(apiKeyValidator, tokenAndRoleValidator( // Room preferences roomRouter.put('/', withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), roomCtrl.updateRoomPreferences); + +// Internal room routes +export const internalRoomRouter = Router(); +internalRoomRouter.use(bodyParser.urlencoded({ extended: true })); +internalRoomRouter.use(bodyParser.json()); + +internalRoomRouter.get('/:roomName/participant-role', validateGetParticipantRoleRequest, roomCtrl.getParticipantRole); diff --git a/backend/src/server.ts b/backend/src/server.ts index 45520e8..cd46b29 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -13,6 +13,7 @@ import { openapiHtmlPath, indexHtmlPath, publicFilesPath, webcomponentBundlePath import { authRouter, internalRecordingRouter, + internalRoomRouter, livekitWebhookRouter, preferencesRouter, recordingRouter, @@ -49,6 +50,7 @@ const createApp = () => { app.use(`${MEET_API_BASE_PATH_V1}/preferences`, /*mediaTypeValidatorMiddleware,*/ preferencesRouter); // Internal routes + app.use(`${MEET_INTERNAL_API_BASE_PATH_V1}/rooms`, internalRoomRouter); app.use(`${MEET_INTERNAL_API_BASE_PATH_V1}/participants`, internalParticipantsRouter); app.use(`${MEET_INTERNAL_API_BASE_PATH_V1}/recordings`, internalRecordingRouter); app.use('/meet/health', (_req: Request, res: Response) => res.status(200).send('OK')); @@ -76,7 +78,10 @@ const startServer = (app: express.Application) => { console.log('---------------------------------------------------------'); console.log(' '); console.log('OpenVidu Meet is listening on port', chalk.cyanBright(SERVER_PORT)); - console.log('REST API Docs: ', chalk.cyanBright(`http://localhost:${SERVER_PORT}${MEET_API_BASE_PATH_V1}/docs`)); + console.log( + 'REST API Docs: ', + chalk.cyanBright(`http://localhost:${SERVER_PORT}${MEET_API_BASE_PATH_V1}/docs`) + ); logEnvVars(); await Promise.all([initializeGlobalPreferences(), container.get(RoomService).initialize()]); });