backend: enhance room members and users filtering

This commit is contained in:
juancarmore 2026-01-07 12:28:55 +01:00
parent a069ebafaf
commit 577c48fe1b
8 changed files with 43 additions and 49 deletions

View File

@ -78,7 +78,9 @@ export const RoomMemberFiltersSchema: z.ZodType<MeetRoomMemberFilters> = 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({

View File

@ -26,7 +26,9 @@ export const UserFiltersSchema: z.ZodType<MeetUserFilters> = 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({

View File

@ -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<MeetRoomMember, MeetRoo
* @param roomId - The ID of the room
* @param options - Query options
* @param options.name - Optional member name to filter by (case-insensitive partial match)
* @param options.fields - Comma-separated list of fields to include in the result
* @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')
@ -128,13 +135,7 @@ export class RoomMemberRepository extends BaseRepository<MeetRoomMember, MeetRoo
*/
async findByRoomId(
roomId: string,
options: {
name?: string;
maxItems?: number;
nextPageToken?: string;
sortField?: string;
sortOrder?: 'asc' | 'desc';
} = {}
options: MeetRoomMemberFilters = {}
): Promise<{
members: MeetRoomMember[];
isTruncated: boolean;
@ -148,7 +149,7 @@ export class RoomMemberRepository extends BaseRepository<MeetRoomMember, MeetRoo
this.currentRoomRoles = room.roles;
const { name, maxItems = 100, nextPageToken, sortField = 'name', sortOrder = 'asc' } = options;
const { name, fields, maxItems = 100, nextPageToken, sortField = 'name', sortOrder = 'asc' } = options;
// Build base filter
const filter: Record<string, unknown> = { roomId };
@ -158,12 +159,16 @@ export class RoomMemberRepository extends BaseRepository<MeetRoomMember, MeetRoo
}
// Use base repository's pagination method
const result = await this.findMany(filter, {
maxItems,
nextPageToken,
sortField,
sortOrder
});
const result = await this.findMany(
filter,
{
maxItems,
nextPageToken,
sortField,
sortOrder
},
fields
);
this.currentRoomRoles = undefined;

View File

@ -1,4 +1,4 @@
import { MeetUser } from '@openvidu-meet/typings';
import { MeetUser, MeetUserFilters } from '@openvidu-meet/typings';
import { inject, injectable } from 'inversify';
import { MeetUserDocument, MeetUserModel } from '../models/mongoose-schemas/user.schema.js';
import { LoggerService } from '../services/logger.service.js';
@ -76,27 +76,19 @@ export class UserRepository<TUser extends MeetUser = MeetUser> 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<string, unknown> = {};
@ -112,6 +104,10 @@ export class UserRepository<TUser extends MeetUser = MeetUser> 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,

View File

@ -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;
}

View File

@ -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.

View File

@ -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';
/**

View File

@ -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<MeetUser, 'passwordHash'>;
export type MeetUserFilters = {
export interface MeetUserFilters extends SortAndPagination {
userId?: string;
name?: string;
maxItems?: number;
nextPageToken?: string;
};
role?: MeetUserRole;
}