From 00b1d8be935900329864de553dd1e0105b47083d Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Tue, 11 Mar 2025 18:35:42 +0100 Subject: [PATCH] backend: Add fields query parameter to get rooms and room details endpoints --- backend/openapi/openvidu-meet-api.yaml | 21 ++++++++++++++ backend/src/controllers/room.controller.ts | 29 ++++++++++++++++++- .../room-validator.middleware.ts | 11 +++++++ backend/src/routes/room.routes.ts | 6 ++-- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/backend/openapi/openvidu-meet-api.yaml b/backend/openapi/openvidu-meet-api.yaml index 0470142..e69b0f1 100644 --- a/backend/openapi/openvidu-meet-api.yaml +++ b/backend/openapi/openvidu-meet-api.yaml @@ -133,10 +133,21 @@ paths: summary: Get a list of OpenVidu Meet rooms description: > Retrieves a list of OpenVidu Meet rooms that are currently active. + You can specify a comma-separated list of fields (using the "fields" query parameter) to include only + those properties in the response (e.g. roomName, preferences). tags: - Room security: - apiKeyInHeader: [] + parameters: + - name: fields + in: query + required: false + description: | + Comma-separated list of fields to include in the response. + For example: "roomName,preferences". Only allowed fields will be returned. + schema: + type: string responses: '200': description: Successfully retrieved the list of OpenVidu Meet rooms @@ -249,6 +260,8 @@ paths: summary: Get details of an OpenVidu Meet room description: > Retrieves the details of an OpenVidu Meet room with the specified room name. + Additionally, you can specify a comma-separated list of fields (using the "fields" query parameter) + to include only those properties in the response (e.g. roomName, preferences). tags: - Room security: @@ -260,6 +273,14 @@ paths: description: The name of the room to retrieve schema: type: string + - name: fields + in: query + required: false + description: | + Comma-separated list of fields to include in the response. + For example: "roomName,preferences". Only allowed fields will be returned. + schema: + type: string responses: '200': description: Successfully retrieved the OpenVidu Meet room diff --git a/backend/src/controllers/room.controller.ts b/backend/src/controllers/room.controller.ts index 3836564..8c0ccad 100644 --- a/backend/src/controllers/room.controller.ts +++ b/backend/src/controllers/room.controller.ts @@ -22,14 +22,21 @@ export const createRoom = async (req: Request, res: Response) => { } }; -export const getRooms = async (_req: Request, res: Response) => { +export const getRooms = async (req: Request, res: Response) => { const logger = container.get(LoggerService); + const fields = req.query.fields as string[] | undefined; try { logger.verbose('Getting rooms'); const roomService = container.get(RoomService); const rooms = await roomService.listOpenViduRooms(); + + if (fields && fields.length > 0) { + const filteredRooms = rooms.map((room) => filterObjectFields(room, fields)); + return res.status(200).json(filteredRooms); + } + return res.status(200).json(rooms); } catch (error) { logger.error('Error getting rooms'); @@ -41,12 +48,19 @@ export const getRoom = async (req: Request, res: Response) => { const logger = container.get(LoggerService); const { roomName } = req.params; + const fields = req.query.fields as string[] | undefined; try { logger.verbose(`Getting room with id '${roomName}'`); const roomService = container.get(RoomService); const room = await roomService.getOpenViduRoom(roomName); + + if (fields && fields.length > 0) { + const filteredRoom = filterObjectFields(room, fields); + return res.status(200).json(filteredRoom); + } + return res.status(200).json(room); } catch (error) { logger.error(`Error getting room with id '${roomName}'`); @@ -106,6 +120,19 @@ export const updateRoomPreferences = async (req: Request, res: Response) => { // } }; +const filterObjectFields = (obj: Record, fields: string[]): Record => { + return fields.reduce( + (acc, field) => { + if (Object.prototype.hasOwnProperty.call(obj, field)) { + acc[field] = obj[field]; + } + + return acc; + }, + {} as Record + ); +}; + const handleError = (res: Response, error: OpenViduMeetError | unknown) => { const logger = container.get(LoggerService); logger.error(String(error)); diff --git a/backend/src/middlewares/request-validators/room-validator.middleware.ts b/backend/src/middlewares/request-validators/room-validator.middleware.ts index 6c49017..efbd1dc 100644 --- a/backend/src/middlewares/request-validators/room-validator.middleware.ts +++ b/backend/src/middlewares/request-validators/room-validator.middleware.ts @@ -70,3 +70,14 @@ export const validateRoomRequest = (req: Request, res: Response, next: NextFunct req.body = data; next(); }; + +export const validateGetRoomQueryParams = (req: Request, res: Response, next: NextFunction) => { + const fieldsQuery = req.query.fields as string | undefined; + + if (fieldsQuery) { + const fields = fieldsQuery.split(',').map((f) => f.trim()); + req.query.fields = fields; + } + + next(); +} diff --git a/backend/src/routes/room.routes.ts b/backend/src/routes/room.routes.ts index ee12dbc..d05e9b4 100644 --- a/backend/src/routes/room.routes.ts +++ b/backend/src/routes/room.routes.ts @@ -2,7 +2,7 @@ import { Router } from 'express'; import bodyParser from 'body-parser'; import * as roomCtrl from '../controllers/room.controller.js'; import { withUserBasicAuth, withValidApiKey } from '../middlewares/auth.middleware.js'; -import { validateRoomRequest } from '../middlewares/request-validators/room-validator.middleware.js'; +import { validateGetRoomQueryParams, validateRoomRequest } from '../middlewares/request-validators/room-validator.middleware.js'; export const roomRouter = Router(); @@ -11,8 +11,8 @@ roomRouter.use(bodyParser.json()); // Room Routes roomRouter.post('/', /*withValidApiKey,*/ validateRoomRequest, roomCtrl.createRoom); -roomRouter.get('/', withUserBasicAuth, roomCtrl.getRooms); -roomRouter.get('/:roomName', withUserBasicAuth, roomCtrl.getRoom); +roomRouter.get('/', withUserBasicAuth, validateGetRoomQueryParams, roomCtrl.getRooms); +roomRouter.get('/:roomName', withUserBasicAuth, validateGetRoomQueryParams, roomCtrl.getRoom); roomRouter.delete('/:roomName', withUserBasicAuth, roomCtrl.deleteRooms); // Room preferences