pundit 2.1.0 → 2.3.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.
data/spec/pundit_spec.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Pundit do
5
+ RSpec.describe Pundit do
6
6
  let(:user) { double }
7
7
  let(:post) { Post.new(user) }
8
8
  let(:customer_post) { Customer::Post.new(user) }
@@ -10,25 +10,48 @@ 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
25
23
  expect(Pundit.authorize(user, post, :update?)).to be_truthy
26
24
  end
27
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
+
28
46
  it "can be given a different policy class" do
29
47
  expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy
30
48
  end
31
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
+
32
55
  it "works with anonymous class policies" do
33
56
  expect(Pundit.authorize(user, article_tag, :show?)).to be_truthy
34
57
  expect { Pundit.authorize(user, article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
@@ -46,6 +69,18 @@ describe Pundit do
46
69
  # rubocop:enable Style/MultilineBlockChain
47
70
  end
48
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
+
49
84
  it "raises an error with a invalid policy constructor" do
50
85
  expect do
51
86
  Pundit.authorize(user, wiki, :update?)
@@ -360,231 +395,22 @@ describe Pundit do
360
395
  end
361
396
  end
362
397
 
363
- describe "#verify_authorized" do
364
- it "does nothing when authorized" do
365
- controller.authorize(post)
366
- controller.verify_authorized
367
- end
368
-
369
- it "raises an exception when not authorized" do
370
- expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
371
- end
372
- end
373
-
374
- describe "#verify_policy_scoped" do
375
- it "does nothing when policy_scope is used" do
376
- controller.policy_scope(Post)
377
- controller.verify_policy_scoped
378
- end
379
-
380
- it "raises an exception when policy_scope is not used" do
381
- expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)
382
- end
383
- end
384
-
385
- describe "#pundit_policy_authorized?" do
386
- it "is true when authorized" do
387
- controller.authorize(post)
388
- expect(controller.pundit_policy_authorized?).to be true
389
- end
390
-
391
- it "is false when not authorized" do
392
- expect(controller.pundit_policy_authorized?).to be false
393
- end
394
- end
395
-
396
- describe "#pundit_policy_scoped?" do
397
- it "is true when policy_scope is used" do
398
- controller.policy_scope(Post)
399
- expect(controller.pundit_policy_scoped?).to be true
400
- end
401
-
402
- it "is false when policy scope is not used" do
403
- expect(controller.pundit_policy_scoped?).to be false
404
- end
405
- end
406
-
407
- describe "#authorize" do
408
- it "infers the policy name and authorizes based on it" do
409
- expect(controller.authorize(post)).to be_truthy
410
- end
411
-
412
- it "returns the record on successful authorization" do
413
- expect(controller.authorize(post)).to be(post)
414
- end
415
-
416
- it "can be given a different permission to check" do
417
- expect(controller.authorize(post, :show?)).to be_truthy
418
- expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
419
- end
420
-
421
- it "can be given a different policy class" do
422
- expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy
423
- end
424
-
425
- it "works with anonymous class policies" do
426
- expect(controller.authorize(article_tag, :show?)).to be_truthy
427
- expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
428
- end
398
+ describe ".included" do
399
+ it "includes Authorization module" do
400
+ klass = Class.new
429
401
 
430
- it "throws an exception when the permission check fails" do
431
- expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
432
- end
433
-
434
- it "throws an exception when a policy cannot be found" do
435
- expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)
436
- end
437
-
438
- it "caches the policy" do
439
- expect(controller.policies[post]).to be_nil
440
- controller.authorize(post)
441
- expect(controller.policies[post]).not_to be_nil
442
- end
443
-
444
- it "raises an error when the given record is nil" do
445
- expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
446
- end
447
-
448
- it "raises an error with a invalid policy constructor" do
449
- expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)
450
- end
451
- end
452
-
453
- describe "#skip_authorization" do
454
- it "disables authorization verification" do
455
- controller.skip_authorization
456
- expect { controller.verify_authorized }.not_to raise_error
457
- end
458
- end
459
-
460
- describe "#skip_policy_scope" do
461
- it "disables policy scope verification" do
462
- controller.skip_policy_scope
463
- expect { controller.verify_policy_scoped }.not_to raise_error
464
- end
465
- end
466
-
467
- describe "#pundit_user" do
468
- it "returns the same thing as current_user" do
469
- expect(controller.pundit_user).to eq controller.current_user
470
- end
471
- end
472
-
473
- describe "#policy" do
474
- it "returns an instantiated policy" do
475
- policy = controller.policy(post)
476
- expect(policy.user).to eq user
477
- expect(policy.post).to eq post
478
- end
479
-
480
- it "throws an exception if the given policy can't be found" do
481
- expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
482
- end
483
-
484
- it "raises an error with a invalid policy constructor" do
485
- expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)
486
- end
487
-
488
- it "allows policy to be injected" do
489
- new_policy = OpenStruct.new
490
- controller.policies[post] = new_policy
491
-
492
- expect(controller.policy(post)).to eq new_policy
493
- end
494
- end
495
-
496
- describe "#policy_scope" do
497
- it "returns an instantiated policy scope" do
498
- expect(controller.policy_scope(Post)).to eq :published
499
- end
500
-
501
- it "allows policy scope class to be overriden" do
502
- expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published
503
- end
504
-
505
- it "throws an exception if the given policy can't be found" do
506
- expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
507
- end
508
-
509
- it "raises an error with a invalid policy scope constructor" do
510
- expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)
511
- end
512
-
513
- it "allows policy_scope to be injected" do
514
- new_scope = OpenStruct.new
515
- controller.policy_scopes[Post] = new_scope
516
-
517
- expect(controller.policy_scope(Post)).to eq new_scope
518
- end
519
- end
402
+ expect do
403
+ klass.include Pundit
404
+ end.to output.to_stderr
520
405
 
