Skip to content

Commit cef4b77

Browse files
committed
Merge branch 'master' into defer-docs
2 parents c68a247 + 8128d59 commit cef4b77

File tree

10 files changed

+63
-12
lines changed

10 files changed

+63
-12
lines changed

CHANGELOG-pro.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
### Bug Fix
1010

11+
## 1.9.13 (4 Mar 2019)
12+
13+
- Pundit integration: correctly authorize fields when Query root is nil
14+
1115
## 1.9.12 (22 Feb 2019)
1216

1317
- Pundit integration: use overriden `pundit_policy_class` for scoping and mutation authorization

graphql.gemspec

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ Gem::Specification.new do |s|
1515
s.email = ["[email protected]"]
1616
s.license = "MIT"
1717
s.required_ruby_version = ">= 2.2.0" # bc `.to_sym` used on user input
18+
s.metadata = {
19+
"homepage_uri" => "https://graphql-ruby.org",
20+
"changelog_uri" => "https://github.com/rmosolgo/graphql-ruby/blob/master/CHANGELOG.md",
21+
"source_code_uri" => "https://github.com/rmosolgo/graphql-ruby",
22+
"bug_tracker_uri" => "https://github.com/rmosolgo/graphql-ruby/issues",
23+
"mailing_list_uri" => "https://tinyletter.com/graphql-ruby",
24+
}
1825

1926
s.files = Dir["{lib}/**/*", "MIT-LICENSE", "readme.md", ".yardopts"]
2027
s.test_files = Dir["spec/**/*"]

guides/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ <h2>Define Your Schema</h2>
3131
<div class="teaser">
3232
<p>
3333
Describe your application with the
34-
<a href="{{ site.baseurl }}/schema/definition">GraphQL type system</a>
34+
<a href="{{ site.baseurl }}/schema/definition">GraphQL schema</a>
3535
to create a self-documenting, strongly-typed API.
3636
</p>
3737
</div>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
074391c2bdc294a1ec027d043a6bf172f70bf5ff75f0062821cabd5ce7469c88a3b60a0ed644e8bae178fdd9db26acef20b0721fcc708c1825da256ec5f2b4fb

