mickhansen / dataloader-sequelize

Batching and simplification of Sequelize with facebook/dataloader
MIT License
284 stars 58 forks source link

Ability to modify `where` and keep dataloader, or hook into `loader.load`? #148

Open charlie-s opened 1 month ago

charlie-s commented 1 month ago

I use Fastify + graphql-http for my router, dataloader-sequelize, and graphql-sequelize. I have an ACL layer that check each node and field in the query, and can optionally alter args. For example:

const aclList = {
  ...
  Category: {
    [Role.Admin]: { 
      fields: '*' // Let admin query all fields on this node.
    },
    [Role.Blogger]: { 
      fields: '*' // Let blogger query all fields on this node.
    }
  },
  BlogPost: {
    [Role.Admin]: { 
      fields: '*' // Let admin query all fields on this node.
    },
    [Role.Blogger]: { 
      fields: ['id', 'title', 'body'], // Restrict fields that this role can query.
      argsFromCtx (ctx) => ({ 
        where: { 
          authorId: ctx.user.id, // Restrict to records that belong to the current user.
          statusArchived: false // Don't let them query for archived records.
        } 
      }) 
    }
  }
  ...
}

Example query:

query {
  Category(where: { name: "Technology" }) {
    id, name
    BlogPosts { id, name, body }
  }
}

Performing this query as an admin user works as expected, because there is no where defined.

Performing this query as a blogger user causes the where to get generated, and subsequently shimBelongsTo ignores this and doesn't use the loader. This results in 1 query for the Category and N queries for BlogPost.

Any recommendations on this approach? I could use the after hook to filter results out, but it is less than ideal to allow users to load lots of data that they don't have access to and filter it out after the fact. Another option could be to hook into loader.load with args/options/ctx passed into the hook for manual overrides. Or more likely I don't understand something that could illuminate a path forward.