pundit 2.2.0 → 2.5.2
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 +4 -4
- data/CHANGELOG.md +98 -29
- data/CONTRIBUTING.md +3 -5
- data/README.md +125 -54
- data/SECURITY.md +19 -0
- data/config/rubocop-rspec.yml +5 -0
- data/lib/generators/pundit/install/install_generator.rb +3 -1
- data/lib/generators/pundit/install/templates/{application_policy.rb → application_policy.rb.tt} +1 -1
- data/lib/generators/pundit/policy/policy_generator.rb +3 -1
- data/lib/generators/pundit/policy/templates/policy.rb.tt +16 -0
- data/lib/generators/rspec/policy_generator.rb +4 -1
- data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +1 -1
- data/lib/generators/test_unit/policy_generator.rb +4 -1
- data/lib/pundit/authorization.rb +176 -75
- data/lib/pundit/cache_store/legacy_store.rb +27 -0
- data/lib/pundit/cache_store/null_store.rb +30 -0
- data/lib/pundit/cache_store.rb +24 -0
- data/lib/pundit/context.rb +190 -0
- data/lib/pundit/error.rb +71 -0
- data/lib/pundit/helper.rb +16 -0
- data/lib/pundit/policy_finder.rb +34 -2
- data/lib/pundit/railtie.rb +20 -0
- data/lib/pundit/rspec.rb +92 -7
- data/lib/pundit/version.rb +2 -1
- data/lib/pundit.rb +45 -140
- metadata +25 -170
- data/.gitignore +0 -19
- data/.rubocop.yml +0 -72
- data/.travis.yml +0 -26
- data/.yardopts +0 -1
- data/CODE_OF_CONDUCT.md +0 -28
- data/Gemfile +0 -7
- data/Rakefile +0 -20
- data/lib/generators/pundit/policy/templates/policy.rb +0 -10
- data/pundit.gemspec +0 -33
- data/spec/authorization_spec.rb +0 -258
- data/spec/generators_spec.rb +0 -43
- data/spec/policies/post_policy_spec.rb +0 -22
- data/spec/policy_finder_spec.rb +0 -187
- data/spec/pundit_spec.rb +0 -427
- data/spec/spec_helper.rb +0 -275
- /data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb37a66715ec9d8c397d11d11429d137673a43317335cd8e255a0b11f92d98ab
|
|
4
|
+
data.tar.gz: 82c44fa243f3dcc18f006dbbb87bb48754dfcae8baf1876a7a8266567dfe8ebe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e650dddbc49cc94209dfdc22b12b5fedec499a07e0266c54c5bf8e93cc6573cdcd7cde045cc10e9e7343cb4de788c1459517b3b89333c2222700e821b624dc54
|
|
7
|
+
data.tar.gz: 443e7fefff8e69fd85aca350f174fa996f4c6fa7d524f17cd60cabec5ec09562bfccc25b25402d811934111b615542d9f470f899cd239cad7508d01471db16b6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
# Pundit
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 2.5.2 (2025-09-24)
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Added `config/rubocop-rspec.yml` back from accidentally being excluded [#866](https://github.com/varvet/pundit/issues/866)
|
|
9
|
+
|
|
10
|
+
## 2.5.1 (2025-09-12)
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Requiring only `pundit/rspec` no longer raises an error in Active Support [#857](https://github.com/varvet/pundit/issues/857)
|
|
14
|
+
|
|
15
|
+
## 2.5.0 (2025-03-03)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Add `Pundit::Authorization#pundit_reset!` hook to reset the policy and policy scope cache. [#830](https://github.com/varvet/pundit/issues/830)
|
|
20
|
+
- Add links to gemspec. [#845](https://github.com/varvet/pundit/issues/845)
|
|
21
|
+
- Register policies directories for Rails 8 code statistics [#833](https://github.com/varvet/pundit/issues/833)
|
|
22
|
+
- Added an example for how to use pundit with Rails 8 authentication generator [#850](https://github.com/varvet/pundit/issues/850)
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Deprecated `Pundit::SUFFIX`, moved it to `Pundit::PolicyFinder::SUFFIX` [#835](https://github.com/varvet/pundit/issues/835)
|
|
27
|
+
- Explicitly require less of `active_support` [#837](https://github.com/varvet/pundit/issues/837)
|
|
28
|
+
- Using `permit` matcher without a surrouding `permissions` block now raises a useful error. [#836](https://github.com/varvet/pundit/issues/836)
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Using a hash as custom cache in `Pundit.authorize` now works as documented. [#838](https://github.com/varvet/pundit/issues/838)
|
|
33
|
+
|
|
34
|
+
## 2.4.0 (2024-08-26)
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Improve the `NotAuthorizedError` message to include the policy class.
|
|
39
|
+
Furthermore, in the case where the record passed is a class instead of an instance, the class name is given. [#812](https://github.com/varvet/pundit/issues/812)
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- Add customizable permit matcher description [#806](https://github.com/varvet/pundit/issues/806)
|
|
44
|
+
- Add support for filter_run_when_matching :focus with permissions helper. [#820](https://github.com/varvet/pundit/issues/820)
|
|
45
|
+
|
|
46
|
+
## 2.3.2 (2024-05-08)
|
|
47
|
+
|
|
48
|
+
- Refactor: First pass of Pundit::Context [#797](https://github.com/varvet/pundit/issues/797)
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- Update `ApplicationPolicy` generator to qualify the `Scope` class name [#792](https://github.com/varvet/pundit/issues/792)
|
|
53
|
+
- Policy generator uses `NoMethodError` to indicate `#resolve` is not implemented [#776](https://github.com/varvet/pundit/issues/776)
|
|
54
|
+
|
|
55
|
+
## Deprecated
|
|
56
|
+
|
|
57
|
+
- Dropped support for Ruby 3.0 [#796](https://github.com/varvet/pundit/issues/796)
|
|
58
|
+
|
|
59
|
+
## 2.3.1 (2023-07-17)
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Use `Kernel.warn` instead of `ActiveSupport::Deprecation.warn` for deprecations [#764](https://github.com/varvet/pundit/issues/764)
|
|
64
|
+
- Policy generator now works on Ruby 3.2 [#754](https://github.com/varvet/pundit/issues/754)
|
|
65
|
+
|
|
66
|
+
## 2.3.0 (2022-12-19)
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- add support for rubocop-rspec syntax extensions [#745](https://github.com/varvet/pundit/issues/745)
|
|
71
|
+
|
|
3
72
|
## 2.2.0 (2022-02-11)
|
|
4
73
|
|
|
5
74
|
### Fixed
|
|
@@ -12,41 +81,41 @@
|
|
|
12
81
|
|
|
13
82
|
### Deprecated
|
|
14
83
|
|
|
15
|
-
- Deprecate `include Pundit` in favor of `include Pundit::Authorization`
|
|
84
|
+
- Deprecate `include Pundit` in favor of `include Pundit::Authorization` [#621](https://github.com/varvet/pundit/issues/621)
|
|
16
85
|
|
|
17
86
|
## 2.1.1 (2021-08-13)
|
|
18
87
|
|
|
19
88
|
Friday 13th-release!
|
|
20
89
|
|
|
21
|
-
Careful! The bugfix below
|
|
90
|
+
Careful! The bugfix below [#626](https://github.com/varvet/pundit/issues/626) could break existing code. If you rely on the
|
|
22
91
|
return value for `authorize` and namespaced policies you might need to do some
|
|
23
92
|
changes.
|
|
24
93
|
|
|
25
94
|
### Fixed
|
|
26
95
|
|
|
27
96
|
- `.authorize` and `#authorize` return the instance, even for namespaced
|
|
28
|
-
policies
|
|
97
|
+
policies [#626](https://github.com/varvet/pundit/issues/626)
|
|
29
98
|
|
|
30
99
|
### Changed
|
|
31
100
|
|
|
32
|
-
- Generate application scope with `protected` attr_readers.
|
|
101
|
+
- Generate application scope with `protected` attr_readers. [#616](https://github.com/varvet/pundit/issues/616)
|
|
33
102
|
|
|
34
103
|
### Removed
|
|
35
104
|
|
|
36
|
-
- Dropped support for Ruby end-of-life versions: 2.1 and 2.2.
|
|
37
|
-
- Dropped support for Ruby end-of-life versions: 2.3
|
|
38
|
-
- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1
|
|
39
|
-
- Dropped support for RSpec 2
|
|
105
|
+
- Dropped support for Ruby end-of-life versions: 2.1 and 2.2. [#604](https://github.com/varvet/pundit/issues/604)
|
|
106
|
+
- Dropped support for Ruby end-of-life versions: 2.3 [#633](https://github.com/varvet/pundit/issues/633)
|
|
107
|
+
- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 [#676](https://github.com/varvet/pundit/issues/676)
|
|
108
|
+
- Dropped support for RSpec 2 [#615](https://github.com/varvet/pundit/issues/615)
|
|
40
109
|
|
|
41
110
|
## 2.1.0 (2019-08-14)
|
|
42
111
|
|
|
43
112
|
### Fixed
|
|
44
113
|
|
|
45
|
-
- Avoid name clashes with the Error class.
|
|
114
|
+
- Avoid name clashes with the Error class. [#590](https://github.com/varvet/pundit/issues/590)
|
|
46
115
|
|
|
47
116
|
### Changed
|
|
48
117
|
|
|
49
|
-
- Return a safer default NotAuthorizedError message.
|
|
118
|
+
- Return a safer default NotAuthorizedError message. [#583](https://github.com/varvet/pundit/issues/583)
|
|
50
119
|
|
|
51
120
|
## 2.0.1 (2019-01-18)
|
|
52
121
|
|
|
@@ -56,8 +125,8 @@ None
|
|
|
56
125
|
|
|
57
126
|
### Other changes
|
|
58
127
|
|
|
59
|
-
- Improve exception handling for `#policy_scope` and `#policy_scope!`.
|
|
60
|
-
- Add `:policy` metadata to RSpec template.
|
|
128
|
+
- Improve exception handling for `#policy_scope` and `#policy_scope!`. [#550](https://github.com/varvet/pundit/issues/550)
|
|
129
|
+
- Add `:policy` metadata to RSpec template. [#566](https://github.com/varvet/pundit/issues/566)
|
|
61
130
|
|
|
62
131
|
## 2.0.0 (2018-07-21)
|
|
63
132
|
|
|
@@ -67,20 +136,20 @@ No changes since beta1
|
|
|
67
136
|
|
|
68
137
|
### Breaking changes
|
|
69
138
|
|
|
70
|
-
- Only pass last element of "namespace array" to policy and scope.
|
|
71
|
-
- Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called.
|
|
72
|
-
- Return passed object from `#authorize` method to make chaining possible.
|
|
139
|
+
- Only pass last element of "namespace array" to policy and scope. [#529](https://github.com/varvet/pundit/issues/529)
|
|
140
|
+
- Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. [#462](https://github.com/varvet/pundit/issues/462)
|
|
141
|
+
- Return passed object from `#authorize` method to make chaining possible. [#385](https://github.com/varvet/pundit/issues/385)
|
|
73
142
|
|
|
74
143
|
### Other changes
|
|
75
144
|
|
|
76
|
-
- Add `policy_class` option to `authorize` to be able to override the policy.
|
|
77
|
-
- Add `policy_scope_class` option to `authorize` to be able to override the policy scope.
|
|
78
|
-
- Fix `param_key` issue when passed an array.
|
|
79
|
-
- Allow specification of a `NilClassPolicy`.
|
|
80
|
-
- Make sure `policy_class` override is called when passed an array.
|
|
145
|
+
- Add `policy_class` option to `authorize` to be able to override the policy. [#441](https://github.com/varvet/pundit/issues/441)
|
|
146
|
+
- Add `policy_scope_class` option to `authorize` to be able to override the policy scope. [#441](https://github.com/varvet/pundit/issues/441)
|
|
147
|
+
- Fix `param_key` issue when passed an array. [#529](https://github.com/varvet/pundit/issues/529)
|
|
148
|
+
- Allow specification of a `NilClassPolicy`. [#525](https://github.com/varvet/pundit/issues/525)
|
|
149
|
+
- Make sure `policy_class` override is called when passed an array. [#475](https://github.com/varvet/pundit/issues/475)
|
|
81
150
|
|
|
82
|
-
- Use `action_name` instead of `params[:action]`.
|
|
83
|
-
- Add `pundit_params_for` method to make it easy to customize params fetching.
|
|
151
|
+
- Use `action_name` instead of `params[:action]`. [#419](https://github.com/varvet/pundit/issues/419)
|
|
152
|
+
- Add `pundit_params_for` method to make it easy to customize params fetching. [#502](https://github.com/varvet/pundit/issues/502)
|
|
84
153
|
|
|
85
154
|
## 1.1.0 (2016-01-14)
|
|
86
155
|
|
|
@@ -112,16 +181,16 @@ No changes since beta1
|
|
|
112
181
|
|
|
113
182
|
## 0.3.0 (2014-08-22)
|
|
114
183
|
|
|
115
|
-
- Extend the default `ApplicationPolicy` with an `ApplicationPolicy::Scope`
|
|
116
|
-
- Fix RSpec 3 deprecation warnings for built-in matchers
|
|
117
|
-
- Generate blank policy spec/test files for Rspec/MiniTest/Test::Unit in Rails
|
|
184
|
+
- Extend the default `ApplicationPolicy` with an `ApplicationPolicy::Scope` [#120](https://github.com/varvet/pundit/issues/120)
|
|
185
|
+
- Fix RSpec 3 deprecation warnings for built-in matchers [#162](https://github.com/varvet/pundit/issues/162)
|
|
186
|
+
- Generate blank policy spec/test files for Rspec/MiniTest/Test::Unit in Rails [#138](https://github.com/varvet/pundit/issues/138)
|
|
118
187
|
|
|
119
188
|
## 0.2.3 (2014-04-06)
|
|
120
189
|
|
|
121
|
-
- Customizable error messages: `#query`, `#record` and `#policy` methods on `Pundit::NotAuthorizedError`
|
|
122
|
-
- Raise a different `Pundit::AuthorizationNotPerformedError` when `authorize` call is expected in controller action but missing
|
|
123
|
-
- Update Rspec matchers for Rspec 3
|
|
190
|
+
- Customizable error messages: `#query`, `#record` and `#policy` methods on `Pundit::NotAuthorizedError` [#114](https://github.com/varvet/pundit/issues/114)
|
|
191
|
+
- Raise a different `Pundit::AuthorizationNotPerformedError` when `authorize` call is expected in controller action but missing [#109](https://github.com/varvet/pundit/issues/109)
|
|
192
|
+
- Update Rspec matchers for Rspec 3 [#124](https://github.com/varvet/pundit/issues/124)
|
|
124
193
|
|
|
125
194
|
## 0.2.2 (2014-02-07)
|
|
126
195
|
|
|
127
|
-
- Customize the user to be passed into policies: `pundit_user`
|
|
196
|
+
- Customize the user to be passed into policies: `pundit_user` [#42](https://github.com/varvet/pundit/issues/42)
|
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
|
|
|
@@ -23,7 +20,7 @@ Pundit version, OS version and any stack traces you have are very valuable.
|
|
|
23
20
|
- **Document any change in behaviour**. Make sure the README and any other
|
|
24
21
|
relevant documentation are kept up-to-date.
|
|
25
22
|
|
|
26
|
-
- **Create topic branches**. Please don't ask us to pull from your
|
|
23
|
+
- **Create topic branches**. Please don't ask us to pull from your main branch.
|
|
27
24
|
|
|
28
25
|
- **One pull request per feature**. If you want to do more than one thing, send
|
|
29
26
|
multiple pull requests.
|
|
@@ -31,3 +28,4 @@ Pundit version, OS version and any stack traces you have are very valuable.
|
|
|
31
28
|
- **Send coherent history**. Make sure each individual commit in your pull
|
|
32
29
|
request is meaningful. If you had to make multiple intermediate commits while
|
|
33
30
|
developing, please squash them before sending them to us.
|
|
31
|
+
- **Update the CHANGELOG.** Don't forget to add your new changes to the CHANGELOG.
|
data/README.md
CHANGED
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
# Pundit
|
|
2
2
|
|
|
3
|
-
[](
|
|
3
|
+
[](https://github.com/varvet/pundit/actions/workflows/main.yml)
|
|
4
|
+
[](https://qlty.sh/gh/varvet/projects/pundit)
|
|
5
|
+
[](https://inch-ci.org/github/varvet/pundit)
|
|
6
|
+
[](https://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
|
|
9
|
+
classes and object oriented design patterns to build a straightforward, robust, and
|
|
10
10
|
scalable authorization system.
|
|
11
11
|
|
|
12
|
-
Links:
|
|
12
|
+
## Links:
|
|
13
13
|
|
|
14
|
-
- [API documentation for the most recent version](
|
|
14
|
+
- [API documentation for the most recent version](https://www.rubydoc.info/gems/pundit)
|
|
15
15
|
- [Source Code](https://github.com/varvet/pundit)
|
|
16
|
-
- [Contributing](https://github.com/varvet/pundit/blob/
|
|
17
|
-
- [Code of Conduct](https://github.com/varvet/pundit/blob/
|
|
16
|
+
- [Contributing](https://github.com/varvet/pundit/blob/main/CONTRIBUTING.md)
|
|
17
|
+
- [Code of Conduct](https://github.com/varvet/pundit/blob/main/CODE_OF_CONDUCT.md)
|
|
18
18
|
|
|
19
|
-
Sponsored by
|
|
20
|
-
|
|
21
|
-
[<img src="https://www.varvet.com/images/wordmark-red.svg" alt="Varvet" height="50px"/>](https://www.varvet.com)
|
|
19
|
+
<strong>Sponsored by:</strong> <a href="https://www.varvet.com">Varvet<br><br><img src="https://github.com/varvet/pundit/assets/99166/aa9efa0a-6903-4037-abee-1824edc57f1a" alt="Varvet logo" height="120"></div>
|
|
22
20
|
|
|
23
21
|
## Installation
|
|
24
22
|
|
|
25
23
|
> **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
24
|
|
|
27
|
-
```
|
|
28
|
-
|
|
25
|
+
``` sh
|
|
26
|
+
bundle add pundit
|
|
29
27
|
```
|
|
30
28
|
|
|
31
29
|
Include `Pundit::Authorization` in your application controller:
|
|
@@ -49,8 +47,8 @@ can pick up any classes in the new `app/policies/` directory.
|
|
|
49
47
|
## Policies
|
|
50
48
|
|
|
51
49
|
Pundit is focused around the notion of policy classes. We suggest that you put
|
|
52
|
-
these classes in `app/policies`. This is
|
|
53
|
-
|
|
50
|
+
these classes in `app/policies`. This is an example that allows updating a post
|
|
51
|
+
if the user is an admin, or if the post is unpublished:
|
|
54
52
|
|
|
55
53
|
``` ruby
|
|
56
54
|
class PostPolicy
|
|
@@ -67,7 +65,7 @@ class PostPolicy
|
|
|
67
65
|
end
|
|
68
66
|
```
|
|
69
67
|
|
|
70
|
-
As you can see, this is
|
|
68
|
+
As you can see, this is a plain Ruby class. Pundit makes the following
|
|
71
69
|
assumptions about this class:
|
|
72
70
|
|
|
73
71
|
- The class has the same name as some kind of model class, only suffixed
|
|
@@ -118,7 +116,7 @@ and the given record. It then infers from the action name, that it should call
|
|
|
118
116
|
|
|
119
117
|
``` ruby
|
|
120
118
|
unless PostPolicy.new(current_user, @post).update?
|
|
121
|
-
raise Pundit::NotAuthorizedError, "not allowed to update? this
|
|
119
|
+
raise Pundit::NotAuthorizedError, "not allowed to PostPolicy#update? this Post"
|
|
122
120
|
end
|
|
123
121
|
```
|
|
124
122
|
|
|
@@ -199,7 +197,7 @@ you can retrieve it by passing a symbol.
|
|
|
199
197
|
class DashboardPolicy
|
|
200
198
|
attr_reader :user
|
|
201
199
|
|
|
202
|
-
# _record in this example will
|
|
200
|
+
# `_record` in this example will be :dashboard
|
|
203
201
|
def initialize(user, _record)
|
|
204
202
|
@user = user
|
|
205
203
|
end
|
|
@@ -211,7 +209,7 @@ end
|
|
|
211
209
|
```
|
|
212
210
|
|
|
213
211
|
Note that the headless policy still needs to accept two arguments. The
|
|
214
|
-
second argument will
|
|
212
|
+
second argument will be the symbol `:dashboard` in this case, which
|
|
215
213
|
is what is passed as the record to `authorize` below.
|
|
216
214
|
|
|
217
215
|
```ruby
|
|
@@ -279,7 +277,7 @@ generator, or create your own base class to inherit from:
|
|
|
279
277
|
|
|
280
278
|
``` ruby
|
|
281
279
|
class PostPolicy < ApplicationPolicy
|
|
282
|
-
class Scope < Scope
|
|
280
|
+
class Scope < ApplicationPolicy::Scope
|
|
283
281
|
def resolve
|
|
284
282
|
if user.admin?
|
|
285
283
|
scope.all
|
|
@@ -362,8 +360,15 @@ authorize individual instances.
|
|
|
362
360
|
``` ruby
|
|
363
361
|
class ApplicationController < ActionController::Base
|
|
364
362
|
include Pundit::Authorization
|
|
365
|
-
after_action :
|
|
366
|
-
|
|
363
|
+
after_action :verify_pundit_authorization
|
|
364
|
+
|
|
365
|
+
def verify_pundit_authorization
|
|
366
|
+
if action_name == "index"
|
|
367
|
+
verify_policy_scoped
|
|
368
|
+
else
|
|
369
|
+
verify_authorized
|
|
370
|
+
end
|
|
371
|
+
end
|
|
367
372
|
end
|
|
368
373
|
```
|
|
369
374
|
|
|
@@ -374,7 +379,7 @@ these filters without affecting how your app works in any way.**
|
|
|
374
379
|
|
|
375
380
|
Some people have found this feature confusing, while many others
|
|
376
381
|
find it extremely helpful. If you fall into the category of people who find it
|
|
377
|
-
confusing then you do not need to use it. Pundit will work
|
|
382
|
+
confusing then you do not need to use it. Pundit will work fine without
|
|
378
383
|
using `verify_authorized` and `verify_policy_scoped`.
|
|
379
384
|
|
|
380
385
|
### Conditional verification
|
|
@@ -419,20 +424,13 @@ class Post
|
|
|
419
424
|
end
|
|
420
425
|
```
|
|
421
426
|
|
|
422
|
-
##
|
|
427
|
+
## Plain old Ruby
|
|
423
428
|
|
|
424
|
-
|
|
425
|
-
yourself. It's a very small library, it just provides a few neat helpers.
|
|
426
|
-
Together these give you the power of building a well structured, fully working
|
|
427
|
-
authorization system without using any special DSLs or funky syntax or
|
|
428
|
-
anything.
|
|
429
|
+
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.
|
|
429
430
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
Encapsulate a set of permissions into a module and include them in multiple
|
|
433
|
-
policies. Use `alias_method` to make some permissions behave the same as
|
|
434
|
-
others. Inherit from a base set of permissions. Use metaprogramming if you
|
|
435
|
-
really have to.
|
|
431
|
+
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.
|
|
432
|
+
|
|
433
|
+
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.
|
|
436
434
|
|
|
437
435
|
## Generator
|
|
438
436
|
|
|
@@ -483,7 +481,7 @@ example, associations which might be `nil`.
|
|
|
483
481
|
|
|
484
482
|
```ruby
|
|
485
483
|
class NilClassPolicy < ApplicationPolicy
|
|
486
|
-
class Scope < Scope
|
|
484
|
+
class Scope < ApplicationPolicy::Scope
|
|
487
485
|
def resolve
|
|
488
486
|
raise Pundit::NotDefinedError, "Cannot scope NilClass"
|
|
489
487
|
end
|
|
@@ -498,7 +496,7 @@ end
|
|
|
498
496
|
## Rescuing a denied Authorization in Rails
|
|
499
497
|
|
|
500
498
|
Pundit raises a `Pundit::NotAuthorizedError` you can
|
|
501
|
-
[rescue_from](
|
|
499
|
+
[rescue_from](https://guides.rubyonrails.org/action_controller_overview.html#rescue-from)
|
|
502
500
|
in your `ApplicationController`. You can customize the `user_not_authorized`
|
|
503
501
|
method in every controller.
|
|
504
502
|
|
|
@@ -512,7 +510,7 @@ class ApplicationController < ActionController::Base
|
|
|
512
510
|
|
|
513
511
|
def user_not_authorized
|
|
514
512
|
flash[:alert] = "You are not authorized to perform this action."
|
|
515
|
-
|
|
513
|
+
redirect_back_or_to(root_path)
|
|
516
514
|
end
|
|
517
515
|
end
|
|
518
516
|
```
|
|
@@ -541,7 +539,7 @@ class ApplicationController < ActionController::Base
|
|
|
541
539
|
policy_name = exception.policy.class.to_s.underscore
|
|
542
540
|
|
|
543
541
|
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
|
|
544
|
-
|
|
542
|
+
redirect_back_or_to(root_path)
|
|
545
543
|
end
|
|
546
544
|
end
|
|
547
545
|
```
|
|
@@ -555,8 +553,7 @@ en:
|
|
|
555
553
|
create?: 'You cannot create posts!'
|
|
556
554
|
```
|
|
557
555
|
|
|
558
|
-
|
|
559
|
-
your error messaging.
|
|
556
|
+
This is an example. Pundit is agnostic as to how you implement your error messaging.
|
|
560
557
|
|
|
561
558
|
## Manually retrieving policies and scopes
|
|
562
559
|
|
|
@@ -578,9 +575,7 @@ those without the bang will return nil.
|
|
|
578
575
|
|
|
579
576
|
## Customize Pundit user
|
|
580
577
|
|
|
581
|
-
|
|
582
|
-
`current_user` is not the method that should be invoked by Pundit. Simply
|
|
583
|
-
define a method in your controller called `pundit_user`.
|
|
578
|
+
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`.
|
|
584
579
|
|
|
585
580
|
```ruby
|
|
586
581
|
def pundit_user
|
|
@@ -588,6 +583,36 @@ def pundit_user
|
|
|
588
583
|
end
|
|
589
584
|
```
|
|
590
585
|
|
|
586
|
+
For instance, Rails 8 includes a built-in [authentication generator](https://github.com/rails/rails/tree/8-0-stable/railties/lib/rails/generators/rails/authentication). If you choose to use it, the currently logged-in user is accessed via `Current.user` instead of `current_user`.
|
|
587
|
+
|
|
588
|
+
To ensure compatibility with Pundit, define a `pundit_user` method in `application_controller.rb` (or another suitable location) as follows:
|
|
589
|
+
|
|
590
|
+
```ruby
|
|
591
|
+
def pundit_user
|
|
592
|
+
Current.user
|
|
593
|
+
end
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Handling User Switching in Pundit
|
|
597
|
+
|
|
598
|
+
When switching users in your application, it's important to reset the Pundit user context to ensure that authorization policies are applied correctly for the new user. Pundit caches the user context, so failing to reset it could result in incorrect permissions being applied.
|
|
599
|
+
|
|
600
|
+
To handle user switching, you can use the following pattern in your controller:
|
|
601
|
+
|
|
602
|
+
```ruby
|
|
603
|
+
class ApplicationController
|
|
604
|
+
include Pundit::Authorization
|
|
605
|
+
|
|
606
|
+
def switch_user_to(user)
|
|
607
|
+
terminate_session if authenticated?
|
|
608
|
+
start_new_session_for user
|
|
609
|
+
pundit_reset!
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
Make sure to invoke `pundit_reset!` whenever changing the user. This ensures the cached authorization context is reset, preventing any incorrect permissions from being applied.
|
|
615
|
+
|
|
591
616
|
## Policy Namespacing
|
|
592
617
|
In some cases it might be helpful to have multiple policies that serve different contexts for a
|
|
593
618
|
resource. A prime example of this is the case where User policies differ from Admin policies. To
|
|
@@ -692,7 +717,7 @@ You can now retrieve these attributes from the policy:
|
|
|
692
717
|
class PostsController < ApplicationController
|
|
693
718
|
def update
|
|
694
719
|
@post = Post.find(params[:id])
|
|
695
|
-
if @post.
|
|
720
|
+
if @post.update(post_params)
|
|
696
721
|
redirect_to @post
|
|
697
722
|
else
|
|
698
723
|
render :edit
|
|
@@ -714,7 +739,7 @@ However, this is a bit cumbersome, so Pundit provides a convenient helper method
|
|
|
714
739
|
class PostsController < ApplicationController
|
|
715
740
|
def update
|
|
716
741
|
@post = Post.find(params[:id])
|
|
717
|
-
if @post.
|
|
742
|
+
if @post.update(permitted_attributes(@post))
|
|
718
743
|
redirect_to @post
|
|
719
744
|
else
|
|
720
745
|
render :edit
|
|
@@ -766,6 +791,10 @@ end
|
|
|
766
791
|
|
|
767
792
|
### Policy Specs
|
|
768
793
|
|
|
794
|
+
> [!TIP]
|
|
795
|
+
> An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this
|
|
796
|
+
[excellent post](https://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.
|
|
797
|
+
|
|
769
798
|
Pundit includes a mini-DSL for writing expressive tests for your policies in RSpec.
|
|
770
799
|
Require `pundit/rspec` in your `spec_helper.rb`:
|
|
771
800
|
|
|
@@ -795,25 +824,67 @@ describe PostPolicy do
|
|
|
795
824
|
end
|
|
796
825
|
```
|
|
797
826
|
|
|
798
|
-
|
|
799
|
-
|
|
827
|
+
### Custom matcher description
|
|
828
|
+
|
|
829
|
+
By default rspec includes an inspected `user` and `record` in the matcher description, which might become overly verbose:
|
|
830
|
+
|
|
831
|
+
```
|
|
832
|
+
PostPolicy
|
|
833
|
+
update? and show?
|
|
834
|
+
is expected to permit #<User:0x0000000104aefd80> and #<Post:0x0000000104aef8d0 @user=#<User:0x0000000104aefd80>>
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
You can override the default description with a static string, or a block:
|
|
838
|
+
|
|
839
|
+
```ruby
|
|
840
|
+
# static alternative: Pundit::RSpec::Matchers.description = "permit the user"
|
|
841
|
+
Pundit::RSpec::Matchers.description = ->(user, record) do
|
|
842
|
+
"permit user with role #{user.role} to access record with ID #{record.id}"
|
|
843
|
+
end
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
Which would make for a less chatty output:
|
|
847
|
+
|
|
848
|
+
```
|
|
849
|
+
PostPolicy
|
|
850
|
+
update? and show?
|
|
851
|
+
is expected to permit user with role admin to access record with ID 130
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Focus Support
|
|
855
|
+
|
|
856
|
+
If your RSpec config has `filter_run_when_matching :focus`, you may tag the `permissions` helper like so:
|
|
857
|
+
|
|
858
|
+
```
|
|
859
|
+
permissions :show?, :focus do
|
|
860
|
+
```
|
|
800
861
|
|
|
801
862
|
### Scope Specs
|
|
802
863
|
|
|
803
|
-
Pundit does not provide a DSL for testing scopes.
|
|
864
|
+
Pundit does not provide a DSL for testing scopes. Test them like you would a regular Ruby class!
|
|
865
|
+
|
|
866
|
+
### Linting with RuboCop RSpec
|
|
867
|
+
|
|
868
|
+
When you lint your RSpec spec files with `rubocop-rspec`, it will fail to properly detect RSpec constructs that Pundit defines, `permissions`.
|
|
869
|
+
Make sure to use `rubocop-rspec` 2.0 or newer and add the following to your `.rubocop.yml`:
|
|
870
|
+
|
|
871
|
+
```yaml
|
|
872
|
+
inherit_gem:
|
|
873
|
+
pundit: config/rubocop-rspec.yml
|
|
874
|
+
```
|
|
804
875
|
|
|
805
876
|
# External Resources
|
|
806
877
|
|
|
807
878
|
- [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
|
|
808
|
-
- [Migrating to Pundit from CanCan](
|
|
809
|
-
- [Testing Pundit Policies with RSpec](
|
|
879
|
+
- [Migrating to Pundit from CanCan](https://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
|
|
880
|
+
- [Testing Pundit Policies with RSpec](https://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
|
|
810
881
|
- [Testing Pundit with Minitest](https://github.com/varvet/pundit/issues/204#issuecomment-60166450)
|
|
811
882
|
- [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
|
|
812
|
-
- [Straightforward Rails Authorization with Pundit](
|
|
883
|
+
- [Straightforward Rails Authorization with Pundit](https://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
|
|
813
884
|
|
|
814
885
|
## Other implementations
|
|
815
886
|
|
|
816
|
-
- [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](
|
|
887
|
+
- [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](https://flask.pocoo.org/) extension "heavily inspired by" Pundit
|
|
817
888
|
|
|
818
889
|
# License
|
|
819
890
|
|
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,12 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Pundit
|
|
4
|
+
# @private
|
|
4
5
|
module Generators
|
|
6
|
+
# @private
|
|
5
7
|
class InstallGenerator < ::Rails::Generators::Base
|
|
6
8
|
source_root File.expand_path("templates", __dir__)
|
|
7
9
|
|
|
8
10
|
def copy_application_policy
|
|
9
|
-
template "application_policy.rb", "app/policies/application_policy.rb"
|
|
11
|
+
template "application_policy.rb.tt", "app/policies/application_policy.rb"
|
|
10
12
|
end
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Pundit
|
|
4
|
+
# @private
|
|
4
5
|
module Generators
|
|
6
|
+
# @private
|
|
5
7
|
class PolicyGenerator < ::Rails::Generators::NamedBase
|
|
6
8
|
source_root File.expand_path("templates", __dir__)
|
|
7
9
|
|
|
8
10
|
def create_policy
|
|
9
|
-
template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
|
|
11
|
+
template "policy.rb.tt", File.join("app/policies", class_path, "#{file_name}_policy.rb")
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
hook_for :test_framework
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
class <%= class_name %>Policy < ApplicationPolicy
|
|
3
|
+
# NOTE: Up to Pundit v2.3.1, the inheritance was declared as
|
|
4
|
+
# `Scope < Scope` rather than `Scope < ApplicationPolicy::Scope`.
|
|
5
|
+
# In most cases the behavior will be identical, but if updating existing
|
|
6
|
+
# code, beware of possible changes to the ancestors:
|
|
7
|
+
# https://gist.github.com/Burgestrand/4b4bc22f31c8a95c425fc0e30d7ef1f5
|
|
8
|
+
|
|
9
|
+
class Scope < ApplicationPolicy::Scope
|
|
10
|
+
# NOTE: Be explicit about which records you allow access to!
|
|
11
|
+
# def resolve
|
|
12
|
+
# scope.all
|
|
13
|
+
# end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
<% end -%>
|