backend: Enhance recording service to support field filtering in getRecording and getAllRecordings methods
This commit is contained in:
parent
18e0fe6a64
commit
a0b7d42002
@ -70,10 +70,12 @@ export const getRecording = async (req: Request, res: Response) => {
|
||||
const logger = container.get(LoggerService);
|
||||
const recordingService = container.get(RecordingService);
|
||||
const recordingId = req.params.recordingId;
|
||||
const fields = req.query.fields as string | undefined;
|
||||
|
||||
logger.info(`Getting recording ${recordingId}`);
|
||||
|
||||
try {
|
||||
const recordingInfo = await recordingService.getRecording(recordingId);
|
||||
const recordingInfo = await recordingService.getRecording(recordingId, fields);
|
||||
return res.status(200).json(recordingInfo);
|
||||
} catch (error) {
|
||||
if (error instanceof OpenViduMeetError) {
|
||||
|
||||
@ -1,18 +1,33 @@
|
||||
import { MeetRecordingInfo, MeetRoom } from '@typings-ce';
|
||||
|
||||
export class UtilsHelper {
|
||||
private constructor() {
|
||||
// Prevent instantiation of this utility class
|
||||
// Prevent instantiation of this utility class.
|
||||
private constructor() {}
|
||||
|
||||
/**
|
||||
* Filters the fields of an object based on a list of keys.
|
||||
*
|
||||
* @param obj - The object to filter (it can be a MeetRoom or MeetRecordingInfo).
|
||||
* @param fields - A comma-separated string or an array of field names to keep.
|
||||
* @returns A new object containing only the specified keys.
|
||||
*/
|
||||
static filterObjectFields<T extends MeetRecordingInfo | MeetRoom>(obj: T, fields?: string | string[]): Partial<T> {
|
||||
// If no fields are provided, return the full object.
|
||||
if (!fields || (typeof fields === 'string' && fields.trim().length === 0)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Convert the string to an array if necessary.
|
||||
const fieldsArray = Array.isArray(fields) ? fields : fields.split(',').map((f) => f.trim());
|
||||
|
||||
// Reduce the object by only including the specified keys.
|
||||
return fieldsArray.reduce((acc, field) => {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, field)) {
|
||||
// Use keyof T to properly type the field access
|
||||
acc[field as keyof T] = obj[field as keyof T];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {} as Partial<T>);
|
||||
}
|
||||
|
||||
static filterObjectFields = (obj: Record<string, unknown>, fields: string[]): Record<string, any> => {
|
||||
return fields.reduce(
|
||||
(acc, field) => {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, field)) {
|
||||
acc[field] = obj[field];
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, unknown>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -52,7 +52,8 @@ const GetRecordingsFiltersSchema: z.ZodType<MeetRecordingFilters> = z.object({
|
||||
.default(10),
|
||||
// status: z.string().optional(),
|
||||
roomId: z.string().optional(),
|
||||
nextPageToken: z.string().optional()
|
||||
nextPageToken: z.string().optional(),
|
||||
fields: z.string().optional(),
|
||||
});
|
||||
|
||||
export const withValidStartRecordingRequest = (req: Request, res: Response, next: NextFunction) => {
|
||||
@ -77,7 +78,7 @@ export const withValidRecordingId = (req: Request, res: Response, next: NextFunc
|
||||
next();
|
||||
};
|
||||
|
||||
export const withValidGetRecordingsRequest = (req: Request, res: Response, next: NextFunction) => {
|
||||
export const withValidRecordingFiltersRequest = (req: Request, res: Response, next: NextFunction) => {
|
||||
const { success, error, data } = GetRecordingsFiltersSchema.safeParse(req.query);
|
||||
|
||||
if (!success) {
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
tokenAndRoleValidator,
|
||||
withRecordingEnabled,
|
||||
withCorrectPermissions,
|
||||
withValidGetRecordingsRequest,
|
||||
withValidRecordingFiltersRequest,
|
||||
withValidRecordingBulkDeleteRequest,
|
||||
withValidRecordingId,
|
||||
withValidStartRecordingRequest,
|
||||
@ -35,7 +35,7 @@ recordingRouter.get(
|
||||
recordingRouter.get(
|
||||
'/',
|
||||
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||
withValidGetRecordingsRequest,
|
||||
withValidRecordingFiltersRequest,
|
||||
recordingCtrl.getRecordings
|
||||
);
|
||||
recordingRouter.delete(
|
||||
|
||||
@ -37,6 +37,7 @@ import { MeetLock } from '../helpers/redis.helper.js';
|
||||
import { IScheduledTask, TaskSchedulerService } from './task-scheduler.service.js';
|
||||
import { SystemEventService } from './system-event.service.js';
|
||||
import { SystemEventType } from '../models/system-event.model.js';
|
||||
import { UtilsHelper } from '../helpers/utils.helper.js';
|
||||
|
||||
@injectable()
|
||||
export class RecordingService {
|
||||
@ -228,10 +229,10 @@ export class RecordingService {
|
||||
* @param recordingId - The unique identifier of the recording.
|
||||
* @returns A promise that resolves to a MeetRecordingInfo object.
|
||||
*/
|
||||
async getRecording(recordingId: string): Promise<MeetRecordingInfo> {
|
||||
async getRecording(recordingId: string, fields?: string): Promise<MeetRecordingInfo> {
|
||||
const { recordingInfo } = await this.getMeetRecordingInfoFromMetadata(recordingId);
|
||||
|
||||
return recordingInfo;
|
||||
return UtilsHelper.filterObjectFields(recordingInfo, fields) as MeetRecordingInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,7 +246,7 @@ export class RecordingService {
|
||||
* - `nextPageToken`: (Optional) A token to retrieve the next page of results, if available.
|
||||
* @throws Will throw an error if there is an issue retrieving the recordings.
|
||||
*/
|
||||
async getAllRecordings({ maxItems, nextPageToken, roomId }: MeetRecordingFilters): Promise<{
|
||||
async getAllRecordings({ maxItems, nextPageToken, roomId, fields }: MeetRecordingFilters): Promise<{
|
||||
recordings: MeetRecordingInfo[];
|
||||
isTruncated: boolean;
|
||||
nextPageToken?: string;
|
||||
@ -274,7 +275,9 @@ export class RecordingService {
|
||||
}
|
||||
});
|
||||
|
||||
const recordings: MeetRecordingInfo[] = await Promise.all(promises);
|
||||
let recordings: MeetRecordingInfo[] = await Promise.all(promises);
|
||||
|
||||
recordings = recordings.map((rec) => UtilsHelper.filterObjectFields(rec, fields)) as MeetRecordingInfo[];
|
||||
|
||||
this.logger.info(`Retrieved ${recordings.length} recordings.`);
|
||||
// Return the paginated list of recordings
|
||||
|
||||
@ -89,7 +89,7 @@ export class RoomService {
|
||||
metadata: JSON.stringify({
|
||||
createdBy: MEET_NAME_ID,
|
||||
roomOptions: MeetRoomHelper.toOpenViduOptions(meetRoom)
|
||||
}),
|
||||
})
|
||||
//TODO: Uncomment this when bug in LiveKit is fixed
|
||||
// When it is defined, the room will be closed although there are participants
|
||||
// emptyTimeout: ms('20s') / 1000,
|
||||
@ -129,13 +129,8 @@ export class RoomService {
|
||||
}> {
|
||||
const response = await this.storageService.getMeetRooms(maxItems, nextPageToken);
|
||||
|
||||
if (fields && fields.length > 0) {
|
||||
const fieldsArray = Array.isArray(fields) ? fields : fields.split(',').map((f) => f.trim());
|
||||
const filteredRooms = response.rooms.map((room) =>
|
||||
UtilsHelper.filterObjectFields(room as unknown as Record<string, unknown>, fieldsArray)
|
||||
);
|
||||
response.rooms = filteredRooms as MeetRoom[];
|
||||
}
|
||||
const filteredRooms = response.rooms.map((room) => UtilsHelper.filterObjectFields(room, fields));
|
||||
response.rooms = filteredRooms as MeetRoom[];
|
||||
|
||||
return response;
|
||||
}
|
||||
@ -149,16 +144,7 @@ export class RoomService {
|
||||
async getMeetRoom(roomId: string, fields?: string): Promise<MeetRoom> {
|
||||
const meetRoom = await this.storageService.getMeetRoom(roomId);
|
||||
|
||||
if (fields && fields.length > 0) {
|
||||
const fieldsArray = Array.isArray(fields) ? fields : fields.split(',').map((f) => f.trim());
|
||||
const filteredRoom = UtilsHelper.filterObjectFields(
|
||||
meetRoom as unknown as Record<string, unknown>,
|
||||
fieldsArray
|
||||
);
|
||||
return filteredRoom as MeetRoom;
|
||||
}
|
||||
|
||||
return meetRoom;
|
||||
return UtilsHelper.filterObjectFields(meetRoom, fields) as MeetRoom;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user