diff --git a/README.md b/README.md index 48d0409..0d4557d 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,14 @@ class GraphqlPolicy end +With `graphql-ruby` gem version >= 1.8 and class-based type definitions, `type` doesn't return the actual type class [rmosolgo/graphql-ruby#1429](https://github.com/rmosolgo/graphql-ruby/issues/1429). To get the actual type class: + +
+def self.guard(type, field) + RULES.dig(type.metadata[:type_class], field) +end ++ Pass this object to `GraphQL::Guard`:
diff --git a/spec/fixtures/policy_object_schema.rb b/spec/fixtures/policy_object_schema.rb index c12bc5e..69bbda4 100644 --- a/spec/fixtures/policy_object_schema.rb +++ b/spec/fixtures/policy_object_schema.rb @@ -1,37 +1,75 @@ # frozen_string_literal: true module PolicyObject - PostType = GraphQL::ObjectType.define do - name "Post" - field :id, !types.ID - field :title, types.String - end + case ENV['GRAPHQL_RUBY_VERSION'] + when '1_7' + PostType = GraphQL::ObjectType.define do + name "Post" + field :id, !types.ID + field :title, types.String + end - QueryType = GraphQL::ObjectType.define do - name "Query" - field :posts, !types[!PostType] do - argument :userId, !types.ID - resolve ->(_obj, args, _ctx) { Post.where(user_id: args[:userId]) } + QueryType = GraphQL::ObjectType.define do + name "Query" + field :posts, !types[!PostType] do + argument :userId, !types.ID + resolve ->(_obj, args, _ctx) { Post.where(user_id: args[:userId]) } + end end - end - class GraphqlPolicy - RULES = { - QueryType => { - posts: ->(_obj, args, ctx) { args[:userId] == ctx[:current_user].id } - }, - PostType => { - '*': ->(_post, args, ctx) { ctx[:current_user].admin? } + class GraphqlPolicy + RULES = { + QueryType => { + posts: ->(_obj, args, ctx) { args[:userId] == ctx[:current_user].id } + }, + PostType => { + '*': ->(_post, args, ctx) { ctx[:current_user].admin? } + } } - } - def self.guard(type, field) - RULES.dig(type, field) + def self.guard(type, field) + RULES.dig(type, field) + end end - end - Schema = GraphQL::Schema.define do - query QueryType - use GraphQL::Guard.new(policy_object: GraphqlPolicy) + Schema = GraphQL::Schema.define do + query QueryType + use GraphQL::Guard.new(policy_object: GraphqlPolicy) + end + when '1_8' + class PostType < GraphQL::Schema::Object + field :id, ID, null: false + field :title, String, null: true + end + + class QueryType < GraphQL::Schema::Object + field :posts, [PostType], null: false do + argument :user_id, ID, required: true + end + + def posts(user_id:) + Post.where(user_id: user_id) + end + end + + class GraphqlPolicy + RULES = { + QueryType => { + posts: ->(_obj, args, ctx) { args[:userId] == ctx[:current_user].id } + }, + PostType => { + '*': ->(_post, args, ctx) { ctx[:current_user].admin? } + } + } + + def self.guard(type, field) + RULES.dig(type.metadata[:type_class], field) + end + end + + class Schema < GraphQL::Schema + query QueryType + use GraphQL::Guard.new(policy_object: GraphqlPolicy) + end end end diff --git a/spec/graphql/testing_spec.rb b/spec/graphql/testing_spec.rb index 23117e7..939c020 100644 --- a/spec/graphql/testing_spec.rb +++ b/spec/graphql/testing_spec.rb @@ -58,6 +58,7 @@ }.to raise_error(GraphQL::Field::NoGuardError, "Guard lambda does not exist for Query.posts") end + if ENV['GRAPHQL_RUBY_VERSION'] == '1_7' it 'raises an error if the field was fetched without guard' do posts_field = PolicyObject::QueryType.get_field('posts') user = User.new(id: '1', role: 'admin') @@ -66,6 +67,7 @@ posts_field.guard(nil, {userId: user.id}, {current_user: user}) }.to raise_error(GraphQL::Field::NoGuardError, "Get your field by calling: Type.field_with_guard('posts')") end + end it 'returns false for a not authorized field' do posts_field = PolicyObject::QueryType.field_with_guard('posts', PolicyObject::GraphqlPolicy)