maticzav / graphql-shield

๐Ÿ›ก A GraphQL tool to ease the creation of permission layer.

Home Page:https://graphql-shield.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fragments in rules using DataLoader

lastmjs opened this issue ยท comments

Question about GraphQL Shield

Thanks for graphql-shield, it is looking pretty slick so far. I have one major issue that isn't specific to graphql-shield, but has been a problem for me in my pursuit of GraphQL permissions for quite some time. The issue has become exacerbated as I've switched from Prisma resolvers to Graphback resolvers. Graphback uses dataloader for resolvers, and thus the parent object to my resolvers does not have lower-level relations resolved. This makes certain types of permissions impossible to achieve (I think) without sacrificing performance. I'm seeking any help I can get in resolving this issue.

Let's take the following example of a graphql-shield rule:

    const isCompanyOwner: Readonly<Rule> = rule({
        cache: 'no_cache',
        fragment: 'fragment CallCompanyOwner on Calls { company { organization { owner { id } } } }'
    })(
        async (parent, args, context, info) => {
            console.log('parent', parent);
            return false;
        }
    );

This is just a quick example to demonstrate the issue. The rule above is for a role that I call COMPANY_OWNER. It's not as simple as having a role on the authenticated user called COMPANY_OWNER. This role requires that the entity that it is applied to actually belongs to the company that the authenticated user owns. If the authenticate user's id is equal to the id of the owner of the organization of the company that the call belongs to, then the auth rule will pass. I have at least one or two other similar permissions that I need to create in my system.

The problem with the dataloader, is that the parent object doesn't have the full relation. In the example above, the fragment resolves to company_id when the resolver for this rule is called. Dataloader somehow resolves everything later on for performance reasons.

Without having the extra relation information above, I can't perform my authorization check. A workaround would be to use the company_id that is returned in the parent, and pull the rest of the information myself from the database. Obviously, this would be very not performant, as if I ask for n calls, in the worst case I would have n requests originating from the resolver of this rule.

I'm not sure how to work around this in a performant way, and I'm hoping someone using graphql-shield has run into this type of issue before.

Hey @lastmjs ๐Ÿ‘‹,

Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our Open Collective and consider contributing financially.

https://opencollective.com/graphql-shield

PS.: We offer priority support for all financial contributors. Don't forget to add priority label once you start contributing ๐Ÿ˜„

Hey @lastmjs ๐Ÿ‘‹ ,

Thank you for opening the issue. I am not entirely sure I understand your problem; is it possible that you are mixing up business logic with permissions? What I mean is whether you are trying to filter out "non-accessible" companies through GraphQL Shield instead of resolver itself.

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.