pundit 1.1.0 → 2.0.0.beta1
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.
- checksums.yaml +5 -5
- data/.rubocop.yml +18 -10
- data/.travis.yml +19 -9
- data/CHANGELOG.md +13 -0
- data/Gemfile +13 -1
- data/README.md +233 -60
- data/Rakefile +0 -1
- data/lib/generators/pundit/install/install_generator.rb +1 -1
- data/lib/generators/pundit/install/templates/application_policy.rb +2 -6
- data/lib/generators/pundit/policy/policy_generator.rb +1 -1
- data/lib/generators/pundit/policy/templates/policy.rb +1 -1
- data/lib/generators/rspec/policy_generator.rb +1 -1
- data/lib/generators/rspec/templates/policy_spec.rb +0 -1
- data/lib/generators/test_unit/policy_generator.rb +1 -1
- data/lib/generators/test_unit/templates/policy_test.rb +0 -1
- data/lib/pundit.rb +84 -59
- data/lib/pundit/policy_finder.rb +25 -31
- data/lib/pundit/rspec.rb +11 -7
- data/lib/pundit/version.rb +3 -1
- data/pundit.gemspec +2 -11
- data/spec/policy_finder_spec.rb +122 -0
- data/spec/pundit_spec.rb +136 -32
- data/spec/spec_helper.rb +73 -11
- metadata +8 -119
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 91c992d8bb2bc907e4c532fb868f0e6f4105d9f4a79f0871593ec374f6f173b0
|
4
|
+
data.tar.gz: a855c49b6ada65cd8d1309ed104d6d089236ec46fcade8e872b66be6b152a054
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17b426b7b0a1410809be20410d20f2f291d26d3fde05bb333b68464f720c7824989f5063ba30c107459debaabb572f9a682738a74f35ebc08c4b3b6638350a3a
|
7
|
+
data.tar.gz: e28ba68e5f8c1a430a4cb1335b0ad95ff2d4dc35d5c2842e74321aad26e42cf8f1c383b217cbac8aab8449f20ef1d9faf10fe1432d27287fce961bea04e53b4e
|
data/.rubocop.yml
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
AllCops:
|
2
|
+
DisplayCopNames: true
|
3
|
+
TargetRubyVersion: 2.1
|
2
4
|
Exclude:
|
3
5
|
- "gemfiles/**/*"
|
4
6
|
- "vendor/**/*"
|
5
7
|
- "lib/generators/**/*"
|
6
8
|
|
9
|
+
Metrics/BlockLength:
|
10
|
+
Exclude:
|
11
|
+
- "**/*_spec.rb"
|
12
|
+
|
7
13
|
Metrics/MethodLength:
|
8
14
|
Max: 40
|
9
15
|
|
10
16
|
Metrics/ModuleLength:
|
11
17
|
Max: 200
|
18
|
+
Exclude:
|
19
|
+
- "**/*_spec.rb"
|
12
20
|
|
13
21
|
Metrics/LineLength:
|
14
22
|
Max: 120
|
@@ -25,7 +33,7 @@ Metrics/PerceivedComplexity:
|
|
25
33
|
Style/StructInheritance:
|
26
34
|
Enabled: false
|
27
35
|
|
28
|
-
|
36
|
+
Layout/AlignParameters:
|
29
37
|
EnforcedStyle: with_fixed_indentation
|
30
38
|
|
31
39
|
Style/StringLiterals:
|
@@ -34,7 +42,7 @@ Style/StringLiterals:
|
|
34
42
|
Style/StringLiteralsInInterpolation:
|
35
43
|
EnforcedStyle: double_quotes
|
36
44
|
|
37
|
-
|
45
|
+
Layout/ClosingParenthesisIndentation:
|
38
46
|
Enabled: false
|
39
47
|
|
40
48
|
Style/OneLineConditional:
|
@@ -49,8 +57,8 @@ Style/Not:
|
|
49
57
|
Documentation:
|
50
58
|
Enabled: false # TODO: Enable again once we have more docs
|
51
59
|
|
52
|
-
|
53
|
-
|
60
|
+
Layout/CaseIndentation:
|
61
|
+
EnforcedStyle: case
|
54
62
|
SupportedStyles:
|
55
63
|
- case
|
56
64
|
- end
|
@@ -61,22 +69,22 @@ Style/PercentLiteralDelimiters:
|
|
61
69
|
'%w': "[]"
|
62
70
|
'%W': "[]"
|
63
71
|
|
64
|
-
|
72
|
+
Layout/AccessModifierIndentation:
|
65
73
|
EnforcedStyle: outdent
|
66
74
|
|
67
75
|
Style/SignalException:
|
68
76
|
Enabled: false
|
69
77
|
|
70
|
-
|
78
|
+
Layout/IndentationWidth:
|
71
79
|
Enabled: false
|
72
80
|
|
73
81
|
Style/TrivialAccessors:
|
74
82
|
ExactNameMatch: true
|
75
83
|
|
76
|
-
|
77
|
-
|
84
|
+
Layout/EndAlignment:
|
85
|
+
EnforcedStyleAlignWith: variable
|
78
86
|
|
79
|
-
|
87
|
+
Layout/DefEndAlignment:
|
80
88
|
Enabled: false
|
81
89
|
|
82
90
|
Lint/HandleExceptions:
|
@@ -88,7 +96,7 @@ Style/SpecialGlobalVars:
|
|
88
96
|
Style/TrivialAccessors:
|
89
97
|
Enabled: false
|
90
98
|
|
91
|
-
|
99
|
+
Layout/IndentHash:
|
92
100
|
Enabled: false
|
93
101
|
|
94
102
|
Style/DoubleNegation:
|
data/.travis.yml
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
|
-
|
4
|
-
-
|
5
|
-
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
before_install:
|
4
|
+
- gem update --system
|
5
|
+
- gem install bundler
|
6
|
+
|
7
|
+
matrix:
|
8
|
+
include:
|
9
|
+
- rvm: 2.5.1
|
10
|
+
script: bundle exec rake rubocop # ONLY lint once, first
|
11
|
+
- rvm: 2.1
|
12
|
+
- rvm: 2.2.8
|
13
|
+
- rvm: 2.3.5
|
14
|
+
- rvm: 2.4.2
|
15
|
+
- rvm: 2.5.1
|
16
|
+
- rvm: jruby-9.1.8.0
|
17
|
+
env:
|
18
|
+
- JRUBY_OPTS="--debug"
|
19
|
+
- rvm: jruby-9.2.0.0
|
20
|
+
env:
|
21
|
+
- JRUBY_OPTS="--debug"
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Pundit
|
2
2
|
|
3
|
+
## 2.0.0.beta1 (2018-07-04)
|
4
|
+
|
5
|
+
- Add `policy_class` option to `authorize` to be able to override the policy. (#441)
|
6
|
+
- Add `policy_scope_class` option to `authorize` to be able to override the policy scope. (#441)
|
7
|
+
- Fix `param_key` issue when passed an array. (#529)
|
8
|
+
- Only pass last element of "namespace array" to policy and scope. (#529)
|
9
|
+
- Allow specification of a `NilClassPolicy`. (#525)
|
10
|
+
- Make sure `policy_class` override is called when passed an array. (#475)
|
11
|
+
- Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. (#462)
|
12
|
+
- Use `action_name` instead of `params[:action]`. (#419)
|
13
|
+
- Add `pundit_params_for` method to make it easy to customize params fetching. (#502)
|
14
|
+
- Return passed object from `#authorize` method to make chaining possible. (#385)
|
15
|
+
|
3
16
|
## 1.1.0 (2016-01-14)
|
4
17
|
|
5
18
|
- Can retrieve policies via an array of symbols/objects.
|
data/Gemfile
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
|
3
|
+
ruby RUBY_VERSION
|
4
|
+
|
4
5
|
gemspec
|
6
|
+
|
7
|
+
group :development, :test do
|
8
|
+
gem "actionpack"
|
9
|
+
gem "activemodel"
|
10
|
+
gem "bundler"
|
11
|
+
gem "pry"
|
12
|
+
gem "rake"
|
13
|
+
gem "rspec"
|
14
|
+
gem "rubocop"
|
15
|
+
gem "yard"
|
16
|
+
end
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Pundit
|
2
2
|
|
3
|
-
[](https://travis-ci.org/varvet/pundit)
|
4
|
+
[](https://codeclimate.com/github/varvet/pundit)
|
5
|
+
[](http://inch-ci.org/github/varvet/pundit)
|
6
6
|
[](http://badge.fury.io/rb/pundit)
|
7
7
|
|
8
8
|
Pundit provides a set of helpers which guide you in leveraging regular Ruby
|
@@ -12,13 +12,13 @@ scaleable authorization system.
|
|
12
12
|
Links:
|
13
13
|
|
14
14
|
- [API documentation](http://www.rubydoc.info/gems/pundit)
|
15
|
-
- [Source Code](https://github.com/
|
16
|
-
- [Contributing](https://github.com/
|
17
|
-
- [Code of Conduct](https://github.com/
|
15
|
+
- [Source Code](https://github.com/varvet/pundit)
|
16
|
+
- [Contributing](https://github.com/varvet/pundit/blob/master/CONTRIBUTING.md)
|
17
|
+
- [Code of Conduct](https://github.com/varvet/pundit/blob/master/CODE_OF_CONDUCT.md)
|
18
18
|
|
19
19
|
Sponsored by:
|
20
20
|
|
21
|
-
[<img src="
|
21
|
+
[<img src="https://www.varvet.com/images/wordmark-red.svg" alt="Varvet" height="50px"/>](https://www.varvet.com)
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
@@ -116,7 +116,9 @@ and the given record. It then infers from the action name, that it should call
|
|
116
116
|
`authorize` would have done something like this:
|
117
117
|
|
118
118
|
``` ruby
|
119
|
-
|
119
|
+
unless PostPolicy.new(current_user, @post).update?
|
120
|
+
raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
|
121
|
+
end
|
120
122
|
```
|
121
123
|
|
122
124
|
You can pass a second argument to `authorize` if the name of the permission you
|
@@ -131,6 +133,18 @@ def publish
|
|
131
133
|
end
|
132
134
|
```
|
133
135
|
|
136
|
+
You can pass an argument to override the policy class if necessary. For example:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
def create
|
140
|
+
@publication = find_publication # assume this method returns any model that behaves like a publication
|
141
|
+
# @publication.class => Post
|
142
|
+
authorize @publication, policy_class: PublicationPolicy
|
143
|
+
@publication.publish!
|
144
|
+
redirect_to @publication
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
134
148
|
If you don't have an instance for the first argument to `authorize`, then you can pass
|
135
149
|
the class. For example:
|
136
150
|
|
@@ -151,6 +165,15 @@ def admin_list
|
|
151
165
|
end
|
152
166
|
```
|
153
167
|
|
168
|
+
`authorize` returns the object passed to it, so you can chain it like this:
|
169
|
+
|
170
|
+
Controller:
|
171
|
+
```ruby
|
172
|
+
def show
|
173
|
+
@user = authorize User.find(params[:id])
|
174
|
+
end
|
175
|
+
```
|
176
|
+
|
154
177
|
You can easily get a hold of an instance of the policy through the `policy`
|
155
178
|
method in both the view and controller. This is especially useful for
|
156
179
|
conditionally showing links or buttons in the view:
|
@@ -184,54 +207,6 @@ authorize :dashboard, :show?
|
|
184
207
|
<% end %>
|
185
208
|
```
|
186
209
|
|
187
|
-
## Ensuring policies are used
|
188
|
-
|
189
|
-
Pundit adds a method called `verify_authorized` to your controllers. This
|
190
|
-
method will raise an exception if `authorize` has not yet been called. You
|
191
|
-
should run this method in an `after_action` to ensure that you haven't
|
192
|
-
forgotten to authorize the action. For example:
|
193
|
-
|
194
|
-
``` ruby
|
195
|
-
class ApplicationController < ActionController::Base
|
196
|
-
after_action :verify_authorized
|
197
|
-
end
|
198
|
-
```
|
199
|
-
|
200
|
-
Likewise, Pundit also adds `verify_policy_scoped` to your controller. This
|
201
|
-
will raise an exception in the vein of `verify_authorized`. However, it tracks
|
202
|
-
if `policy_scope` is used instead of `authorize`. This is mostly useful for
|
203
|
-
controller actions like `index` which find collections with a scope and don't
|
204
|
-
authorize individual instances.
|
205
|
-
|
206
|
-
``` ruby
|
207
|
-
class ApplicationController < ActionController::Base
|
208
|
-
after_action :verify_authorized, except: :index
|
209
|
-
after_action :verify_policy_scoped, only: :index
|
210
|
-
end
|
211
|
-
```
|
212
|
-
|
213
|
-
If you're using `verify_authorized` in your controllers but need to
|
214
|
-
conditionally bypass verification, you can use `skip_authorization`. For
|
215
|
-
bypassing `verify_policy_scoped`, use `skip_policy_scope`. These are useful
|
216
|
-
in circumstances where you don't want to disable verification for the
|
217
|
-
entire action, but have some cases where you intend to not authorize.
|
218
|
-
|
219
|
-
```ruby
|
220
|
-
def show
|
221
|
-
record = Record.find_by(attribute: "value")
|
222
|
-
if record.present?
|
223
|
-
authorize record
|
224
|
-
else
|
225
|
-
skip_authorization
|
226
|
-
end
|
227
|
-
end
|
228
|
-
```
|
229
|
-
|
230
|
-
If you need to perform some more sophisticated logic or you want to raise a custom
|
231
|
-
exception you can use the two lower level methods `pundit_policy_authorized?`
|
232
|
-
and `pundit_policy_scoped?` which return `true` or `false` depending on whether
|
233
|
-
`authorize` or `policy_scope` have been called, respectively.
|
234
|
-
|
235
210
|
## Scopes
|
236
211
|
|
237
212
|
Often, you will want to have some kind of view listing records which a
|
@@ -258,7 +233,7 @@ class PostPolicy < ApplicationPolicy
|
|
258
233
|
end
|
259
234
|
|
260
235
|
def update?
|
261
|
-
user.admin? or not
|
236
|
+
user.admin? or not record.published?
|
262
237
|
end
|
263
238
|
end
|
264
239
|
```
|
@@ -291,7 +266,7 @@ class PostPolicy < ApplicationPolicy
|
|
291
266
|
end
|
292
267
|
|
293
268
|
def update?
|
294
|
-
user.admin? or not
|
269
|
+
user.admin? or not record.published?
|
295
270
|
end
|
296
271
|
end
|
297
272
|
```
|
@@ -302,6 +277,19 @@ You can now use this class from your controller via the `policy_scope` method:
|
|
302
277
|
def index
|
303
278
|
@posts = policy_scope(Post)
|
304
279
|
end
|
280
|
+
|
281
|
+
def show
|
282
|
+
@post = policy_scope(Post).find(params[:id])
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
Like with the authorize method, you can also override the policy scope class:
|
287
|
+
|
288
|
+
``` ruby
|
289
|
+
def index
|
290
|
+
# publication_class => Post
|
291
|
+
@publications = policy_scope(publication_class, policy_scope_class: PublicationPolicy::Scope)
|
292
|
+
end
|
305
293
|
```
|
306
294
|
|
307
295
|
Just as with your policy, this will automatically infer that you want to use
|
@@ -322,6 +310,70 @@ You can, and are encouraged to, use this method in views:
|
|
322
310
|
<% end %>
|
323
311
|
```
|
324
312
|
|
313
|
+
## Ensuring policies and scopes are used
|
314
|
+
|
315
|
+
When you are developing an application with Pundit it can be easy to forget to
|
316
|
+
authorize some action. People are forgetful after all. Since Pundit encourages
|
317
|
+
you to add the `authorize` call manually to each controller action, it's really
|
318
|
+
easy to miss one.
|
319
|
+
|
320
|
+
Thankfully, Pundit has a handy feature which reminds you in case you forget.
|
321
|
+
Pundit tracks whether you have called `authorize` anywhere in your controller
|
322
|
+
action. Pundit also adds a method to your controllers called
|
323
|
+
`verify_authorized`. This method will raise an exception if `authorize` has not
|
324
|
+
yet been called. You should run this method in an `after_action` hook to ensure
|
325
|
+
that you haven't forgotten to authorize the action. For example:
|
326
|
+
|
327
|
+
``` ruby
|
328
|
+
class ApplicationController < ActionController::Base
|
329
|
+
include Pundit
|
330
|
+
after_action :verify_authorized
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
Likewise, Pundit also adds `verify_policy_scoped` to your controller. This
|
335
|
+
will raise an exception similar to `verify_authorized`. However, it tracks
|
336
|
+
if `policy_scope` is used instead of `authorize`. This is mostly useful for
|
337
|
+
controller actions like `index` which find collections with a scope and don't
|
338
|
+
authorize individual instances.
|
339
|
+
|
340
|
+
``` ruby
|
341
|
+
class ApplicationController < ActionController::Base
|
342
|
+
include Pundit
|
343
|
+
after_action :verify_authorized, except: :index
|
344
|
+
after_action :verify_policy_scoped, only: :index
|
345
|
+
end
|
346
|
+
```
|
347
|
+
|
348
|
+
**This verification mechanism only exists to aid you while developing your
|
349
|
+
application, so you don't forget to call `authorize`. It is not some kind of
|
350
|
+
failsafe mechanism or authorization mechanism. You should be able to remove
|
351
|
+
these filters without affecting how your app works in any way.**
|
352
|
+
|
353
|
+
Some people have found this feature confusing, while many others
|
354
|
+
find it extremely helpful. If you fall into the category of people who find it
|
355
|
+
confusing then you do not need to use it. Pundit will work just fine without
|
356
|
+
using `verify_authorized` and `verify_policy_scoped`.
|
357
|
+
|
358
|
+
### Conditional verification
|
359
|
+
|
360
|
+
If you're using `verify_authorized` in your controllers but need to
|
361
|
+
conditionally bypass verification, you can use `skip_authorization`. For
|
362
|
+
bypassing `verify_policy_scoped`, use `skip_policy_scope`. These are useful
|
363
|
+
in circumstances where you don't want to disable verification for the
|
364
|
+
entire action, but have some cases where you intend to not authorize.
|
365
|
+
|
366
|
+
```ruby
|
367
|
+
def show
|
368
|
+
record = Record.find_by(attribute: "value")
|
369
|
+
if record.present?
|
370
|
+
authorize record
|
371
|
+
else
|
372
|
+
skip_authorization
|
373
|
+
end
|
374
|
+
end
|
375
|
+
```
|
376
|
+
|
325
377
|
## Manually specifying policy classes
|
326
378
|
|
327
379
|
Sometimes you might want to explicitly declare which policy to use for a given
|
@@ -362,7 +414,8 @@ rails g pundit:policy post
|
|
362
414
|
|
363
415
|
In many applications, only logged in users are really able to do anything. If
|
364
416
|
you're building such a system, it can be kind of cumbersome to check that the
|
365
|
-
user in a policy isn't `nil` for every single permission.
|
417
|
+
user in a policy isn't `nil` for every single permission. Aside from policies,
|
418
|
+
you can add this check to the base class for scopes.
|
366
419
|
|
367
420
|
We suggest that you define a filter that redirects unauthenticated users to the
|
368
421
|
login page. As a secondary defence, if you've defined an ApplicationPolicy, it
|
@@ -376,6 +429,37 @@ class ApplicationPolicy
|
|
376
429
|
@user = user
|
377
430
|
@record = record
|
378
431
|
end
|
432
|
+
|
433
|
+
class Scope
|
434
|
+
attr_reader :user, :scope
|
435
|
+
|
436
|
+
def initialize(user, scope)
|
437
|
+
raise Pundit::NotAuthorizedError, "must be logged in" unless user
|
438
|
+
@user = user
|
439
|
+
@scope = scope
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
```
|
444
|
+
|
445
|
+
## NilClassPolicy
|
446
|
+
|
447
|
+
To support a [null object pattern](https://en.wikipedia.org/wiki/Null_Object_pattern)
|
448
|
+
you may find that you want to implement a `NilClassPolicy`. This might be useful
|
449
|
+
where you want to extend your ApplicationPolicy to allow some tolerance of, for
|
450
|
+
example, associations which might be `nil`.
|
451
|
+
|
452
|
+
```ruby
|
453
|
+
class NilClassPolicy < ApplicationPolicy
|
454
|
+
class Scope < Scope
|
455
|
+
def resolve
|
456
|
+
raise Pundit::NotDefinedError, "Cannot scope NilClass"
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
def show?
|
461
|
+
false # Nobody can see nothing
|
462
|
+
end
|
379
463
|
end
|
380
464
|
```
|
381
465
|
|
@@ -402,6 +486,10 @@ class ApplicationController < ActionController::Base
|
|
402
486
|
end
|
403
487
|
```
|
404
488
|
|
489
|
+
Alternatively, you can globally handle Pundit::NotAuthorizedError's by having rails handle them as a 403 error and serving a 403 error page. Add the following to application.rb:
|
490
|
+
|
491
|
+
```config.action_dispatch.rescue_responses["Pundit::NotAuthorizedError"] = :forbidden```
|
492
|
+
|
405
493
|
## Creating custom error messages
|
406
494
|
|
407
495
|
`NotAuthorizedError`s provide information on what query (e.g. `:create?`), what
|
@@ -469,6 +557,48 @@ def pundit_user
|
|
469
557
|
end
|
470
558
|
```
|
471
559
|
|
560
|
+
## Policy Namespacing
|
561
|
+
In some cases it might be helpful to have multiple policies that serve different contexts for a
|
562
|
+
resource. A prime example of this is the case where User policies differ from Admin policies. To
|
563
|
+
authorize with a namespaced policy, pass the namespace into the `authorize` helper in an array:
|
564
|
+
|
565
|
+
```ruby
|
566
|
+
authorize(post) # => will look for a PostPolicy
|
567
|
+
authorize([:admin, post]) # => will look for an Admin::PostPolicy
|
568
|
+
authorize([:foo, :bar, post]) # => will look for a Foo::Bar::PostPolicy
|
569
|
+
|
570
|
+
policy_scope(Post) # => will look for a PostPolicy::Scope
|
571
|
+
policy_scope([:admin, Post]) # => will look for an Admin::PostPolicy::Scope
|
572
|
+
policy_scope([:foo, :bar, Post]) # => will look for a Foo::Bar::PostPolicy::Scope
|
573
|
+
```
|
574
|
+
|
575
|
+
If you are using namespaced policies for something like Admin views, it can be useful to
|
576
|
+
override the `policy_scope` and `authorize` helpers in your `AdminController` to automatically
|
577
|
+
apply the namespacing:
|
578
|
+
|
579
|
+
```ruby
|
580
|
+
class AdminController < ApplicationController
|
581
|
+
def policy_scope(scope)
|
582
|
+
super([:admin, scope])
|
583
|
+
end
|
584
|
+
|
585
|
+
def authorize(record, query = nil)
|
586
|
+
super([:admin, record], query)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
class Admin::PostController < AdminController
|
591
|
+
def index
|
592
|
+
policy_scope(Post)
|
593
|
+
end
|
594
|
+
|
595
|
+
def show
|
596
|
+
post = Post.find(params[:id])
|
597
|
+
authorize(post)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
```
|
601
|
+
|
472
602
|
## Additional context
|
473
603
|
|
474
604
|
Pundit strongly encourages you to model your application in such a way that the
|
@@ -564,6 +694,45 @@ class PostsController < ApplicationController
|
|
564
694
|
end
|
565
695
|
```
|
566
696
|
|
697
|
+
If you want to permit different attributes based on the current action, you can define a `permitted_attributes_for_#{action}` method on your policy:
|
698
|
+
|
699
|
+
```ruby
|
700
|
+
# app/policies/post_policy.rb
|
701
|
+
class PostPolicy < ApplicationPolicy
|
702
|
+
def permitted_attributes_for_create
|
703
|
+
[:title, :body]
|
704
|
+
end
|
705
|
+
|
706
|
+
def permitted_attributes_for_edit
|
707
|
+
[:body]
|
708
|
+
end
|
709
|
+
end
|
710
|
+
```
|
711
|
+
|
712
|
+
If you have defined an action-specific method on your policy for the current action, the `permitted_attributes` helper will call it instead of calling `permitted_attributes` on your controller.
|
713
|
+
|
714
|
+
If you need to fetch parameters based on namespaces different from the suggested one, override the below method, in your controller, and return an instance of `ActionController::Parameters`.
|
715
|
+
|
716
|
+
```ruby
|
717
|
+
def pundit_params_for(record)
|
718
|
+
params.require(PolicyFinder.new(record).param_key)
|
719
|
+
end
|
720
|
+
```
|
721
|
+
|
722
|
+
For example:
|
723
|
+
|
724
|
+
```ruby
|
725
|
+
# If you don't want to use require
|
726
|
+
def pundit_params_for(record)
|
727
|
+
params.fetch(PolicyFinder.new(record).param_key, {})
|
728
|
+
end
|
729
|
+
|
730
|
+
# If you are using something like the JSON API spec
|
731
|
+
def pundit_params_for(_record)
|
732
|
+
params.fetch(:data, {}).fetch(:attributes, {})
|
733
|
+
end
|
734
|
+
```
|
735
|
+
|
567
736
|
## RSpec
|
568
737
|
|
569
738
|
### Policy Specs
|
@@ -600,12 +769,16 @@ end
|
|
600
769
|
An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this
|
601
770
|
[excellent post](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/) and implemented in the third party [pundit-matchers](https://github.com/chrisalley/pundit-matchers) gem.
|
602
771
|
|
772
|
+
### Scope Specs
|
773
|
+
|
774
|
+
Pundit does not provide a DSL for testing scopes. Just test it like a regular Ruby class!
|
775
|
+
|
603
776
|
# External Resources
|
604
777
|
|
605
778
|
- [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
|
606
779
|
- [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
|
607
780
|
- [Testing Pundit Policies with RSpec](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
|
608
|
-
- [Using Pundit outside of a Rails controller](https://github.com/
|
781
|
+
- [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
|
609
782
|
- [Straightforward Rails Authorization with Pundit](http://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
|
610
783
|
|
611
784
|
# License
|