521
- describe "#permitted_attributes" do
522
- it "checks policy for permitted attributes" do
523
- params = ActionController::Parameters.new(
524
- post: {
525
- title: "Hello",
526
- votes: 5,
527
- admin: true
528
- }
529
- )
530
-
531
- action = "update"
532
-
533
- expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(
534
- "title" => "Hello",
535
- "votes" => 5
536
- )
537
- expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq("votes" => 5)
538
- end
539
-
540
- it "checks policy for permitted attributes for record of a ActiveModel type" do
541
- params = ActionController::Parameters.new(
542
- customer_post: {
543
- title: "Hello",
544
- votes: 5,
545
- admin: true
546
- }
547
- )
548
-
549
- action = "update"
550
-
551
- expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(
552
- "title" => "Hello",
553
- "votes" => 5
554
- )
555
- expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(
556
- "votes" => 5
557
- )
406
+ expect(klass).to include Pundit::Authorization
558
407
  end
559
- end
560
408
 
561
- describe "#permitted_attributes_for_action" do
562
- it "is checked if it is defined in the policy" do
563
- params = ActionController::Parameters.new(
564
- post: {
565
- title: "Hello",
566
- body: "blah",
567
- votes: 5,
568
- admin: true
569
- }
570
- )
571
-
572
- action = "revise"
573
- expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
574
- end
575
-
576
- it "can be explicitly set" do
577
- params = ActionController::Parameters.new(
578
- post: {
579
- title: "Hello",
580
- body: "blah",
581
- votes: 5,
582
- admin: true
583
- }
584
- )
585
-
586
- action = "update"
587
- expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
409
+ it "warns about deprecation" do
410
+ klass = Class.new
411
+ expect do
412
+ klass.include Pundit
413
+ end.to output(a_string_starting_with("'include Pundit' is deprecated")).to_stderr
588
414
  end
589
415
  end
590
416
 
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "simplecov"
4
+ SimpleCov.start do
5
+ add_filter "/spec/"
6
+ end
7
+
3
8
  require "pundit"
4
9
  require "pundit/rspec"
5
10
 
