pundit 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b973703e2b1653c804d138fb24c204807e41885a81f5b172656d032d7c2a75a
4
- data.tar.gz: 01211cab222a4c16f274e041c074b2d2a1763a4943ab26b6dba938272297a48d
3
+ metadata.gz: 82606dec60dec4ddb9086a4d1a71447bda39f9f17fd5e38025937f0fdb7b9b1a
4
+ data.tar.gz: e154a0dadc701871c49687ff843117e590011362be4cf3dfa7bc63ea4e5e698b
5
5
  SHA512:
6
- metadata.gz: 812528978ec4e8d3322af071c3ebd5b31f4123be449d3fe9bfea1e1fd2845704e0fee308d4cdd6e787636987b1d7a03527f8eae5fe5968483a1f4c5f751b40ef
7
- data.tar.gz: c433160a559102336b9a268ec1311a47e8f54e427ad8618b048634435259612a92d9b9187fefb6d7cc4a1ce5576a37f3e51b7adad1e3773d21c2bb6e9827c26f
6
+ metadata.gz: 0414e7e35eb8e2aa3bac79a75f2d8ae4e45f5cf4152150be239664f620560732990b3547aeac678b50e4b62036ab25c45170f12ca1897c6bf41938589e5ef0bd
7
+ data.tar.gz: 964d660d1f79b36b8ace58452ca0adfef4f5ea68a7436f6373ae248f33cda7f017db5d5c5fbd0efca26fb5ee88a507cf900edc8bd0d7dad89a676cb308bd7bd1
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  *.rbc
3
3
  .bundle
4
4
  .config
5
+ .coverage
5
6
  .yardoc
6
7
  Gemfile.lock
7
8
  InstalledFiles
data/.rubocop.yml CHANGED
@@ -1,10 +1,9 @@
1
1
  AllCops:
2
- DisplayCopNames: true
3
- TargetRubyVersion: 2.1
2
+ TargetRubyVersion: 2.6
4
3
  Exclude:
5
- - "gemfiles/**/*"
6
- - "vendor/**/*"
7
- - "lib/generators/**/*"
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
- Metrics/LineLength:
20
+ Layout/LineLength:
22
21
  Max: 120
23
22
 
24
23
  Metrics/AbcSize:
@@ -30,33 +29,12 @@ Metrics/CyclomaticComplexity:
30
29
  Metrics/PerceivedComplexity:
31
30
  Enabled: false
32
31
 
33
- Style/StructInheritance:
34
- Enabled: false
32
+ Gemspec/RequiredRubyVersion:
33
+ Enabled: false
35
34
 
36
- Layout/AlignParameters:
35
+ Layout/ParameterAlignment:
37
36
  EnforcedStyle: with_fixed_indentation
38
37
 
39
- Style/StringLiterals:
40
- EnforcedStyle: double_quotes
41
-
42
- Style/StringLiteralsInInterpolation:
43
- EnforcedStyle: double_quotes
44
-
45
- Layout/ClosingParenthesisIndentation:
46
- Enabled: false
47
-
48
- Style/OneLineConditional:
49
- Enabled: false
50
-
51
- Style/AndOr:
52
- Enabled: false
53
-
54
- Style/Not:
55
- Enabled: false
56
-
57
- Documentation:
58
- Enabled: false # TODO: Enable again once we have more docs
59
-
60
38
  Layout/CaseIndentation:
61
39
  EnforcedStyle: case
62
40
  SupportedStyles:
@@ -64,40 +42,31 @@ Layout/CaseIndentation:
64
42
  - end
65
43
  IndentOneStep: true
66
44
 
45
+ Layout/EndAlignment:
46
+ EnforcedStyleAlignWith: variable
47
+
67
48
  Style/PercentLiteralDelimiters:
68
49
  PreferredDelimiters:
69
50
  '%w': "[]"
70
51
  '%W': "[]"
71
52
 
72
- Layout/AccessModifierIndentation:
73
- EnforcedStyle: outdent
74
-
75
- Style/SignalException:
76
- Enabled: false
77
-
78
- Layout/IndentationWidth:
79
- Enabled: false
80
-
81
- Style/TrivialAccessors:
82
- ExactNameMatch: true
83
-
84
- Layout/EndAlignment:
85
- EnforcedStyleAlignWith: variable
86
-
87
- Layout/DefEndAlignment:
88
- Enabled: false
53
+ Style/StringLiterals:
54
+ EnforcedStyle: double_quotes
89
55
 
