pundit 2.0.1 → 2.3.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
- SHA1:
3
- metadata.gz: dffd7b483c73feb3955b9f1eb6767d9fedb72eaf
4
- data.tar.gz: 5de4a5628f75bfcd87879c52917634f1ddde7072
2
+ SHA256:
3
+ metadata.gz: 74f2f6efff0c12342afad4bb45dc75f12443e20f6ab5a9ed40274f2f842f2441
4
+ data.tar.gz: ad984e338045f040964301fdf2c79323d2e1a1ebffad16fc332d49315de14da2
5
5
  SHA512:
6
- metadata.gz: f21abdc81639b1d05209f1dfc71579294ba5226372493936ea9e6cfc2cc356e620223042f9f58679a2bb276dabab3f81e793a22d4b6e4bb69ef7edb467d399c1
7
- data.tar.gz: fe50e431d42e21e415ad361a1a0f536373e4a90b6f0631321dce3ba1b8e804c13b3e1d44f0446b3b1e71c68dbd868b5881b7bbaf6367e69b92bf23acf34a1022
6
+ metadata.gz: 106c8df42fc14b485dc4ea3951fba00232b6fa739b0a5910d9c33a33dde04cb1c015ecbf77f07a38274b9f9ae43ea5cfbbafb283f5eddc42fbf9454820ab87af
7
+ data.tar.gz: 4ab2a989938496acf224a9b20c247010e8d5882de168a995a02dbde021d308d7602f6305d675b26d461dcfb171346b02a1979325471f8713644aab8aac2dab9a
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.2
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,20 +1,26 @@
1
1
  language: ruby
2
- before_install:
3
- - gem install bundler -v 1.17.3
2
+ dist: focal
4
3
 
5
4
  matrix:
6
5
  include:
7
- - 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
8
10
  script: bundle exec rake rubocop # ONLY lint once, first
9
- - rvm: 2.1
10
- - rvm: 2.2
11
- - rvm: 2.3.5
12
- - rvm: 2.4.2
13
- - rvm: 2.5.1
14
- - rvm: 2.6.0
15
- - rvm: jruby-9.1.8.0
16
- env:
17
- - JRUBY_OPTS="--debug"
18
- - rvm: jruby-9.2.5.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
19
22
  env:
20
23
  - JRUBY_OPTS="--debug"
24
+ - rvm: truffleruby-head
25
+ allow_failures:
26
+ - rvm: truffleruby-head
data/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # Pundit
2
2
 
3
+ ## 2.3.0 (2022-12-19)
4
+
5
+ ### Added
6
+
7
+ - add support for rubocop-rspec syntax extensions (#745)
8
+
9
+ ## 2.2.0 (2022-02-11)
10
+
11
+ ### Fixed
12
+
13
+ - Using `policy_class` and a namespaced record now passes only the record when instantiating the policy. (#697, #689, #694, #666)
14
+
15
+ ### Changed
16
+
17
+ - Require users to explicitly define Scope#resolve in generated policies (#711, #722)
18
+
19
+ ### Deprecated
20
+
21
+ - Deprecate `include Pundit` in favor of `include Pundit::Authorization` (#621)
22
+
23
+ ## 2.1.1 (2021-08-13)
24
+
25
+ Friday 13th-release!
26
+
27
+ Careful! The bugfix below (#626) could break existing code. If you rely on the
28
+ return value for `authorize` and namespaced policies you might need to do some
29
+ changes.
30
+
31
+ ### Fixed
32
+
33
+ - `.authorize` and `#authorize` return the instance, even for namespaced
34
+ policies (#626)
35
+
36
+ ### Changed
37
+
38
+ - Generate application scope with `protected` attr_readers. (#616)
39
+
40
+ ### Removed
41
+
42
+ - Dropped support for Ruby end-of-life versions: 2.1 and 2.2. (#604)
43
+ - Dropped support for Ruby end-of-life versions: 2.3 (#633)
44
+ - Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
45
+ - Dropped support for RSpec 2 (#615)
46
+
47
+ ## 2.1.0 (2019-08-14)
48
+
49
+ ### Fixed
50
+
51
+ - Avoid name clashes with the Error class. (#590)
52
+
53
+ ### Changed
54
+
55
+ - Return a safer default NotAuthorizedError message. (#583)
56
+
3
57
  ## 2.0.1 (2019-01-18)
4
58
 
5
59
  ### Breaking changes
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) 2018 Jonas Nicklas, Varvet 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
- ``` ruby
26
- gem "pundit"
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
 
@@ -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,8 +196,17 @@ 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
 
@@ -201,7 +216,10 @@ is what is passed as the record to `authorize` below.
201
216
 
202
217
  ```ruby
203
218
  # In controllers
204
- authorize :dashboard, :show?
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
- Just as with your policy, this will automatically infer that you want to use
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
- @posts = PostPolicy::Scope.new(current_user, Post).resolve
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
@@ -391,6 +409,16 @@ class Post
391
409
  end
392
410
  ```
393
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
+
394
422
  ## Just plain old Ruby
395
423
 
396
424
  As you can see, Pundit doesn't do anything you couldn't have easily done
@@ -476,8 +504,7 @@ method in every controller.
476
504
 
477
505
  ```ruby
478
506
  class ApplicationController < ActionController::Base
479
- protect_from_forgery
480
- include Pundit
507
+ include Pundit::Authorization
481
508
 
482
509
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
483
510
 
@@ -485,7 +512,7 @@ class ApplicationController < ActionController::Base
485
512
 
486
513
  def user_not_authorized
487
514
  flash[:alert] = "You are not authorized to perform this action."
488
- redirect_to(request.referrer || root_path)
515
+ redirect_back(fallback_location: root_path)
489
516
  end
490
517
  end
491
518
  ```
@@ -514,7 +541,7 @@ class ApplicationController < ActionController::Base
514
541
  policy_name = exception.policy.class.to_s.underscore
515
542
 
516
543
  flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
517
- redirect_to(request.referrer || root_path)
544
+ redirect_back(fallback_url: root_path)
518
545
  end
519
546
  end
520
547
  ```
@@ -597,8 +624,7 @@ class Admin::PostController < AdminController
597
624
  end
598
625
 
599
626
  def show
600
- post = Post.find(params[:id])
601
- authorize(post)
627
+ post = authorize Post.find(params[:id])
602
628
  end
603
629
  end
604
630
  ```
@@ -631,7 +657,7 @@ class UserContext
631
657
  end
632
658
 
633
659
  class ApplicationController
634
- include Pundit
660
+ include Pundit::Authorization
635
661
 
636
662
  def pundit_user
637
663
  UserContext.new(current_user, request.ip)
@@ -641,9 +667,8 @@ end
641
667
 
642
668
  ## Strong parameters
643
669
 
644
- In Rails 4 (or Rails 3.2 with the
645
- [strong_parameters](https://github.com/rails/strong_parameters) gem),
646
- 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
647
672
  control which attributes a user has access to update via your policies. You can
648
673
  set up a `permitted_attributes` method in your policy like this:
649
674
 
@@ -667,7 +692,7 @@ You can now retrieve these attributes from the policy:
667
692
  class PostsController < ApplicationController
668
693
  def update
669
694
  @post = Post.find(params[:id])
670
- if @post.update_attributes(post_params)
695
+ if @post.update(post_params)
671
696
  redirect_to @post
672
697
  else
673
698
  render :edit
@@ -689,7 +714,7 @@ However, this is a bit cumbersome, so Pundit provides a convenient helper method
689
714
  class PostsController < ApplicationController
690
715
  def update
691
716
  @post = Post.find(params[:id])
692
- if @post.update_attributes(permitted_attributes(@post))
717
+ if @post.update(permitted_attributes(@post))
693
718
  redirect_to @post
694
719
  else
695
720
  render :edit
@@ -777,14 +802,29 @@ An alternative approach to Pundit policy specs is scoping them to a user context
777
802
 
778
803
  Pundit does not provide a DSL for testing scopes. Just test it like a regular Ruby class!
779
804
 
805
+ ### Linting with RuboCop RSpec
806
+
807
+ When you lint your RSpec spec files with `rubocop-rspec`, it will fail to properly detect RSpec constructs that Pundit defines, `permissions`.
808
+ Make sure to use `rubocop-rspec` 2.0 or newer and add the following to your `.rubocop.yml`:
809
+
810
+ ```yaml
811
+ inherit_gem:
812
+ pundit: config/rubocop-rspec.yml
813
+ ```
814
+
780
815
  # External Resources
781
816
 
782
817
  - [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
783
818
  - [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
784
819
  - [Testing Pundit Policies with RSpec](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
820
+ - [Testing Pundit with Minitest](https://github.com/varvet/pundit/issues/204#issuecomment-60166450)
785
821
  - [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
786
822
  - [Straightforward Rails Authorization with Pundit](http://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
787
823
 
824
+ ## Other implementations
825
+
826
+ - [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](http://flask.pocoo.org/) extension "heavily inspired by" Pundit
827
+
788
828
  # License
789
829
 
790
830
  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"
@@ -0,0 +1,5 @@
1
+ RSpec:
2
+ Language:
3
+ ExampleGroups:
4
+ Regular:
5
+ - permissions
@@ -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,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