@@ -11,22 +16,6 @@ require "active_support/core_ext"
11
16
  require "active_model/naming"
12
17
  require "action_controller/metal/strong_parameters"
13
18
 
14
- I18n.enforce_available_locales = false
15
-
16
- module PunditSpecHelper
17
- extend RSpec::Matchers::DSL
18
-
19
- matcher :be_truthy do
20
- match do |actual|
21
- actual
22
- end
23
- end
24
- end
25
-
26
- RSpec.configure do |config|
27
- config.include PunditSpecHelper
28
- end
29
-
30
19
  class PostPolicy < Struct.new(:user, :post)
31
20
  class Scope < Struct.new(:user, :scope)
32
21
  def resolve
@@ -86,15 +75,12 @@ module Customer
86
75
  def self.policy_class
87
76
  PostPolicy
88
77
  end
89
-
90
- def policy_class
91
- self.class.policy_class
92
- end
93
78
  end
94
79
  end
95
80
 
96
81
  class CommentScope
97
82
  attr_reader :original_object
83
+
98
84
  def initialize(original_object)
99
85
  @original_object = original_object
100
86
  end
@@ -129,7 +115,7 @@ class Comment
129
115
  end
130
116
 
131
117
  class CommentsRelation
132
- def initialize(empty = false)
118
+ def initialize(empty: false)
133
119
  @empty = empty
134
120
  end
135
121
 
@@ -137,7 +123,7 @@ class CommentsRelation
137
123
  @empty
138
124
  end
139
125
 
140
- def model_name
126
+ def self.model_name
141
127
  Comment.model_name
142
128
  end
143
129
  end
@@ -174,6 +160,10 @@ class CriteriaPolicy < Struct.new(:user, :criteria); end
174
160
 
175
161
  module Project
176
162
  class CommentPolicy < Struct.new(:user, :comment)
163
+ def update?
164
+ true
165
+ end
166
+
177
167
  class Scope < Struct.new(:user, :scope)
178
168
  def resolve
179
169
  scope
@@ -190,6 +180,18 @@ module Project
190
180
  end
191
181
  end
192
182
  end
183
+
184
+ module Admin
185
+ class CommentPolicy < Struct.new(:user, :comment)
186
+ def update?
187
+ true
188
+ end
189
+
190
+ def destroy?
191
+ false
192
+ end
193
+ end
194
+ end
193
195
  end
194
196
 
195
197
  class DenierPolicy < Struct.new(:user, :record)
@@ -199,11 +201,11 @@ class DenierPolicy < Struct.new(:user, :record)
199
201
  end
200
202
 
201
203
  class Controller
202
- include Pundit
204
+ include Pundit::Authorization
203
205
  # Mark protected methods public so they may be called in test
204
- # rubocop:disable Layout/AccessModifierIndentation, Style/AccessModifierDeclarations
205
- public(*Pundit.protected_instance_methods)
206
- # rubocop:enable Layout/AccessModifierIndentation, Style/AccessModifierDeclarations
206
+ # rubocop:disable Style/AccessModifierDeclarations
207
+ public(*Pundit::Authorization.protected_instance_methods)
208
+ # rubocop:enable Style/AccessModifierDeclarations
207
209
 
208
210
  attr_reader :current_user, :action_name, :params
209
211
 
@@ -231,6 +233,7 @@ class NilClassPolicy < Struct.new(:user, :record)
231
233
  end
232
234
 
233
235
  class Wiki; end
236
+
234
237
  class WikiPolicy
235
238
  class Scope
236
239
  # deliberate typo method
@@ -241,6 +244,7 @@ end
241
244
  class Thread
242
245
  def self.all; end
243
246
  end
247
+
244
248
  class ThreadPolicy < Struct.new(:user, :thread)
245
249
  class Scope < Struct.new(:user, :scope)
246
250
  def resolve
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pundit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
8
8
  - Varvet AB
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-08-14 00:00:00.000000000 Z
12
+ date: 2023-07-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: railties
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 3.0.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 3.0.0
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: rake
86
100
  requirement: !ruby/object:Gem::Requirement
