From 577c48fe1b55ba4bcd8bb5497bb9573495165999 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Wed, 7 Jan 2026 12:28:55 +0100 Subject: [PATCH] backend: enhance room members and users filtering --- .../models/zod-schemas/room-member.schema.ts | 4 ++- .../src/models/zod-schemas/user.schema.ts | 4 ++- .../repositories/room-member.repository.ts | 35 +++++++++++-------- .../src/repositories/user.repository.ts | 20 +++++------ .../src/services/room-member.service.ts | 12 +------ meet-ce/typings/src/room-member.ts | 7 ++-- meet-ce/typings/src/room.ts | 1 - meet-ce/typings/src/user.ts | 9 ++--- 8 files changed, 43 insertions(+), 49 deletions(-) diff --git a/meet-ce/backend/src/models/zod-schemas/room-member.schema.ts b/meet-ce/backend/src/models/zod-schemas/room-member.schema.ts index 82cb9102..f5a67ca7 100644 --- a/meet-ce/backend/src/models/zod-schemas/room-member.schema.ts +++ b/meet-ce/backend/src/models/zod-schemas/room-member.schema.ts @@ -78,7 +78,9 @@ export const RoomMemberFiltersSchema: z.ZodType = z.objec return intVal > 100 ? 100 : intVal; }) .default(10), - nextPageToken: z.string().optional() + nextPageToken: z.string().optional(), + sortField: z.enum(['name', 'membershipDate']).optional().default('membershipDate'), + sortOrder: z.enum(['asc', 'desc']).optional().default('desc') }); export const BulkDeleteRoomMembersReqSchema = z.object({ diff --git a/meet-ce/backend/src/models/zod-schemas/user.schema.ts b/meet-ce/backend/src/models/zod-schemas/user.schema.ts index 09103757..06e0c958 100644 --- a/meet-ce/backend/src/models/zod-schemas/user.schema.ts +++ b/meet-ce/backend/src/models/zod-schemas/user.schema.ts @@ -26,7 +26,9 @@ export const UserFiltersSchema: z.ZodType = z.object({ return intVal > 100 ? 100 : intVal; }) .default(10), - nextPageToken: z.string().optional() + nextPageToken: z.string().optional(), + sortField: z.enum(['name', 'registrationDate']).optional().default('registrationDate'), + sortOrder: z.enum(['asc', 'desc']).optional().default('desc') }); export const BulkDeleteUsersReqSchema = z.object({ diff --git a/meet-ce/backend/src/repositories/room-member.repository.ts b/meet-ce/backend/src/repositories/room-member.repository.ts index 1a51776d..4dc73934 100644 --- a/meet-ce/backend/src/repositories/room-member.repository.ts +++ b/meet-ce/backend/src/repositories/room-member.repository.ts @@ -1,4 +1,10 @@ -import { MeetRoomMember, MeetRoomMemberPermissions, MeetRoomMemberRole, MeetRoomRoles } from '@openvidu-meet/typings'; +import { + MeetRoomMember, + MeetRoomMemberFilters, + MeetRoomMemberPermissions, + MeetRoomMemberRole, + MeetRoomRoles +} from '@openvidu-meet/typings'; import { inject, injectable } from 'inversify'; import { errorRoomNotFound } from '../models/error.model.js'; import { MeetRoomMemberDocument, MeetRoomMemberModel } from '../models/mongoose-schemas/room-member.schema.js'; @@ -120,6 +126,7 @@ export class RoomMemberRepository extends BaseRepository = { roomId }; @@ -158,12 +159,16 @@ export class RoomMemberRepository extends BaseRepository extends BaseRepos * @param options - Query options * @param options.userId - Optional user ID to filter by (case-insensitive partial match) * @param options.name - Optional name to filter by (case-insensitive partial match) + * @param options.role - Optional role to filter by * @param options.maxItems - Maximum number of results to return (default: 100) * @param options.nextPageToken - Token for pagination * @param options.sortField - Field to sort by (default: 'name') * @param options.sortOrder - Sort order: 'asc' or 'desc' (default: 'asc') * @returns Object containing users array, pagination info, and optional next page token */ - async find( - options: { - userId?: string; - name?: string; - maxItems?: number; - nextPageToken?: string; - sortField?: string; - sortOrder?: 'asc' | 'desc'; - } = {} - ): Promise<{ + async find(options: MeetUserFilters = {}): Promise<{ users: TUser[]; isTruncated: boolean; nextPageToken?: string; }> { - const { userId, name, maxItems = 100, nextPageToken, sortField = 'name', sortOrder = 'asc' } = options; + const { userId, name, role, maxItems = 100, nextPageToken, sortField = 'name', sortOrder = 'asc' } = options; // Build base filter const filter: Record = {}; @@ -112,6 +104,10 @@ export class UserRepository extends BaseRepos filter.name = new RegExp(name, 'i'); } + if (role) { + filter.role = role; + } + // Use base repository's pagination method const result = await this.findMany(filter, { maxItems, diff --git a/meet-ce/backend/src/services/room-member.service.ts b/meet-ce/backend/src/services/room-member.service.ts index 5e04a092..ef788fb8 100644 --- a/meet-ce/backend/src/services/room-member.service.ts +++ b/meet-ce/backend/src/services/room-member.service.ts @@ -17,7 +17,6 @@ import { uid as secureUid } from 'uid/secure'; import { uid } from 'uid/single'; import { MEET_ENV } from '../environment.js'; import { MeetRoomHelper } from '../helpers/room.helper.js'; -import { UtilsHelper } from '../helpers/utils.helper.js'; import { validateRoomMemberTokenMetadata } from '../middlewares/request-validators/room-member-validator.middleware.js'; import { errorInsufficientPermissions, @@ -135,16 +134,7 @@ export class RoomMemberService { isTruncated: boolean; nextPageToken?: string; }> { - const { fields, ...findOptions } = filters; - const response = await this.roomMemberRepository.findByRoomId(roomId, findOptions); - - if (fields) { - const filteredMembers = response.members.map((member: MeetRoomMember) => - UtilsHelper.filterObjectFields(member, fields) - ); - response.members = filteredMembers as MeetRoomMember[]; - } - + const response = await this.roomMemberRepository.findByRoomId(roomId, filters); return response; } diff --git a/meet-ce/typings/src/room-member.ts b/meet-ce/typings/src/room-member.ts index e5574456..2fe16c4f 100644 --- a/meet-ce/typings/src/room-member.ts +++ b/meet-ce/typings/src/room-member.ts @@ -1,4 +1,5 @@ import { MeetRoomMemberPermissions } from './permissions/meet-permissions.js'; +import { SortAndPagination } from './sort-pagination.js'; /** * Options for adding a member to a room. @@ -31,12 +32,10 @@ export enum MeetRoomMemberRole { SPEAKER = 'speaker' } -export type MeetRoomMemberFilters = { +export interface MeetRoomMemberFilters extends SortAndPagination { name?: string; fields?: string; - maxItems?: number; - nextPageToken?: string; -}; +} /** * Options for generating a room member token. diff --git a/meet-ce/typings/src/room.ts b/meet-ce/typings/src/room.ts index ab7dfe3e..d8dc987e 100644 --- a/meet-ce/typings/src/room.ts +++ b/meet-ce/typings/src/room.ts @@ -1,6 +1,5 @@ import { MeetRoomMemberPermissions } from './permissions/meet-permissions.js'; import { MeetRoomConfig } from './room-config.js'; -import { MeetRoomMemberPermissions, MeetRoomMemberRole } from './room-member.js'; import { SortAndPagination } from './sort-pagination.js'; /** diff --git a/meet-ce/typings/src/user.ts b/meet-ce/typings/src/user.ts index ccd08620..d387a480 100644 --- a/meet-ce/typings/src/user.ts +++ b/meet-ce/typings/src/user.ts @@ -1,3 +1,5 @@ +import { SortAndPagination } from './sort-pagination.js'; + /** * Options for creating a new Meet user. */ @@ -26,9 +28,8 @@ export enum MeetUserRole { export type MeetUserDTO = Omit; -export type MeetUserFilters = { +export interface MeetUserFilters extends SortAndPagination { userId?: string; name?: string; - maxItems?: number; - nextPageToken?: string; -}; + role?: MeetUserRole; +}