90
- Lint/HandleExceptions:
91
- Enabled: false
56
+ Style/StringLiteralsInInterpolation:
57
+ EnforcedStyle: double_quotes
92
58
 
93
- Style/SpecialGlobalVars:
59
+ Style/StructInheritance:
94
60
  Enabled: false
95
61
 
96
- Style/TrivialAccessors:
62
+ Style/AndOr:
97
63
  Enabled: false
98
64
 
99
- Layout/IndentHash:
65
+ Style/Not:
100
66
  Enabled: false
101
67
 
102
68
  Style/DoubleNegation:
103
69
  Enabled: false
70
+
71
+ Style/Documentation:
72
+ Enabled: false # TODO: Enable again once we have more docs
data/.travis.yml CHANGED
@@ -1,21 +1,26 @@
1
1
  language: ruby
2
- sudo: false
3
- before_install:
4
- - gem update --system
5
- - gem install bundler
2
+ dist: focal
6
3
 
7
4
  matrix:
8
5
  include:
9
- - rvm: 2.5.1
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
10
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
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: jruby-9.2.17.0
20
22
  env:
21
23
  - JRUBY_OPTS="--debug"
24
+ - rvm: truffleruby-head
25
+ allow_failures:
26
+ - rvm: truffleruby-head
data/CHANGELOG.md CHANGED
@@ -1,21 +1,86 @@
1
1
  # Pundit
2
2
 
3
+ ## 2.2.0 (2022-02-11)
4
+
5
+ ### Fixed
6
+
7
+ - Using `policy_class` and a namespaced record now passes only the record when instantiating the policy. (#697, #689, #694, #666)
8
+
9
+ ### Changed
10
+
11
+ - Require users to explicitly define Scope#resolve in generated policies (#711, #722)
12
+
13
+ ### Deprecated
14
+
15
+ - Deprecate `include Pundit` in favor of `include Pundit::Authorization` (#621)
16
+
17
+ ## 2.1.1 (2021-08-13)
18
+
19
+ Friday 13th-release!
20
+
21
+ Careful! The bugfix below (#626) could break existing code. If you rely on the
22
+ return value for `authorize` and namespaced policies you might need to do some
23
+ changes.
24
+
25
+ ### Fixed
26
+
27
+ - `.authorize` and `#authorize` return the instance, even for namespaced
28
+ policies (#626)
29
+
30
+ ### Changed
31
+
32
+ - Generate application scope with `protected` attr_readers. (#616)
33
+
34
+ ### Removed
35
+
36
+ - Dropped support for Ruby end-of-life versions: 2.1 and 2.2. (#604)
37
+ - Dropped support for Ruby end-of-life versions: 2.3 (#633)
38
+ - Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
39
+ - Dropped support for RSpec 2 (#615)
40
+
41
+ ## 2.1.0 (2019-08-14)
42
+
43
+ ### Fixed
44
+
45
+ - Avoid name clashes with the Error class. (#590)
46
+
47
+ ### Changed
48
+
49
+ - Return a safer default NotAuthorizedError message. (#583)
50
+
51
+ ## 2.0.1 (2019-01-18)
52
+
53
+ ### Breaking changes
54
+
55
+ None
56
+
57
+ ### Other changes
58
+
59
+ - Improve exception handling for `#policy_scope` and `#policy_scope!`. (#550)
60
+ - Add `:policy` metadata to RSpec template. (#566)
61
+
3
62
  ## 2.0.0 (2018-07-21)
4
63
 
5
64
  No changes since beta1
6
65
 
7
66
  ## 2.0.0.beta1 (2018-07-04)
8
67
 
68
+ ### Breaking changes
69
+
70
+ - Only pass last element of "namespace array" to policy and scope. (#529)
71
+ - Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. (#462)
72
+ - Return passed object from `#authorize` method to make chaining possible. (#385)
73
+
74
+ ### Other changes
75
+
9
76
  - Add `policy_class` option to `authorize` to be able to override the policy. (#441)
10
77
  - Add `policy_scope_class` option to `authorize` to be able to override the policy scope. (#441)
11
78
  - Fix `param_key` issue when passed an array. (#529)
12
- - Only pass last element of "namespace array" to policy and scope. (#529)
13
79
  - Allow specification of a `NilClassPolicy`. (#525)
14
80
  - Make sure `policy_class` override is called when passed an array. (#475)
15
- - Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. (#462)
81
+
16
82
  - Use `action_name` instead of `params[:action]`. (#419)
17
83
  - Add `pundit_params_for` method to make it easy to customize params fetching. (#502)
18
- - Return passed object from `#authorize` method to make chaining possible. (#385)
19
84
 
20
85
  ## 1.1.0 (2016-01-14)
21
86
 
data/Gemfile CHANGED
@@ -1,16 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  ruby RUBY_VERSION
4
6
 
5
7
  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/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Jonas Nicklas, Elabs AB
1
+ Copyright (c) 2019 Jonas Nicklas, Varvet AB
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -7,11 +7,11 @@
7
7
 
8
8
  Pundit provides a set of helpers which guide you in leveraging regular Ruby
9
9
  classes and object oriented design patterns to build a simple, robust and
10
- scaleable authorization system.
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
+ > **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
+
25
27
  ``` ruby
26
28
  gem "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
 
@@ -61,7 +62,7 @@ class PostPolicy
61
62
  end
62
63
 
63
64
  def update?
64
- user.admin? or not post.published?
65
+ user.admin? || !post.published?
65
66
  end
66
67
  end
67
68
  ```
@@ -165,13 +166,18 @@ def admin_list
165
166
  end
166
167
  ```
167
168
 
168
- `authorize` returns the object passed to it, so you can chain it like this:
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,14 +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 < Struct.new(:user, :dashboard)
194
- # ...
199
+ class DashboardPolicy
200
+ attr_reader :user
201
+
202
+ # _record in this example will just 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
 
213
+ Note that the headless policy still needs to accept two arguments. The
214
+ second argument will just be the symbol `:dashboard` in this case which
215
+ is what is passed as the record to `authorize` below.
216
+
198
217
  ```ruby
199
218
  # In controllers
200
- authorize :dashboard, :show?
219
+ def show
220
+ authorize :dashboard, :show?
221
+ ...
222
+ end
201
223
  ```
202
224
 
203
225
  ```erb
@@ -216,8 +238,6 @@ define a class called a policy scope. It can look something like this:
216
238
  ``` ruby
217
239
  class PostPolicy < ApplicationPolicy
218
240
  class Scope
219
- attr_reader :user, :scope
220
-
221
241
  def initialize(user, scope)
222
242
  @user = user
223
243
  @scope = scope
@@ -230,6 +250,10 @@ class PostPolicy < ApplicationPolicy
230
250
  scope.where(published: true)
231
251
  end
232
252
  end
253
+
254
+ private
255
+
256
+ attr_reader :user, :scope
233
257
  end
234
258
 
235
259
  def update?
@@ -292,13 +316,11 @@ def index
292
316
  end
293
317
  ```
294
318
 
295
- Just as with your policy, this will automatically infer that you want to use
296
- the `PostPolicy::Scope` class, it will instantiate this class and call
297
- `resolve` on the instance. In this case it is a shortcut for doing:
319
+ In this case it is a shortcut for doing:
298
320
 
299
321
  ``` ruby
300
322
  def index
301
- @posts = PostPolicy::Scope.new(current_user, Post).resolve
323
+ @publications = PublicationPolicy::Scope.new(current_user, Post).resolve
302
324
  end
303
325
  ```
304
326
 
@@ -326,7 +348,7 @@ that you haven't forgotten to authorize the action. For example:
326
348
 
327
349
  ``` ruby
328
350
  class ApplicationController < ActionController::Base
329
- include Pundit
351
+ include Pundit::Authorization
330
352
  after_action :verify_authorized
331
353
  end
332
354
  ```
@@ -339,7 +361,7 @@ authorize individual instances.
339
361
 
340
362
  ``` ruby
341
363
  class ApplicationController < ActionController::Base
342
- include Pundit
364
+ include Pundit::Authorization
343
365
  after_action :verify_authorized, except: :index
344
366
  after_action :verify_policy_scoped, only: :index
345
367
  end
@@ -387,6 +409,16 @@ class Post
387
409
  end
388
410
  ```
389
411
 
412
+ Alternatively, you can declare an instance method:
413
+
414
+ ``` ruby
415
+ class Post
416
+ def policy_class
417
+ PostablePolicy
418
+ end
419
+ end
420
+ ```
421
+
390
422
  ## Just plain old Ruby
391
423
 
392
424
  As you can see, Pundit doesn't do anything you couldn't have easily done
@@ -472,8 +504,7 @@ method in every controller.
472
504
 
473
505
  ```ruby
474
506
  class ApplicationController < ActionController::Base
475
- protect_from_forgery
476
- include Pundit
507
+ include Pundit::Authorization
477
508
 
478
509
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
479
510
 
@@ -593,8 +624,7 @@ class Admin::PostController < AdminController
593
624
  end
594
625
 
595
626
  def show
596
- post = Post.find(params[:id])
597
- authorize(post)
627
+ post = authorize Post.find(params[:id])
598
628
  end
599
629
  end
600
630
  ```
@@ -627,7 +657,7 @@ class UserContext
627
657
  end
628
658
 
629
659
  class ApplicationController
630
- include Pundit
660
+ include Pundit::Authorization
631
661
 
632
662
  def pundit_user
633
663
  UserContext.new(current_user, request.ip)
@@ -637,9 +667,8 @@ end
637
667
 
638
668
  ## Strong parameters
639
669
 
640
- In Rails 4 (or Rails 3.2 with the
641
- [strong_parameters](https://github.com/rails/strong_parameters) gem),
642
- mass-assignment protection is handled in the controller. With Pundit you can
670
+ In Rails,
671
+ mass-assignment protection is handled in the controller. With Pundit you can
643
672
  control which attributes a user has access to update via your policies. You can
644
673
  set up a `permitted_attributes` method in your policy like this:
645
674
 
@@ -778,9 +807,14 @@ Pundit does not provide a DSL for testing scopes. Just test it like a regular Ru
778
807
  - [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
779
808
  - [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
780
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)
781
811
  - [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
782
812
  - [Straightforward Rails Authorization with Pundit](http://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
783
813
 
814
+ ## Other implementations
815
+
816
+ - [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](http://flask.pocoo.org/) extension "heavily inspired by" Pundit
817
+
784
818
  # License
785
819
 
786
820
  Licensed under the MIT license, see the separate LICENSE.txt file.
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rubygems"
2
4
  require "bundler/gem_tasks"
3
5
  require "rspec/core/rake_task"
@@ -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('templates', __dir__)
6
+ source_root File.expand_path("templates", __dir__)
5
7
 
6
8
  def copy_application_policy
7
- template 'application_policy.rb', 'app/policies/application_policy.rb'
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
- scope.all
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('templates', __dir__)
6
+ source_root File.expand_path("templates", __dir__)
5
7
 
6
8
  def create_policy
7
- template 'policy.rb', File.join('app/policies', class_path, "#{file_name}_policy.rb")
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
- def resolve
5
- scope.all
6
- end
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('templates', __dir__)
6
+ source_root File.expand_path("templates", __dir__)
5
7
 
6
8
  def create_policy_spec
7
- template 'policy_spec.rb', File.join('spec/policies', class_path, "#{file_name}_policy_spec.rb")
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
@@ -1,6 +1,6 @@
1
1
  require '<%= File.exists?('spec/rails_helper.rb') ? 'rails_helper' : 'spec_helper' %>'
2
2
 
3
- RSpec.describe <%= class_name %>Policy do
3
+ RSpec.describe <%= class_name %>Policy, type: :policy do
4
4
  let(:user) { User.new }
5
5
 
6
6
  subject { described_class }
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TestUnit
2
4
  module Generators
3
5
  class PolicyGenerator < ::Rails::Generators::NamedBase
4
- source_root File.expand_path('templates', __dir__)
6
+ source_root File.expand_path("templates", __dir__)
5
7
 
6
8
  def create_policy_test
7
- template 'policy_test.rb', File.join('test/policies', class_path, "#{file_name}_policy_test.rb")
9
+ template "policy_test.rb", File.join("test/policies", class_path, "#{file_name}_policy_test.rb")
8
10
  end
9
11
  end
10
12
  end