Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization: Scoping #1671

Closed
rmosolgo opened this issue Jul 15, 2018 · 3 comments
Closed

Authorization: Scoping #1671

rmosolgo opened this issue Jul 15, 2018 · 3 comments
Assignees

Comments

@rmosolgo
Copy link
Owner

One related feature to authorization is scoping (see a comment on the auth PR, Pundit scopes and CanCan accessible_by.

In this feature, there's a function that takes (items, context) as input and returns filtered_items, where items has been scoped to remove items that are inaccessible to context. For example, an ActiveRecord::Relation might receive .where calls or an Array might receive .select.

This is different than filtering a list based on a GraphQL field's arguments, because the filtering might be based on something outside the client's control (for example, the current user's permission level). Also, the same filter may apply to lists of the same kinds of objects, even if those lists are returned from different fields or different combinations of arguments.

This feature is complementary to authorization. Authorization is a last-ditch effort to avoid returning unauthorized objects to clients; scoping is part of the application logic to filter return values. (An authorization failure should probably be corrected by adding filtering to a resolve method; scoping may be that filtering.)

How can it be added to GraphQL-Ruby? How about:

  • Objects, Interfaces and Unions have a .scope_list(list, context) method
  • Inside the runtime, after calling a field which returns a list of type T, it calls T.scope_list(list, context) with the returned values. The return of T.scope_list is used in place of the originally-returned list.
  • The default implementation of .scope_list is return list (no-op)

Advantages:

  • The filter method is inside the type definition whose objects are filtered
  • It can be implemented any which way

Disadvantages:

  • It uses GraphQL type, not Ruby class, so it could be hard to cover all your bases
  • Arrays and AR::Relations get routed to the same method, is that bad? (This could also be fixed in user-land, by switching on the class of list and routing it to different methods, eg filter_array and filter_relation)

Any other thoughts on this?

@eapache
Copy link
Contributor

eapache commented Jul 16, 2018

Inside the runtime, after calling a field which returns a list of type T, it calls T.scope_list(list, context) with the returned values. The return of T.scope_list is used in place of the originally-returned list.

I suppose this works with fields that return AR relations because AR won't materialize the actual array until as late as possible so you can always append more .where calls. We have an internal pagination thing which isn't quite as lazy though, so this kind of scoping really of necessity needs to be built into the resolver for us.

(It's not clear to me if there's any kind of helper that would make our use case better though.)

@rmosolgo
Copy link
Owner Author

any kind of helper

There's really not yet, but maybe the trick is to implement this feature on top of #1411, which would give a proper way to add layers to resolve.

@rmosolgo rmosolgo self-assigned this Jul 26, 2018
@rmosolgo
Copy link
Owner Author

Fixed by #1723

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants