pundit 2.4.0 → 2.5.1

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -42
  3. data/README.md +31 -1
  4. data/lib/generators/pundit/install/install_generator.rb +3 -1
  5. data/lib/generators/pundit/policy/policy_generator.rb +3 -1
  6. data/lib/generators/rspec/policy_generator.rb +4 -1
  7. data/lib/generators/test_unit/policy_generator.rb +4 -1
  8. data/lib/pundit/authorization.rb +170 -77
  9. data/lib/pundit/cache_store/legacy_store.rb +10 -0
  10. data/lib/pundit/cache_store/null_store.rb +12 -0
  11. data/lib/pundit/cache_store.rb +24 -0
  12. data/lib/pundit/context.rb +89 -26
  13. data/lib/pundit/error.rb +71 -0
  14. data/lib/pundit/helper.rb +16 -0
  15. data/lib/pundit/policy_finder.rb +33 -1
  16. data/lib/pundit/railtie.rb +20 -0
  17. data/lib/pundit/rspec.rb +69 -6
  18. data/lib/pundit/version.rb +2 -1
  19. data/lib/pundit.rb +27 -61
  20. metadata +19 -179
  21. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -20
  22. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  23. data/.github/PULL_REQUEST_TEMPLATE/gem_release_template.md +0 -8
  24. data/.github/pull_request_template.md +0 -9
  25. data/.github/workflows/main.yml +0 -112
  26. data/.github/workflows/push_gem.yml +0 -33
  27. data/.gitignore +0 -19
  28. data/.rubocop.yml +0 -63
  29. data/.yardopts +0 -1
  30. data/CODE_OF_CONDUCT.md +0 -28
  31. data/CONTRIBUTING.md +0 -31
  32. data/Gemfile +0 -8
  33. data/Rakefile +0 -20
  34. data/config/rubocop-rspec.yml +0 -5
  35. data/pundit.gemspec +0 -35
  36. data/spec/authorization_spec.rb +0 -274
  37. data/spec/dsl_spec.rb +0 -30
  38. data/spec/generators_spec.rb +0 -43
  39. data/spec/policies/post_policy_spec.rb +0 -49
  40. data/spec/policy_finder_spec.rb +0 -187
  41. data/spec/pundit_spec.rb +0 -448
  42. data/spec/spec_helper.rb +0 -352
  43. /data/lib/generators/pundit/install/templates/{application_policy.rb → application_policy.rb.tt} +0 -0
  44. /data/lib/generators/pundit/policy/templates/{policy.rb → policy.rb.tt} +0 -0
  45. /data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
  46. /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: 1cc7a931867875af2c1a7cd5c4225da689b33e101f76bb7a471afb967323e615
4
- data.tar.gz: 8ca35ba01f65b52b1b8bbb2061858bdc61cd0034b01818b07dbbba4b7ddd3a69
3
+ metadata.gz: 5c6f7c834aabbea0d1c74b4101d67a936f0c062db2c5a67dcb45c824d0a1f80e
4
+ data.tar.gz: 651d652baa3a1f511e794b80f4e514b5e2bb74f75abeaa184dff48dae63e27bf
5
5
  SHA512:
6
- metadata.gz: 0f495747f61c744c04dffa7811d3a86fc818812807a971591d71542d798d5a7aa4438333534082e755bbead592b4b1b5465e23030e535b03420c643e088bcaf1
7
- data.tar.gz: 951ec8a8c02c081bc6b412bb0b5d1d6ffcc33543fa71f66fef9c4f4a6f391ea53a057e20b94bdef5faf4c8f2ef0deffd09357c9580ef6a739575c94a70d9d950
6
+ metadata.gz: e4081cc21e4827985808334e5753a6b6f812743308cc251f8e4923b0b3a73c41b64bb6da64da57919ac62672537e3d464b187f0d28811a0aaab9c17ea9354ec5
7
+ data.tar.gz: a7868288d12d4f63cc95b5d18f54bfdafbcf586c7f415a713713f1f520140c2f7c353572cdab770baf16f5525ec4fc369679fd5e640233360b743f34d66580d9
data/CHANGELOG.md CHANGED
@@ -2,43 +2,67 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.5.1 (2025-09-12)
6
+
7
+ ### Fixed
8
+ - Requiring only `pundit/rspec` no longer raises an error in Active Support [#857](https://github.com/varvet/pundit/issues/857)
9
+
10
+ ## 2.5.0 (2025-03-03)
11
+
12
+ ### Added
13
+
14
+ - Add `Pundit::Authorization#pundit_reset!` hook to reset the policy and policy scope cache. [#830](https://github.com/varvet/pundit/issues/830)
15
+ - Add links to gemspec. [#845](https://github.com/varvet/pundit/issues/845)
16
+ - Register policies directories for Rails 8 code statistics [#833](https://github.com/varvet/pundit/issues/833)
17
+ - Added an example for how to use pundit with Rails 8 authentication generator [#850](https://github.com/varvet/pundit/issues/850)
18
+
19
+ ### Changed
20
+
21
+ - Deprecated `Pundit::SUFFIX`, moved it to `Pundit::PolicyFinder::SUFFIX` [#835](https://github.com/varvet/pundit/issues/835)
22
+ - Explicitly require less of `active_support` [#837](https://github.com/varvet/pundit/issues/837)
23
+ - Using `permit` matcher without a surrouding `permissions` block now raises a useful error. [#836](https://github.com/varvet/pundit/issues/836)
24
+
25
+ ### Fixed
26
+
27
+ - Using a hash as custom cache in `Pundit.authorize` now works as documented. [#838](https://github.com/varvet/pundit/issues/838)
28
+
5
29
  ## 2.4.0 (2024-08-26)
6
30
 
7
- ## Changed
31
+ ### Changed
8
32
 
9
33
  - Improve the `NotAuthorizedError` message to include the policy class.
10
- Furthermore, in the case where the record passed is a class instead of an instance, the class name is given. (#812)
34
+ 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)
11
35
 
12
- ## Added
36
+ ### Added
13
37
 
14
- - Add customizable permit matcher description (#806)
15
- - Add support for filter_run_when_matching :focus with permissions helper. (#820)
38
+ - Add customizable permit matcher description [#806](https://github.com/varvet/pundit/issues/806)
39
+ - Add support for filter_run_when_matching :focus with permissions helper. [#820](https://github.com/varvet/pundit/issues/820)
16
40
 
17
41
  ## 2.3.2 (2024-05-08)
18
42
 
19
- - Refactor: First pass of Pundit::Context (#797)
43
+ - Refactor: First pass of Pundit::Context [#797](https://github.com/varvet/pundit/issues/797)
20
44
 
21
- ## Changed
45
+ ### Changed
22
46
 
23
- - Update `ApplicationPolicy` generator to qualify the `Scope` class name (#792)
24
- - Policy generator uses `NoMethodError` to indicate `#resolve` is not implemented (#776)
47
+ - Update `ApplicationPolicy` generator to qualify the `Scope` class name [#792](https://github.com/varvet/pundit/issues/792)
48
+ - Policy generator uses `NoMethodError` to indicate `#resolve` is not implemented [#776](https://github.com/varvet/pundit/issues/776)
25
49
 
26
50
  ## Deprecated
27
51
 
28
- - Dropped support for Ruby 3.0 (#796)
52
+ - Dropped support for Ruby 3.0 [#796](https://github.com/varvet/pundit/issues/796)
29
53
 
30
54
  ## 2.3.1 (2023-07-17)
31
55
 
32
56
  ### Fixed
33
57
 
34
- - Use `Kernel.warn` instead of `ActiveSupport::Deprecation.warn` for deprecations (#764)
35
- - Policy generator now works on Ruby 3.2 (#754)
58
+ - Use `Kernel.warn` instead of `ActiveSupport::Deprecation.warn` for deprecations [#764](https://github.com/varvet/pundit/issues/764)
59
+ - Policy generator now works on Ruby 3.2 [#754](https://github.com/varvet/pundit/issues/754)
36
60
 
37
61
  ## 2.3.0 (2022-12-19)
38
62
 
39
63
  ### Added
40
64
 
41
- - add support for rubocop-rspec syntax extensions (#745)
65
+ - add support for rubocop-rspec syntax extensions [#745](https://github.com/varvet/pundit/issues/745)
42
66
 
43
67
  ## 2.2.0 (2022-02-11)
44
68
 
@@ -52,41 +76,41 @@
52
76
 
53
77
  ### Deprecated
54
78
 
55
- - Deprecate `include Pundit` in favor of `include Pundit::Authorization` (#621)
79
+ - Deprecate `include Pundit` in favor of `include Pundit::Authorization` [#621](https://github.com/varvet/pundit/issues/621)
56
80
 
57
81
  ## 2.1.1 (2021-08-13)
58
82
 
59
83
  Friday 13th-release!
60
84
 
61
- Careful! The bugfix below (#626) could break existing code. If you rely on the
85
+ Careful! The bugfix below [#626](https://github.com/varvet/pundit/issues/626) could break existing code. If you rely on the
62
86
  return value for `authorize` and namespaced policies you might need to do some
63
87
  changes.
64
88
 
65
89
  ### Fixed
66
90
 
67
91
  - `.authorize` and `#authorize` return the instance, even for namespaced
68
- policies (#626)
92
+ policies [#626](https://github.com/varvet/pundit/issues/626)
69
93
 
70
94
  ### Changed
71
95
 
72
- - Generate application scope with `protected` attr_readers. (#616)
96
+ - Generate application scope with `protected` attr_readers. [#616](https://github.com/varvet/pundit/issues/616)
73
97
 
74
98
  ### Removed
75
99
 
76
- - Dropped support for Ruby end-of-life versions: 2.1 and 2.2. (#604)
77
- - Dropped support for Ruby end-of-life versions: 2.3 (#633)
78
- - Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
79
- - Dropped support for RSpec 2 (#615)
100
+ - Dropped support for Ruby end-of-life versions: 2.1 and 2.2. [#604](https://github.com/varvet/pundit/issues/604)
101
+ - Dropped support for Ruby end-of-life versions: 2.3 [#633](https://github.com/varvet/pundit/issues/633)
102
+ - Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 [#676](https://github.com/varvet/pundit/issues/676)
103
+ - Dropped support for RSpec 2 [#615](https://github.com/varvet/pundit/issues/615)
80
104
 
81
105
  ## 2.1.0 (2019-08-14)
82
106
 
83
107
  ### Fixed
84
108
 
85
- - Avoid name clashes with the Error class. (#590)
109
+ - Avoid name clashes with the Error class. [#590](https://github.com/varvet/pundit/issues/590)
86
110
 
87
111
  ### Changed
88
112
 
89
- - Return a safer default NotAuthorizedError message. (#583)
113
+ - Return a safer default NotAuthorizedError message. [#583](https://github.com/varvet/pundit/issues/583)
90
114
 
91
115
  ## 2.0.1 (2019-01-18)
92
116
 
@@ -96,8 +120,8 @@ None
96
120
 
97
121
  ### Other changes
98
122
 
99
- - Improve exception handling for `#policy_scope` and `#policy_scope!`. (#550)
100
- - Add `:policy` metadata to RSpec template. (#566)
123
+ - Improve exception handling for `#policy_scope` and `#policy_scope!`. [#550](https://github.com/varvet/pundit/issues/550)
124
+ - Add `:policy` metadata to RSpec template. [#566](https://github.com/varvet/pundit/issues/566)
101
125
 
102
126
  ## 2.0.0 (2018-07-21)
103
127
 
@@ -107,20 +131,20 @@ No changes since beta1
107
131
 
108
132
  ### Breaking changes
109
133
 
110
- - Only pass last element of "namespace array" to policy and scope. (#529)
111
- - Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. (#462)
112
- - Return passed object from `#authorize` method to make chaining possible. (#385)
134
+ - Only pass last element of "namespace array" to policy and scope. [#529](https://github.com/varvet/pundit/issues/529)
135
+ - Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. [#462](https://github.com/varvet/pundit/issues/462)
136
+ - Return passed object from `#authorize` method to make chaining possible. [#385](https://github.com/varvet/pundit/issues/385)
113
137
 
114
138
  ### Other changes
115
139
 
116
- - Add `policy_class` option to `authorize` to be able to override the policy. (#441)
117
- - Add `policy_scope_class` option to `authorize` to be able to override the policy scope. (#441)
118
- - Fix `param_key` issue when passed an array. (#529)
119
- - Allow specification of a `NilClassPolicy`. (#525)
120
- - Make sure `policy_class` override is called when passed an array. (#475)
140
+ - Add `policy_class` option to `authorize` to be able to override the policy. [#441](https://github.com/varvet/pundit/issues/441)
141
+ - Add `policy_scope_class` option to `authorize` to be able to override the policy scope. [#441](https://github.com/varvet/pundit/issues/441)
142
+ - Fix `param_key` issue when passed an array. [#529](https://github.com/varvet/pundit/issues/529)
143
+ - Allow specification of a `NilClassPolicy`. [#525](https://github.com/varvet/pundit/issues/525)
144
+ - Make sure `policy_class` override is called when passed an array. [#475](https://github.com/varvet/pundit/issues/475)
121
145
 
122
- - Use `action_name` instead of `params[:action]`. (#419)
123
- - Add `pundit_params_for` method to make it easy to customize params fetching. (#502)
146
+ - Use `action_name` instead of `params[:action]`. [#419](https://github.com/varvet/pundit/issues/419)
147
+ - Add `pundit_params_for` method to make it easy to customize params fetching. [#502](https://github.com/varvet/pundit/issues/502)
124
148
 
125
149
  ## 1.1.0 (2016-01-14)
126
150
 
@@ -152,16 +176,16 @@ No changes since beta1
152
176
 
153
177
  ## 0.3.0 (2014-08-22)
154
178
 
155
- - Extend the default `ApplicationPolicy` with an `ApplicationPolicy::Scope` (#120)
156
- - Fix RSpec 3 deprecation warnings for built-in matchers (#162)
157
- - Generate blank policy spec/test files for Rspec/MiniTest/Test::Unit in Rails (#138)
179
+ - Extend the default `ApplicationPolicy` with an `ApplicationPolicy::Scope` [#120](https://github.com/varvet/pundit/issues/120)
180
+ - Fix RSpec 3 deprecation warnings for built-in matchers [#162](https://github.com/varvet/pundit/issues/162)
181
+ - Generate blank policy spec/test files for Rspec/MiniTest/Test::Unit in Rails [#138](https://github.com/varvet/pundit/issues/138)
158
182
 
159
183
  ## 0.2.3 (2014-04-06)
160
184
 
161
- - Customizable error messages: `#query`, `#record` and `#policy` methods on `Pundit::NotAuthorizedError` (#114)
162
- - Raise a different `Pundit::AuthorizationNotPerformedError` when `authorize` call is expected in controller action but missing (#109)
163
- - Update Rspec matchers for Rspec 3 (#124)
185
+ - Customizable error messages: `#query`, `#record` and `#policy` methods on `Pundit::NotAuthorizedError` [#114](https://github.com/varvet/pundit/issues/114)
186
+ - Raise a different `Pundit::AuthorizationNotPerformedError` when `authorize` call is expected in controller action but missing [#109](https://github.com/varvet/pundit/issues/109)
187
+ - Update Rspec matchers for Rspec 3 [#124](https://github.com/varvet/pundit/issues/124)
164
188
 
165
189
  ## 0.2.2 (2014-02-07)
166
190
 
167
- - Customize the user to be passed into policies: `pundit_user` (#42)
191
+ - Customize the user to be passed into policies: `pundit_user` [#42](https://github.com/varvet/pundit/issues/42)
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Pundit
2
2
 
3
3
  [![Main](https://github.com/varvet/pundit/actions/workflows/main.yml/badge.svg)](https://github.com/varvet/pundit/actions/workflows/main.yml)
4
- [![Code Climate](https://api.codeclimate.com/v1/badges/a940030f96c9fb43046a/maintainability)](https://codeclimate.com/github/varvet/pundit/maintainability)
4
+ [![Maintainability](https://qlty.sh/gh/varvet/projects/pundit/maintainability.svg)](https://qlty.sh/gh/varvet/projects/pundit)
5
5
  [![Inline docs](https://inch-ci.org/github/varvet/pundit.svg?branch=main)](https://inch-ci.org/github/varvet/pundit)
6
6
  [![Gem Version](https://badge.fury.io/rb/pundit.svg)](https://badge.fury.io/rb/pundit)
7
7
 
@@ -583,6 +583,36 @@ def pundit_user
583
583
  end
584
584
  ```
585
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
+
586
616
  ## Policy Namespacing
587
617
  In some cases it might be helpful to have multiple policies that serve different contexts for a
588
618
  resource. A prime example of this is the case where User policies differ from Admin policies. To
@@ -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
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @private
3
4
  module Rspec
5
+ # @private
4
6
  module Generators
7
+ # @private
5
8
  class PolicyGenerator < ::Rails::Generators::NamedBase
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  def create_policy_spec
9
- template "policy_spec.rb", File.join("spec/policies", class_path, "#{file_name}_policy_spec.rb")
12
+ template "policy_spec.rb.tt", File.join("spec/policies", class_path, "#{file_name}_policy_spec.rb")
10
13
  end
11
14
  end
12
15
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @private
3
4
  module TestUnit
5
+ # @private
4
6
  module Generators
7
+ # @private
5
8
  class PolicyGenerator < ::Rails::Generators::NamedBase
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  def create_policy_test
9
- template "policy_test.rb", File.join("test/policies", class_path, "#{file_name}_policy_test.rb")
12
+ template "policy_test.rb.tt", File.join("test/policies", class_path, "#{file_name}_policy_test.rb")
10
13
  end
11
14
  end
12
15
  end
@@ -1,6 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pundit
4
+ # Pundit DSL to include in your controllers to provide authorization helpers.
5
+ #
6
+ # @example
7
+ # class ApplicationController < ActionController::Base
8
+ # include Pundit::Authorization
9
+ # end
10
+ # @see #pundit
11
+ # @api public
12
+ # @since v2.2.0
4
13
  module Authorization
5
14
  extend ActiveSupport::Concern
6
15
 
@@ -15,7 +24,14 @@ module Pundit
15
24
 
16
25
  protected
17
26
 
18
- # @return [Pundit::Context] a new instance of {Pundit::Context} with the current user
27
+ # An instance of {Pundit::Context} initialized with the current user.
28
+ #
29
+ # @note this method is memoized and will return the same instance during the request.
30
+ # @api public
31
+ # @return [Pundit::Context]
32
+ # @see #pundit_user
33
+ # @see #policies
34
+ # @since v2.3.2
19
35
  def pundit
20
36
  @pundit ||= Pundit::Context.new(
21
37
  user: pundit_user,
@@ -23,40 +39,40 @@ module Pundit
23
39
  )
24
40
  end
25
41
 
26
- # @return [Boolean] whether authorization has been performed, i.e. whether
27
- # one {#authorize} or {#skip_authorization} has been called
28
- def pundit_policy_authorized?
29
- !!@_pundit_policy_authorized
30
- end
31
-
32
- # @return [Boolean] whether policy scoping has been performed, i.e. whether
33
- # one {#policy_scope} or {#skip_policy_scope} has been called
34
- def pundit_policy_scoped?
35
- !!@_pundit_policy_scoped
36
- end
37
-
38
- # Raises an error if authorization has not been performed, usually used as an
39
- # `after_action` filter to prevent programmer error in forgetting to call
40
- # {#authorize} or {#skip_authorization}.
42
+ # Hook method which allows customizing which user is passed to policies and
43
+ # scopes initialized by {#authorize}, {#policy} and {#policy_scope}.
41
44
  #
42
- # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
43
- # @raise [AuthorizationNotPerformedError] if authorization has not been performed
44
- # @return [void]
45
- def verify_authorized
46
- raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?
45
+ # @note Make sure to call `pundit_reset!` if this changes during a request.
46
+ # @see https://github.com/varvet/pundit#customize-pundit-user
47
+ # @see #pundit
48
+ # @see #pundit_reset!
49
+ # @return [Object] the user object to be used with pundit
50
+ # @since v0.2.2
51
+ def pundit_user
52
+ current_user
47
53
  end
48
54
 
49
- # Raises an error if policy scoping has not been performed, usually used as an
50
- # `after_action` filter to prevent programmer error in forgetting to call
51
- # {#policy_scope} or {#skip_policy_scope} in index actions.
55
+ # Clears the cached Pundit authorization data.
56
+ #
57
+ # This method should be called when the pundit_user is changed,
58
+ # such as during user switching, to ensure that stale authorization
59
+ # data is not used. Pundit caches authorization policies and scopes
60
+ # for the pundit_user, so calling this method will reset those
61
+ # caches and ensure that the next authorization checks are performed
62
+ # with the correct context for the new pundit_user.
52
63
  #
53
- # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
54
- # @raise [AuthorizationNotPerformedError] if policy scoping has not been performed
55
64
  # @return [void]
56
- def verify_policy_scoped
57
- raise PolicyScopingNotPerformedError, self.class unless pundit_policy_scoped?
65
+ # @since v2.5.0
66
+ def pundit_reset!
67
+ @pundit = nil
68
+ @_pundit_policies = nil
69
+ @_pundit_policy_scopes = nil
70
+ @_pundit_policy_authorized = nil
71
+ @_pundit_policy_scoped = nil
58
72
  end
59
73
 
74
+ # @!group Policies
75
+
60
76
  # Retrieves the policy for the given record, initializing it with the record
61
77
  # and current user and finally throwing an error if the user is not
62
78
  # authorized to perform the given action.
@@ -66,7 +82,10 @@ module Pundit
66
82
  # If omitted then this defaults to the Rails controller action name.
67
83
  # @param policy_class [Class] the policy class we want to force use of
68
84
  # @raise [NotAuthorizedError] if the given query method returned false
69
- # @return [Object] Always returns the passed object record
85
+ # @return [record] Always returns the passed object record
86
+ # @see Pundit::Context#authorize
87
+ # @see #verify_authorized
88
+ # @since v0.1.0
70
89
  def authorize(record, query = nil, policy_class: nil)
71
90
  query ||= "#{action_name}?"
72
91
 
@@ -79,49 +98,153 @@ module Pundit
79
98
  #
80
99
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
81
100
  # @return [void]
101
+ # @see #verify_authorized
102
+ # @since v1.0.0
82
103
  def skip_authorization
83
104
  @_pundit_policy_authorized = :skipped
84
105
  end
85
106
 
86
- # Allow this action not to perform policy scoping.
107
+ # @return [Boolean] wether or not authorization has been performed
108
+ # @see #authorize
109
+ # @see #skip_authorization
110
+ # @since v1.0.0
111
+ def pundit_policy_authorized?
112
+ !!@_pundit_policy_authorized
113
+ end
114
+
115
+ # Raises an error if authorization has not been performed.
116
+ #
117
+ # Usually used as an `after_action` filter to prevent programmer error in
118
+ # forgetting to call {#authorize} or {#skip_authorization}.
87
119
  #
88
120
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
121
+ # @raise [AuthorizationNotPerformedError] if authorization has not been performed
89
122
  # @return [void]
90
- def skip_policy_scope
91
- @_pundit_policy_scoped = :skipped
123
+ # @see #authorize
124
+ # @see #skip_authorization
125
+ # @since v0.1.0
126
+ def verify_authorized
127
+ raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?
92
128
  end
93
129
 
94
- # Retrieves the policy scope for the given record.
130
+ # rubocop:disable Naming/MemoizedInstanceVariableName
131
+
132
+ # Cache of policies. You should not rely on this method.
95
133
  #
96
- # @see https://github.com/varvet/pundit#scopes
97
- # @param scope [Object] the object we're retrieving the policy scope for
98
- # @param policy_scope_class [Class] the policy scope class we want to force use of
99
- # @return [Scope{#resolve}, nil] instance of scope class which can resolve to a scope
100
- def policy_scope(scope, policy_scope_class: nil)
101
- @_pundit_policy_scoped = true
102
- policy_scope_class ? policy_scope_class.new(pundit_user, scope).resolve : pundit_policy_scope(scope)
134
+ # @api private
135
+ # @since v1.0.0
136
+ def policies
137
+ @_pundit_policies ||= {}
103
138
  end
104
139
 
140
+ # rubocop:enable Naming/MemoizedInstanceVariableName
141
+
142
+ # @!endgroup
143
+
105
144
  # Retrieves the policy for the given record.
106
145
  #
107
146
  # @see https://github.com/varvet/pundit#policies
108
147
  # @param record [Object] the object we're retrieving the policy for
109
148
  # @return [Object] instance of policy class with query methods
149
+ # @since v0.1.0
110
150
  def policy(record)
111
151
  pundit.policy!(record)
112
152
  end
113
153
 
114
- # Retrieves a set of permitted attributes from the policy by instantiating
115
- # the policy class for the given record and calling `permitted_attributes` on
116
- # it, or `permitted_attributes_for_{action}` if `action` is defined. It then infers
117
- # what key the record should have in the params hash and retrieves the
118
- # permitted attributes from the params hash under that key.
154
+ # @!group Policy Scopes
155
+
156
+ # Retrieves the policy scope for the given record.
157
+ #
158
+ # @see https://github.com/varvet/pundit#scopes
159
+ # @param scope [Object] the object we're retrieving the policy scope for
160
+ # @param policy_scope_class [#resolve] the policy scope class we want to force use of
161
+ # @return [#resolve, nil] instance of scope class which can resolve to a scope
162
+ # @since v0.1.0
163
+ def policy_scope(scope, policy_scope_class: nil)
164
+ @_pundit_policy_scoped = true
165
+ policy_scope_class ? policy_scope_class.new(pundit_user, scope).resolve : pundit_policy_scope(scope)
166
+ end
167
+
168
+ # Allow this action not to perform policy scoping.
169
+ #
170
+ # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
171
+ # @return [void]
172
+ # @see #verify_policy_scoped
173
+ # @since v1.0.0
174
+ def skip_policy_scope
175
+ @_pundit_policy_scoped = :skipped
176
+ end
177
+
178
+ # @return [Boolean] wether or not policy scoping has been performed
179
+ # @see #policy_scope
180
+ # @see #skip_policy_scope
181
+ # @since v1.0.0
182
+ def pundit_policy_scoped?
183
+ !!@_pundit_policy_scoped
184
+ end
185
+
186
+ # Raises an error if policy scoping has not been performed.
187
+ #
188
+ # Usually used as an `after_action` filter to prevent programmer error in
189
+ # forgetting to call {#policy_scope} or {#skip_policy_scope} in index
190
+ # actions.
191
+ #
192
+ # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
193
+ # @raise [AuthorizationNotPerformedError] if policy scoping has not been performed
194
+ # @return [void]
195
+ # @see #policy_scope
196
+ # @see #skip_policy_scope
197
+ # @since v0.2.1
198
+ def verify_policy_scoped
199
+ raise PolicyScopingNotPerformedError, self.class unless pundit_policy_scoped?
200
+ end
201
+
202
+ # rubocop:disable Naming/MemoizedInstanceVariableName
203
+
204
+ # Cache of policy scope. You should not rely on this method.
205
+ #
206
+ # @api private
207
+ # @since v1.0.0
208
+ def policy_scopes
209
+ @_pundit_policy_scopes ||= {}
210
+ end
211
+
212
+ # rubocop:enable Naming/MemoizedInstanceVariableName
213
+
214
+ # This was added to allow calling `policy_scope!` without flipping the
215
+ # `pundit_policy_scoped?` flag.
216
+ #
217
+ # It's used internally by `policy_scope`, as well as from the views
218
+ # when they call `policy_scope`. It works because views get their helper
219
+ # from {Pundit::Helper}.
220
+ #
221
+ # @note This also memoizes the instance with `scope` as the key.
222
+ # @see Pundit::Helper#policy_scope
223
+ # @api private
224
+ # @since v1.0.0
225
+ def pundit_policy_scope(scope)
226
+ policy_scopes[scope] ||= pundit.policy_scope!(scope)
227
+ end
228
+ private :pundit_policy_scope
229
+
230
+ # @!endgroup
231
+
232
+ # @!group Strong Parameters
233
+
234
+ # Retrieves a set of permitted attributes from the policy.
235
+ #
236
+ # Done by instantiating the policy class for the given record and calling
237
+ # `permitted_attributes` on it, or `permitted_attributes_for_{action}` if
238
+ # `action` is defined. It then infers what key the record should have in the
239
+ # params hash and retrieves the permitted attributes from the params hash
240
+ # under that key.
119
241
  #
120
242
  # @see https://github.com/varvet/pundit#strong-parameters
121
243
  # @param record [Object] the object we're retrieving permitted attributes for
122
244
  # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`).
123
245
  # If omitted then this defaults to the Rails controller action name.
124
246
  # @return [Hash{String => Object}] the permitted attributes
247
+ # @since v1.0.0
125
248
  def permitted_attributes(record, action = action_name)
126
249
  policy = policy(record)
127
250
  method_name = if policy.respond_to?("permitted_attributes_for_#{action}")
@@ -136,41 +259,11 @@ module Pundit
136
259
  #
137
260
  # @param record [Object] the object we're retrieving params for
138
261
  # @return [ActionController::Parameters] the params
262
+ # @since v2.0.0
139
263
  def pundit_params_for(record)
140
264
  params.require(PolicyFinder.new(record).param_key)
141
265
  end
142
266
 
143
- # Cache of policies. You should not rely on this method.
144
- #
145
- # @api private
146
- # rubocop:disable Naming/MemoizedInstanceVariableName
147
- def policies
148
- @_pundit_policies ||= {}
149
- end
150
- # rubocop:enable Naming/MemoizedInstanceVariableName
151
-
152
- # Cache of policy scope. You should not rely on this method.
153
- #
154
- # @api private
155
- # rubocop:disable Naming/MemoizedInstanceVariableName
156
- def policy_scopes
157
- @_pundit_policy_scopes ||= {}
158
- end
159
- # rubocop:enable Naming/MemoizedInstanceVariableName
160
-
161
- # Hook method which allows customizing which user is passed to policies and
162
- # scopes initialized by {#authorize}, {#policy} and {#policy_scope}.
163
- #
164
- # @see https://github.com/varvet/pundit#customize-pundit-user
165
- # @return [Object] the user object to be used with pundit
166
- def pundit_user
167
- current_user
168
- end
169
-
170
- private
171
-
172
- def pundit_policy_scope(scope)
173
- policy_scopes[scope] ||= pundit.policy_scope!(scope)
174
- end
267
+ # @!endgroup
175
268
  end
176
269
  end