pundit 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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