feathersjs / feathers

The API and real-time application framework
https://feathersjs.com
MIT License
15.07k stars 752 forks source link

dispatch resolver does not run on related collections #2917

Closed alwex closed 1 year ago

alwex commented 1 year ago

Steps to reproduce

Create a schema with some one to many relationship like so: Classroom has many Users through UserClassrooms

// User resolver
export const usersDispatchResolver = resolve<UsersResult, HookContext>({
  schema: usersResultSchema,
  validate: false,
  properties: {
    password: async () => undefined,
    resetAttempts: async () => undefined,
    resetExpires: async () => undefined,
    resetToken: async () => undefined,
    resetShortToken: async () => undefined,
  },
})

// Classroom schema
export type ClassroomsResult = Infer<typeof classroomsResultSchema> & {
  teacher: UsersResult
  students: UsersResult[] 
}

// Classroom result resolver
export const classroomsResultResolver = resolve<ClassroomsResult, HookContext>({
  schema: classroomsResultSchema,
  validate: false,
  properties: {
    teacher: async (_value, classroom, context) => {
      const teacher = await context.app
        .service("users")
        .get(classroom.teacherId)

      return teacher
    },
    students: async (_value, classroom, context) => {
      const result = await context.app.service("users-classrooms").find({
        query: {
          classroomId: classroom.id,
        },
      })

      const allUserIds = result.map(relation => relation.userId)

      const students = await context.app.service("users").find({
        query: {
          id: {
            $in: allUserIds,
          },
        },
      })

      return students
    },
  },
})

teacher get resolved correctly with usersDispatchResolver and fields are correctly removed from the returned data students is not resolved using usersDispatchResolver and password and reset related fields are present in the returned data

I managed to get my data resolved by adding this dispatch resolver to the classrooms resolver and manually resolve each students:

// Work around
export const classroomsDispatchResolver = resolve<
  ClassroomsResult,
  HookContext
>({
  schema: classroomsResultSchema,
  validate: false,
  properties: {
    students: async (value, classroom, context) => {
      if (!value || value.length === 0) {
        return []
      }
      const resolvedStudents = value.map(student =>
        usersDispatchResolver.resolve(student, context),
      )
      const allStudents = await Promise.all(resolvedStudents)

      return allStudents
    },
  },
})

Expected behavior

Actual behavior

teacher is correctly resolved using usersDispatchResolver, the collection of students does not get resolved with usersDispatchResolver and sensitive data are present in the result

System configuration

Module versions (especially the part that's not working): using feathers 5.0.0-pre.29

NodeJS version: 16.13.0

Operating System: linux bullseye

Browser Version: N/A

React Native Version: N/A

Module Loader: N/A

daffl commented 1 year ago

I created a test in https://github.com/feathersjs/feathers/pull/2929 which verifies that paginated dispatch data are processed properly. Can you reproduce your issue with the lates .pre?