Skip to content

Commit 9bb76ff

Browse files
authored
Merge pull request #4868 from rmosolgo/fix-unauthorized-args-during-complexity
Handle unauthorized argument errors properly during complexity analysis
2 parents 78f5e5f + e204168 commit 9bb76ff

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

lib/graphql/analysis/ast.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ def analyze_query(query, analyzers, multiplex_analyzers: [])
8181
end
8282
rescue Timeout::Error
8383
[GraphQL::AnalysisError.new("Timeout on validation of query")]
84+
rescue GraphQL::UnauthorizedError
85+
# This error was raised during analysis and will be returned the client before execution
86+
[]
8487
end
8588

8689
def analysis_errors(results)

lib/graphql/schema/field.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ def calculate_complexity(query:, nodes:, child_complexity:)
471471
if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
472472
max_possible_page_size = arguments[:last]
473473
end
474+
elsif arguments.is_a?(GraphQL::UnauthorizedError)
475+
raise arguments
474476
end
475477

476478
if max_possible_page_size.nil?

spec/graphql/analysis/ast/max_query_complexity_spec.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,50 @@
145145
end
146146
end
147147
end
148+
149+
describe "when an argument is unauthorized by type" do
150+
class AuthorizedTypeSchema < GraphQL::Schema
151+
class Thing < GraphQL::Schema::Object
152+
def self.authorized?(obj, ctx)
153+
!!ctx[:authorized] && super
154+
end
155+
field :name, String
156+
end
157+
158+
class Query < GraphQL::Schema::Object
159+
field :things, Thing.connection_type do
160+
argument :thing_id, ID, loads: Thing
161+
end
162+
163+
def things(thing:)
164+
[thing]
165+
end
166+
end
167+
168+
query(Query)
169+
def self.resolve_type(abs_type, object, ctx)
170+
Thing
171+
end
172+
173+
def self.object_from_id(id, ctx)
174+
{ name: "Loaded thing #{id}" }
175+
end
176+
177+
def self.unauthorized_object(err)
178+
raise GraphQL::ExecutionError, "Unauthorized Object: #{err.object[:name].inspect}"
179+
end
180+
181+
default_max_page_size 30
182+
max_complexity 10
183+
end
184+
185+
it "when the arg is unauthorized, returns an authorization error, not a complexity error" do
186+
query_str = "{ things(thingId: \"123\", first: 1) { nodes { name } } }"
187+
res = AuthorizedTypeSchema.execute(query_str, context: { authorized: true })
188+
assert_equal "Loaded thing 123", res["data"]["things"]["nodes"].first["name"]
189+
190+
res2 = AuthorizedTypeSchema.execute(query_str)
191+
assert_equal ["Unauthorized Object: \"Loaded thing 123\""], res2["errors"].map { |e| e["message"] }
192+
end
193+
end
148194
end

0 commit comments

Comments
 (0)