pundit 2.1.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +9 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +10 -14
- data/.travis.yml +20 -14
- data/CHANGELOG.md +57 -0
- data/CONTRIBUTING.md +1 -4
- data/README.md +84 -58
- data/SECURITY.md +19 -0
- data/config/rubocop-rspec.yml +5 -0
- data/lib/generators/pundit/install/install_generator.rb +4 -2
- data/lib/generators/pundit/install/templates/application_policy.rb +7 -3
- data/lib/generators/pundit/policy/policy_generator.rb +4 -2
- data/lib/generators/pundit/policy/templates/policy.rb +4 -3
- data/lib/generators/rspec/policy_generator.rb +4 -2
- data/lib/generators/rspec/templates/policy_spec.rb +1 -1
- data/lib/generators/test_unit/policy_generator.rb +4 -2
- data/lib/pundit/authorization.rb +168 -0
- data/lib/pundit/policy_finder.rb +1 -1
- data/lib/pundit/rspec.rb +5 -15
- data/lib/pundit/version.rb +1 -1
- data/lib/pundit.rb +21 -172
- data/pundit.gemspec +7 -3
- data/spec/authorization_spec.rb +258 -0
- data/spec/generators_spec.rb +43 -0
- data/spec/policies/post_policy_spec.rb +1 -1
- data/spec/policy_finder_spec.rb +80 -17
- data/spec/pundit_spec.rb +52 -226
- data/spec/spec_helper.rb +30 -26
- metadata +49 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5c9e118c59bc3a683734817ac6fb9036a2b909df7abce2dbbdc00fc16aebdf7
|
4
|
+
data.tar.gz: 843cc1b7652e88d598a37a28f93bf13c41710bf3dddefeb96acf74e659279581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2430ece33471f7a321a124aeafab7dbc3be4688fbda581b758d90649f4ae06d0cbaf86df768e881d0a2f1c0ab55581cb5dc0f1d3012ab7611b2fd81b8a0f321
|
7
|
+
data.tar.gz: 3432cc545ca5139cfcd7e1fc26a17d0882c11de71a3c6949c1d1da232183eba495de18aa06b64462c1233b820099788b43feeb0e9b439911bc9761dc7bd1e141
|
@@ -0,0 +1,9 @@
|
|
1
|
+
## To do
|
2
|
+
|
3
|
+
- [ ] I have read the [contributing guidelines](https://github.com/varvet/pundit/contribute).
|
4
|
+
- [ ] I have added relevant tests.
|
5
|
+
- [ ] I have adjusted relevant documentation.
|
6
|
+
- [ ] I have made sure the individual commits are meaningful.
|
7
|
+
- [ ] I have added relevant lines to the CHANGELOG.
|
8
|
+
|
9
|
+
PS: Thank you for contributing to Pundit ❤️
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
AllCops:
|
2
|
-
|
3
|
-
TargetRubyVersion: 2.2
|
2
|
+
TargetRubyVersion: 2.6
|
4
3
|
Exclude:
|
5
|
-
- "
|
6
|
-
|
7
|
-
|
4
|
+
- "lib/generators/**/templates/**/*"
|
5
|
+
SuggestExtensions: false
|
6
|
+
NewCops: disable
|
8
7
|
|
9
8
|
Metrics/BlockLength:
|
10
9
|
Exclude:
|
@@ -18,7 +17,7 @@ Metrics/ModuleLength:
|
|
18
17
|
Exclude:
|
19
18
|
- "**/*_spec.rb"
|
20
19
|
|
21
|
-
|
20
|
+
Layout/LineLength:
|
22
21
|
Max: 120
|
23
22
|
|
24
23
|
Metrics/AbcSize:
|
@@ -30,7 +29,10 @@ Metrics/CyclomaticComplexity:
|
|
30
29
|
Metrics/PerceivedComplexity:
|
31
30
|
Enabled: false
|
32
31
|
|
33
|
-
|
32
|
+
Gemspec/RequiredRubyVersion:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Layout/ParameterAlignment:
|
34
36
|
EnforcedStyle: with_fixed_indentation
|
35
37
|
|
36
38
|
Layout/CaseIndentation:
|
@@ -40,15 +42,9 @@ Layout/CaseIndentation:
|
|
40
42
|
- end
|
41
43
|
IndentOneStep: true
|
42
44
|
|
43
|
-
Layout/AccessModifierIndentation:
|
44
|
-
EnforcedStyle: outdent
|
45
|
-
|
46
45
|
Layout/EndAlignment:
|
47
46
|
EnforcedStyleAlignWith: variable
|
48
47
|
|
49
|
-
Style/FrozenStringLiteralComment:
|
50
|
-
Enabled: true
|
51
|
-
|
52
48
|
Style/PercentLiteralDelimiters:
|
53
49
|
PreferredDelimiters:
|
54
50
|
'%w': "[]"
|
@@ -72,5 +68,5 @@ Style/Not:
|
|
72
68
|
Style/DoubleNegation:
|
73
69
|
Enabled: false
|
74
70
|
|
75
|
-
Documentation:
|
71
|
+
Style/Documentation:
|
76
72
|
Enabled: false # TODO: Enable again once we have more docs
|
data/.travis.yml
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
language: ruby
|
2
|
-
|
3
|
-
- gem install bundler -v 1.17.3
|
2
|
+
dist: focal
|
4
3
|
|
5
4
|
matrix:
|
6
5
|
include:
|
7
|
-
-
|
6
|
+
- name: "RuboCop lint on pre-installed Ruby version"
|
7
|
+
rvm: 2.7.1 # Pre-installed Ruby version
|
8
|
+
before_install:
|
9
|
+
- gem install bundler
|
8
10
|
script: bundle exec rake rubocop # ONLY lint once, first
|
9
|
-
- rvm: 2.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
- rvm:
|
11
|
+
- rvm: 2.6.7
|
12
|
+
before_script:
|
13
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
14
|
+
- chmod +x ./cc-test-reporter
|
15
|
+
- ./cc-test-reporter before-build
|
16
|
+
after_script:
|
17
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
18
|
+
- rvm: 2.7.3
|
19
|
+
- rvm: 3.0.1
|
20
|
+
- rvm: 3.1.0
|
21
|
+
- rvm: 3.2.0
|
22
|
+
- rvm: jruby-9.3.10.0
|
20
23
|
env:
|
21
24
|
- JRUBY_OPTS="--debug"
|
25
|
+
- rvm: truffleruby-head
|
26
|
+
allow_failures:
|
27
|
+
- rvm: truffleruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,62 @@
|
|
1
1
|
# Pundit
|
2
2
|
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
Nothing.
|
6
|
+
|
7
|
+
## 2.3.1 (2023-07-17)
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
- Use `Kernel.warn` instead of `ActiveSupport::Deprecation.warn` for deprecations (#764)
|
12
|
+
- Policy generator now works on Ruby 3.2 (#754)
|
13
|
+
|
14
|
+
## 2.3.0 (2022-12-19)
|
15
|
+
|
16
|
+
### Added
|
17
|
+
|
18
|
+
- add support for rubocop-rspec syntax extensions (#745)
|
19
|
+
|
20
|
+
## 2.2.0 (2022-02-11)
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
|
24
|
+
- Using `policy_class` and a namespaced record now passes only the record when instantiating the policy. (#697, #689, #694, #666)
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
|
28
|
+
- Require users to explicitly define Scope#resolve in generated policies (#711, #722)
|
29
|
+
|
30
|
+
### Deprecated
|
31
|
+
|
32
|
+
- Deprecate `include Pundit` in favor of `include Pundit::Authorization` (#621)
|
33
|
+
|
34
|
+
## 2.1.1 (2021-08-13)
|
35
|
+
|
36
|
+
Friday 13th-release!
|
37
|
+
|
38
|
+
Careful! The bugfix below (#626) could break existing code. If you rely on the
|
39
|
+
return value for `authorize` and namespaced policies you might need to do some
|
40
|
+
changes.
|
41
|
+
|
42
|
+
### Fixed
|
43
|
+
|
44
|
+
- `.authorize` and `#authorize` return the instance, even for namespaced
|
45
|
+
policies (#626)
|
46
|
+
|
47
|
+
### Changed
|
48
|
+
|
49
|
+
- Generate application scope with `protected` attr_readers. (#616)
|
50
|
+
|
51
|
+
### Removed
|
52
|
+
|
53
|
+
- Dropped support for Ruby end-of-life versions: 2.1 and 2.2. (#604)
|
54
|
+
- Dropped support for Ruby end-of-life versions: 2.3 (#633)
|
55
|
+
- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
|
56
|
+
- Dropped support for RSpec 2 (#615)
|
57
|
+
|
58
|
+
## 2.1.0 (2019-08-14)
|
59
|
+
|
3
60
|
### Fixed
|
4
61
|
|
5
62
|
- Avoid name clashes with the Error class. (#590)
|
data/CONTRIBUTING.md
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
## Security issues
|
2
2
|
|
3
|
-
If you have found a security related issue, please do not file an issue on
|
4
|
-
GitHub or send a PR addressing the issue. Contact
|
5
|
-
[Jonas](mailto:jonas.nicklas@gmail.com) directly. You will be given public
|
6
|
-
credit for your disclosure.
|
3
|
+
If you have found a security related issue, please do not file an issue on GitHub or send a PR addressing the issue. Refer to [SECURITY.md](./SECURITY.md) for instructions.
|
7
4
|
|
8
5
|
## Reporting issues
|
9
6
|
|
data/README.md
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# Pundit
|
2
2
|
|
3
|
-
[![Build Status](https://
|
3
|
+
[![Build Status](https://app.travis-ci.com/varvet/pundit.svg?branch=main)](https://app.travis-ci.com/varvet/pundit)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/varvet/pundit.svg)](https://codeclimate.com/github/varvet/pundit)
|
5
5
|
[![Inline docs](http://inch-ci.org/github/varvet/pundit.svg?branch=master)](http://inch-ci.org/github/varvet/pundit)
|
6
6
|
[![Gem Version](https://badge.fury.io/rb/pundit.svg)](http://badge.fury.io/rb/pundit)
|
7
7
|
|
8
8
|
Pundit provides a set of helpers which guide you in leveraging regular Ruby
|
9
|
-
classes and object oriented design patterns to build a
|
10
|
-
|
9
|
+
classes and object oriented design patterns to build a straightforward, robust, and
|
10
|
+
scalable authorization system.
|
11
11
|
|
12
12
|
Links:
|
13
13
|
|
14
|
-
- [API documentation](http://www.rubydoc.info/gems/pundit)
|
14
|
+
- [API documentation for the most recent version](http://www.rubydoc.info/gems/pundit)
|
15
15
|
- [Source Code](https://github.com/varvet/pundit)
|
16
16
|
- [Contributing](https://github.com/varvet/pundit/blob/master/CONTRIBUTING.md)
|
17
17
|
- [Code of Conduct](https://github.com/varvet/pundit/blob/master/CODE_OF_CONDUCT.md)
|
@@ -22,16 +22,17 @@ Sponsored by:
|
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
> **Please note** that the README on GitHub is accurate with the _latest code on GitHub_. You are most likely using a released version of Pundit, so please refer to the [documentation for the latest released version of Pundit](https://www.rubydoc.info/gems/pundit).
|
26
|
+
|
27
|
+
``` sh
|
28
|
+
bundle add pundit
|
27
29
|
```
|
28
30
|
|
29
|
-
Include Pundit in your application controller:
|
31
|
+
Include `Pundit::Authorization` in your application controller:
|
30
32
|
|
31
33
|
``` ruby
|
32
34
|
class ApplicationController < ActionController::Base
|
33
|
-
include Pundit
|
34
|
-
protect_from_forgery
|
35
|
+
include Pundit::Authorization
|
35
36
|
end
|
36
37
|
```
|
37
38
|
|
@@ -48,8 +49,8 @@ can pick up any classes in the new `app/policies/` directory.
|
|
48
49
|
## Policies
|
49
50
|
|
50
51
|
Pundit is focused around the notion of policy classes. We suggest that you put
|
51
|
-
these classes in `app/policies`. This is
|
52
|
-
|
52
|
+
these classes in `app/policies`. This is an example that allows updating a post
|
53
|
+
if the user is an admin, or if the post is unpublished:
|
53
54
|
|
54
55
|
``` ruby
|
55
56
|
class PostPolicy
|
@@ -61,12 +62,12 @@ class PostPolicy
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def update?
|
64
|
-
user.admin?
|
65
|
+
user.admin? || !post.published?
|
65
66
|
end
|
66
67
|
end
|
67
68
|
```
|
68
69
|
|
69
|
-
As you can see, this is
|
70
|
+
As you can see, this is a plain Ruby class. Pundit makes the following
|
70
71
|
assumptions about this class:
|
71
72
|
|
72
73
|
- The class has the same name as some kind of model class, only suffixed
|
@@ -165,13 +166,18 @@ def admin_list
|
|
165
166
|
end
|
166
167
|
```
|
167
168
|
|
168
|
-
`authorize` returns the
|
169
|
+
`authorize` returns the instance passed to it, so you can chain it like this:
|
169
170
|
|
170
171
|
Controller:
|
171
172
|
```ruby
|
172
173
|
def show
|
173
174
|
@user = authorize User.find(params[:id])
|
174
175
|
end
|
176
|
+
|
177
|
+
# return the record even for namespaced policies
|
178
|
+
def show
|
179
|
+
@user = authorize [:admin, User.find(params[:id])]
|
180
|
+
end
|
175
181
|
```
|
176
182
|
|
177
183
|
You can easily get a hold of an instance of the policy through the `policy`
|
@@ -190,18 +196,30 @@ you can retrieve it by passing a symbol.
|
|
190
196
|
|
191
197
|
```ruby
|
192
198
|
# app/policies/dashboard_policy.rb
|
193
|
-
class DashboardPolicy
|
194
|
-
|
199
|
+
class DashboardPolicy
|
200
|
+
attr_reader :user
|
201
|
+
|
202
|
+
# `_record` in this example will be :dashboard
|
203
|
+
def initialize(user, _record)
|
204
|
+
@user = user
|
205
|
+
end
|
206
|
+
|
207
|
+
def show?
|
208
|
+
user.admin?
|
209
|
+
end
|
195
210
|
end
|
196
211
|
```
|
197
212
|
|
198
213
|
Note that the headless policy still needs to accept two arguments. The
|
199
|
-
second argument will
|
214
|
+
second argument will be the symbol `:dashboard` in this case, which
|
200
215
|
is what is passed as the record to `authorize` below.
|
201
216
|
|
202
217
|
```ruby
|
203
218
|
# In controllers
|
204
|
-
|
219
|
+
def show
|
220
|
+
authorize :dashboard, :show?
|
221
|
+
...
|
222
|
+
end
|
205
223
|
```
|
206
224
|
|
207
225
|
```erb
|
@@ -220,8 +238,6 @@ define a class called a policy scope. It can look something like this:
|
|
220
238
|
``` ruby
|
221
239
|
class PostPolicy < ApplicationPolicy
|
222
240
|
class Scope
|
223
|
-
attr_reader :user, :scope
|
224
|
-
|
225
241
|
def initialize(user, scope)
|
226
242
|
@user = user
|
227
243
|
@scope = scope
|
@@ -234,6 +250,10 @@ class PostPolicy < ApplicationPolicy
|
|
234
250
|
scope.where(published: true)
|
235
251
|
end
|
236
252
|
end
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
attr_reader :user, :scope
|
237
257
|
end
|
238
258
|
|
239
259
|
def update?
|
@@ -296,13 +316,11 @@ def index
|
|
296
316
|
end
|
297
317
|
```
|
298
318
|
|
299
|
-
|
300
|
-
the `PostPolicy::Scope` class, it will instantiate this class and call
|
301
|
-
`resolve` on the instance. In this case it is a shortcut for doing:
|
319
|
+
In this case it is a shortcut for doing:
|
302
320
|
|
303
321
|
``` ruby
|
304
322
|
def index
|
305
|
-
@
|
323
|
+
@publications = PublicationPolicy::Scope.new(current_user, Post).resolve
|
306
324
|
end
|
307
325
|
```
|
308
326
|
|
@@ -330,7 +348,7 @@ that you haven't forgotten to authorize the action. For example:
|
|
330
348
|
|
331
349
|
``` ruby
|
332
350
|
class ApplicationController < ActionController::Base
|
333
|
-
include Pundit
|
351
|
+
include Pundit::Authorization
|
334
352
|
after_action :verify_authorized
|
335
353
|
end
|
336
354
|
```
|
@@ -343,7 +361,7 @@ authorize individual instances.
|
|
343
361
|
|
344
362
|
``` ruby
|
345
363
|
class ApplicationController < ActionController::Base
|
346
|
-
include Pundit
|
364
|
+
include Pundit::Authorization
|
347
365
|
after_action :verify_authorized, except: :index
|
348
366
|
after_action :verify_policy_scoped, only: :index
|
349
367
|
end
|
@@ -356,7 +374,7 @@ these filters without affecting how your app works in any way.**
|
|
356
374
|
|
357
375
|
Some people have found this feature confusing, while many others
|
358
376
|
find it extremely helpful. If you fall into the category of people who find it
|
359
|
-
confusing then you do not need to use it. Pundit will work
|
377
|
+
confusing then you do not need to use it. Pundit will work fine without
|
360
378
|
using `verify_authorized` and `verify_policy_scoped`.
|
361
379
|
|
362
380
|
### Conditional verification
|
@@ -391,20 +409,23 @@ class Post
|
|
391
409
|
end
|
392
410
|
```
|
393
411
|
|
394
|
-
|
412
|
+
Alternatively, you can declare an instance method:
|
395
413
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
414
|
+
``` ruby
|
415
|
+
class Post
|
416
|
+
def policy_class
|
417
|
+
PostablePolicy
|
418
|
+
end
|
419
|
+
end
|
420
|
+
```
|
401
421
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
422
|
+
## Plain old Ruby
|
423
|
+
|
424
|
+
Pundit is a very small library on purpose, and it doesn't do anything you can't do yourself. There's no secret sauce here. It does as little as possible, and then gets out of your way.
|
425
|
+
|
426
|
+
With the few but powerful helpers available in Pundit, you have the power to build a well structured, fully working authorization system without using any special DSLs or funky syntax.
|
427
|
+
|
428
|
+
Remember that all of the policy and scope classes are plain Ruby classes, which means you can use the same mechanisms you always use to DRY things up. Encapsulate a set of permissions into a module and include them in multiple policies. Use `alias_method` to make some permissions behave the same as others. Inherit from a base set of permissions. Use metaprogramming if you really have to.
|
408
429
|
|
409
430
|
## Generator
|
410
431
|
|
@@ -476,8 +497,7 @@ method in every controller.
|
|
476
497
|
|
477
498
|
```ruby
|
478
499
|
class ApplicationController < ActionController::Base
|
479
|
-
|
480
|
-
include Pundit
|
500
|
+
include Pundit::Authorization
|
481
501
|
|
482
502
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
483
503
|
|
@@ -485,7 +505,7 @@ class ApplicationController < ActionController::Base
|
|
485
505
|
|
486
506
|
def user_not_authorized
|
487
507
|
flash[:alert] = "You are not authorized to perform this action."
|
488
|
-
|
508
|
+
redirect_back(fallback_location: root_path)
|
489
509
|
end
|
490
510
|
end
|
491
511
|
```
|
@@ -514,7 +534,7 @@ class ApplicationController < ActionController::Base
|
|
514
534
|
policy_name = exception.policy.class.to_s.underscore
|
515
535
|
|
516
536
|
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
|
517
|
-
|
537
|
+
redirect_back(fallback_location: root_path)
|
518
538
|
end
|
519
539
|
end
|
520
540
|
```
|
@@ -528,8 +548,7 @@ en:
|
|
528
548
|
create?: 'You cannot create posts!'
|
529
549
|
```
|
530
550
|
|
531
|
-
|
532
|
-
your error messaging.
|
551
|
+
This is an example. Pundit is agnostic as to how you implement your error messaging.
|
533
552
|
|
534
553
|
## Manually retrieving policies and scopes
|
535
554
|
|
@@ -551,9 +570,7 @@ those without the bang will return nil.
|
|
551
570
|
|
552
571
|
## Customize Pundit user
|
553
572
|
|
554
|
-
|
555
|
-
`current_user` is not the method that should be invoked by Pundit. Simply
|
556
|
-
define a method in your controller called `pundit_user`.
|
573
|
+
On occasion, your controller may be unable to access `current_user`, or the method that should be invoked by Pundit may not be `current_user`. To address this, you can define a method in your controller named `pundit_user`.
|
557
574
|
|
558
575
|
```ruby
|
559
576
|
def pundit_user
|
@@ -597,8 +614,7 @@ class Admin::PostController < AdminController
|
|
597
614
|
end
|
598
615
|
|
599
616
|
def show
|
600
|
-
post = Post.find(params[:id])
|
601
|
-
authorize(post)
|
617
|
+
post = authorize Post.find(params[:id])
|
602
618
|
end
|
603
619
|
end
|
604
620
|
```
|
@@ -631,7 +647,7 @@ class UserContext
|
|
631
647
|
end
|
632
648
|
|
633
649
|
class ApplicationController
|
634
|
-
include Pundit
|
650
|
+
include Pundit::Authorization
|
635
651
|
|
636
652
|
def pundit_user
|
637
653
|
UserContext.new(current_user, request.ip)
|
@@ -641,9 +657,8 @@ end
|
|
641
657
|
|
642
658
|
## Strong parameters
|
643
659
|
|
644
|
-
In Rails
|
645
|
-
|
646
|
-
mass-assignment protection is handled in the controller. With Pundit you can
|
660
|
+
In Rails,
|
661
|
+
mass-assignment protection is handled in the controller. With Pundit you can
|
647
662
|
control which attributes a user has access to update via your policies. You can
|
648
663
|
set up a `permitted_attributes` method in your policy like this:
|
649
664
|
|
@@ -667,7 +682,7 @@ You can now retrieve these attributes from the policy:
|
|
667
682
|
class PostsController < ApplicationController
|
668
683
|
def update
|
669
684
|
@post = Post.find(params[:id])
|
670
|
-
if @post.
|
685
|
+
if @post.update(post_params)
|
671
686
|
redirect_to @post
|
672
687
|
else
|
673
688
|
render :edit
|
@@ -689,7 +704,7 @@ However, this is a bit cumbersome, so Pundit provides a convenient helper method
|
|
689
704
|
class PostsController < ApplicationController
|
690
705
|
def update
|
691
706
|
@post = Post.find(params[:id])
|
692
|
-
if @post.
|
707
|
+
if @post.update(permitted_attributes(@post))
|
693
708
|
redirect_to @post
|
694
709
|
else
|
695
710
|
render :edit
|
@@ -771,17 +786,28 @@ end
|
|
771
786
|
```
|
772
787
|
|
773
788
|
An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this
|
774
|
-
[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/
|
789
|
+
[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/punditcommunity/pundit-matchers) gem.
|
775
790
|
|
776
791
|
### Scope Specs
|
777
792
|
|
778
|
-
Pundit does not provide a DSL for testing scopes.
|
793
|
+
Pundit does not provide a DSL for testing scopes. Test them like you would a regular Ruby class!
|
794
|
+
|
795
|
+
### Linting with RuboCop RSpec
|
796
|
+
|
797
|
+
When you lint your RSpec spec files with `rubocop-rspec`, it will fail to properly detect RSpec constructs that Pundit defines, `permissions`.
|
798
|
+
Make sure to use `rubocop-rspec` 2.0 or newer and add the following to your `.rubocop.yml`:
|
799
|
+
|
800
|
+
```yaml
|
801
|
+
inherit_gem:
|
802
|
+
pundit: config/rubocop-rspec.yml
|
803
|
+
```
|
779
804
|
|
780
805
|
# External Resources
|
781
806
|
|
782
807
|
- [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
|
783
808
|
- [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
|
784
809
|
- [Testing Pundit Policies with RSpec](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
|
810
|
+
- [Testing Pundit with Minitest](https://github.com/varvet/pundit/issues/204#issuecomment-60166450)
|
785
811
|
- [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
|
786
812
|
- [Straightforward Rails Authorization with Pundit](http://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
|
787
813
|
|
data/SECURITY.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
Please do not file an issue on GitHub, or send a PR addressing the issue.
|
4
|
+
|
5
|
+
## Supported versions
|
6
|
+
|
7
|
+
Most recent major version only.
|
8
|
+
|
9
|
+
## Reporting a vulnerability
|
10
|
+
|
11
|
+
Contact one of the maintainers directly:
|
12
|
+
|
13
|
+
* [@Burgestrand](https://github.com/Burgestrand)
|
14
|
+
* [@dgmstuart](https://github.com/dgmstuart)
|
15
|
+
* [@varvet](https://github.com/varvet)
|
16
|
+
|
17
|
+
You can report vulnerabilities on GitHub too: https://github.com/varvet/pundit/security
|
18
|
+
|
19
|
+
Thank you!
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Pundit
|
2
4
|
module Generators
|
3
5
|
class InstallGenerator < ::Rails::Generators::Base
|
4
|
-
source_root File.expand_path(
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
5
7
|
|
6
8
|
def copy_application_policy
|
7
|
-
template
|
9
|
+
template "application_policy.rb", "app/policies/application_policy.rb"
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ApplicationPolicy
|
2
4
|
attr_reader :user, :record
|
3
5
|
|
@@ -35,15 +37,17 @@ class ApplicationPolicy
|
|
35
37
|
end
|
36
38
|
|
37
39
|
class Scope
|
38
|
-
attr_reader :user, :scope
|
39
|
-
|
40
40
|
def initialize(user, scope)
|
41
41
|
@user = user
|
42
42
|
@scope = scope
|
43
43
|
end
|
44
44
|
|
45
45
|
def resolve
|
46
|
-
|
46
|
+
raise NotImplementedError, "You must define #resolve in #{self.class}"
|
47
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_reader :user, :scope
|
48
52
|
end
|
49
53
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Pundit
|
2
4
|
module Generators
|
3
5
|
class PolicyGenerator < ::Rails::Generators::NamedBase
|
4
|
-
source_root File.expand_path(
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
5
7
|
|
6
8
|
def create_policy
|
7
|
-
template
|
9
|
+
template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
|
8
10
|
end
|
9
11
|
|
10
12
|
hook_for :test_framework
|
@@ -1,9 +1,10 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
class <%= class_name %>Policy < ApplicationPolicy
|
3
3
|
class Scope < Scope
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
# NOTE: Be explicit about which records you allow access to!
|
5
|
+
# def resolve
|
6
|
+
# scope.all
|
7
|
+
# end
|
7
8
|
end
|
8
9
|
end
|
9
10
|
<% end -%>
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rspec
|
2
4
|
module Generators
|
3
5
|
class PolicyGenerator < ::Rails::Generators::NamedBase
|
4
|
-
source_root File.expand_path(
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
5
7
|
|
6
8
|
def create_policy_spec
|
7
|
-
template
|
9
|
+
template "policy_spec.rb", File.join("spec/policies", class_path, "#{file_name}_policy_spec.rb")
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|