Skip to content

Authorization: Scoping #1671

@rmosolgo

Description

@rmosolgo

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?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions