action_policy 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -171
  3. data/LICENSE.txt +1 -1
  4. data/README.md +7 -11
  5. data/lib/action_policy.rb +7 -1
  6. data/lib/action_policy/behaviour.rb +22 -16
  7. data/lib/action_policy/behaviours/policy_for.rb +10 -3
  8. data/lib/action_policy/behaviours/scoping.rb +2 -1
  9. data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
  10. data/lib/action_policy/ext/module_namespace.rb +1 -6
  11. data/lib/action_policy/ext/policy_cache_key.rb +15 -33
  12. data/lib/action_policy/ext/{symbol_classify.rb → symbol_camelize.rb} +6 -6
  13. data/lib/action_policy/i18n.rb +1 -1
  14. data/lib/action_policy/lookup_chain.rb +41 -21
  15. data/lib/action_policy/policy/aliases.rb +7 -12
  16. data/lib/action_policy/policy/authorization.rb +14 -17
  17. data/lib/action_policy/policy/cache.rb +34 -18
  18. data/lib/action_policy/policy/core.rb +25 -12
  19. data/lib/action_policy/policy/defaults.rb +3 -9
  20. data/lib/action_policy/policy/execution_result.rb +3 -9
  21. data/lib/action_policy/policy/pre_check.rb +19 -58
  22. data/lib/action_policy/policy/reasons.rb +30 -20
  23. data/lib/action_policy/policy/scoping.rb +5 -6
  24. data/lib/action_policy/rails/controller.rb +6 -1
  25. data/lib/action_policy/rails/ext/active_record.rb +7 -0
  26. data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
  27. data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
  28. data/lib/action_policy/rspec/dsl.rb +3 -3
  29. data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
  30. data/lib/action_policy/testing.rb +1 -1
  31. data/lib/action_policy/utils/pretty_print.rb +21 -24
  32. data/lib/action_policy/utils/suggest_message.rb +1 -3
  33. data/lib/action_policy/version.rb +1 -1
  34. data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +1 -1
  35. data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
  36. data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
  37. data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
  38. data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
  39. metadata +30 -119
  40. data/.gitattributes +0 -2
  41. data/.github/FUNDING.yml +0 -1
  42. data/.github/ISSUE_TEMPLATE.md +0 -18
  43. data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
  44. data/.gitignore +0 -15
  45. data/.rubocop.yml +0 -54
  46. data/.tidelift.yml +0 -6
  47. data/.travis.yml +0 -31
  48. data/Gemfile +0 -22
  49. data/Rakefile +0 -27
  50. data/action_policy.gemspec +0 -44
  51. data/benchmarks/namespaced_lookup_cache.rb +0 -71
  52. data/bin/console +0 -14
  53. data/bin/setup +0 -8
  54. data/docs/.nojekyll +0 -0
  55. data/docs/CNAME +0 -1
  56. data/docs/README.md +0 -77
  57. data/docs/_sidebar.md +0 -27
  58. data/docs/aliases.md +0 -122
  59. data/docs/assets/docsify-search.js +0 -364
  60. data/docs/assets/docsify.min.js +0 -3
  61. data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
  62. data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
  63. data/docs/assets/images/banner.png +0 -0
  64. data/docs/assets/images/cache.png +0 -0
  65. data/docs/assets/images/cache.svg +0 -70
  66. data/docs/assets/images/layer.png +0 -0
  67. data/docs/assets/images/layer.svg +0 -35
  68. data/docs/assets/prism-ruby.min.js +0 -1
  69. data/docs/assets/styles.css +0 -347
  70. data/docs/assets/vue.min.css +0 -1
  71. data/docs/authorization_context.md +0 -92
  72. data/docs/behaviour.md +0 -113
  73. data/docs/caching.md +0 -273
  74. data/docs/controller_action_aliases.md +0 -109
  75. data/docs/custom_lookup_chain.md +0 -48
  76. data/docs/custom_policy.md +0 -53
  77. data/docs/debugging.md +0 -55
  78. data/docs/decorators.md +0 -27
  79. data/docs/favicon.ico +0 -0
  80. data/docs/graphql.md +0 -302
  81. data/docs/i18n.md +0 -44
  82. data/docs/index.html +0 -43
  83. data/docs/instrumentation.md +0 -84
  84. data/docs/lookup_chain.md +0 -17
  85. data/docs/namespaces.md +0 -77
  86. data/docs/non_rails.md +0 -28
  87. data/docs/pre_checks.md +0 -57
  88. data/docs/pundit_migration.md +0 -80
  89. data/docs/quick_start.md +0 -118
  90. data/docs/rails.md +0 -120
  91. data/docs/reasons.md +0 -120
  92. data/docs/scoping.md +0 -255
  93. data/docs/testing.md +0 -333
  94. data/docs/writing_policies.md +0 -107
  95. data/gemfiles/jruby.gemfile +0 -8
  96. data/gemfiles/rails42.gemfile +0 -8
  97. data/gemfiles/rails6.gemfile +0 -8
  98. data/gemfiles/railsmaster.gemfile +0 -6
  99. data/lib/action_policy/ext/string_match.rb +0 -14
  100. data/lib/action_policy/ext/yield_self_then.rb +0 -25
@@ -1,109 +0,0 @@
1
- # Controller Action Aliases
2
-
3
- **This is a feature proposed here: https://github.com/palkan/action_policy/issues/25**
4
-
5
- If you'd like to see this feature implemented, please comment on the issue to show your support.
6
-
7
- ## Outline
8
-
9
- Say you have abstracted your `authorize!` call to a controller superclass because your policy can
10
- be executed without regard to the record in any of the subclass controllers:
11
-
12
- ```ruby
13
- class AbstractController < ApplicationController
14
- authorize :context
15
- before_action :authorize_context
16
-
17
- def context
18
- # Some code to get your policy context
19
- end
20
-
21
- private
22
-
23
- def authorize_context
24
- authorize! Context
25
- end
26
- end
27
- ```
28
-
29
- Your policy might look like this:
30
-
31
- ```ruby
32
- class ContextPolicy < ApplicationPolicy
33
- authorize :context
34
-
35
- alias_rule :index?, :show?, to: :view?
36
- alias_rule :new?, :create?, :update?, :destroy?, to: :edit?
37
-
38
- def view?
39
- context.has_permission_to(:view, user)
40
- end
41
-
42
- def edit?
43
- context.has_permission_to(:edit, user)
44
- end
45
- end
46
- ```
47
-
48
- We can safely add aliases for the common REST actions in the policy.
49
-
50
- You may then want to include a concern in your subclass controller(s) that add extra actions to the controller.
51
-
52
-
53
- ```ruby
54
- class ConcreteController < AbstractController
55
- include AdditionalFunctionalityConcern
56
-
57
- def index
58
- # Index Action
59
- end
60
-
61
- def new
62
- # New Action
63
- end
64
-
65
- # etc...
66
- end
67
- ```
68
-
69
- At this point you may be wondering how to tell your abstracted policy that these new methods map to either
70
- the `view?` or `edit?` rule. You can currently provide the rule to execute to the `authorize!` method with
71
- the `to:` parameter but since our call to `authorize!` is in a superclass it has no idea about our concern.
72
- I propose the following controller method:
73
-
74
- ```ruby
75
- alias_action(*actions, to_rule: rule)
76
- ```
77
-
78
- Here's an example:
79
-
80
- ```ruby
81
- module AdditionalFunctionalityConcern
82
- extend ActiveSupport::Concern
83
-
84
- included do
85
- alias_action [:first_action, :second_action], to_rule: :view?
86
- alias_action [:third_action], to_rule: :edit?
87
- end
88
-
89
- def first_action
90
- # First Action
91
- end
92
-
93
- def second_action
94
- # Second Action
95
- end
96
-
97
- def third_action
98
- # Third Action
99
- end
100
- end
101
- ```
102
-
103
- When `authorize!` is called in a controller, it will first check the action aliases for a corresponding
104
- rule. If one is found, it will execute that rule instead of a rule matching the name of the current action.
105
- The rule may point at a concrete rule in the policy, or a rule alias in the policy, it doens't matter, the
106
- alias in the policy will be resolved like normal.
107
-
108
- If you'd like to see this feature implemented, please show your support on the
109
- [Github Issue](https://github.com/palkan/action_policy/issues/25).
@@ -1,48 +0,0 @@
1
- # Custom Lookup Chain
2
-
3
- Action Policy's lookup chain is just an array of _probes_ (lambdas with a specific interface).
4
-
5
- The lookup process itself is pretty simple:
6
- - Call the first probe;
7
- - Return the result if it is not `nil`;
8
- - Go to the next probe.
9
-
10
- You can override the default chain with your own. For example:
11
-
12
- ```ruby
13
- ActionPolicy::LookupChain.chain = [
14
- # Probe accepts record as the first argument
15
- # and arbitrary options (passed to `authorize!` / `allowed_to?` call)
16
- lambda do |record, **options|
17
- # your custom lookup logic
18
- end
19
- ]
20
- ```
21
-
22
- ## NullPolicy example
23
-
24
- Let's consider a simple example of extending the existing lookup chain with one more probe.
25
-
26
- Suppose that we want to have a fallback policy (policy used when none found for the resource) instead of raising an `ActionPolicy::NotFound` error.
27
-
28
- Let's call this policy a `NullPolicy`:
29
-
30
- ```ruby
31
- class NullPolicy < ActionPolicy::Base
32
- default_rule :any?
33
-
34
- def any?
35
- false
36
- end
37
- end
38
- ```
39
-
40
- Here we use the [default rule](aliases.md#default-rule) to handle any rule applied.
41
-
42
- Now we need to add a simple probe to the end of our lookup chain:
43
-
44
- ```ruby
45
- ActionPolicy::LookupChain.chain << ->(_, _) { NullPolicy }
46
- ```
47
-
48
- That's it!
@@ -1,53 +0,0 @@
1
- # Custom Base Policy
2
-
3
- `ActionPolicy::Base` is a combination of all available policy extensions with the default configuration.
4
-
5
- It looks like this:
6
-
7
-
8
- ```ruby
9
- class ActionPolicy::Base
10
- include ActionPolicy::Policy::Core
11
- include ActionPolicy::Policy::Authorization
12
- include ActionPolicy::Policy::PreCheck
13
- include ActionPolicy::Policy::Reasons
14
- include ActionPolicy::Policy::Aliases
15
- include ActionPolicy::Policy::Scoping
16
- include ActionPolicy::Policy::Cache
17
- include ActionPolicy::Policy::CachedApply
18
- include ActionPolicy::Policy::Defaults
19
-
20
- # ActionPolicy::Policy::Defaults module adds the following
21
-
22
- authorize :user
23
-
24
- default_rule :manage?
25
- alias_rule :new?, to: :create?
26
-
27
- def index?
28
- false
29
- end
30
-
31
- def create?
32
- false
33
- end
34
-
35
- def manage?
36
- false
37
- end
38
- end
39
- ```
40
-
41
-
42
-
43
- You can write your `ApplicationPolicy` from scratch instead of inheriting from `ActionPolicy::Base`
44
- if the defaults above do not fit your needs. The only required component is `ActionPolicy::Policy::Core`:
45
-
46
- ```ruby
47
- # minimal ApplicationPolicy
48
- class ApplicationPolicy
49
- include ActionPolicy::Policy::Core
50
- end
51
- ```
52
-
53
- The `Core` module provides `apply` and `allowed_to?` methods.
@@ -1,55 +0,0 @@
1
- # Debug Helpers
2
-
3
- **NOTE:** this functionality requires two additional gems to be available in the app:
4
- - [unparser](https://github.com/mbj/unparser)
5
- - [method_source](https://github.com/banister/method_source).
6
-
7
- We usually describe policy rules using _boolean expressions_ (e.g. `A or (B and C)` where each of `A`, `B` and `C` is a simple boolean expression or predicate method).
8
-
9
- When dealing with complex policies, it could be hard to figure out which predicate/check made policy to fail.
10
-
11
- The `Policy#pp(rule)` method aims to help debug such situations.
12
-
13
- Consider a (synthetic) example:
14
-
15
- ```ruby
16
- def feed?
17
- (admin? || allowed_to?(:access_feed?)) &&
18
- (user.name == "Jack" || user.name == "Kate")
19
- end
20
-
21
- ```
22
-
23
- Suppose that you want to debug this rule ("Why does it return false?").
24
- You can drop a [`binding.pry`](https://github.com/deivid-rodriguez/pry-byebug) (or `binding.irb`) right at the beginning of the method:
25
-
26
- ```ruby
27
- def feed?
28
- binding.pry # rubocop:disable Lint/Debugger
29
- #...
30
- end
31
- ```
32
-
33
- Now, run your code and trigger the breakpoint (i.e., run the method):
34
-
35
- ```
36
- # now you can preview the execution of the rule using the `pp` method (defined on the policy instance)
37
- pry> pp :feed?
38
- MyPolicy#feed?
39
- ↳ (
40
- admin? #=> false
41
- OR
42
- allowed_to?(:access_feed?) #=> true
43
- )
44
- AND
45
- (
46
- user.name == "Jack" #=> false
47
- OR
48
- user.name == "Kate" #=> true
49
- )
50
-
51
- # you can also check other rules or methods as well
52
- pry> pp :admin?
53
- MyPolicy#admin?
54
- ↳ user.admin? #=> false
55
- ```
@@ -1,27 +0,0 @@
1
- # Dealing with Decorators
2
-
3
- Ref: [action_policy#7](https://github.com/palkan/action_policy/issues/7).
4
-
5
- Since Action Policy [lookup mechanism](./lookup_chain.md) relies on the target
6
- record's class properties (names, methods) it could break when using with _decorators_.
7
-
8
- To make `authorize!` and other [behaviour](./behaviour.md) methods work seamlessly with decorated
9
- objects, you might want to _enhance_ the `policy_for` method.
10
-
11
- For example, when using the [Draper](https://github.com/drapergem/draper) gem:
12
-
13
- ```ruby
14
- module ActionPolicy
15
- module Draper
16
- def policy_for(record:, **opts)
17
- # From https://github.com/GoodMeasuresLLC/draper-cancancan/blob/master/lib/draper/cancancan.rb
18
- record = record.model while record.is_a?(::Draper::Decorator)
19
- super(record: record, **opts)
20
- end
21
- end
22
- end
23
-
24
- class ApplicationController < ActionController::Base
25
- prepend ActionPolicy::Draper
26
- end
27
- ```
Binary file
@@ -1,302 +0,0 @@
1
- # GraphQL integration
2
-
3
- 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).
4
-
5
- This integration provides the following features:
6
- - Fields & mutations authorization
7
- - List and connections scoping
8
- - [**Exposing permissions/authorization rules in the API**](https://evilmartians.com/chronicles/exposing-permissions-in-graphql-apis-with-action-policy).
9
-
10
- ## Getting Started
11
-
12
- First, add the `action_policy-graphql` gem to your Gemfile (see [installation instructions](https://github.com/palkan/action_policy-graphql#installation)).
13
-
14
- Then, include `ActionPolicy::GraphQL::Behaviour` to your base type (or any other type/mutation where you want to use authorization features):
15
-
16
- ```ruby
17
- # For fields authorization, lists scoping and rules exposing
18
- class Types::BaseObject < GraphQL::Schema::Object
19
- include ActionPolicy::GraphQL::Behaviour
20
- end
21
-
22
- # For using authorization helpers in mutations
23
- class Types::BaseMutation < GraphQL::Schema::Mutation
24
- include ActionPolicy::GraphQL::Behaviour
25
- end
26
-
27
- # For using authorization helpers in resolvers
28
- class Types::BaseResolver < GraphQL::Schema::Resolver
29
- include ActionPolicy::GraphQL::Behaviour
30
- end
31
- ```
32
-
33
- ## Authorization Context
34
-
35
- By default, Action Policy uses `context[:current_user]` as the `user` [authorization context](./authorization_context.md).
36
-
37
- **NOTE:** see below for more information on what's included into `ActionPolicy::GraphQL::Behaviour`.
38
-
39
- ## Authorizing Fields
40
-
41
- You can add `authorize: true` option to any field (=underlying object) to protect the access (it's equal to calling `authorize! object, to: :show?`):
42
-
43
- ```ruby
44
- # authorization could be useful for find-like methods,
45
- # where the object is resolved from the provided params (e.g., ID)
46
- field :home, Home, null: false, authorize: true do
47
- argument :id, ID, required: true
48
- end
49
-
50
- def home(id:)
51
- Home.find(id)
52
- end
53
-
54
- # Without `authorize: true` the code would look like this
55
- def home(id:)
56
- Home.find(id).tap { |home| authorize! home, to: :show? }
57
- end
58
- ```
59
-
60
- You can use authorization options to customize the behaviour, e.g. `authorize: {to: :preview?, with: CustomPolicy}`.
61
-
62
- By default, if a user is not authorized to access the field, an `ActionPolicy::Unauthorized` exception is raised.
63
-
64
- If you want to return a `nil` instead, you should add `raise: false` to the options:
65
-
66
- ```ruby
67
- # NOTE: don't forget to mark your field as nullable
68
- field :home, Home, null: true, authorize: {raise: false}
69
- ```
70
-
71
- You can make non-raising behaviour a default by setting a configuration option:
72
-
73
- ```ruby
74
- ActionPolicy::GraphQL.authorize_raise_exception = false
75
- ```
76
-
77
- You can also change the default `show?` rule globally:
78
-
79
- ```ruby
80
- ActionPolicy::GraphQL.default_authorize_rule = :show_graphql_field?
81
- ```
82
-
83
- If you want to perform authorization before resolving the field value, you can use `preauthorize: *` option:
84
-
85
- ```ruby
86
- field :homes, [Home], null: false, preauthorize: {with: HomePolicy}
87
-
88
- def homes
89
- Home.all
90
- end
91
- ```
92
-
93
- The code above is equal to:
94
-
95
- ```ruby
96
- field :homes, [Home], null: false
97
-
98
- def homes
99
- authorize! "homes", to: :index?, with: HomePolicy
100
- Home.all
101
- end
102
- ```
103
-
104
- **NOTE:** we pass the field's name as the `record` to the policy rule. We assume that preauthorization rules do not depend on
105
- the record itself and pass the field's name for debugging purposes only.
106
-
107
- You can customize the authorization options, e.g. `authorize: {to: :preview?, with: CustomPolicy}`.
108
-
109
- **NOTE:** unlike `authorize: *` you MUST specify the `with: SomePolicy` option.
110
- The default authorization rule depends on the type of the field:
111
-
112
- - for lists we use `index?` (configured by `ActionPolicy::GraphQL.default_preauthorize_list_rule` parameter)
113
- - for _singleton_ fields we use `show?` (configured by `ActionPolicy::GraphQL.default_preauthorize_node_rule` parameter)
114
-
115
- ### Class-level authorization
116
-
117
- You can use Action Policy in the class-level [authorization hooks](https://graphql-ruby.org/authorization/authorization.html) (`self.authorized?`) like this:
118
-
119
- ```ruby
120
- class Types::Friendship < Types::BaseObject
121
- def self.authorized?(object, context)
122
- super &&
123
- allowed_to?(
124
- :show?,
125
- object,
126
- # NOTE: you must provide context explicitly
127
- context: {user: context[:current_user]}
128
- )
129
- end
130
- end
131
- ```
132
-
133
- ## Authorizing Mutations
134
-
135
- 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).
136
-
137
- If you want to authorize the mutation, you call `authorize!` method. For example:
138
-
139
- ```ruby
140
- class Mutations::DestroyUser < Types::BaseMutation
141
- argument :id, ID, required: true
142
-
143
- def resolve(id:)
144
- user = User.find(id)
145
-
146
- # Raise an exception if the user has not enough permissions
147
- authorize! user, to: :destroy?
148
- # Or check without raising and do what you want
149
- #
150
- # if allowed_to?(:destroy?, user)
151
-
152
- user.destroy!
153
-
154
- {deleted_id: user.id}
155
- end
156
- end
157
- ```
158
-
159
- ## Handling exceptions
160
-
161
- The query would fail with `ActionPolicy::Unauthorized` exception when using `authorize: true` (in raising mode) or calling `authorize!` explicitly.
162
-
163
- That could be useful to handle this exception and send a more detailed error message to the client, for example:
164
-
165
- ```ruby
166
- # in your schema file
167
- rescue_from(ActionPolicy::Unauthorized) do |exp|
168
- raise GraphQL::ExecutionError.new(
169
- # use result.message (backed by i18n) as an error message
170
- exp.result.message,
171
- # use GraphQL error extensions to provide more context
172
- extensions: {
173
- code: :unauthorized,
174
- fullMessages: exp.result.reasons.full_messages,
175
- details: exp.result.reasons.details
176
- }
177
- )
178
- end
179
- ```
180
-
181
- ## Scoping Data
182
-
183
- You can add `authorized_scope: true` option to a field (list or [_connection_](https://graphql-ruby.org/relay/connections.html)) to apply the corresponding policy rules to the data:
184
-
185
- ```ruby
186
- class CityType < ::Common::Graphql::Type
187
- # It would automatically apply the relation scope from the EventPolicy to
188
- # the relation (city.events)
189
- field :events, EventType.connection_type,
190
- null: false,
191
- authorized_scope: true
192
-
193
- # you can specify the policy explicitly
194
- field :events, EventType.connection_type,
195
- null: false,
196
- authorized_scope: {with: CustomEventPolicy}
197
-
198
- # without the option you would write the following code
199
- def events
200
- authorized_scope object.events
201
- # or if `with` option specified
202
- authorized_scope object.events, with: CustomEventPolicy
203
- end
204
- end
205
- ```
206
-
207
- **NOTE:** you cannot use `authorize: *` and `authorized_scope: *` at the same time but you can combine `preauthorize: *` with `authorized_scope: *`.
208
-
209
- See the documenation on [scoping](./scoping.md).
210
-
211
- ## Exposing Authorization Rules
212
-
213
- With `action_policy-graphql` gem, you can easily expose your authorization logic to the client in a standardized way.
214
-
215
- For example, if you want to "tell" the client which actions could be performed against the object you
216
- can use the `expose_authorization_rules` macro to add authorization-related fields to your type:
217
-
218
- ```ruby
219
- class ProfileType < Types::BaseType
220
- # Adds can_edit, can_destroy fields with
221
- # AuthorizationResult type.
222
-
223
- # NOTE: prefix "can_" is used by default, no need to specify it explicitly
224
- expose_authorization_rules :edit?, :destroy?, prefix: "can_"
225
- end
226
- ```
227
-
228
- **NOTE:** you can use [aliases](./aliases.md) here as well as defined rules.
229
-
230
- **NOTE:** This feature relies the [_failure reasons_](./reasons.md) and
231
- the [i18n integration](./i18n.md) extensions. If your policies don't include any of these,
232
- you won't be able to use it.
233
-
234
- Then the client could perform the following query:
235
-
236
- ```gql
237
- {
238
- post(id: $id) {
239
- canEdit {
240
- # (bool) true|false; not null
241
- value
242
- # top-level decline message ("Not authorized" by default); null if value is true
243
- message
244
- # detailed information about the decline reasons; null if value is true or you don't have "failure reasons" extension enabled
245
- reasons {
246
- details # JSON-encoded hash of the form { "event" => [:privacy_off?] }
247
- fullMessages # Array of human-readable reasons
248
- }
249
- }
250
-
251
- canDestroy {
252
- # ...
253
- }
254
- }
255
- }
256
- ```
257
-
258
- You can override a custom authorization field prefix (`can_`):
259
-
260
- ```ruby
261
- ActionPolicy::GraphQL.default_authorization_field_prefix = "allowed_to_"
262
- ```
263
-
264
- You can specify a custom field name as well (only for a single rule):
265
-
266
- ```ruby
267
- class ProfileType < ::Common::Graphql::Type
268
- # Adds can_create_post field.
269
-
270
- expose_authorization_rules :create?, with: PostPolicy, field_name: "can_create_post"
271
- end
272
- ```
273
-
274
- ## Custom Behaviour
275
-
276
- Including the default `ActionPolicy::GraphQL::Behaviour` is equal to adding the following to your base class:
277
-
278
- ```ruby
279
- class Types::BaseObject < GraphQL::Schema::Object
280
- # include Action Policy behaviour and its extensions
281
- include ActionPolicy::Behaviour
282
- include ActionPolicy::Behaviours::ThreadMemoized
283
- include ActionPolicy::Behaviours::Memoized
284
- include ActionPolicy::Behaviours::Namespaced
285
-
286
- # define authorization context
287
- authorize :user, through: :current_user
288
-
289
- # add a method helper to get the current_user from the context
290
- def current_user
291
- context[:current_user]
292
- end
293
-
294
- # extend the field class to add `authorize` and `authorized_scope` options
295
- field_class.prepend(ActionPolicy::GraphQL::AuthorizedField)
296
-
297
- # add `expose_authorization_rules` macro
298
- include ActionPolicy::GraphQL::Fields
299
- end
300
- ```
301
-
302
- Feel free to create your own behaviour by adding only the functionality you need.