Created
December 1, 2021 15:17
-
-
Save rmosolgo/44703c57612e61bd20b261a5d4b607b1 to your computer and use it in GitHub Desktop.
Argument auth with loads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "bundler/inline" | |
gemfile do | |
gem "graphql", "1.13.0" | |
gem "graphql-pro", "1.20.3" | |
gem "pundit" | |
end | |
require "ostruct" | |
class Schema < GraphQL::Schema | |
# first, base classes with Pundit as needed: | |
class BaseArgument < GraphQL::Schema::Argument | |
include GraphQL::Pro::PunditIntegration::ArgumentIntegration | |
end | |
class BaseField < GraphQL::Schema::Field | |
include GraphQL::Pro::PunditIntegration::FieldIntegration | |
pundit_role nil | |
argument_class BaseArgument | |
end | |
class BaseObject < GraphQL::Schema::Object | |
include GraphQL::Pro::PunditIntegration::ObjectIntegration | |
field_class BaseField | |
end | |
# some pundit policies | |
class QueryPolicy | |
def initialize(viewer, object) | |
@viewer = viewer | |
@object = object | |
end | |
def load_thing? | |
@viewer.load_thing | |
end | |
end | |
class ThingPolicy | |
def initialize(viewer, object) | |
@viewer = viewer | |
@object = object | |
end | |
def view? | |
@viewer.view_thing | |
end | |
end | |
# Then the schema: | |
class Thing < BaseObject | |
pundit_policy_class ThingPolicy | |
pundit_role :view | |
field :name, String | |
end | |
class Query < BaseObject | |
pundit_policy_class QueryPolicy | |
pundit_role nil # No auth for base query | |
field :thing, Thing, null: true do | |
argument :thing_id, ID, loads: Thing, pundit_role: :load_thing | |
end | |
def thing(thing:) | |
thing | |
end | |
end | |
query(Query) | |
def self.object_from_id(id, ctx) | |
puts "Loading from #{id.inspect}" | |
{ name: id, graphql_type: Thing } | |
end | |
def self.resolve_type(_abs_type, obj, ctx) | |
obj.fetch(:graphql_type) | |
end | |
def self.unauthorized_object(err) | |
raise GraphQL::ExecutionError, err.message | |
end | |
end | |
# This is fully authorized: | |
pp Schema.execute("{ thing(thingId: \"hat\") { name } }", context: { current_user: OpenStruct.new(view_thing: true, load_thing: true)}).to_h | |
# Loading from "hat" | |
# {"data"=>{"thing"=>{"name"=>"hat"}}} | |
# This one succeeds to load, but fails arg auth: | |
pp Schema.execute("{ thing(thingId: \"hat\") { name } }", context: { current_user: OpenStruct.new(view_thing: true)}).to_h | |
# Loading from "hat" | |
# {"data"=>{"thing"=>nil}, | |
# "errors"=> | |
# [{"message"=>"Failed Schema::Query's authorization check on field thing", | |
# "locations"=>[{"line"=>1, "column"=>3}], | |
# "path"=>["thing"]}]} | |
# This one loads, but then the check on the loaded object fails auth: | |
pp Schema.execute("{ thing(thingId: \"hat\") { name } }", context: { current_user: OpenStruct.new(load_thing: true)}).to_h | |
# Loading from "hat" | |
# {"data"=>{"thing"=>nil}, | |
# "errors"=> | |
# [{"message"=>"An instance of Hash failed Thing's authorization check", | |
# "locations"=>[{"line"=>1, "column"=>3}], | |
# "path"=>["thing"]}]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment