GraphQL::Pundit
Use field authorize api with pundit
Installation
Add this line to your application's Gemfile:
gem 'graphql_pundit'
And then execute:
$ bundle
Upgrading notes
If you are coming from ontobot
Add this to your BaseField:
def initialize(*args, raise_unauthorized: false, authorize: nil, record: nil, policy: nil, **kwargs, &block)
super(*args, **kwargs, &block)
@raise_unauthorized = raise_unauthorized
@authorize = authorize
@record = record
@policy = policy
extension(GraphqlPundit::AuthorizationExtension, current_user: :current_user)
end
Usage
class Car < BaseObject
field :trunk, CarContent, null: true,
authorize: true
end
The above example shows the most basic usage of this gem. The example would
use CarPolicy#trunk?
for authorizing access to the field, passing in the
parent object (in this case probably a Car
model).
Options
Two styles of declaring fields is supported:
- the inline style, passing all the options as a hash to the field method
- the block style
Both styles are presented below side by side.
authorize
To use authorization on a field, you must pass either the authorize
option. Both options will cause the field to return nil
if the
access is unauthorized. Use raise_unauthorized: true
to also add an error message (e.g.
for usage with mutations).
authorize
can be passed three different things:
class User < BaseObject
# will use the `UserPolicy#display_name?` method
field :display_name, ..., authorize: true
# will use the passed lambda instead of a policy method
field :password_hash, ..., authorize: ->(obj, args, ctx) { ... }
# will use the `UserPolicy#personal_info?` method
field :email, ..., authorize: :personal_info
end
-
true
will trigger the inference mechanism, meaning that the method that will be called on the policy class will be inferred from the (snake_case) field name. - a lambda function that will be called with the parent object, the arguments of the field and the context object; if the lambda returns a truthy value, authorization succeeds; otherwise (including thrown exceptions), authorization fails
- a string or a symbol that corresponds to the policy method that should be called minus the "?"
policy
policy
is an optional argument that can also be passed three different values:
class User < BaseObject
# will use the `UserPolicy#display_name?` method (default inference)
field :display_name, ..., authorize: true, policy: nil
# will use OtherUserPolicy#password_hash?
field :password_hash, ...,
authorize: true,
policy: ->(obj, args, ctx) { OtherUserPolicy }
# will use MemberPolicy#email?
field :email, ..., authorize: true, policy: MemberPolicy
end
-
nil
is the default behavior and results in inferring the policy class from the record (see below) - a lambda function that will be called with the parent object, the arguments of the field and the context object; the return value of this function will be used as the policy class
- an actual policy class
record
record
can be used to pass a different value to the policy. Like policy
,
this argument also can receive three different values:
class User < BaseObject
# will use the parent object
field :display_name, ..., authorize: true, record: nil
# will use the current user as the record
field :password_hash, ...,
authorize: true,
record: ->(obj, args, ctx) { ctx[:current_user] }
# will use AccountPolicy#email? with the first account as the record (the policy was inferred from the record class)
field :email, ..., authorize: true, record: Account.first
end
-
nil
is again used for the inference; in this case, the parent object is used - a lambda function, again called with the parent object, the field arguments and the context object; the result will be used as the record
- any other value that will be used as the record
Using record
can be helpful for e.g. mutations, where you need a value to
initialize the policy with, but for mutations there is no parent object.
Current user
By default, ctx[:current_user]
will be used as the user to authorize. To change that behavior, pass a symbol to GraphQL::Pundit::Instrumenter
.
GraphQL::Pundit::Instrumenter.new(:me) # will use ctx[:me]
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/lubosch/graphql-pundit.
License
The gem is available as open source under the terms of the MIT License.