@@ -101,28 +115,42 @@ dependencies:
101
115
  requirements:
102
116
  - - ">="
103
117
  - !ruby/object:Gem::Version
104
- version: 2.0.0
118
+ version: 3.0.0
105
119
  type: :development
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
108
122
  requirements:
109
123
  - - ">="
110
124
  - !ruby/object:Gem::Version
111
- version: 2.0.0
125
+ version: 3.0.0
112
126
  - !ruby/object:Gem::Dependency
113
127
  name: rubocop
114
128
  requirement: !ruby/object:Gem::Requirement
115
129
  requirements:
116
130
  - - '='
117
131
  - !ruby/object:Gem::Version
118
- version: 0.57.2
132
+ version: 1.24.0
119
133
  type: :development
120
134
  prerelease: false
121
135
  version_requirements: !ruby/object:Gem::Requirement
122
136
  requirements:
123
137
  - - '='
124
138
  - !ruby/object:Gem::Version
125
- version: 0.57.2
139
+ version: 1.24.0
140
+ - !ruby/object:Gem::Dependency
141
+ name: simplecov
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: 0.17.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.17.0
126
154
  - !ruby/object:Gem::Dependency
127
155
  name: yard
128
156
  requirement: !ruby/object:Gem::Requirement
@@ -140,11 +168,12 @@ dependencies:
140
168
  description: Object oriented authorization for Rails applications
141
169
  email:
142
170
  - jonas.nicklas@gmail.com
143
- - dev@elabs.se
171
+ - info@varvet.com
144
172
  executables: []
145
173
  extensions: []
146
174
  extra_rdoc_files: []
147
175
  files:
176
+ - ".github/pull_request_template.md"
148
177
  - ".gitignore"
149
178
  - ".rubocop.yml"
150
179
  - ".travis.yml"
@@ -156,6 +185,8 @@ files:
156
185
  - LICENSE.txt
157
186
  - README.md
158
187
  - Rakefile
188
+ - SECURITY.md
189
+ - config/rubocop-rspec.yml
159
190
  - lib/generators/pundit/install/USAGE
160
191
  - lib/generators/pundit/install/install_generator.rb
161
192
  - lib/generators/pundit/install/templates/application_policy.rb
@@ -167,10 +198,13 @@ files:
167
198
  - lib/generators/test_unit/policy_generator.rb
168
199
  - lib/generators/test_unit/templates/policy_test.rb
169
200
  - lib/pundit.rb
201
+ - lib/pundit/authorization.rb
170
202
  - lib/pundit/policy_finder.rb
171
203
  - lib/pundit/rspec.rb
172
204
  - lib/pundit/version.rb
173
205
  - pundit.gemspec
206
+ - spec/authorization_spec.rb
207
+ - spec/generators_spec.rb
174
208
  - spec/policies/post_policy_spec.rb
175
209
  - spec/policy_finder_spec.rb
176
210
  - spec/pundit_spec.rb
@@ -178,8 +212,9 @@ files:
178
212
  homepage: https://github.com/varvet/pundit
179
213
  licenses:
180
214
  - MIT
181
- metadata: {}
182
- post_install_message:
215
+ metadata:
216
+ rubygems_mfa_required: 'true'
217
+ post_install_message:
183
218
  rdoc_options: []
184
219
  require_paths:
185
220
  - lib
@@ -194,11 +229,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
229
  - !ruby/object:Gem::Version
195
230
  version: '0'
196
231
  requirements: []
197
- rubygems_version: 3.0.3
198
- signing_key:
232
+ rubygems_version: 3.4.10
233
+ signing_key:
199
234
  specification_version: 4
200
235
  summary: OO authorization for Rails
201
236
  test_files:
237
+ - spec/authorization_spec.rb
238
+ - spec/generators_spec.rb
202
239
  - spec/policies/post_policy_spec.rb
203
240
  - spec/policy_finder_spec.rb
204
241
  - spec/pundit_spec.rb