lib/graphql/execution/interpreter/runtime.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,10 @@ def evaluate_selections(path, owner_object, owner_type, selections, root_operati
200200

201201
field_result = resolve_with_directives(object, ast_node) do
202202
# Actually call the field resolver and capture the result
203-
app_result = query.trace("execute_field", {field: field_defn, path: next_path}) do
203+
app_result = query.trace("execute_field", {owner: owner_type, field: field_defn, path: next_path}) do
204204
field_defn.resolve(object, kwarg_arguments, context)
205205
end
206-
after_lazy(app_result, field: field_defn, path: next_path) do |inner_result|
206+
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path) do |inner_result|
207207
continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
208208
if HALT != continue_value
209209
continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false)
@@ -277,7 +277,7 @@ def continue_field(path, value, field, type, ast_node, next_selections, is_non_n
277277
r
278278
when "UNION", "INTERFACE"
279279
resolved_type_or_lazy = query.resolve_type(type, value)
280-
after_lazy(resolved_type_or_lazy, path: path, field: field) do |resolved_type|
280+
after_lazy(resolved_type_or_lazy, owner: type, path: path, field: field) do |resolved_type|
281281
possible_types = query.possible_types(type)
282282

283283
if !possible_types.include?(resolved_type)
@@ -297,7 +297,7 @@ def continue_field(path, value, field, type, ast_node, next_selections, is_non_n
297297
rescue GraphQL::ExecutionError => err
298298
err
299299
end
300-
after_lazy(object_proxy, path: path, field: field) do |inner_object|
300+
after_lazy(object_proxy, owner: type, path: path, field: field) do |inner_object|
301301
continue_value = continue_value(path, inner_object, field, is_non_null, ast_node)
302302
if HALT != continue_value
303303
response_hash = {}
@@ -318,7 +318,7 @@ def continue_field(path, value, field, type, ast_node, next_selections, is_non_n
318318
idx += 1
319319
set_type_at_path(next_path, inner_type)
320320
# This will update `response_list` with the lazy
321-
after_lazy(inner_value, path: next_path, field: field) do |inner_inner_value|
321+
after_lazy(inner_value, owner: inner_type, path: next_path, field: field) do |inner_inner_value|
322322
# reset `is_non_null` here and below, because the inner type will have its own nullability constraint
323323
continue_value = continue_value(next_path, inner_inner_value, field, false, ast_node)
324324
if HALT != continue_value
@@ -384,7 +384,7 @@ def resolve_if_late_bound_type(type)
384384
# @param field [GraphQL::Schema::Field]
385385
# @param eager [Boolean] Set to `true` for mutation root fields only
386386
# @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
387-
def after_lazy(obj, field:, path:, eager: false)
387+
def after_lazy(obj, owner:, field:, path:, eager: false)
388388
@interpreter_context[:current_path] = path
389389
@interpreter_context[:current_field] = field
390390
if schema.lazy?(obj)
@@ -393,14 +393,14 @@ def after_lazy(obj, field:, path:, eager: false)
393393
@interpreter_context[:current_field] = field
394394
# Wrap the execution of _this_ method with tracing,
395395
# but don't wrap the continuation below
396-
inner_obj = query.trace("execute_field_lazy", {field: field, path: path}) do
396+
inner_obj = query.trace("execute_field_lazy", {owner: owner, field: field, path: path}) do
397397
begin
398398
schema.sync_lazy(obj)
399399
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
400400
yield(err)
401401
end
402402
end
403-
after_lazy(inner_obj, field: field, path: path, eager: eager) do |really_inner_obj|
403+
after_lazy(inner_obj, owner: owner, field: field, path: path, eager: eager) do |really_inner_obj|
404404
yield(really_inner_obj)
405405
end
406406
end

lib/graphql/tracing.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ module GraphQL
4242
# execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
4343
# execute_query | `{ query: GraphQL::Query }`
4444
# execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
45-
# execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
46-
# execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
45+
# execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
46+
# execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
4747
#
4848
# Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
4949
#

lib/graphql/tracing/platform_tracing.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ def trace(key, data)
3232
trace_field = true # implemented with instrumenter
3333
else
3434
field = data[:field]
35+
owner = data[:owner]
3536
# Lots of duplicated work here, can this be done ahead of time?
36-
platform_key = platform_field_key(field.owner, field)
37+
platform_key = platform_field_key(owner, field)
3738
return_type = field.type.unwrap
3839
# Handle LateBoundTypes, which don't have `#kind`
3940
trace_field = if return_type.respond_to?(:kind) && (return_type.kind.scalar? || return_type.kind.enum?)

spec/graphql/schema/introspection_system_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
assert_equal "Set", res["data"]["__classname"]
1919
end
2020

21+
it "calls authorization methods of those types" do
22+
res = Jazz::Schema.execute(%|{ __type(name: "Ensemble") { name } }|)
23+
assert_equal "ENSEMBLE", res["data"]["__type"]["name"]
24+
25+
unauth_res = Jazz::Schema.execute(%|{ __type(name: "Ensemble") { name } }|, context: { cant_introspect: true })
26+
assert_nil unauth_res["data"].fetch("__type")
27+
assert_equal ["You're not allowed to introspect here"], unauth_res["errors"].map { |e| e["message"] }
28+
end
29+
2130
it "serves custom dynamic fields" do
2231
res = Jazz::Schema.execute("{ nowPlaying { __typename __typenameLength __astNodeClass } }")
2332
assert_equal "Ensemble", res["data"]["nowPlaying"]["__typename"]

spec/graphql/tracing/new_relic_tracing_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33

44
describe GraphQL::Tracing::NewRelicTracing do
55
module NewRelicTest
6+
class Thing < GraphQL::Schema::Object
7+
implements GraphQL::Types::Relay::Node
8+
end
9+
610
class Query < GraphQL::Schema::Object
11+
add_field GraphQL::Types::Relay::NodeField
12+
713
field :int, Integer, null: false
814

915
def int
@@ -14,6 +20,16 @@ def int
1420
class SchemaWithoutTransactionName < GraphQL::Schema
1521
query(Query)
1622
use(GraphQL::Tracing::NewRelicTracing)
23+
orphan_types(Thing)
24+
25+
def self.object_from_id(_id, _ctx)
26+
:thing
27+
end
28+
29+
def self.resolve_type(_type, _obj, _ctx)
30+
Thing
31+
end
32+
1733
if TESTING_INTERPRETER
1834
use GraphQL::Execution::Interpreter
1935
end
@@ -37,6 +53,11 @@ class SchemaWithScalarTrace < GraphQL::Schema
3753
NewRelic.clear_all
3854
end
3955

56+
it "works with the built-in node field, even though it doesn't have an @owner" do
57+
res = NewRelicTest::SchemaWithoutTransactionName.execute '{ node(id: "1") { __typename } }'
58+
assert_equal "Thing", res["data"]["node"]["__typename"]
59+
end
60+
4061
it "can leave the transaction name in place" do
4162
NewRelicTest::SchemaWithoutTransactionName.execute "query X { int }"
4263
assert_equal [], NewRelic::TRANSACTION_NAMES

spec/support/jazz.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,14 @@ def custom_method
682682

683683
module Introspection
684684
class TypeType < GraphQL::Introspection::TypeType
685+
def self.authorized?(_obj, ctx)
686+
if ctx[:cant_introspect]
687+
raise GraphQL::ExecutionError, "You're not allowed to introspect here"
688+
else
689+
super
690+
end
691+
end
692+
685693
def name
686694
n = object.graphql_name
687695
n && n.upcase

0 commit comments

Comments
 (0)