backend: add fields validation schema for RoomMember and update filters to use typed array

This commit is contained in:
juancarmore 2026-02-19 14:02:54 +01:00
parent c6742fd5eb
commit 66978509b1
3 changed files with 58 additions and 8 deletions

View File

@ -9,9 +9,11 @@ import {
import { z } from 'zod';
import { encodingValidator, nonEmptySanitizedRoomId } from './room.schema.js';
// Shared fields validation schema for Recording entity
// Validates and transforms comma-separated string to typed array
// Only allows fields that exist in MEET_RECORDING_FIELDS
/**
* Shared fields validation schema for Recording entity
* Validates and transforms comma-separated string to typed array
* Only allows fields that exist in MEET_RECORDING_FIELDS
*/
const fieldsSchema = z
.string()
.optional()

View File

@ -1,6 +1,7 @@
import {
MEET_ROOM_MEMBER_FIELDS,
MEET_ROOM_MEMBER_SORT_FIELDS,
MeetRoomMemberFilters,
MeetRoomMemberField,
MeetRoomMemberOptions,
MeetRoomMemberPermissions,
MeetRoomMemberRole,
@ -10,6 +11,32 @@ import {
} from '@openvidu-meet/typings';
import { z } from 'zod';
/**
* Shared fields validation schema for RoomMember entity
* Validates and transforms comma-separated string to typed array
* Only allows fields that exist in MEET_ROOM_MEMBER_FIELDS
*/
const fieldsSchema = z
.string()
.optional()
.transform((value) => {
if (!value) return undefined;
const requested = value
.split(',')
.map((field) => field.trim())
.filter((field) => field !== '');
// Filter: only keep valid fields that exist in MeetRoomMember
const validFields = requested.filter((field) =>
MEET_ROOM_MEMBER_FIELDS.includes(field as MeetRoomMemberField)
) as MeetRoomMemberField[];
const unique = Array.from(new Set(validFields));
return unique.length > 0 ? unique : undefined;
});
const RoomMemberRoleSchema: z.ZodType<MeetRoomMemberRole> = z.nativeEnum(MeetRoomMemberRole);
export const MeetPermissionsSchema: z.ZodType<MeetRoomMemberPermissions> = z.object({
@ -67,9 +94,9 @@ export const RoomMemberOptionsSchema: z.ZodType<MeetRoomMemberOptions> = z
}
);
export const RoomMemberFiltersSchema: z.ZodType<MeetRoomMemberFilters> = z.object({
export const RoomMemberFiltersSchema = z.object({
name: z.string().optional(),
fields: z.string().optional(),
fields: fieldsSchema,
maxItems: z.coerce
.number()
.positive('maxItems must be a positive number')

View File

@ -2,6 +2,27 @@ import { MeetRoomMemberPermissions } from '../database/room-member-permissions.j
import { MeetRoomMember, MeetRoomMemberRole } from '../database/room-member.entity.js';
import { SortAndPagination, SortableFieldKey } from './sort-pagination.js';
/**
* List of all valid fields that can be selected from a MeetRoomMember.
* This array is the source of truth and TypeScript validates it matches the MeetRoomMember interface.
*/
export const MEET_ROOM_MEMBER_FIELDS = [
'memberId',
'roomId',
'name',
'membershipDate',
'accessUrl',
'baseRole',
'customPermissions',
'effectivePermissions',
'permissionsUpdatedAt'
] as const satisfies readonly (keyof MeetRoomMember)[];
/**
* Properties of a {@link MeetRoomMember} that can be included in the API response when fields filtering is applied.
*/
export type MeetRoomMemberField = (typeof MEET_ROOM_MEMBER_FIELDS)[number];
/**
* Room member fields that are allowed for sorting in room member list queries.
*/
@ -21,8 +42,8 @@ export type MeetRoomMemberSortField = (typeof MEET_ROOM_MEMBER_SORT_FIELDS)[numb
export interface MeetRoomMemberFilters extends SortAndPagination<MeetRoomMemberSortField> {
/** Filter by member name (partial match) */
name?: string;
/** Comma-separated list of fields to include in the response (e.g., "userId,name,baseRole") */
fields?: string;
/** Array of fields to include in the response */
fields?: MeetRoomMemberField[];
}
/**