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

No way to specify a directive on a field definition #2122

Closed
dwayne opened this issue Feb 18, 2019 · 9 comments
Closed

No way to specify a directive on a field definition #2122

dwayne opened this issue Feb 18, 2019 · 9 comments

Comments

@dwayne
Copy link

dwayne commented Feb 18, 2019

Given the following directive:

module Directive
  class Permission < GraphQL::Schema::Directive
    description 'Directs the executor to include this field only if the user has the given permission.'

    locations(
      GraphQL::Schema::Directive::FIELD_DEFINITION
    )

    argument :value, String, required: true,
      description: 'The required permission.'

    def self.include?(_object, arguments, context)
      permission = arguments[:value]
      if context[:user]
        context[:user].has_permissions?(permission)
      else
        true
      end
    end
  end
end

There doesn't seem to be a documented way to add the directive to a field definition. Is it currently possible?

@rmosolgo
Copy link
Owner

It sounds like you're asking about using directives in the SDL, for example:

type MyObject {
  someField @permission(value: "admin")
}

Is that right?

There's no special handling for directives like that right now. If you parse a schema from SDL, you can access the underlying AST node as .ast_node.

@cpinsach
Copy link

@dwayne you may need to add directive(Directive::Permission) on your schema definition.
This might help, but a quick .md about custom directives would be helpful as well.

@dwayne
Copy link
Author

dwayne commented Feb 19, 2019

@rmosolgo Yes, that's right. I want to be able to specify directives on fields in my type definitions. I'm trying to enforce permissions via directives as suggested here and here.

@mpinsach Thanks for the suggestion. I did all that. But my issue is that there is no way in the DSL to specify directives on the field definitions, in particular the fields of the root query.

@jturkel
Copy link
Contributor

jturkel commented Mar 4, 2019

I was struggling with a similar problem i.e. how to use directives to factor out cross cutting behavior in my schema that was defined with the class based Ruby API rather than the GraphQL SDL. Then I stumbled across field extensions which worked well for my use case. Perhaps the intent is that directives should be used to allow query authors to modify execution behavior or factor out common execution handling with SDL defined schemas and field extensions/resolvers/standard Ruby constructs like modules should be used to factor out commonality in Ruby defined schemas?

Also since your example is security related, you might want to checkout the authorization framework if you haven't already done so.

@dwayne
Copy link
Author

dwayne commented Mar 6, 2019

@jturkel I decided to use field metadata and write custom instrumentation.

For e.g.

class PermissionWhitelister
  def instrument(type, field)
    if field.metadata[:permissions]
      permissions = Array(field.metadata[:permissions])

      old_resolve_proc = field.resolve_proc
      new_resolve_proc = ->(object, arguments, context) {
        if context[:authorizer].has_permissions?(*permissions)
          old_resolve_proc.call(object, arguments, context)
        else
          raise GraphQL::ExecutionError, "You don't have the required permissions"
        end
      }

      field.redefine do
        resolve(new_resolve_proc)
      end
    else
      field
    end
  end
end

@jturkel
Copy link
Contributor

jturkel commented Mar 11, 2019

It looks like field instrumentation is being deprecated in 1.10 (see #2174) so I think you'll eventually need to use a different approach.

@dwayne
Copy link
Author

dwayne commented Mar 11, 2019

It looks like field instrumentation is being deprecated in 1.10 (see #2174) so I think you'll eventually need to use a different approach.

Thanks for the heads up.

@glappen
Copy link

glappen commented May 11, 2019

So is it not possible to attach directives to field definitions in our schemes? I made a custom directive and attached it do a field in a query using standard @ syntax but it would be nicer to attach it to my schema for my use case (declaring that some fields might not exist on the underlying objective due to u dynamic data model).

@rmosolgo
Copy link
Owner

I recently released 1.12.0 which includes a "schema directives" system, please give it a try and open a new issue if you run into any trouble with it!

https://graphql-ruby.org/type_definitions/directives.html#schema-directives

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

5 participants