pundit 2.5.0 → 2.5.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/pundit/authorization.rb +18 -0
- data/lib/pundit/cache_store/legacy_store.rb +3 -0
- data/lib/pundit/cache_store/null_store.rb +3 -0
- data/lib/pundit/cache_store.rb +2 -0
- data/lib/pundit/context.rb +13 -0
- data/lib/pundit/error.rb +71 -0
- data/lib/pundit/helper.rb +16 -0
- data/lib/pundit/policy_finder.rb +11 -0
- data/lib/pundit/railtie.rb +1 -0
- data/lib/pundit/rspec.rb +2 -0
- data/lib/pundit/version.rb +1 -1
- data/lib/pundit.rb +10 -69
- metadata +4 -68
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -20
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
- data/.github/PULL_REQUEST_TEMPLATE/gem_release_template.md +0 -8
- data/.github/pull_request_template.md +0 -9
- data/.github/workflows/main.yml +0 -147
- data/.github/workflows/push_gem.yml +0 -33
- data/.gitignore +0 -19
- data/.rubocop.yml +0 -73
- data/.rubocop_ignore_git.yml +0 -7
- data/.yardopts +0 -1
- data/CODE_OF_CONDUCT.md +0 -28
- data/CONTRIBUTING.md +0 -31
- data/Gemfile +0 -28
- data/Rakefile +0 -21
- data/config/rubocop-rspec.yml +0 -5
- data/pundit.gemspec +0 -31
- data/spec/authorization_spec.rb +0 -331
- data/spec/generators_spec.rb +0 -43
- data/spec/policies/post_policy_spec.rb +0 -49
- data/spec/policy_finder_spec.rb +0 -191
- data/spec/pundit/helper_spec.rb +0 -18
- data/spec/pundit_spec.rb +0 -474
- data/spec/rspec_dsl_spec.rb +0 -81
- data/spec/simple_cov_check_action_formatter.rb +0 -79
- data/spec/spec_helper.rb +0 -35
- data/spec/support/lib/controller.rb +0 -38
- data/spec/support/lib/custom_cache.rb +0 -19
- data/spec/support/lib/instance_tracking.rb +0 -20
- data/spec/support/models/article.rb +0 -4
- data/spec/support/models/article_tag.rb +0 -7
- data/spec/support/models/artificial_blog.rb +0 -7
- data/spec/support/models/blog.rb +0 -4
- data/spec/support/models/comment.rb +0 -5
- data/spec/support/models/comment_four_five_six.rb +0 -5
- data/spec/support/models/comment_scope.rb +0 -13
- data/spec/support/models/comments_relation.rb +0 -15
- data/spec/support/models/customer/post.rb +0 -11
- data/spec/support/models/default_scope_contains_error.rb +0 -5
- data/spec/support/models/dummy_current_user.rb +0 -7
- data/spec/support/models/foo.rb +0 -4
- data/spec/support/models/post.rb +0 -25
- data/spec/support/models/post_four_five_six.rb +0 -9
- data/spec/support/models/project_one_two_three/avatar_four_five_six.rb +0 -7
- data/spec/support/models/project_one_two_three/tag_four_five_six.rb +0 -11
- data/spec/support/models/wiki.rb +0 -4
- data/spec/support/policies/article_tag_other_name_policy.rb +0 -13
- data/spec/support/policies/base_policy.rb +0 -23
- data/spec/support/policies/blog_policy.rb +0 -5
- data/spec/support/policies/comment_policy.rb +0 -11
- data/spec/support/policies/criteria_policy.rb +0 -5
- data/spec/support/policies/default_scope_contains_error_policy.rb +0 -10
- data/spec/support/policies/denier_policy.rb +0 -7
- data/spec/support/policies/dummy_current_user_policy.rb +0 -9
- data/spec/support/policies/nil_class_policy.rb +0 -17
- data/spec/support/policies/post_policy.rb +0 -36
- data/spec/support/policies/project/admin/comment_policy.rb +0 -15
- data/spec/support/policies/project/comment_policy.rb +0 -17
- data/spec/support/policies/project/criteria_policy.rb +0 -7
- data/spec/support/policies/project/post_policy.rb +0 -13
- data/spec/support/policies/project_one_two_three/avatar_four_five_six_policy.rb +0 -6
- data/spec/support/policies/project_one_two_three/comment_four_five_six_policy.rb +0 -6
- data/spec/support/policies/project_one_two_three/criteria_four_five_six_policy.rb +0 -6
- data/spec/support/policies/project_one_two_three/post_four_five_six_policy.rb +0 -6
- data/spec/support/policies/project_one_two_three/tag_four_five_six_policy.rb +0 -6
- data/spec/support/policies/publication_policy.rb +0 -13
- data/spec/support/policies/wiki_policy.rb +0 -8
data/spec/pundit_spec.rb
DELETED
@@ -1,474 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
RSpec.describe Pundit do
|
6
|
-
let(:user) { double }
|
7
|
-
let(:post) { Post.new(user) }
|
8
|
-
let(:customer_post) { Customer::Post.new(user) }
|
9
|
-
let(:post_four_five_six) { PostFourFiveSix.new(user) }
|
10
|
-
let(:comment) { Comment.new }
|
11
|
-
let(:comment_four_five_six) { CommentFourFiveSix.new }
|
12
|
-
let(:article) { Article.new }
|
13
|
-
let(:artificial_blog) { ArtificialBlog.new }
|
14
|
-
let(:article_tag) { ArticleTag.new }
|
15
|
-
let(:comments_relation) { CommentsRelation.new(empty: false) }
|
16
|
-
let(:empty_comments_relation) { CommentsRelation.new(empty: true) }
|
17
|
-
let(:tag_four_five_six) { ProjectOneTwoThree::TagFourFiveSix.new(user) }
|
18
|
-
let(:avatar_four_five_six) { ProjectOneTwoThree::AvatarFourFiveSix.new }
|
19
|
-
let(:wiki) { Wiki.new }
|
20
|
-
|
21
|
-
describe ".authorize" do
|
22
|
-
it "infers the policy and authorizes based on it" do
|
23
|
-
expect(Pundit.authorize(user, post, :update?)).to be_truthy
|
24
|
-
end
|
25
|
-
|
26
|
-
it "returns the record on successful authorization" do
|
27
|
-
expect(Pundit.authorize(user, post, :update?)).to eq(post)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "returns the record when passed record with namespace " do
|
31
|
-
expect(Pundit.authorize(user, [:project, comment], :update?)).to eq(comment)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "returns the record when passed record with nested namespace " do
|
35
|
-
expect(Pundit.authorize(user, [:project, :admin, comment], :update?)).to eq(comment)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "returns the policy name symbol when passed record with headless policy" do
|
39
|
-
expect(Pundit.authorize(user, :publication, :create?)).to eq(:publication)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "returns the class when passed record not a particular instance" do
|
43
|
-
expect(Pundit.authorize(user, Post, :show?)).to eq(Post)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "works with anonymous class policies" do
|
47
|
-
expect(Pundit.authorize(user, article_tag, :show?)).to be_truthy
|
48
|
-
expect { Pundit.authorize(user, article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
|
49
|
-
end
|
50
|
-
|
51
|
-
it "raises an error with the policy, query and record" do
|
52
|
-
# rubocop:disable Style/MultilineBlockChain
|
53
|
-
expect do
|
54
|
-
Pundit.authorize(user, post, :destroy?)
|
55
|
-
end.to raise_error(Pundit::NotAuthorizedError, "not allowed to PostPolicy#destroy? this Post") do |error|
|
56
|
-
expect(error.query).to eq :destroy?
|
57
|
-
expect(error.record).to eq post
|
58
|
-
expect(error.policy).to have_attributes(
|
59
|
-
user: user,
|
60
|
-
record: post
|
61
|
-
)
|
62
|
-
expect(error.policy).to be_a(PostPolicy)
|
63
|
-
end
|
64
|
-
# rubocop:enable Style/MultilineBlockChain
|
65
|
-
end
|
66
|
-
|
67
|
-
it "raises an error with the policy, query and record when the record is namespaced" do
|
68
|
-
# rubocop:disable Style/MultilineBlockChain
|
69
|
-
expect do
|
70
|
-
Pundit.authorize(user, [:project, :admin, comment], :destroy?)
|
71
|
-
end.to raise_error(Pundit::NotAuthorizedError,
|
72
|
-
"not allowed to Project::Admin::CommentPolicy#destroy? this Comment") do |error|
|
73
|
-
expect(error.query).to eq :destroy?
|
74
|
-
expect(error.record).to eq comment
|
75
|
-
expect(error.policy).to have_attributes(
|
76
|
-
user: user,
|
77
|
-
record: comment
|
78
|
-
)
|
79
|
-
expect(error.policy).to be_a(Project::Admin::CommentPolicy)
|
80
|
-
end
|
81
|
-
# rubocop:enable Style/MultilineBlockChain
|
82
|
-
end
|
83
|
-
|
84
|
-
it "raises an error with the policy, query and the class name when a Class is given" do
|
85
|
-
# rubocop:disable Style/MultilineBlockChain
|
86
|
-
expect do
|
87
|
-
Pundit.authorize(user, Post, :destroy?)
|
88
|
-
end.to raise_error(Pundit::NotAuthorizedError, "not allowed to PostPolicy#destroy? Post") do |error|
|
89
|
-
expect(error.query).to eq :destroy?
|
90
|
-
expect(error.record).to eq Post
|
91
|
-
expect(error.policy).to have_attributes(
|
92
|
-
user: user,
|
93
|
-
record: Post
|
94
|
-
)
|
95
|
-
expect(error.policy).to be_a(PostPolicy)
|
96
|
-
end
|
97
|
-
# rubocop:enable Style/MultilineBlockChain
|
98
|
-
end
|
99
|
-
|
100
|
-
it "raises an error with a invalid policy constructor" do
|
101
|
-
expect do
|
102
|
-
Pundit.authorize(user, wiki, :update?)
|
103
|
-
end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
|
104
|
-
end
|
105
|
-
|
106
|
-
context "when passed a policy class" do
|
107
|
-
it "uses the passed policy class" do
|
108
|
-
expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy
|
109
|
-
end
|
110
|
-
|
111
|
-
# This is documenting past behaviour.
|
112
|
-
it "doesn't cache the policy class" do
|
113
|
-
cache = {}
|
114
|
-
|
115
|
-
expect do
|
116
|
-
Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)
|
117
|
-
Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)
|
118
|
-
end.to change { PublicationPolicy.instances }.by(2)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
context "when passed a policy class while simultaenously passing a namespace" do
|
123
|
-
it "uses the passed policy class" do
|
124
|
-
expect(PublicationPolicy).to receive(:new).with(user, comment).and_call_original
|
125
|
-
expect(Pundit.authorize(user, [:project, comment], :create?, policy_class: PublicationPolicy)).to be_truthy
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
context "when passed an explicit cache" do
|
130
|
-
it "uses the hash assignment interface on the cache" do
|
131
|
-
custom_cache = CustomCache.new
|
132
|
-
|
133
|
-
Pundit.authorize(user, post, :update?, cache: custom_cache)
|
134
|
-
|
135
|
-
expect(custom_cache.to_h).to match({
|
136
|
-
post => kind_of(PostPolicy)
|
137
|
-
})
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe ".policy_scope" do
|
143
|
-
it "returns an instantiated policy scope given a plain model class" do
|
144
|
-
expect(Pundit.policy_scope(user, Post)).to eq :published
|
145
|
-
end
|
146
|
-
|
147
|
-
it "returns an instantiated policy scope given an active model class" do
|
148
|
-
expect(Pundit.policy_scope(user, Comment)).to eq CommentScope.new(Comment)
|
149
|
-
end
|
150
|
-
|
151
|
-
it "returns an instantiated policy scope given an active record relation" do
|
152
|
-
expect(Pundit.policy_scope(user, comments_relation)).to eq CommentScope.new(comments_relation)
|
153
|
-
end
|
154
|
-
|
155
|
-
it "returns an instantiated policy scope given an empty active record relation" do
|
156
|
-
expect(Pundit.policy_scope(user, empty_comments_relation)).to eq CommentScope.new(empty_comments_relation)
|
157
|
-
end
|
158
|
-
|
159
|
-
it "returns an instantiated policy scope given an array of a symbol and plain model class" do
|
160
|
-
expect(Pundit.policy_scope(user, [:project, Post])).to eq :read
|
161
|
-
end
|
162
|
-
|
163
|
-
it "returns an instantiated policy scope given an array of a symbol and active model class" do
|
164
|
-
expect(Pundit.policy_scope(user, [:project, Comment])).to eq Comment
|
165
|
-
end
|
166
|
-
|
167
|
-
it "returns nil if the given policy scope can't be found" do
|
168
|
-
expect(Pundit.policy_scope(user, Article)).to be_nil
|
169
|
-
end
|
170
|
-
|
171
|
-
it "raises an exception if nil object given" do
|
172
|
-
expect { Pundit.policy_scope(user, nil) }.to raise_error(Pundit::NotDefinedError)
|
173
|
-
end
|
174
|
-
|
175
|
-
it "raises an error with a invalid policy scope constructor" do
|
176
|
-
expect do
|
177
|
-
Pundit.policy_scope(user, Wiki)
|
178
|
-
end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy::Scope> constructor is called")
|
179
|
-
end
|
180
|
-
|
181
|
-
it "raises an original error with a policy scope that contains error" do
|
182
|
-
expect do
|
183
|
-
Pundit.policy_scope(user, DefaultScopeContainsError)
|
184
|
-
end.to raise_error(RuntimeError, "This is an arbitrary error that should bubble up")
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
describe ".policy_scope!" do
|
189
|
-
it "returns an instantiated policy scope given a plain model class" do
|
190
|
-
expect(Pundit.policy_scope!(user, Post)).to eq :published
|
191
|
-
end
|
192
|
-
|
193
|
-
it "returns an instantiated policy scope given an active model class" do
|
194
|
-
expect(Pundit.policy_scope!(user, Comment)).to eq CommentScope.new(Comment)
|
195
|
-
end
|
196
|
-
|
197
|
-
it "throws an exception if the given policy scope can't be found" do
|
198
|
-
expect { Pundit.policy_scope!(user, Article) }.to raise_error(Pundit::NotDefinedError)
|
199
|
-
end
|
200
|
-
|
201
|
-
it "throws an exception if the given policy scope can't be found" do
|
202
|
-
expect { Pundit.policy_scope!(user, ArticleTag) }.to raise_error(Pundit::NotDefinedError)
|
203
|
-
end
|
204
|
-
|
205
|
-
it "throws an exception if the given policy scope is nil" do
|
206
|
-
expect do
|
207
|
-
Pundit.policy_scope!(user, nil)
|
208
|
-
end.to raise_error(Pundit::NotDefinedError, "Cannot scope NilClass")
|
209
|
-
end
|
210
|
-
|
211
|
-
it "returns an instantiated policy scope given an array of a symbol and plain model class" do
|
212
|
-
expect(Pundit.policy_scope!(user, [:project, Post])).to eq :read
|
213
|
-
end
|
214
|
-
|
215
|
-
it "returns an instantiated policy scope given an array of a symbol and active model class" do
|
216
|
-
expect(Pundit.policy_scope!(user, [:project, Comment])).to eq Comment
|
217
|
-
end
|
218
|
-
|
219
|
-
it "raises an error with a invalid policy scope constructor" do
|
220
|
-
expect do
|
221
|
-
Pundit.policy_scope(user, Wiki)
|
222
|
-
end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy::Scope> constructor is called")
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
describe ".policy" do
|
227
|
-
it "returns an instantiated policy given a plain model instance" do
|
228
|
-
policy = Pundit.policy(user, post)
|
229
|
-
expect(policy.user).to eq user
|
230
|
-
expect(policy.post).to eq post
|
231
|
-
end
|
232
|
-
|
233
|
-
it "returns an instantiated policy given an active model instance" do
|
234
|
-
policy = Pundit.policy(user, comment)
|
235
|
-
expect(policy.user).to eq user
|
236
|
-
expect(policy.comment).to eq comment
|
237
|
-
end
|
238
|
-
|
239
|
-
it "returns an instantiated policy given a plain model class" do
|
240
|
-
policy = Pundit.policy(user, Post)
|
241
|
-
expect(policy.user).to eq user
|
242
|
-
expect(policy.post).to eq Post
|
243
|
-
end
|
244
|
-
|
245
|
-
it "returns an instantiated policy given an active model class" do
|
246
|
-
policy = Pundit.policy(user, Comment)
|
247
|
-
expect(policy.user).to eq user
|
248
|
-
expect(policy.comment).to eq Comment
|
249
|
-
end
|
250
|
-
|
251
|
-
it "returns an instantiated policy given a symbol" do
|
252
|
-
policy = Pundit.policy(user, :criteria)
|
253
|
-
expect(policy.class).to eq CriteriaPolicy
|
254
|
-
expect(policy.user).to eq user
|
255
|
-
expect(policy.criteria).to eq :criteria
|
256
|
-
end
|
257
|
-
|
258
|
-
it "returns an instantiated policy given an array of symbols" do
|
259
|
-
policy = Pundit.policy(user, %i[project criteria])
|
260
|
-
expect(policy.class).to eq Project::CriteriaPolicy
|
261
|
-
expect(policy.user).to eq user
|
262
|
-
expect(policy.criteria).to eq :criteria
|
263
|
-
end
|
264
|
-
|
265
|
-
it "returns an instantiated policy given an array of a symbol and plain model instance" do
|
266
|
-
policy = Pundit.policy(user, [:project, post])
|
267
|
-
expect(policy.class).to eq Project::PostPolicy
|
268
|
-
expect(policy.user).to eq user
|
269
|
-
expect(policy.post).to eq post
|
270
|
-
end
|
271
|
-
|
272
|
-
it "returns an instantiated policy given an array of a symbol and a model instance with policy_class override" do
|
273
|
-
policy = Pundit.policy(user, [:project, customer_post])
|
274
|
-
expect(policy.class).to eq Project::PostPolicy
|
275
|
-
expect(policy.user).to eq user
|
276
|
-
expect(policy.post).to eq customer_post
|
277
|
-
end
|
278
|
-
|
279
|
-
it "returns an instantiated policy given an array of a symbol and an active model instance" do
|
280
|
-
policy = Pundit.policy(user, [:project, comment])
|
281
|
-
expect(policy.class).to eq Project::CommentPolicy
|
282
|
-
expect(policy.user).to eq user
|
283
|
-
expect(policy.comment).to eq comment
|
284
|
-
end
|
285
|
-
|
286
|
-
it "returns an instantiated policy given an array of a symbol and a plain model class" do
|
287
|
-
policy = Pundit.policy(user, [:project, Post])
|
288
|
-
expect(policy.class).to eq Project::PostPolicy
|
289
|
-
expect(policy.user).to eq user
|
290
|
-
expect(policy.post).to eq Post
|
291
|
-
end
|
292
|
-
|
293
|
-
it "raises an error with a invalid policy constructor" do
|
294
|
-
expect do
|
295
|
-
Pundit.policy(user, Wiki)
|
296
|
-
end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
|
297
|
-
end
|
298
|
-
|
299
|
-
it "returns an instantiated policy given an array of a symbol and an active model class" do
|
300
|
-
policy = Pundit.policy(user, [:project, Comment])
|
301
|
-
expect(policy.class).to eq Project::CommentPolicy
|
302
|
-
expect(policy.user).to eq user
|
303
|
-
expect(policy.comment).to eq Comment
|
304
|
-
end
|
305
|
-
|
306
|
-
it "returns an instantiated policy given an array of a symbol and a class with policy_class override" do
|
307
|
-
policy = Pundit.policy(user, [:project, Customer::Post])
|
308
|
-
expect(policy.class).to eq Project::PostPolicy
|
309
|
-
expect(policy.user).to eq user
|
310
|
-
expect(policy.post).to eq Customer::Post
|
311
|
-
end
|
312
|
-
|
313
|
-
it "returns correct policy class for an array of a multi-word symbols" do
|
314
|
-
policy = Pundit.policy(user, %i[project_one_two_three criteria_four_five_six])
|
315
|
-
expect(policy.class).to eq ProjectOneTwoThree::CriteriaFourFiveSixPolicy
|
316
|
-
end
|
317
|
-
|
318
|
-
it "returns correct policy class for an array of a multi-word symbol and a multi-word plain model instance" do
|
319
|
-
policy = Pundit.policy(user, [:project_one_two_three, post_four_five_six])
|
320
|
-
expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy
|
321
|
-
end
|
322
|
-
|
323
|
-
it "returns correct policy class for an array of a multi-word symbol and a multi-word active model instance" do
|
324
|
-
policy = Pundit.policy(user, [:project_one_two_three, comment_four_five_six])
|
325
|
-
expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy
|
326
|
-
end
|
327
|
-
|
328
|
-
it "returns correct policy class for an array of a multi-word symbol and a multi-word plain model class" do
|
329
|
-
policy = Pundit.policy(user, [:project_one_two_three, PostFourFiveSix])
|
330
|
-
expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy
|
331
|
-
end
|
332
|
-
|
333
|
-
it "returns correct policy class for an array of a multi-word symbol and a multi-word active model class" do
|
334
|
-
policy = Pundit.policy(user, [:project_one_two_three, CommentFourFiveSix])
|
335
|
-
expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy
|
336
|
-
end
|
337
|
-
|
338
|
-
it "returns correct policy class for a multi-word scoped plain model class" do
|
339
|
-
policy = Pundit.policy(user, ProjectOneTwoThree::TagFourFiveSix)
|
340
|
-
expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy
|
341
|
-
end
|
342
|
-
|
343
|
-
it "returns correct policy class for a multi-word scoped plain model instance" do
|
344
|
-
policy = Pundit.policy(user, tag_four_five_six)
|
345
|
-
expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy
|
346
|
-
end
|
347
|
-
|
348
|
-
it "returns correct policy class for a multi-word scoped active model class" do
|
349
|
-
policy = Pundit.policy(user, ProjectOneTwoThree::AvatarFourFiveSix)
|
350
|
-
expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy
|
351
|
-
end
|
352
|
-
|
353
|
-
it "returns correct policy class for a multi-word scoped active model instance" do
|
354
|
-
policy = Pundit.policy(user, avatar_four_five_six)
|
355
|
-
expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy
|
356
|
-
end
|
357
|
-
|
358
|
-
it "returns nil if the given policy can't be found" do
|
359
|
-
expect(Pundit.policy(user, article)).to be_nil
|
360
|
-
expect(Pundit.policy(user, Article)).to be_nil
|
361
|
-
end
|
362
|
-
|
363
|
-
it "returns the specified NilClassPolicy for nil" do
|
364
|
-
expect(Pundit.policy(user, nil)).to be_a NilClassPolicy
|
365
|
-
end
|
366
|
-
|
367
|
-
describe "with .policy_class set on the model" do
|
368
|
-
it "returns an instantiated policy given a plain model instance" do
|
369
|
-
policy = Pundit.policy(user, artificial_blog)
|
370
|
-
expect(policy.user).to eq user
|
371
|
-
expect(policy.blog).to eq artificial_blog
|
372
|
-
end
|
373
|
-
|
374
|
-
it "returns an instantiated policy given a plain model class" do
|
375
|
-
policy = Pundit.policy(user, ArtificialBlog)
|
376
|
-
expect(policy.user).to eq user
|
377
|
-
expect(policy.blog).to eq ArtificialBlog
|
378
|
-
end
|
379
|
-
|
380
|
-
it "returns an instantiated policy given a plain model instance providing an anonymous class" do
|
381
|
-
policy = Pundit.policy(user, article_tag)
|
382
|
-
expect(policy.user).to eq user
|
383
|
-
expect(policy.tag).to eq article_tag
|
384
|
-
end
|
385
|
-
|
386
|
-
it "returns an instantiated policy given a plain model class providing an anonymous class" do
|
387
|
-
policy = Pundit.policy(user, ArticleTag)
|
388
|
-
expect(policy.user).to eq user
|
389
|
-
expect(policy.tag).to eq ArticleTag
|
390
|
-
end
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
describe ".policy!" do
|
395
|
-
it "returns an instantiated policy given a plain model instance" do
|
396
|
-
policy = Pundit.policy!(user, post)
|
397
|
-
expect(policy.user).to eq user
|
398
|
-
expect(policy.post).to eq post
|
399
|
-
end
|
400
|
-
|
401
|
-
it "returns an instantiated policy given an active model instance" do
|
402
|
-
policy = Pundit.policy!(user, comment)
|
403
|
-
expect(policy.user).to eq user
|
404
|
-
expect(policy.comment).to eq comment
|
405
|
-
end
|
406
|
-
|
407
|
-
it "returns an instantiated policy given a plain model class" do
|
408
|
-
policy = Pundit.policy!(user, Post)
|
409
|
-
expect(policy.user).to eq user
|
410
|
-
expect(policy.post).to eq Post
|
411
|
-
end
|
412
|
-
|
413
|
-
it "returns an instantiated policy given an active model class" do
|
414
|
-
policy = Pundit.policy!(user, Comment)
|
415
|
-
expect(policy.user).to eq user
|
416
|
-
expect(policy.comment).to eq Comment
|
417
|
-
end
|
418
|
-
|
419
|
-
it "returns an instantiated policy given a symbol" do
|
420
|
-
policy = Pundit.policy!(user, :criteria)
|
421
|
-
expect(policy.class).to eq CriteriaPolicy
|
422
|
-
expect(policy.user).to eq user
|
423
|
-
expect(policy.criteria).to eq :criteria
|
424
|
-
end
|
425
|
-
|
426
|
-
it "returns an instantiated policy given an array of symbols" do
|
427
|
-
policy = Pundit.policy!(user, %i[project criteria])
|
428
|
-
expect(policy.class).to eq Project::CriteriaPolicy
|
429
|
-
expect(policy.user).to eq user
|
430
|
-
expect(policy.criteria).to eq :criteria
|
431
|
-
end
|
432
|
-
|
433
|
-
it "throws an exception if the given policy can't be found" do
|
434
|
-
expect { Pundit.policy!(user, article) }.to raise_error(Pundit::NotDefinedError)
|
435
|
-
expect { Pundit.policy!(user, Article) }.to raise_error(Pundit::NotDefinedError)
|
436
|
-
end
|
437
|
-
|
438
|
-
it "returns the specified NilClassPolicy for nil" do
|
439
|
-
expect(Pundit.policy!(user, nil)).to be_a NilClassPolicy
|
440
|
-
end
|
441
|
-
|
442
|
-
it "raises an error with a invalid policy constructor" do
|
443
|
-
expect do
|
444
|
-
Pundit.policy(user, Wiki)
|
445
|
-
end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
describe ".included" do
|
450
|
-
it "includes Authorization module" do
|
451
|
-
klass = Class.new
|
452
|
-
|
453
|
-
expect do
|
454
|
-
klass.include Pundit
|
455
|
-
end.to output.to_stderr
|
456
|
-
|
457
|
-
expect(klass).to include Pundit::Authorization
|
458
|
-
end
|
459
|
-
|
460
|
-
it "warns about deprecation" do
|
461
|
-
klass = Class.new
|
462
|
-
expect do
|
463
|
-
klass.include Pundit
|
464
|
-
end.to output(a_string_starting_with("'include Pundit' is deprecated")).to_stderr
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
describe "Pundit::NotAuthorizedError" do
|
469
|
-
it "can be initialized with a string as message" do
|
470
|
-
error = Pundit::NotAuthorizedError.new("must be logged in")
|
471
|
-
expect(error.message).to eq "must be logged in"
|
472
|
-
end
|
473
|
-
end
|
474
|
-
end
|
data/spec/rspec_dsl_spec.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
RSpec.describe "Pundit RSpec DSL" do
|
6
|
-
include Pundit::RSpec::PolicyExampleGroup
|
7
|
-
|
8
|
-
let(:fake_rspec) do
|
9
|
-
double = class_double(RSpec::ExampleGroups)
|
10
|
-
double.extend(::Pundit::RSpec::DSL)
|
11
|
-
double
|
12
|
-
end
|
13
|
-
let(:block) { proc { "block content" } }
|
14
|
-
|
15
|
-
let(:user) { double }
|
16
|
-
let(:other_user) { double }
|
17
|
-
let(:post) { Post.new(user) }
|
18
|
-
let(:policy) { PostPolicy }
|
19
|
-
|
20
|
-
it "calls describe with the correct metadata and without :focus" do
|
21
|
-
expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array) }
|
22
|
-
expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block|
|
23
|
-
expect(block.call).to eq("block content")
|
24
|
-
end
|
25
|
-
|
26
|
-
fake_rspec.permissions(:item1, :item2, &block)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "calls describe with the correct metadata and with :focus" do
|
30
|
-
expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array), focus: true }
|
31
|
-
expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block|
|
32
|
-
expect(block.call).to eq("block content")
|
33
|
-
end
|
34
|
-
|
35
|
-
fake_rspec.permissions(:item1, :item2, :focus, &block)
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#permit" do
|
39
|
-
context "when not appropriately wrapped in permissions" do
|
40
|
-
it "raises a descriptive error" do
|
41
|
-
expect do
|
42
|
-
expect(policy).to permit(user, post)
|
43
|
-
end.to raise_error(KeyError, <<~MSG.strip)
|
44
|
-
No permissions in example metadata, did you forget to wrap with `permissions :show?, ...`?
|
45
|
-
MSG
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
permissions :edit?, :update? do
|
50
|
-
it "succeeds when action is permitted" do
|
51
|
-
expect(policy).to permit(user, post)
|
52
|
-
end
|
53
|
-
|
54
|
-
context "when it fails" do
|
55
|
-
it "fails with a descriptive error message" do
|
56
|
-
expect do
|
57
|
-
expect(policy).to permit(other_user, post)
|
58
|
-
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)
|
59
|
-
Expected PostPolicy to grant edit? and update? on Post but edit? and update? were not granted
|
60
|
-
MSG
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context "when negated" do
|
65
|
-
it "succeeds when action is not permitted" do
|
66
|
-
expect(policy).not_to permit(other_user, post)
|
67
|
-
end
|
68
|
-
|
69
|
-
context "when it fails" do
|
70
|
-
it "fails with a descriptive error message" do
|
71
|
-
expect do
|
72
|
-
expect(policy).not_to permit(user, post)
|
73
|
-
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)
|
74
|
-
Expected PostPolicy not to grant edit? and update? on Post but edit? and update? were granted
|
75
|
-
MSG
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "simplecov"
|
4
|
-
require "json"
|
5
|
-
|
6
|
-
class SimpleCovCheckActionFormatter
|
7
|
-
SourceFile = Data.define(:source_file) do
|
8
|
-
def covered_strength = source_file.covered_strength
|
9
|
-
def covered_percent = source_file.covered_percent
|
10
|
-
|
11
|
-
def to_json(*args)
|
12
|
-
{
|
13
|
-
filename: source_file.filename,
|
14
|
-
covered_percent: covered_percent.nan? ? 0.0 : covered_percent,
|
15
|
-
coverage: source_file.coverage_data,
|
16
|
-
covered_strength: covered_strength.nan? ? 0.0 : covered_strength,
|
17
|
-
covered_lines: source_file.covered_lines.count,
|
18
|
-
lines_of_code: source_file.lines_of_code
|
19
|
-
}.to_json(*args)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
Result = Data.define(:result) do
|
24
|
-
def included?(source_file) = result.filenames.include?(source_file.filename)
|
25
|
-
|
26
|
-
def files
|
27
|
-
result.files.filter_map do |source_file|
|
28
|
-
next unless result.filenames.include? source_file.filename
|
29
|
-
|
30
|
-
SourceFile.new(source_file)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_json(*args) # rubocop:disable Metrics/AbcSize
|
35
|
-
{
|
36
|
-
timestamp: result.created_at.to_i,
|
37
|
-
command_name: result.command_name,
|
38
|
-
files: files,
|
39
|
-
metrics: {
|
40
|
-
covered_percent: result.covered_percent,
|
41
|
-
covered_strength: result.covered_strength.nan? ? 0.0 : result.covered_strength,
|
42
|
-
covered_lines: result.covered_lines,
|
43
|
-
total_lines: result.total_lines
|
44
|
-
}
|
45
|
-
}.to_json(*args)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
FormatterWithOptions = Data.define(:formatter) do
|
50
|
-
def new = formatter
|
51
|
-
end
|
52
|
-
|
53
|
-
class << self
|
54
|
-
def with_options(...)
|
55
|
-
FormatterWithOptions.new(new(...))
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def initialize(output_filename: "coverage.json", output_directory: SimpleCov.coverage_path)
|
60
|
-
@output_filename = output_filename
|
61
|
-
@output_directory = output_directory
|
62
|
-
end
|
63
|
-
|
64
|
-
attr_reader :output_filename, :output_directory
|
65
|
-
|
66
|
-
def output_filepath = File.join(output_directory, output_filename)
|
67
|
-
|
68
|
-
def format(result_data)
|
69
|
-
result = Result.new(result_data)
|
70
|
-
json = JSON.generate(result)
|
71
|
-
File.write(output_filepath, json)
|
72
|
-
puts output_message(result_data)
|
73
|
-
json
|
74
|
-
end
|
75
|
-
|
76
|
-
def output_message(result)
|
77
|
-
"Coverage report generated for #{result.command_name} to #{output_filepath}. #{result.covered_lines} / #{result.total_lines} LOC (#{result.covered_percent.round(2)}%) covered." # rubocop:disable Layout/LineLength
|
78
|
-
end
|
79
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
if ENV["COVERAGE"]
|
4
|
-
require "simplecov"
|
5
|
-
require "simplecov_json_formatter"
|
6
|
-
require_relative "simple_cov_check_action_formatter"
|
7
|
-
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
|
8
|
-
SimpleCov::Formatter::HTMLFormatter,
|
9
|
-
SimpleCov::Formatter::JSONFormatter,
|
10
|
-
SimpleCovCheckActionFormatter.with_options(
|
11
|
-
output_filename: "simplecov-check-action.json"
|
12
|
-
)
|
13
|
-
])
|
14
|
-
SimpleCov.start do
|
15
|
-
add_filter "/spec/"
|
16
|
-
enable_coverage :branch
|
17
|
-
primary_coverage :branch
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# @see https://github.com/rails/rails/issues/54260
|
22
|
-
require "logger" if RUBY_ENGINE == "jruby" && RUBY_ENGINE_VERSION.start_with?("9.3")
|
23
|
-
|
24
|
-
require "pundit"
|
25
|
-
require "pundit/rspec"
|
26
|
-
require "active_model/naming"
|
27
|
-
|
28
|
-
# Load all supporting files: models, policies, etc.
|
29
|
-
require "zeitwerk"
|
30
|
-
loader = Zeitwerk::Loader.new
|
31
|
-
loader.push_dir(File.expand_path("support/models", __dir__))
|
32
|
-
loader.push_dir(File.expand_path("support/policies", __dir__))
|
33
|
-
loader.push_dir(File.expand_path("support/lib", __dir__))
|
34
|
-
loader.setup
|
35
|
-
loader.eager_load
|