Skip to content

Commit

Permalink
Use trace GraphQL API instead of field extension
Browse files Browse the repository at this point in the history
  • Loading branch information
exAspArk committed Apr 8, 2020
1 parent 975c9e3 commit 538a157
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 57 deletions.
32 changes: 22 additions & 10 deletions lib/graphql/guard.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "graphql"
require "graphql/guard/field_extension"
require "graphql/guard/version"

module GraphQL
class Guard
NotAuthorizedError = Class.new(StandardError)

ANY_FIELD_NAME = :'*'
EXECUTE_FIELD_EVENTS = %w[execute_field execute_field_lazy]

DEFAULT_NOT_AUTHORIZED = ->(type, field) do
raise NotAuthorizedError.new("Not authorized to access: #{type.graphql_definition}.#{field}")
Expand All @@ -28,16 +28,22 @@ def initialize(policy_object: nil, not_authorized: DEFAULT_NOT_AUTHORIZED)

def use(schema_definition)
if schema_definition.interpreter?
fields(schema_definition).each do |field|
field.type_class.extension(GraphQL::Guard::FieldExtension, guard_instance: self)
end
schema_definition.tracer(self)
else
raise "Please use the graphql gem version >= 1.10 with GraphQL::Execution::Interpreter"
end

add_schema_masking!(schema_definition)
end

def trace(event, trace_data)
if EXECUTE_FIELD_EVENTS.include?(event)
ensure_guarded(trace_data) { yield }
else
yield
end
end

def find_guard_proc(type, field)
inline_guard(field) ||
policy_object_guard(type, field.name.to_sym) ||
Expand All @@ -47,12 +53,6 @@ def find_guard_proc(type, field)

private

def fields(schema_definition)
schema_definition.types.values.flat_map { |type|
type.fields.values if type.name && type.respond_to?(:fields)
}.compact
end

def add_schema_masking!(schema_definition)
schema_definition.class_eval do
def self.default_filter
Expand All @@ -61,6 +61,18 @@ def self.default_filter
end
end

def ensure_guarded(trace_data)
field = trace_data[:field]
guard_proc = find_guard_proc(field.owner, field)
return yield unless guard_proc

if guard_proc.call(trace_data[:object], trace_data[:arguments], trace_data[:query].context)
yield
else
not_authorized.call(field.owner, field.name.to_sym)
end
end

def policy_object_guard(type, field_name)
@policy_object && @policy_object.guard(type.type_class, field_name)
end
Expand Down
16 changes: 0 additions & 16 deletions lib/graphql/guard/field_extension.rb

This file was deleted.

9 changes: 9 additions & 0 deletions spec/fixtures/inline_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,13 @@ class Schema < GraphQL::Schema
query QueryType
use GraphQL::Guard.new
end

class SchemaWithoutExceptions < GraphQL::Schema
use GraphQL::Execution::Interpreter
use GraphQL::Analysis::AST
query QueryType
use GraphQL::Guard.new(not_authorized: ->(type, field) {
GraphQL::ExecutionError.new("Not authorized to access #{type.graphql_definition}.#{field}")
})
end
end
29 changes: 0 additions & 29 deletions spec/fixtures/inline_without_exceptions_schema.rb

This file was deleted.

3 changes: 1 addition & 2 deletions spec/graphql/guard_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
require 'fixtures/user'
require 'fixtures/post'
require 'fixtures/inline_schema'
require 'fixtures/inline_without_exceptions_schema'
require 'fixtures/policy_object_schema'

RSpec.describe GraphQL::Guard do
Expand Down Expand Up @@ -41,7 +40,7 @@
user = User.new(id: '1', role: 'not_admin')
query = "query($userId: ID!) { posts(userId: $userId) { id title } }"

result = InlineWithoutExceptions::Schema.execute(query, variables: {userId: 1}, context: {current_user: user})
result = Inline::SchemaWithoutExceptions.execute(query, variables: {userId: 1}, context: {current_user: user})

expect(result['errors']).to eq([{
"message" => "Not authorized to access Post.id",
Expand Down

0 comments on commit 538a157

Please sign in to comment.