pundit 2.1.1 → 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 +4 -4
- data/.rubocop.yml +8 -3
- data/.travis.yml +1 -0
- data/CHANGELOG.md +13 -1
- data/README.md +24 -10
- data/lib/generators/pundit/install/templates/application_policy.rb +1 -1
- data/lib/generators/pundit/policy/templates/policy.rb +4 -3
- data/lib/pundit/authorization.rb +168 -0
- data/lib/pundit/version.rb +1 -1
- data/lib/pundit.rb +17 -170
- data/pundit.gemspec +2 -1
- data/spec/authorization_spec.rb +258 -0
- data/spec/generators_spec.rb +43 -0
- data/spec/policy_finder_spec.rb +1 -1
- data/spec/pundit_spec.rb +33 -239
- data/spec/spec_helper.rb +10 -3
- metadata +27 -8
@@ -0,0 +1,258 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Pundit::Authorization do
|
6
|
+
let(:controller) { Controller.new(user, "update", {}) }
|
7
|
+
let(:user) { double }
|
8
|
+
let(:post) { Post.new(user) }
|
9
|
+
let(:customer_post) { Customer::Post.new(user) }
|
10
|
+
let(:comment) { Comment.new }
|
11
|
+
let(:article) { Article.new }
|
12
|
+
let(:article_tag) { ArticleTag.new }
|
13
|
+
let(:wiki) { Wiki.new }
|
14
|
+
|
15
|
+
describe "#verify_authorized" do
|
16
|
+
it "does nothing when authorized" do
|
17
|
+
controller.authorize(post)
|
18
|
+
controller.verify_authorized
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises an exception when not authorized" do
|
22
|
+
expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#verify_policy_scoped" do
|
27
|
+
it "does nothing when policy_scope is used" do
|
28
|
+
controller.policy_scope(Post)
|
29
|
+
controller.verify_policy_scoped
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises an exception when policy_scope is not used" do
|
33
|
+
expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#pundit_policy_authorized?" do
|
38
|
+
it "is true when authorized" do
|
39
|
+
controller.authorize(post)
|
40
|
+
expect(controller.pundit_policy_authorized?).to be true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is false when not authorized" do
|
44
|
+
expect(controller.pundit_policy_authorized?).to be false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#pundit_policy_scoped?" do
|
49
|
+
it "is true when policy_scope is used" do
|
50
|
+
controller.policy_scope(Post)
|
51
|
+
expect(controller.pundit_policy_scoped?).to be true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "is false when policy scope is not used" do
|
55
|
+
expect(controller.pundit_policy_scoped?).to be false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#authorize" do
|
60
|
+
it "infers the policy name and authorizes based on it" do
|
61
|
+
expect(controller.authorize(post)).to be_truthy
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns the record on successful authorization" do
|
65
|
+
expect(controller.authorize(post)).to eq(post)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns the record when passed record with namespace " do
|
69
|
+
expect(controller.authorize([:project, comment], :update?)).to eq(comment)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns the record when passed record with nested namespace " do
|
73
|
+
expect(controller.authorize([:project, :admin, comment], :update?)).to eq(comment)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns the policy name symbol when passed record with headless policy" do
|
77
|
+
expect(controller.authorize(:publication, :create?)).to eq(:publication)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns the class when passed record not a particular instance" do
|
81
|
+
expect(controller.authorize(Post, :show?)).to eq(Post)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "can be given a different permission to check" do
|
85
|
+
expect(controller.authorize(post, :show?)).to be_truthy
|
86
|
+
expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "can be given a different policy class" do
|
90
|
+
expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy
|
91
|
+
end
|
92
|
+
|
93
|
+
it "works with anonymous class policies" do
|
94
|
+
expect(controller.authorize(article_tag, :show?)).to be_truthy
|
95
|
+
expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "throws an exception when the permission check fails" do
|
99
|
+
expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "throws an exception when a policy cannot be found" do
|
103
|
+
expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "caches the policy" do
|
107
|
+
expect(controller.policies[post]).to be_nil
|
108
|
+
controller.authorize(post)
|
109
|
+
expect(controller.policies[post]).not_to be_nil
|
110
|
+
end
|
111
|
+
|
112
|
+
it "raises an error when the given record is nil" do
|
113
|
+
expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "raises an error with a invalid policy constructor" do
|
117
|
+
expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#skip_authorization" do
|
122
|
+
it "disables authorization verification" do
|
123
|
+
controller.skip_authorization
|
124
|
+
expect { controller.verify_authorized }.not_to raise_error
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#skip_policy_scope" do
|
129
|
+
it "disables policy scope verification" do
|
130
|
+
controller.skip_policy_scope
|
131
|
+
expect { controller.verify_policy_scoped }.not_to raise_error
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#pundit_user" do
|
136
|
+
it "returns the same thing as current_user" do
|
137
|
+
expect(controller.pundit_user).to eq controller.current_user
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "#policy" do
|
142
|
+
it "returns an instantiated policy" do
|
143
|
+
policy = controller.policy(post)
|
144
|
+
expect(policy.user).to eq user
|
145
|
+
expect(policy.post).to eq post
|
146
|
+
end
|
147
|
+
|
148
|
+
it "throws an exception if the given policy can't be found" do
|
149
|
+
expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "raises an error with a invalid policy constructor" do
|
153
|
+
expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "allows policy to be injected" do
|
157
|
+
new_policy = OpenStruct.new
|
158
|
+
controller.policies[post] = new_policy
|
159
|
+
|
160
|
+
expect(controller.policy(post)).to eq new_policy
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#policy_scope" do
|
165
|
+
it "returns an instantiated policy scope" do
|
166
|
+
expect(controller.policy_scope(Post)).to eq :published
|
167
|
+
end
|
168
|
+
|
169
|
+
it "allows policy scope class to be overriden" do
|
170
|
+
expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published
|
171
|
+
end
|
172
|
+
|
173
|
+
it "throws an exception if the given policy can't be found" do
|
174
|
+
expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "raises an error with a invalid policy scope constructor" do
|
178
|
+
expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "allows policy_scope to be injected" do
|
182
|
+
new_scope = OpenStruct.new
|
183
|
+
controller.policy_scopes[Post] = new_scope
|
184
|
+
|
185
|
+
expect(controller.policy_scope(Post)).to eq new_scope
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#permitted_attributes" do
|
190
|
+
it "checks policy for permitted attributes" do
|
191
|
+
params = ActionController::Parameters.new(
|
192
|
+
post: {
|
193
|
+
title: "Hello",
|
194
|
+
votes: 5,
|
195
|
+
admin: true
|
196
|
+
}
|
197
|
+
)
|
198
|
+
|
199
|
+
action = "update"
|
200
|
+
|
201
|
+
expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(
|
202
|
+
"title" => "Hello",
|
203
|
+
"votes" => 5
|
204
|
+
)
|
205
|
+
expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq("votes" => 5)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "checks policy for permitted attributes for record of a ActiveModel type" do
|
209
|
+
params = ActionController::Parameters.new(
|
210
|
+
customer_post: {
|
211
|
+
title: "Hello",
|
212
|
+
votes: 5,
|
213
|
+
admin: true
|
214
|
+
}
|
215
|
+
)
|
216
|
+
|
217
|
+
action = "update"
|
218
|
+
|
219
|
+
expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(
|
220
|
+
"title" => "Hello",
|
221
|
+
"votes" => 5
|
222
|
+
)
|
223
|
+
expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(
|
224
|
+
"votes" => 5
|
225
|
+
)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#permitted_attributes_for_action" do
|
230
|
+
it "is checked if it is defined in the policy" do
|
231
|
+
params = ActionController::Parameters.new(
|
232
|
+
post: {
|
233
|
+
title: "Hello",
|
234
|
+
body: "blah",
|
235
|
+
votes: 5,
|
236
|
+
admin: true
|
237
|
+
}
|
238
|
+
)
|
239
|
+
|
240
|
+
action = "revise"
|
241
|
+
expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
|
242
|
+
end
|
243
|
+
|
244
|
+
it "can be explicitly set" do
|
245
|
+
params = ActionController::Parameters.new(
|
246
|
+
post: {
|
247
|
+
title: "Hello",
|
248
|
+
body: "blah",
|
249
|
+
votes: 5,
|
250
|
+
admin: true
|
251
|
+
}
|
252
|
+
)
|
253
|
+
|
254
|
+
action = "update"
|
255
|
+
expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "tmpdir"
|
5
|
+
|
6
|
+
require "rails/generators"
|
7
|
+
require "generators/pundit/install/install_generator"
|
8
|
+
require "generators/pundit/policy/policy_generator"
|
9
|
+
|
10
|
+
RSpec.describe "generators" do
|
11
|
+
before(:all) do
|
12
|
+
@tmpdir = Dir.mktmpdir
|
13
|
+
|
14
|
+
Dir.chdir(@tmpdir) do
|
15
|
+
Pundit::Generators::InstallGenerator.new([], { quiet: true }).invoke_all
|
16
|
+
Pundit::Generators::PolicyGenerator.new(%w[Widget], { quiet: true }).invoke_all
|
17
|
+
|
18
|
+
require "./app/policies/application_policy"
|
19
|
+
require "./app/policies/widget_policy"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:all) do
|
24
|
+
FileUtils.remove_entry(@tmpdir)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "WidgetPolicy", type: :policy do
|
28
|
+
permissions :index?, :show?, :create?, :new?, :update?, :edit?, :destroy? do
|
29
|
+
it "has safe defaults" do
|
30
|
+
expect(WidgetPolicy).not_to permit(double("User"), double("Widget"))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "WidgetPolicy::Scope" do
|
35
|
+
describe "#resolve" do
|
36
|
+
it "raises a descriptive error" do
|
37
|
+
scope = WidgetPolicy::Scope.new(double("User"), double("User.all"))
|
38
|
+
expect { scope.resolve }.to raise_error(NotImplementedError, /WidgetPolicy::Scope/)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/policy_finder_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
+
class Foo; end
|
5
6
|
RSpec.describe Pundit::PolicyFinder do
|
6
7
|
let(:user) { double }
|
7
8
|
let(:post) { Post.new(user) }
|
@@ -114,7 +115,6 @@ RSpec.describe Pundit::PolicyFinder do
|
|
114
115
|
|
115
116
|
context "with a class that doesn't have an associated policy" do
|
116
117
|
it "returns nil" do
|
117
|
-
class Foo; end
|
118
118
|
object = described_class.new(Foo)
|
119
119
|
|
120
120
|
expect(object.policy).to eq nil
|
data/spec/pundit_spec.rb
CHANGED
@@ -10,15 +10,13 @@ RSpec.describe Pundit do
|
|
10
10
|
let(:comment) { Comment.new }
|
11
11
|
let(:comment_four_five_six) { CommentFourFiveSix.new }
|
12
12
|
let(:article) { Article.new }
|
13
|
-
let(:controller) { Controller.new(user, "update", {}) }
|
14
13
|
let(:artificial_blog) { ArtificialBlog.new }
|
15
14
|
let(:article_tag) { ArticleTag.new }
|
16
|
-
let(:comments_relation) { CommentsRelation.new }
|
17
|
-
let(:empty_comments_relation) { CommentsRelation.new(true) }
|
15
|
+
let(:comments_relation) { CommentsRelation.new(empty: false) }
|
16
|
+
let(:empty_comments_relation) { CommentsRelation.new(empty: true) }
|
18
17
|
let(:tag_four_five_six) { ProjectOneTwoThree::TagFourFiveSix.new(user) }
|
19
18
|
let(:avatar_four_five_six) { ProjectOneTwoThree::AvatarFourFiveSix.new }
|
20
19
|
let(:wiki) { Wiki.new }
|
21
|
-
let(:thread) { Thread.new }
|
22
20
|
|
23
21
|
describe ".authorize" do
|
24
22
|
it "infers the policy and authorizes based on it" do
|
@@ -49,6 +47,11 @@ RSpec.describe Pundit do
|
|
49
47
|
expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy
|
50
48
|
end
|
51
49
|
|
50
|
+
it "can be given a different policy class using namespaces" do
|
51
|
+
expect(PublicationPolicy).to receive(:new).with(user, comment).and_call_original
|
52
|
+
expect(Pundit.authorize(user, [:project, comment], :create?, policy_class: PublicationPolicy)).to be_truthy
|
53
|
+
end
|
54
|
+
|
52
55
|
it "works with anonymous class policies" do
|
53
56
|
expect(Pundit.authorize(user, article_tag, :show?)).to be_truthy
|
54
57
|
expect { Pundit.authorize(user, article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
@@ -66,6 +69,18 @@ RSpec.describe Pundit do
|
|
66
69
|
# rubocop:enable Style/MultilineBlockChain
|
67
70
|
end
|
68
71
|
|
72
|
+
it "raises an error with a the record, query and action when the record is namespaced" do
|
73
|
+
# rubocop:disable Style/MultilineBlockChain
|
74
|
+
expect do
|
75
|
+
Pundit.authorize(user, [:project, :admin, comment], :destroy?)
|
76
|
+
end.to raise_error(Pundit::NotAuthorizedError, "not allowed to destroy? this Comment") do |error|
|
77
|
+
expect(error.query).to eq :destroy?
|
78
|
+
expect(error.record).to eq comment
|
79
|
+
expect(error.policy).to eq Pundit.policy(user, [:project, :admin, comment])
|
80
|
+
end
|
81
|
+
# rubocop:enable Style/MultilineBlockChain
|
82
|
+
end
|
83
|
+
|
69
84
|
it "raises an error with a invalid policy constructor" do
|
70
85
|
expect do
|
71
86
|
Pundit.authorize(user, wiki, :update?)
|
@@ -380,247 +395,26 @@ RSpec.describe Pundit do
|
|
380
395
|
end
|
381
396
|
end
|
382
397
|
|
383
|
-
describe "
|
384
|
-
it "
|
385
|
-
|
386
|
-
controller.verify_authorized
|
387
|
-
end
|
388
|
-
|
389
|
-
it "raises an exception when not authorized" do
|
390
|
-
expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
describe "#verify_policy_scoped" do
|
395
|
-
it "does nothing when policy_scope is used" do
|
396
|
-
controller.policy_scope(Post)
|
397
|
-
controller.verify_policy_scoped
|
398
|
-
end
|
399
|
-
|
400
|
-
it "raises an exception when policy_scope is not used" do
|
401
|
-
expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
describe "#pundit_policy_authorized?" do
|
406
|
-
it "is true when authorized" do
|
407
|
-
controller.authorize(post)
|
408
|
-
expect(controller.pundit_policy_authorized?).to be true
|
409
|
-
end
|
410
|
-
|
411
|
-
it "is false when not authorized" do
|
412
|
-
expect(controller.pundit_policy_authorized?).to be false
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
describe "#pundit_policy_scoped?" do
|
417
|
-
it "is true when policy_scope is used" do
|
418
|
-
controller.policy_scope(Post)
|
419
|
-
expect(controller.pundit_policy_scoped?).to be true
|
420
|
-
end
|
421
|
-
|
422
|
-
it "is false when policy scope is not used" do
|
423
|
-
expect(controller.pundit_policy_scoped?).to be false
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
describe "#authorize" do
|
428
|
-
it "infers the policy name and authorizes based on it" do
|
429
|
-
expect(controller.authorize(post)).to be_truthy
|
430
|
-
end
|
431
|
-
|
432
|
-
it "returns the record on successful authorization" do
|
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)
|
450
|
-
end
|
451
|
-
|
452
|
-
it "can be given a different permission to check" do
|
453
|
-
expect(controller.authorize(post, :show?)).to be_truthy
|
454
|
-
expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
455
|
-
end
|
456
|
-
|
457
|
-
it "can be given a different policy class" do
|
458
|
-
expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy
|
459
|
-
end
|
460
|
-
|
461
|
-
it "works with anonymous class policies" do
|
462
|
-
expect(controller.authorize(article_tag, :show?)).to be_truthy
|
463
|
-
expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
464
|
-
end
|
465
|
-
|
466
|
-
it "throws an exception when the permission check fails" do
|
467
|
-
expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
|
468
|
-
end
|
469
|
-
|
470
|
-
it "throws an exception when a policy cannot be found" do
|
471
|
-
expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)
|
472
|
-
end
|
473
|
-
|
474
|
-
it "caches the policy" do
|
475
|
-
expect(controller.policies[post]).to be_nil
|
476
|
-
controller.authorize(post)
|
477
|
-
expect(controller.policies[post]).not_to be_nil
|
478
|
-
end
|
479
|
-
|
480
|
-
it "raises an error when the given record is nil" do
|
481
|
-
expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
482
|
-
end
|
483
|
-
|
484
|
-
it "raises an error with a invalid policy constructor" do
|
485
|
-
expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
describe "#skip_authorization" do
|
490
|
-
it "disables authorization verification" do
|
491
|
-
controller.skip_authorization
|
492
|
-
expect { controller.verify_authorized }.not_to raise_error
|
493
|
-
end
|
494
|
-
end
|
495
|
-
|
496
|
-
describe "#skip_policy_scope" do
|
497
|
-
it "disables policy scope verification" do
|
498
|
-
controller.skip_policy_scope
|
499
|
-
expect { controller.verify_policy_scoped }.not_to raise_error
|
500
|
-
end
|
501
|
-
end
|
398
|
+
describe ".included" do
|
399
|
+
it "includes Authorization module" do
|
400
|
+
klass = Class.new
|
502
401
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
describe "#policy" do
|
510
|
-
it "returns an instantiated policy" do
|
511
|
-
policy = controller.policy(post)
|
512
|
-
expect(policy.user).to eq user
|
513
|
-
expect(policy.post).to eq post
|
514
|
-
end
|
515
|
-
|
516
|
-
it "throws an exception if the given policy can't be found" do
|
517
|
-
expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
|
518
|
-
end
|
519
|
-
|
520
|
-
it "raises an error with a invalid policy constructor" do
|
521
|
-
expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)
|
522
|
-
end
|
523
|
-
|
524
|
-
it "allows policy to be injected" do
|
525
|
-
new_policy = OpenStruct.new
|
526
|
-
controller.policies[post] = new_policy
|
527
|
-
|
528
|
-
expect(controller.policy(post)).to eq new_policy
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
describe "#policy_scope" do
|
533
|
-
it "returns an instantiated policy scope" do
|
534
|
-
expect(controller.policy_scope(Post)).to eq :published
|
535
|
-
end
|
536
|
-
|
537
|
-
it "allows policy scope class to be overriden" do
|
538
|
-
expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published
|
539
|
-
end
|
540
|
-
|
541
|
-
it "throws an exception if the given policy can't be found" do
|
542
|
-
expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
|
543
|
-
end
|
402
|
+
ActiveSupport::Deprecation.silence do
|
403
|
+
klass.include Pundit
|
404
|
+
end
|
544
405
|
|
545
|
-
|
546
|
-
expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)
|
406
|
+
expect(klass).to include Pundit::Authorization
|
547
407
|
end
|
548
408
|
|
549
|
-
it "
|
550
|
-
|
551
|
-
|
409
|
+
it "warns about deprecation" do
|
410
|
+
klass = Class.new
|
411
|
+
allow(ActiveSupport::Deprecation).to receive(:warn)
|
552
412
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
describe "#permitted_attributes" do
|
558
|
-
it "checks policy for permitted attributes" do
|
559
|
-
params = ActionController::Parameters.new(
|
560
|
-
post: {
|
561
|
-
title: "Hello",
|
562
|
-
votes: 5,
|
563
|
-
admin: true
|
564
|
-
}
|
565
|
-
)
|
566
|
-
|
567
|
-
action = "update"
|
568
|
-
|
569
|
-
expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(
|
570
|
-
"title" => "Hello",
|
571
|
-
"votes" => 5
|
572
|
-
)
|
573
|
-
expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq("votes" => 5)
|
574
|
-
end
|
575
|
-
|
576
|
-
it "checks policy for permitted attributes for record of a ActiveModel type" do
|
577
|
-
params = ActionController::Parameters.new(
|
578
|
-
customer_post: {
|
579
|
-
title: "Hello",
|
580
|
-
votes: 5,
|
581
|
-
admin: true
|
582
|
-
}
|
583
|
-
)
|
584
|
-
|
585
|
-
action = "update"
|
586
|
-
|
587
|
-
expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(
|
588
|
-
"title" => "Hello",
|
589
|
-
"votes" => 5
|
590
|
-
)
|
591
|
-
expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(
|
592
|
-
"votes" => 5
|
593
|
-
)
|
594
|
-
end
|
595
|
-
end
|
413
|
+
ActiveSupport::Deprecation.silence do
|
414
|
+
klass.include Pundit
|
415
|
+
end
|
596
416
|
|
597
|
-
|
598
|
-
it "is checked if it is defined in the policy" do
|
599
|
-
params = ActionController::Parameters.new(
|
600
|
-
post: {
|
601
|
-
title: "Hello",
|
602
|
-
body: "blah",
|
603
|
-
votes: 5,
|
604
|
-
admin: true
|
605
|
-
}
|
606
|
-
)
|
607
|
-
|
608
|
-
action = "revise"
|
609
|
-
expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
|
610
|
-
end
|
611
|
-
|
612
|
-
it "can be explicitly set" do
|
613
|
-
params = ActionController::Parameters.new(
|
614
|
-
post: {
|
615
|
-
title: "Hello",
|
616
|
-
body: "blah",
|
617
|
-
votes: 5,
|
618
|
-
admin: true
|
619
|
-
}
|
620
|
-
)
|
621
|
-
|
622
|
-
action = "update"
|
623
|
-
expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
|
417
|
+
expect(ActiveSupport::Deprecation).to have_received(:warn).with start_with("'include Pundit' is deprecated")
|
624
418
|
end
|
625
419
|
end
|
626
420
|
|
data/spec/spec_helper.rb
CHANGED
@@ -80,6 +80,7 @@ end
|
|
80
80
|
|
81
81
|
class CommentScope
|
82
82
|
attr_reader :original_object
|
83
|
+
|
83
84
|
def initialize(original_object)
|
84
85
|
@original_object = original_object
|
85
86
|
end
|
@@ -114,7 +115,7 @@ class Comment
|
|
114
115
|
end
|
115
116
|
|
116
117
|
class CommentsRelation
|
117
|
-
def initialize(empty
|
118
|
+
def initialize(empty: false)
|
118
119
|
@empty = empty
|
119
120
|
end
|
120
121
|
|
@@ -185,6 +186,10 @@ module Project
|
|
185
186
|
def update?
|
186
187
|
true
|
187
188
|
end
|
189
|
+
|
190
|
+
def destroy?
|
191
|
+
false
|
192
|
+
end
|
188
193
|
end
|
189
194
|
end
|
190
195
|
end
|
@@ -196,10 +201,10 @@ class DenierPolicy < Struct.new(:user, :record)
|
|
196
201
|
end
|
197
202
|
|
198
203
|
class Controller
|
199
|
-
include Pundit
|
204
|
+
include Pundit::Authorization
|
200
205
|
# Mark protected methods public so they may be called in test
|
201
206
|
# rubocop:disable Style/AccessModifierDeclarations
|
202
|
-
public(*Pundit.protected_instance_methods)
|
207
|
+
public(*Pundit::Authorization.protected_instance_methods)
|
203
208
|
# rubocop:enable Style/AccessModifierDeclarations
|
204
209
|
|
205
210
|
attr_reader :current_user, :action_name, :params
|
@@ -228,6 +233,7 @@ class NilClassPolicy < Struct.new(:user, :record)
|
|
228
233
|
end
|
229
234
|
|
230
235
|
class Wiki; end
|
236
|
+
|
231
237
|
class WikiPolicy
|
232
238
|
class Scope
|
233
239
|
# deliberate typo method
|
@@ -238,6 +244,7 @@ end
|
|
238
244
|
class Thread
|
239
245
|
def self.all; end
|
240
246
|
end
|
247
|
+
|
241
248
|
class ThreadPolicy < Struct.new(:user, :thread)
|
242
249
|
class Scope < Struct.new(:user, :scope)
|
243
250
|
def resolve
|