docs/graphql.md in action_policy-0.3.2 vs docs/graphql.md in action_policy-0.3.3

- old
+ new

@@ -1,17 +1,17 @@ # GraphQL integration -You can use Action Policy as an authorization library for you [GraphQL Ruby](https://graphql-ruby.org/) application via the [`action_policy-graphql` gem](https://github.com/palkan/action_policy-graphql). +You can use Action Policy as an authorization library for your [GraphQL Ruby](https://graphql-ruby.org/) application via the [`action_policy-graphql` gem](https://github.com/palkan/action_policy-graphql). This integration provides the following features: - Fields & mutations authorization - List and connections scoping -- [**Exposing permissions/authorization rules in the API**](https://dev.to/evilmartians/exposing-permissions-in-graphql-apis-with-action-policy-1mfh). +- [**Exposing permissions/authorization rules in the API**](https://evilmartians.com/chronicles/exposing-permissions-in-graphql-apis-with-action-policy). ## Getting Started -First, add `action_policy-graphql` gem to your Gemfile (see [installation instructions](https://github.com/palkan/action_policy-graphql#installation)). +First, add the `action_policy-graphql` gem to your Gemfile (see [installation instructions](https://github.com/palkan/action_policy-graphql#installation)). Then, include `ActionPolicy::GraphQL::Behaviour` to your base type (or any other type/mutation where you want to use authorization features): ```ruby # For fields authorization, lists scoping and rules exposing @@ -21,15 +21,20 @@ # For using authorization helpers in mutations class Types::BaseMutation < GraphQL::Schema::Mutation include ActionPolicy::GraphQL::Behaviour end + +# For using authorization helpers in resolvers +class Types::BaseResolver < GraphQL::Schema::Resolver + include ActionPolicy::GraphQL::Behaviour +end ``` ## Authorization Context -By default, Action Policy use `context[:current_user]` as the `user` [authorization context](./authoriation_context.md). +By default, Action Policy uses `context[:current_user]` as the `user` [authorization context](./authorization_context.md). **NOTE:** see below for more information on what's included into `ActionPolicy::GraphQL::Behaviour`. ## Authorizing Fields @@ -73,30 +78,63 @@ ```ruby ActionPolicy::GraphQL.default_authorize_rule = :show_graphql_field? ``` +If you want to perform authorization before resolving the field value, you can use `preauthorize: *` option: + +```ruby +field :homes, [Home], null: false, preauthorize: {with: HomePolicy} + +def homes + Home.all +end +``` + +The code above is equal to: + +```ruby +field :homes, [Home], null: false + +def homes + authorize! "homes", to: :index?, with: HomePolicy + Home.all +end +``` + +**NOTE:** we pass the field's name as the `record` to the policy rule. We assume that preauthorization rules do not depend on +the record itself and pass the field's name for debugging purposes only. + +You can customize the authorization options, e.g. `authorize: {to: :preview?, with: CustomPolicy}`. + +**NOTE:** unlike `authorize: *` you MUST specify the `with: SomePolicy` option. +The default authorization rule depends on the type of the field: + +- for lists we use `index?` (configured by `ActionPolicy::GraphQL.default_preauthorize_list_rule` parameter) +- for _singleton_ fields we use `show?` (configured by `ActionPolicy::GraphQL.default_preauthorize_node_rule` parameter) + ### Class-level authorization You can use Action Policy in the class-level [authorization hooks](https://graphql-ruby.org/authorization/authorization.html) (`self.authorized?`) like this: ```ruby class Types::Friendship < Types::BaseObject def self.authorized?(object, context) super && - object.allowed_to?( + allowed_to?( :show?, object, + # NOTE: you must provide context explicitly context: {user: context[:current_user]} ) end end ``` ## Authorizing Mutations -Mutation is just a Ruby class with a single API method. There is nothing specific in authorizing mutations: from the Action Policy point of view, they are just [_behaviours_](./behaviour.md). +A mutation is just a Ruby class with a single API method. There is nothing specific in authorizing mutations: from the Action Policy point of view, they are just [_behaviours_](./behaviour.md). If you want to authorize the mutation, you call `authorize!` method. For example: ```ruby class Mutations::DestroyUser < Types::BaseMutation @@ -164,10 +202,12 @@ authorized_scope object.events, with: CustomEventPolicy end end ``` +**NOTE:** you cannot use `authorize: *` and `authorized_scope: *` at the same time but you can combine `preauthorize: *` with `authorized_scope: *`. + See the documenation on [scoping](./scoping.md). ## Exposing Authorization Rules With `action_policy-graphql` gem, you can easily expose your authorization logic to the client in a standardized way. @@ -217,9 +257,19 @@ You can override a custom authorization field prefix (`can_`): ```ruby ActionPolicy::GraphQL.default_authorization_field_prefix = "allowed_to_" +``` + +You can specify a custom field name as well (only for a single rule): + +```ruby +class ProfileType < ::Common::Graphql::Type + # Adds can_create_post field. + + expose_authorization_rules :create?, with: PostPolicy, field_name: "can_create_post" +end ``` ## Custom Behaviour Including the default `ActionPolicy::GraphQL::Behaviour` is equal to adding the following to your base class: