pundit 2.0.1 → 2.1.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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -51
- data/.travis.yml +18 -13
- data/CHANGELOG.md +36 -0
- data/Gemfile +2 -11
- data/LICENSE.txt +1 -1
- data/README.md +32 -16
- data/Rakefile +2 -0
- data/lib/generators/pundit/install/install_generator.rb +4 -2
- data/lib/generators/pundit/install/templates/application_policy.rb +6 -2
- data/lib/generators/pundit/policy/policy_generator.rb +4 -2
- data/lib/generators/rspec/policy_generator.rb +4 -2
- data/lib/generators/test_unit/policy_generator.rb +4 -2
- data/lib/pundit/policy_finder.rb +3 -1
- data/lib/pundit/rspec.rb +6 -14
- data/lib/pundit/version.rb +1 -1
- data/lib/pundit.rb +13 -11
- data/pundit.gemspec +12 -1
- data/spec/policies/post_policy_spec.rb +3 -1
- data/spec/policy_finder_spec.rb +82 -17
- data/spec/pundit_spec.rb +71 -25
- data/spec/spec_helper.rb +22 -23
- metadata +129 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: def6c710d9f9d1705ca43cdad9364bb34ce5d878b8a3a9bf26d336802e40efeb
|
|
4
|
+
data.tar.gz: 0d6618cb61dfef8ae18f811a73b3f059d9945f8def7f9b2f794ae095b3a0f0cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7105cd0a84469071de9211e19f7e7a31f4ea8b5283d7b1ed007b6533805de18d105c09128a9936144612f3daa8fadfdf0698f7448d8db94e47bb459efaa11c4b
|
|
7
|
+
data.tar.gz: 3805e2664f21f30c66e9a9a05606f0d0d18b1607137e794948c7907bd33c6d6e64a45b9abb97d2f1a21df0d46497ff708679442807e152fa167abc461c8c0abe
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
AllCops:
|
|
2
|
-
|
|
3
|
-
TargetRubyVersion: 2.2
|
|
2
|
+
TargetRubyVersion: 2.6
|
|
4
3
|
Exclude:
|
|
5
|
-
- "
|
|
6
|
-
- "vendor/**/*"
|
|
7
|
-
- "lib/generators/**/*"
|
|
4
|
+
- "lib/generators/**/templates/**/*"
|
|
8
5
|
|
|
9
6
|
Metrics/BlockLength:
|
|
10
7
|
Exclude:
|
|
@@ -30,33 +27,9 @@ Metrics/CyclomaticComplexity:
|
|
|
30
27
|
Metrics/PerceivedComplexity:
|
|
31
28
|
Enabled: false
|
|
32
29
|
|
|
33
|
-
Style/StructInheritance:
|
|
34
|
-
Enabled: false
|
|
35
|
-
|
|
36
30
|
Layout/AlignParameters:
|
|
37
31
|
EnforcedStyle: with_fixed_indentation
|
|
38
32
|
|
|
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
33
|
Layout/CaseIndentation:
|
|
61
34
|
EnforcedStyle: case
|
|
62
35
|
SupportedStyles:
|
|
@@ -64,40 +37,31 @@ Layout/CaseIndentation:
|
|
|
64
37
|
- end
|
|
65
38
|
IndentOneStep: true
|
|
66
39
|
|
|
40
|
+
Layout/EndAlignment:
|
|
41
|
+
EnforcedStyleAlignWith: variable
|
|
42
|
+
|
|
67
43
|
Style/PercentLiteralDelimiters:
|
|
68
44
|
PreferredDelimiters:
|
|
69
45
|
'%w': "[]"
|
|
70
46
|
'%W': "[]"
|
|
71
47
|
|
|
72
|
-
|
|
73
|
-
EnforcedStyle:
|
|
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
|
|
48
|
+
Style/StringLiterals:
|
|
49
|
+
EnforcedStyle: double_quotes
|
|
89
50
|
|
|
90
|
-
|
|
91
|
-
|
|
51
|
+
Style/StringLiteralsInInterpolation:
|
|
52
|
+
EnforcedStyle: double_quotes
|
|
92
53
|
|
|
93
|
-
Style/
|
|
54
|
+
Style/StructInheritance:
|
|
94
55
|
Enabled: false
|
|
95
56
|
|
|
96
|
-
Style/
|
|
57
|
+
Style/AndOr:
|
|
97
58
|
Enabled: false
|
|
98
59
|
|
|
99
|
-
|
|
60
|
+
Style/Not:
|
|
100
61
|
Enabled: false
|
|
101
62
|
|
|
102
63
|
Style/DoubleNegation:
|
|
103
64
|
Enabled: false
|
|
65
|
+
|
|
66
|
+
Documentation:
|
|
67
|
+
Enabled: false # TODO: Enable again once we have more docs
|
data/.travis.yml
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
-
|
|
3
|
-
- gem install bundler -v 1.17.3
|
|
2
|
+
dist: focal
|
|
4
3
|
|
|
5
4
|
matrix:
|
|
6
5
|
include:
|
|
7
|
-
-
|
|
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.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- rvm: jruby-9.2.
|
|
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: jruby-9.2.17.0
|
|
19
21
|
env:
|
|
20
22
|
- JRUBY_OPTS="--debug"
|
|
23
|
+
- rvm: truffleruby-head
|
|
24
|
+
allow_failures:
|
|
25
|
+
- rvm: truffleruby-head
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Pundit
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 2.1.1 (2021-08-13)
|
|
6
|
+
|
|
7
|
+
Friday 13th-release!
|
|
8
|
+
|
|
9
|
+
Careful! The bugfix below (#626) could break existing code. If you rely on the
|
|
10
|
+
return value for `authorize` and namespaced policies you might need to do some
|
|
11
|
+
changes.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- `.authorize` and `#authorize` return the instance, even for namespaced
|
|
16
|
+
policies (#626)
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Generate application scope with `protected` attr_readers. (#616)
|
|
21
|
+
|
|
22
|
+
### Removed
|
|
23
|
+
|
|
24
|
+
- Dropped support for Ruby end-of-life versions: 2.1 and 2.2. (#604)
|
|
25
|
+
- Dropped support for Ruby end-of-life versions: 2.3 (#633)
|
|
26
|
+
- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
|
|
27
|
+
- Dropped support for RSpec 2 (#615)
|
|
28
|
+
|
|
29
|
+
## 2.1.0 (2019-08-14)
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Avoid name clashes with the Error class. (#590)
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Return a safer default NotAuthorizedError message. (#583)
|
|
38
|
+
|
|
3
39
|
## 2.0.1 (2019-01-18)
|
|
4
40
|
|
|
5
41
|
### 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
data/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
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
|
-
|
|
10
|
+
scalable authorization system.
|
|
11
11
|
|
|
12
12
|
Links:
|
|
13
13
|
|
|
@@ -31,7 +31,6 @@ Include Pundit in your application controller:
|
|
|
31
31
|
``` ruby
|
|
32
32
|
class ApplicationController < ActionController::Base
|
|
33
33
|
include Pundit
|
|
34
|
-
protect_from_forgery
|
|
35
34
|
end
|
|
36
35
|
```
|
|
37
36
|
|
|
@@ -61,7 +60,7 @@ class PostPolicy
|
|
|
61
60
|
end
|
|
62
61
|
|
|
63
62
|
def update?
|
|
64
|
-
user.admin?
|
|
63
|
+
user.admin? || !post.published?
|
|
65
64
|
end
|
|
66
65
|
end
|
|
67
66
|
```
|
|
@@ -165,13 +164,18 @@ def admin_list
|
|
|
165
164
|
end
|
|
166
165
|
```
|
|
167
166
|
|
|
168
|
-
`authorize` returns the
|
|
167
|
+
`authorize` returns the instance passed to it, so you can chain it like this:
|
|
169
168
|
|
|
170
169
|
Controller:
|
|
171
170
|
```ruby
|
|
172
171
|
def show
|
|
173
172
|
@user = authorize User.find(params[:id])
|
|
174
173
|
end
|
|
174
|
+
|
|
175
|
+
# return the record even for namespaced policies
|
|
176
|
+
def show
|
|
177
|
+
@user = authorize [:admin, User.find(params[:id])]
|
|
178
|
+
end
|
|
175
179
|
```
|
|
176
180
|
|
|
177
181
|
You can easily get a hold of an instance of the policy through the `policy`
|
|
@@ -220,8 +224,6 @@ define a class called a policy scope. It can look something like this:
|
|
|
220
224
|
``` ruby
|
|
221
225
|
class PostPolicy < ApplicationPolicy
|
|
222
226
|
class Scope
|
|
223
|
-
attr_reader :user, :scope
|
|
224
|
-
|
|
225
227
|
def initialize(user, scope)
|
|
226
228
|
@user = user
|
|
227
229
|
@scope = scope
|
|
@@ -234,6 +236,10 @@ class PostPolicy < ApplicationPolicy
|
|
|
234
236
|
scope.where(published: true)
|
|
235
237
|
end
|
|
236
238
|
end
|
|
239
|
+
|
|
240
|
+
private
|
|
241
|
+
|
|
242
|
+
attr_reader :user, :scope
|
|
237
243
|
end
|
|
238
244
|
|
|
239
245
|
def update?
|
|
@@ -296,13 +302,11 @@ def index
|
|
|
296
302
|
end
|
|
297
303
|
```
|
|
298
304
|
|
|
299
|
-
|
|
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:
|
|
305
|
+
In this case it is a shortcut for doing:
|
|
302
306
|
|
|
303
307
|
``` ruby
|
|
304
308
|
def index
|
|
305
|
-
@
|
|
309
|
+
@publications = PublicationPolicy::Scope.new(current_user, Post).resolve
|
|
306
310
|
end
|
|
307
311
|
```
|
|
308
312
|
|
|
@@ -391,6 +395,16 @@ class Post
|
|
|
391
395
|
end
|
|
392
396
|
```
|
|
393
397
|
|
|
398
|
+
Alternatively, you can declare an instance method:
|
|
399
|
+
|
|
400
|
+
``` ruby
|
|
401
|
+
class Post
|
|
402
|
+
def policy_class
|
|
403
|
+
PostablePolicy
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
```
|
|
407
|
+
|
|
394
408
|
## Just plain old Ruby
|
|
395
409
|
|
|
396
410
|
As you can see, Pundit doesn't do anything you couldn't have easily done
|
|
@@ -476,7 +490,6 @@ method in every controller.
|
|
|
476
490
|
|
|
477
491
|
```ruby
|
|
478
492
|
class ApplicationController < ActionController::Base
|
|
479
|
-
protect_from_forgery
|
|
480
493
|
include Pundit
|
|
481
494
|
|
|
482
495
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
|
@@ -597,8 +610,7 @@ class Admin::PostController < AdminController
|
|
|
597
610
|
end
|
|
598
611
|
|
|
599
612
|
def show
|
|
600
|
-
post = Post.find(params[:id])
|
|
601
|
-
authorize(post)
|
|
613
|
+
post = authorize Post.find(params[:id])
|
|
602
614
|
end
|
|
603
615
|
end
|
|
604
616
|
```
|
|
@@ -641,9 +653,8 @@ end
|
|
|
641
653
|
|
|
642
654
|
## Strong parameters
|
|
643
655
|
|
|
644
|
-
In Rails
|
|
645
|
-
|
|
646
|
-
mass-assignment protection is handled in the controller. With Pundit you can
|
|
656
|
+
In Rails,
|
|
657
|
+
mass-assignment protection is handled in the controller. With Pundit you can
|
|
647
658
|
control which attributes a user has access to update via your policies. You can
|
|
648
659
|
set up a `permitted_attributes` method in your policy like this:
|
|
649
660
|
|
|
@@ -782,9 +793,14 @@ Pundit does not provide a DSL for testing scopes. Just test it like a regular Ru
|
|
|
782
793
|
- [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
|
|
783
794
|
- [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
|
|
784
795
|
- [Testing Pundit Policies with RSpec](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
|
|
796
|
+
- [Testing Pundit with Minitest](https://github.com/varvet/pundit/issues/204#issuecomment-60166450)
|
|
785
797
|
- [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)
|
|
786
798
|
- [Straightforward Rails Authorization with Pundit](http://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)
|
|
787
799
|
|
|
800
|
+
## Other implementations
|
|
801
|
+
|
|
802
|
+
- [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](http://flask.pocoo.org/) extension "heavily inspired by" Pundit
|
|
803
|
+
|
|
788
804
|
# License
|
|
789
805
|
|
|
790
806
|
Licensed under the MIT license, see the separate LICENSE.txt file.
|
data/Rakefile
CHANGED
|
@@ -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(
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
7
|
|
|
6
8
|
def copy_application_policy
|
|
7
|
-
template
|
|
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,8 +37,6 @@ 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
|
|
@@ -45,5 +45,9 @@ class ApplicationPolicy
|
|
|
45
45
|
def resolve
|
|
46
46
|
scope.all
|
|
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(
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
7
|
|
|
6
8
|
def create_policy
|
|
7
|
-
template
|
|
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,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(
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
7
|
|
|
6
8
|
def create_policy_spec
|
|
7
|
-
template
|
|
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(
|
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
|
5
7
|
|
|
6
8
|
def create_policy_test
|
|
7
|
-
template
|
|
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
|
data/lib/pundit/policy_finder.rb
CHANGED
data/lib/pundit/rspec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Pundit
|
|
4
4
|
module RSpec
|
|
@@ -72,17 +72,9 @@ module Pundit
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
RSpec.configure do |config|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
)
|
|
81
|
-
else
|
|
82
|
-
config.include(
|
|
83
|
-
Pundit::RSpec::PolicyExampleGroup,
|
|
84
|
-
type: :policy,
|
|
85
|
-
example_group: { file_path: %r{spec/policies} }
|
|
86
|
-
)
|
|
87
|
-
end
|
|
75
|
+
config.include(
|
|
76
|
+
Pundit::RSpec::PolicyExampleGroup,
|
|
77
|
+
type: :policy,
|
|
78
|
+
file_path: %r{spec/policies}
|
|
79
|
+
)
|
|
88
80
|
end
|
data/lib/pundit/version.rb
CHANGED
data/lib/pundit.rb
CHANGED
|
@@ -8,16 +8,18 @@ require "active_support/core_ext/object/blank"
|
|
|
8
8
|
require "active_support/core_ext/module/introspection"
|
|
9
9
|
require "active_support/dependencies/autoload"
|
|
10
10
|
|
|
11
|
+
# @api private
|
|
12
|
+
# To avoid name clashes with common Error naming when mixing in Pundit,
|
|
13
|
+
# keep it here with compact class style definition.
|
|
14
|
+
class Pundit::Error < StandardError; end # rubocop:disable Style/ClassAndModuleChildren
|
|
15
|
+
|
|
11
16
|
# @api public
|
|
12
17
|
module Pundit
|
|
13
|
-
SUFFIX = "Policy"
|
|
18
|
+
SUFFIX = "Policy"
|
|
14
19
|
|
|
15
20
|
# @api private
|
|
16
21
|
module Generators; end
|
|
17
22
|
|
|
18
|
-
# @api private
|
|
19
|
-
class Error < StandardError; end
|
|
20
|
-
|
|
21
23
|
# Error that will be raised when authorization has failed
|
|
22
24
|
class NotAuthorizedError < Error
|
|
23
25
|
attr_reader :query, :record, :policy
|
|
@@ -30,7 +32,7 @@ module Pundit
|
|
|
30
32
|
@record = options[:record]
|
|
31
33
|
@policy = options[:policy]
|
|
32
34
|
|
|
33
|
-
message = options.fetch(:message) { "not allowed to #{query} this #{record.
|
|
35
|
+
message = options.fetch(:message) { "not allowed to #{query} this #{record.class}" }
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
super(message)
|
|
@@ -69,7 +71,7 @@ module Pundit
|
|
|
69
71
|
|
|
70
72
|
raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query)
|
|
71
73
|
|
|
72
|
-
record
|
|
74
|
+
record.is_a?(Array) ? record.last : record
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
# Retrieves the policy scope for the given record.
|
|
@@ -122,7 +124,7 @@ module Pundit
|
|
|
122
124
|
# @return [Object, nil] instance of policy class with query methods
|
|
123
125
|
def policy(user, record)
|
|
124
126
|
policy = PolicyFinder.new(record).policy
|
|
125
|
-
policy
|
|
127
|
+
policy&.new(user, pundit_model(record))
|
|
126
128
|
rescue ArgumentError
|
|
127
129
|
raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
|
|
128
130
|
end
|
|
@@ -142,7 +144,7 @@ module Pundit
|
|
|
142
144
|
raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
|
|
143
145
|
end
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
private
|
|
146
148
|
|
|
147
149
|
def pundit_model(record)
|
|
148
150
|
record.is_a?(Array) ? record.last : record
|
|
@@ -165,7 +167,7 @@ module Pundit
|
|
|
165
167
|
end
|
|
166
168
|
end
|
|
167
169
|
|
|
168
|
-
protected
|
|
170
|
+
protected
|
|
169
171
|
|
|
170
172
|
# @return [Boolean] whether authorization has been performed, i.e. whether
|
|
171
173
|
# one {#authorize} or {#skip_authorization} has been called
|
|
@@ -220,7 +222,7 @@ protected
|
|
|
220
222
|
|
|
221
223
|
raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query)
|
|
222
224
|
|
|
223
|
-
record
|
|
225
|
+
record.is_a?(Array) ? record.last : record
|
|
224
226
|
end
|
|
225
227
|
|
|
226
228
|
# Allow this action not to perform authorization.
|
|
@@ -315,7 +317,7 @@ protected
|
|
|
315
317
|
current_user
|
|
316
318
|
end
|
|
317
319
|
|
|
318
|
-
private
|
|
320
|
+
private
|
|
319
321
|
|
|
320
322
|
def pundit_policy_scope(scope)
|
|
321
323
|
policy_scopes[scope] ||= Pundit.policy_scope!(pundit_user, scope)
|
data/pundit.gemspec
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
lib = File.expand_path("lib", __dir__)
|
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
5
|
require "pundit/version"
|
|
@@ -12,10 +14,19 @@ Gem::Specification.new do |gem|
|
|
|
12
14
|
gem.homepage = "https://github.com/varvet/pundit"
|
|
13
15
|
gem.license = "MIT"
|
|
14
16
|
|
|
15
|
-
gem.files = `git ls-files`.split(
|
|
17
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
16
18
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
|
17
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
18
20
|
gem.require_paths = ["lib"]
|
|
19
21
|
|
|
20
22
|
gem.add_dependency "activesupport", ">= 3.0.0"
|
|
23
|
+
gem.add_development_dependency "actionpack", ">= 3.0.0"
|
|
24
|
+
gem.add_development_dependency "activemodel", ">= 3.0.0"
|
|
25
|
+
gem.add_development_dependency "bundler"
|
|
26
|
+
gem.add_development_dependency "pry"
|
|
27
|
+
gem.add_development_dependency "rake"
|
|
28
|
+
gem.add_development_dependency "rspec", ">= 3.0.0"
|
|
29
|
+
gem.add_development_dependency "rubocop", "0.74.0"
|
|
30
|
+
gem.add_development_dependency "simplecov", ">= 0.17.0"
|
|
31
|
+
gem.add_development_dependency "yard"
|
|
21
32
|
end
|
data/spec/policy_finder_spec.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "spec_helper"
|
|
2
4
|
|
|
3
|
-
describe Pundit::PolicyFinder do
|
|
5
|
+
RSpec.describe Pundit::PolicyFinder do
|
|
4
6
|
let(:user) { double }
|
|
5
7
|
let(:post) { Post.new(user) }
|
|
6
8
|
let(:comment) { CommentFourFiveSix.new }
|
|
@@ -22,37 +24,100 @@ describe Pundit::PolicyFinder do
|
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
describe "#policy" do
|
|
25
|
-
|
|
27
|
+
context "with an instance" do
|
|
28
|
+
it "returns the associated policy" do
|
|
29
|
+
object = described_class.new(post)
|
|
30
|
+
|
|
31
|
+
expect(object.policy).to eq PostPolicy
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "with an array of symbols" do
|
|
36
|
+
it "returns the associated namespaced policy" do
|
|
37
|
+
object = described_class.new(%i[project post])
|
|
38
|
+
|
|
39
|
+
expect(object.policy).to eq Project::PostPolicy
|
|
40
|
+
end
|
|
41
|
+
end
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
context "with an array of a symbol and an instance" do
|
|
44
|
+
it "returns the associated namespaced policy" do
|
|
45
|
+
object = described_class.new([:project, post])
|
|
46
|
+
|
|
47
|
+
expect(object.policy).to eq Project::PostPolicy
|
|
48
|
+
end
|
|
29
49
|
end
|
|
30
50
|
|
|
31
|
-
context "with a
|
|
32
|
-
it "returns
|
|
33
|
-
|
|
34
|
-
|
|
51
|
+
context "with an array of a symbol and a class with a specified policy class" do
|
|
52
|
+
it "returns the associated namespaced policy" do
|
|
53
|
+
object = described_class.new([:project, Customer::Post])
|
|
54
|
+
|
|
55
|
+
expect(object.policy).to eq Project::PostPolicy
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "with an array of a symbol and a class with a specified model name" do
|
|
60
|
+
it "returns the associated namespaced policy" do
|
|
61
|
+
object = described_class.new([:project, CommentsRelation])
|
|
62
|
+
|
|
63
|
+
expect(object.policy).to eq Project::CommentPolicy
|
|
35
64
|
end
|
|
36
65
|
end
|
|
37
66
|
|
|
38
67
|
context "with a class" do
|
|
39
|
-
it "returns
|
|
40
|
-
|
|
41
|
-
|
|
68
|
+
it "returns the associated policy" do
|
|
69
|
+
object = described_class.new(Post)
|
|
70
|
+
|
|
71
|
+
expect(object.policy).to eq PostPolicy
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "with a class which has a specified policy class" do
|
|
76
|
+
it "returns the associated policy" do
|
|
77
|
+
object = described_class.new(Customer::Post)
|
|
78
|
+
|
|
79
|
+
expect(object.policy).to eq PostPolicy
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "with an instance which has a specified policy class" do
|
|
84
|
+
it "returns the associated policy" do
|
|
85
|
+
object = described_class.new(Customer::Post.new(user))
|
|
86
|
+
|
|
87
|
+
expect(object.policy).to eq PostPolicy
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context "with a class which has a specified model name" do
|
|
92
|
+
it "returns the associated policy" do
|
|
93
|
+
object = described_class.new(CommentsRelation)
|
|
94
|
+
|
|
95
|
+
expect(object.policy).to eq CommentPolicy
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "with an instance which has a specified policy class" do
|
|
100
|
+
it "returns the associated policy" do
|
|
101
|
+
object = described_class.new(CommentsRelation.new)
|
|
102
|
+
|
|
103
|
+
expect(object.policy).to eq CommentPolicy
|
|
42
104
|
end
|
|
43
105
|
end
|
|
44
106
|
|
|
45
107
|
context "with nil" do
|
|
46
|
-
it "returns
|
|
47
|
-
|
|
48
|
-
|
|
108
|
+
it "returns a NilClassPolicy" do
|
|
109
|
+
object = described_class.new(nil)
|
|
110
|
+
|
|
111
|
+
expect(object.policy).to eq NilClassPolicy
|
|
49
112
|
end
|
|
50
113
|
end
|
|
51
114
|
|
|
52
|
-
context "with a
|
|
115
|
+
context "with a class that doesn't have an associated policy" do
|
|
53
116
|
it "returns nil" do
|
|
54
|
-
|
|
55
|
-
|
|
117
|
+
class Foo; end
|
|
118
|
+
object = described_class.new(Foo)
|
|
119
|
+
|
|
120
|
+
expect(object.policy).to eq nil
|
|
56
121
|
end
|
|
57
122
|
end
|
|
58
123
|
end
|
data/spec/pundit_spec.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "spec_helper"
|
|
2
4
|
|
|
3
|
-
describe Pundit do
|
|
5
|
+
RSpec.describe Pundit do
|
|
4
6
|
let(:user) { double }
|
|
5
7
|
let(:post) { Post.new(user) }
|
|
6
8
|
let(:customer_post) { Customer::Post.new(user) }
|
|
@@ -23,6 +25,26 @@ describe Pundit do
|
|
|
23
25
|
expect(Pundit.authorize(user, post, :update?)).to be_truthy
|
|
24
26
|
end
|
|
25
27
|
|
|
28
|
+
it "returns the record on successful authorization" do
|
|
29
|
+
expect(Pundit.authorize(user, post, :update?)).to eq(post)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "returns the record when passed record with namespace " do
|
|
33
|
+
expect(Pundit.authorize(user, [:project, comment], :update?)).to eq(comment)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "returns the record when passed record with nested namespace " do
|
|
37
|
+
expect(Pundit.authorize(user, [:project, :admin, comment], :update?)).to eq(comment)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "returns the policy name symbol when passed record with headless policy" do
|
|
41
|
+
expect(Pundit.authorize(user, :publication, :create?)).to eq(:publication)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "returns the class when passed record not a particular instance" do
|
|
45
|
+
expect(Pundit.authorize(user, Post, :show?)).to eq(Post)
|
|
46
|
+
end
|
|
47
|
+
|
|
26
48
|
it "can be given a different policy class" do
|
|
27
49
|
expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy
|
|
28
50
|
end
|
|
@@ -36,7 +58,7 @@ describe Pundit do
|
|
|
36
58
|
# rubocop:disable Style/MultilineBlockChain
|
|
37
59
|
expect do
|
|
38
60
|
Pundit.authorize(user, post, :destroy?)
|
|
39
|
-
end.to raise_error(Pundit::NotAuthorizedError, "not allowed to destroy? this
|
|
61
|
+
end.to raise_error(Pundit::NotAuthorizedError, "not allowed to destroy? this Post") do |error|
|
|
40
62
|
expect(error.query).to eq :destroy?
|
|
41
63
|
expect(error.record).to eq post
|
|
42
64
|
expect(error.policy).to eq Pundit.policy(user, post)
|
|
@@ -408,7 +430,23 @@ describe Pundit do
|
|
|
408
430
|
end
|
|
409
431
|
|
|
410
432
|
it "returns the record on successful authorization" do
|
|
411
|
-
expect(controller.authorize(post)).to
|
|
433
|
+
expect(controller.authorize(post)).to eq(post)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
it "returns the record when passed record with namespace " do
|
|
437
|
+
expect(controller.authorize([:project, comment], :update?)).to eq(comment)
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it "returns the record when passed record with nested namespace " do
|
|
441
|
+
expect(controller.authorize([:project, :admin, comment], :update?)).to eq(comment)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
it "returns the policy name symbol when passed record with headless policy" do
|
|
445
|
+
expect(controller.authorize(:publication, :create?)).to eq(:publication)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
it "returns the class when passed record not a particular instance" do
|
|
449
|
+
expect(controller.authorize(Post, :show?)).to eq(Post)
|
|
412
450
|
end
|
|
413
451
|
|
|
414
452
|
it "can be given a different permission to check" do
|
|
@@ -518,11 +556,13 @@ describe Pundit do
|
|
|
518
556
|
|
|
519
557
|
describe "#permitted_attributes" do
|
|
520
558
|
it "checks policy for permitted attributes" do
|
|
521
|
-
params = ActionController::Parameters.new(
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
559
|
+
params = ActionController::Parameters.new(
|
|
560
|
+
post: {
|
|
561
|
+
title: "Hello",
|
|
562
|
+
votes: 5,
|
|
563
|
+
admin: true
|
|
564
|
+
}
|
|
565
|
+
)
|
|
526
566
|
|
|
527
567
|
action = "update"
|
|
528
568
|
|
|
@@ -534,11 +574,13 @@ describe Pundit do
|
|
|
534
574
|
end
|
|
535
575
|
|
|
536
576
|
it "checks policy for permitted attributes for record of a ActiveModel type" do
|
|
537
|
-
params = ActionController::Parameters.new(
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
577
|
+
params = ActionController::Parameters.new(
|
|
578
|
+
customer_post: {
|
|
579
|
+
title: "Hello",
|
|
580
|
+
votes: 5,
|
|
581
|
+
admin: true
|
|
582
|
+
}
|
|
583
|
+
)
|
|
542
584
|
|
|
543
585
|
action = "update"
|
|
544
586
|
|
|
@@ -554,24 +596,28 @@ describe Pundit do
|
|
|
554
596
|
|
|
555
597
|
describe "#permitted_attributes_for_action" do
|
|
556
598
|
it "is checked if it is defined in the policy" do
|
|
557
|
-
params = ActionController::Parameters.new(
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
599
|
+
params = ActionController::Parameters.new(
|
|
600
|
+
post: {
|
|
601
|
+
title: "Hello",
|
|
602
|
+
body: "blah",
|
|
603
|
+
votes: 5,
|
|
604
|
+
admin: true
|
|
605
|
+
}
|
|
606
|
+
)
|
|
563
607
|
|
|
564
608
|
action = "revise"
|
|
565
609
|
expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
|
|
566
610
|
end
|
|
567
611
|
|
|
568
612
|
it "can be explicitly set" do
|
|
569
|
-
params = ActionController::Parameters.new(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
613
|
+
params = ActionController::Parameters.new(
|
|
614
|
+
post: {
|
|
615
|
+
title: "Hello",
|
|
616
|
+
body: "blah",
|
|
617
|
+
votes: 5,
|
|
618
|
+
admin: true
|
|
619
|
+
}
|
|
620
|
+
)
|
|
575
621
|
|
|
576
622
|
action = "update"
|
|
577
623
|
expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "simplecov"
|
|
4
|
+
SimpleCov.start do
|
|
5
|
+
add_filter "/spec/"
|
|
6
|
+
end
|
|
7
|
+
|
|
1
8
|
require "pundit"
|
|
2
9
|
require "pundit/rspec"
|
|
3
10
|
|
|
@@ -9,22 +16,6 @@ require "active_support/core_ext"
|
|
|
9
16
|
require "active_model/naming"
|
|
10
17
|
require "action_controller/metal/strong_parameters"
|
|
11
18
|
|
|
12
|
-
I18n.enforce_available_locales = false
|
|
13
|
-
|
|
14
|
-
module PunditSpecHelper
|
|
15
|
-
extend RSpec::Matchers::DSL
|
|
16
|
-
|
|
17
|
-
matcher :be_truthy do
|
|
18
|
-
match do |actual|
|
|
19
|
-
actual
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
RSpec.configure do |config|
|
|
25
|
-
config.include PunditSpecHelper
|
|
26
|
-
end
|
|
27
|
-
|
|
28
19
|
class PostPolicy < Struct.new(:user, :post)
|
|
29
20
|
class Scope < Struct.new(:user, :scope)
|
|
30
21
|
def resolve
|
|
@@ -84,10 +75,6 @@ module Customer
|
|
|
84
75
|
def self.policy_class
|
|
85
76
|
PostPolicy
|
|
86
77
|
end
|
|
87
|
-
|
|
88
|
-
def policy_class
|
|
89
|
-
self.class.policy_class
|
|
90
|
-
end
|
|
91
78
|
end
|
|
92
79
|
end
|
|
93
80
|
|
|
@@ -135,7 +122,7 @@ class CommentsRelation
|
|
|
135
122
|
@empty
|
|
136
123
|
end
|
|
137
124
|
|
|
138
|
-
def model_name
|
|
125
|
+
def self.model_name
|
|
139
126
|
Comment.model_name
|
|
140
127
|
end
|
|
141
128
|
end
|
|
@@ -172,6 +159,10 @@ class CriteriaPolicy < Struct.new(:user, :criteria); end
|
|
|
172
159
|
|
|
173
160
|
module Project
|
|
174
161
|
class CommentPolicy < Struct.new(:user, :comment)
|
|
162
|
+
def update?
|
|
163
|
+
true
|
|
164
|
+
end
|
|
165
|
+
|
|
175
166
|
class Scope < Struct.new(:user, :scope)
|
|
176
167
|
def resolve
|
|
177
168
|
scope
|
|
@@ -188,6 +179,14 @@ module Project
|
|
|
188
179
|
end
|
|
189
180
|
end
|
|
190
181
|
end
|
|
182
|
+
|
|
183
|
+
module Admin
|
|
184
|
+
class CommentPolicy < Struct.new(:user, :comment)
|
|
185
|
+
def update?
|
|
186
|
+
true
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
191
190
|
end
|
|
192
191
|
|
|
193
192
|
class DenierPolicy < Struct.new(:user, :record)
|
|
@@ -199,9 +198,9 @@ end
|
|
|
199
198
|
class Controller
|
|
200
199
|
include Pundit
|
|
201
200
|
# Mark protected methods public so they may be called in test
|
|
202
|
-
# rubocop:disable
|
|
201
|
+
# rubocop:disable Style/AccessModifierDeclarations
|
|
203
202
|
public(*Pundit.protected_instance_methods)
|
|
204
|
-
# rubocop:enable
|
|
203
|
+
# rubocop:enable Style/AccessModifierDeclarations
|
|
205
204
|
|
|
206
205
|
attr_reader :current_user, :action_name, :params
|
|
207
206
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pundit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonas Nicklas
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2021-08-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -25,6 +25,132 @@ dependencies:
|
|
|
25
25
|
- - ">="
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
27
|
version: 3.0.0
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: actionpack
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - ">="
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: 3.0.0
|
|
35
|
+
type: :development
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: 3.0.0
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: activemodel
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: 3.0.0
|
|
49
|
+
type: :development
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: 3.0.0
|
|
56
|
+
- !ruby/object:Gem::Dependency
|
|
57
|
+
name: bundler
|
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
- !ruby/object:Gem::Dependency
|
|
71
|
+
name: pry
|
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
- !ruby/object:Gem::Dependency
|
|
85
|
+
name: rake
|
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - ">="
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
type: :development
|
|
92
|
+
prerelease: false
|
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
- !ruby/object:Gem::Dependency
|
|
99
|
+
name: rspec
|
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: 3.0.0
|
|
105
|
+
type: :development
|
|
106
|
+
prerelease: false
|
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: 3.0.0
|
|
112
|
+
- !ruby/object:Gem::Dependency
|
|
113
|
+
name: rubocop
|
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
|
115
|
+
requirements:
|
|
116
|
+
- - '='
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: 0.74.0
|
|
119
|
+
type: :development
|
|
120
|
+
prerelease: false
|
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - '='
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: 0.74.0
|
|
126
|
+
- !ruby/object:Gem::Dependency
|
|
127
|
+
name: simplecov
|
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
|
129
|
+
requirements:
|
|
130
|
+
- - ">="
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: 0.17.0
|
|
133
|
+
type: :development
|
|
134
|
+
prerelease: false
|
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: 0.17.0
|
|
140
|
+
- !ruby/object:Gem::Dependency
|
|
141
|
+
name: yard
|
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
type: :development
|
|
148
|
+
prerelease: false
|
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
150
|
+
requirements:
|
|
151
|
+
- - ">="
|
|
152
|
+
- !ruby/object:Gem::Version
|
|
153
|
+
version: '0'
|
|
28
154
|
description: Object oriented authorization for Rails applications
|
|
29
155
|
email:
|
|
30
156
|
- jonas.nicklas@gmail.com
|
|
@@ -82,8 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
82
208
|
- !ruby/object:Gem::Version
|
|
83
209
|
version: '0'
|
|
84
210
|
requirements: []
|
|
85
|
-
|
|
86
|
-
rubygems_version: 2.5.2
|
|
211
|
+
rubygems_version: 3.2.25
|
|
87
212
|
signing_key:
|
|
88
213
|
specification_version: 4
|
|
89
214
|
summary: OO authorization for Rails
|