cancancan 1.11.0 → 2.3.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.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/cancancan.gemspec +15 -19
  3. data/lib/cancan/ability/actions.rb +91 -0
  4. data/lib/cancan/ability/rules.rb +85 -0
  5. data/lib/cancan/ability.rb +74 -136
  6. data/lib/cancan/conditions_matcher.rb +93 -0
  7. data/lib/cancan/controller_additions.rb +34 -40
  8. data/lib/cancan/controller_resource.rb +47 -212
  9. data/lib/cancan/controller_resource_builder.rb +24 -0
  10. data/lib/cancan/controller_resource_finder.rb +40 -0
  11. data/lib/cancan/controller_resource_loader.rb +116 -0
  12. data/lib/cancan/controller_resource_name_finder.rb +21 -0
  13. data/lib/cancan/controller_resource_sanitizer.rb +30 -0
  14. data/lib/cancan/exceptions.rb +7 -3
  15. data/lib/cancan/matchers.rb +12 -3
  16. data/lib/cancan/model_adapters/abstract_adapter.rb +8 -8
  17. data/lib/cancan/model_adapters/active_record_4_adapter.rb +33 -10
  18. data/lib/cancan/model_adapters/active_record_5_adapter.rb +70 -0
  19. data/lib/cancan/model_adapters/active_record_adapter.rb +41 -81
  20. data/lib/cancan/model_adapters/can_can/model_adapters/active_record_adapter/joins.rb +39 -0
  21. data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
  22. data/lib/cancan/model_additions.rb +0 -1
  23. data/lib/cancan/rule.rb +36 -92
  24. data/lib/cancan/rules_compressor.rb +20 -0
  25. data/lib/cancan/version.rb +1 -1
  26. data/lib/cancan.rb +5 -12
  27. data/lib/generators/cancan/ability/ability_generator.rb +1 -1
  28. metadata +54 -65
  29. data/.gitignore +0 -15
  30. data/.rspec +0 -1
  31. data/.travis.yml +0 -55
  32. data/Appraisals +0 -136
  33. data/CHANGELOG.rdoc +0 -503
  34. data/CONTRIBUTING.md +0 -23
  35. data/Gemfile +0 -3
  36. data/LICENSE +0 -22
  37. data/README.md +0 -188
  38. data/Rakefile +0 -9
  39. data/gemfiles/activerecord_3.0.gemfile +0 -18
  40. data/gemfiles/activerecord_3.1.gemfile +0 -20
  41. data/gemfiles/activerecord_3.2.gemfile +0 -20
  42. data/gemfiles/activerecord_4.0.gemfile +0 -17
  43. data/gemfiles/activerecord_4.1.gemfile +0 -17
  44. data/gemfiles/activerecord_4.2.gemfile +0 -18
  45. data/gemfiles/datamapper_1.x.gemfile +0 -14
  46. data/gemfiles/mongoid_2.x.gemfile +0 -20
  47. data/gemfiles/sequel_3.x.gemfile +0 -20
  48. data/lib/cancan/inherited_resource.rb +0 -20
  49. data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
  50. data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
  51. data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
  52. data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
  53. data/spec/README.rdoc +0 -27
  54. data/spec/cancan/ability_spec.rb +0 -487
  55. data/spec/cancan/controller_additions_spec.rb +0 -141
  56. data/spec/cancan/controller_resource_spec.rb +0 -632
  57. data/spec/cancan/exceptions_spec.rb +0 -58
  58. data/spec/cancan/inherited_resource_spec.rb +0 -71
  59. data/spec/cancan/matchers_spec.rb +0 -29
  60. data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -85
  61. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
  62. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
  63. data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
  64. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
  65. data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
  66. data/spec/cancan/rule_spec.rb +0 -52
  67. data/spec/matchers.rb +0 -13
  68. data/spec/spec.opts +0 -2
  69. data/spec/spec_helper.rb +0 -28
  70. data/spec/support/ability.rb +0 -7
@@ -1,487 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CanCan::Ability do
4
- before(:each) do
5
- (@ability = double).extend(CanCan::Ability)
6
- end
7
-
8
- it "is able to :read anything" do
9
- @ability.can :read, :all
10
- expect(@ability.can?(:read, String)).to be(true)
11
- expect(@ability.can?(:read, 123)).to be(true)
12
- end
13
-
14
- it "does not have permission to do something it doesn't know about" do
15
- expect(@ability.can?(:foodfight, String)).to be(false)
16
- end
17
-
18
- it "passes true to `can?` when non false/nil is returned in block" do
19
- @ability.can :read, :all
20
- @ability.can :read, Symbol do |sym|
21
- "foo" # TODO test that sym is nil when no instance is passed
22
- end
23
- expect(@ability.can?(:read, :some_symbol)).to be(true)
24
- end
25
-
26
- it "passes nil to a block when no instance is passed" do
27
- @ability.can :read, Symbol do |sym|
28
- expect(sym).to be_nil
29
- true
30
- end
31
- expect(@ability.can?(:read, Symbol)).to be(true)
32
- end
33
-
34
- it "passes to previous rule, if block returns false or nil" do
35
- @ability.can :read, Symbol
36
- @ability.can :read, Integer do |i|
37
- i < 5
38
- end
39
- @ability.can :read, Integer do |i|
40
- i > 10
41
- end
42
- expect(@ability.can?(:read, Symbol)).to be(true)
43
- expect(@ability.can?(:read, 11)).to be(true)
44
- expect(@ability.can?(:read, 1)).to be(true)
45
- expect(@ability.can?(:read, 6)).to be(false)
46
- end
47
-
48
- it "does not pass class with object if :all objects are accepted" do
49
- @ability.can :preview, :all do |object|
50
- expect(object).to eq(123)
51
- @block_called = true
52
- end
53
- @ability.can?(:preview, 123)
54
- expect(@block_called).to be(true)
55
- end
56
-
57
- it "does not call block when only class is passed, only return true" do
58
- @block_called = false
59
- @ability.can :preview, :all do |object|
60
- @block_called = true
61
- end
62
- expect(@ability.can?(:preview, Hash)).to be(true)
63
- expect(@block_called).to be(false)
64
- end
65
-
66
- it "passes only object for global manage actions" do
67
- @ability.can :manage, String do |object|
68
- expect(object).to eq("foo")
69
- @block_called = true
70
- end
71
- expect(@ability.can?(:stuff, "foo")).to be(true)
72
- expect(@block_called).to be(true)
73
- end
74
-
75
- it "makes alias for update or destroy actions to modify action" do
76
- @ability.alias_action :update, :destroy, :to => :modify
77
- @ability.can :modify, :all
78
- expect(@ability.can?(:update, 123)).to be(true)
79
- expect(@ability.can?(:destroy, 123)).to be(true)
80
- end
81
-
82
- it "allows deeply nested aliased actions" do
83
- @ability.alias_action :increment, :to => :sort
84
- @ability.alias_action :sort, :to => :modify
85
- @ability.can :modify, :all
86
- expect(@ability.can?(:increment, 123)).to be(true)
87
- end
88
-
89
- it "raises an Error if alias target is an exist action" do
90
- expect { @ability.alias_action :show, :to => :show }.to raise_error(CanCan::Error, "You can't specify target (show) as alias because it is real action name")
91
- end
92
-
93
- it "always calls block with arguments when passing no arguments to can" do
94
- @ability.can do |action, object_class, object|
95
- expect(action).to eq(:foo)
96
- expect(object_class).to eq(123.class)
97
- expect(object).to eq(123)
98
- @block_called = true
99
- end
100
- @ability.can?(:foo, 123)
101
- expect(@block_called).to be(true)
102
- end
103
-
104
- it "passes nil to object when comparing class with can check" do
105
- @ability.can do |action, object_class, object|
106
- expect(action).to eq(:foo)
107
- expect(object_class).to eq(Hash)
108
- expect(object).to be_nil
109
- @block_called = true
110
- end
111
- @ability.can?(:foo, Hash)
112
- expect(@block_called).to be(true)
113
- end
114
-
115
- it "automatically makes alias for index and show into read calls" do
116
- @ability.can :read, :all
117
- expect(@ability.can?(:index, 123)).to be(true)
118
- expect(@ability.can?(:show, 123)).to be(true)
119
- end
120
-
121
- it "automatically makes alias for new and edit into create and update respectively" do
122
- @ability.can :create, :all
123
- @ability.can :update, :all
124
- expect(@ability.can?(:new, 123)).to be(true)
125
- expect(@ability.can?(:edit, 123)).to be(true)
126
- end
127
-
128
- it "does not respond to prepare (now using initialize)" do
129
- expect(@ability).to_not respond_to(:prepare)
130
- end
131
-
132
- it "offers cannot? method which is simply invert of can?" do
133
- expect(@ability.cannot?(:tie, String)).to be(true)
134
- end
135
-
136
- it "is able to specify multiple actions and match any" do
137
- @ability.can [:read, :update], :all
138
- expect(@ability.can?(:read, 123)).to be(true)
139
- expect(@ability.can?(:update, 123)).to be(true)
140
- expect(@ability.can?(:count, 123)).to be(false)
141
- end
142
-
143
- it "is able to specify multiple classes and match any" do
144
- @ability.can :update, [String, Range]
145
- expect(@ability.can?(:update, "foo")).to be(true)
146
- expect(@ability.can?(:update, 1..3)).to be(true)
147
- expect(@ability.can?(:update, 123)).to be(false)
148
- end
149
-
150
- it "checks if there is a permission for any of given subjects" do
151
- @ability.can :update, [String, Range]
152
- expect(@ability.can?(:update, {:any => ["foo", 1..3]})).to be(true)
153
- expect(@ability.can?(:update, {:any => [1..3, "foo"]})).to be(true)
154
- expect(@ability.can?(:update, {:any => [123, "foo"]})).to be(true)
155
- expect(@ability.can?(:update, {:any => [123, 1.0]})).to be(false)
156
- end
157
-
158
- it "supports custom objects in the rule" do
159
- @ability.can :read, :stats
160
- expect(@ability.can?(:read, :stats)).to be(true)
161
- expect(@ability.can?(:update, :stats)).to be(false)
162
- expect(@ability.can?(:read, :nonstats)).to be(false)
163
- expect(@ability.can?(:read, {:any => [:stats, :nonstats]})).to be(true)
164
- expect(@ability.can?(:read, {:any => [:nonstats, :neitherstats]})).to be(false)
165
- end
166
-
167
- it "checks ancestors of class" do
168
- @ability.can :read, Numeric
169
- expect(@ability.can?(:read, Integer)).to be(true)
170
- expect(@ability.can?(:read, 1.23)).to be(true)
171
- expect(@ability.can?(:read, "foo")).to be(false)
172
- expect(@ability.can?(:read, {:any => [Integer, String]})).to be(true)
173
- end
174
-
175
- it "supports 'cannot' method to define what user cannot do" do
176
- @ability.can :read, :all
177
- @ability.cannot :read, Integer
178
- expect(@ability.can?(:read, "foo")).to be(true)
179
- expect(@ability.can?(:read, 123)).to be(false)
180
- expect(@ability.can?(:read, {:any => ["foo", "bar"]})).to be(true)
181
- expect(@ability.can?(:read, {:any => [123, "foo"]})).to be(false)
182
- expect(@ability.can?(:read, {:any => [123, 456]})).to be(false)
183
- end
184
-
185
- it "passes to previous rule, if block returns false or nil" do
186
- @ability.can :read, :all
187
- @ability.cannot :read, Integer do |int|
188
- int > 10 ? nil : ( int > 5 )
189
- end
190
-
191
- expect(@ability.can?(:read, "foo")).to be(true)
192
- expect(@ability.can?(:read, 3)).to be(true)
193
- expect(@ability.can?(:read, 8)).to be(false)
194
- expect(@ability.can?(:read, 123)).to be(true)
195
- expect(@ability.can?(:read, {:any => [123, 8]})).to be(true)
196
- expect(@ability.can?(:read, {:any => [8, 9]})).to be(false)
197
- end
198
-
199
- it "always returns `false` for single cannot definition" do
200
- @ability.cannot :read, Integer do |int|
201
- int > 10 ? nil : ( int > 5 )
202
- end
203
- expect(@ability.can?(:read, "foo")).to be(false)
204
- expect(@ability.can?(:read, 3)).to be(false)
205
- expect(@ability.can?(:read, 8)).to be(false)
206
- expect(@ability.can?(:read, 123)).to be(false)
207
- end
208
-
209
- it "passes to previous cannot definition, if block returns false or nil" do
210
- @ability.cannot :read, :all
211
- @ability.can :read, Integer do |int|
212
- int > 10 ? nil : ( int > 5 )
213
- end
214
- expect(@ability.can?(:read, "foo")).to be(false)
215
- expect(@ability.can?(:read, 3)).to be(false)
216
- expect(@ability.can?(:read, 10)).to be(true)
217
- expect(@ability.can?(:read, 123)).to be(false)
218
- end
219
-
220
- it "appends aliased actions" do
221
- @ability.alias_action :update, :to => :modify
222
- @ability.alias_action :destroy, :to => :modify
223
- expect(@ability.aliased_actions[:modify]).to eq([:update, :destroy])
224
- end
225
-
226
- it "clears aliased actions" do
227
- @ability.alias_action :update, :to => :modify
228
- @ability.clear_aliased_actions
229
- expect(@ability.aliased_actions[:modify]).to be_nil
230
- end
231
-
232
- it "passes additional arguments to block from can?" do
233
- @ability.can :read, Integer do |int, x|
234
- int > x
235
- end
236
-
237
- expect(@ability.can?(:read, 2, 1)).to be(true)
238
- expect(@ability.can?(:read, 2, 3)).to be(false)
239
- expect(@ability.can?(:read, {:any => [4, 5]}, 3)).to be(true)
240
- expect(@ability.can?(:read, {:any => [2, 3]}, 3)).to be(false)
241
- end
242
-
243
- it "uses conditions as third parameter and determine abilities from it" do
244
- @ability.can :read, Range, :begin => 1, :end => 3
245
-
246
- expect(@ability.can?(:read, 1..3)).to be(true)
247
- expect(@ability.can?(:read, 1..4)).to be(false)
248
- expect(@ability.can?(:read, Range)).to be(true)
249
- expect(@ability.can?(:read, {:any => [1..3, 1..4]})).to be(true)
250
- expect(@ability.can?(:read, {:any => [1..4, 2..4]})).to be(false)
251
- end
252
-
253
- it "allows an array of options in conditions hash" do
254
- @ability.can :read, Range, :begin => [1, 3, 5]
255
-
256
- expect(@ability.can?(:read, 1..3)).to be(true)
257
- expect(@ability.can?(:read, 2..4)).to be(false)
258
- expect(@ability.can?(:read, 3..5)).to be(true)
259
- expect(@ability.can?(:read, {:any => [2..4, 3..5]})).to be(true)
260
- expect(@ability.can?(:read, {:any => [2..4, 2..5]})).to be(false)
261
- end
262
-
263
- it "allows a range of options in conditions hash" do
264
- @ability.can :read, Range, :begin => 1..3
265
- expect(@ability.can?(:read, 1..10)).to be(true)
266
- expect(@ability.can?(:read, 3..30)).to be(true)
267
- expect(@ability.can?(:read, 4..40)).to be(false)
268
- end
269
-
270
- it "allows nested hashes in conditions hash" do
271
- @ability.can :read, Range, :begin => { :to_i => 5 }
272
- expect(@ability.can?(:read, 5..7)).to be(true)
273
- expect(@ability.can?(:read, 6..8)).to be(false)
274
- end
275
-
276
- it "matches any element passed in to nesting if it's an array (for has_many associations)" do
277
- @ability.can :read, Range, :to_a => { :to_i => 3 }
278
- expect(@ability.can?(:read, 1..5)).to be(true)
279
- expect(@ability.can?(:read, 4..6)).to be(false)
280
- end
281
-
282
- it "accepts a set as a condition value" do
283
- expect(object_with_foo_2 = double(:foo => 2)).to receive(:foo)
284
- expect(object_with_foo_3 = double(:foo => 3)).to receive(:foo)
285
- @ability.can :read, Object, :foo => [1, 2, 5].to_set
286
- expect(@ability.can?(:read, object_with_foo_2)).to be(true)
287
- expect(@ability.can?(:read, object_with_foo_3)).to be(false)
288
- end
289
-
290
- it "does not match subjects return nil for methods that must match nested a nested conditions hash" do
291
- expect(object_with_foo = double(:foo => :bar)).to receive(:foo)
292
- @ability.can :read, Array, :first => { :foo => :bar }
293
- expect(@ability.can?(:read, [object_with_foo])).to be(true)
294
- expect(@ability.can?(:read, [])).to be(false)
295
- end
296
-
297
- it "matches strings but not substrings specified in a conditions hash" do
298
- @ability.can :read, String, :presence => "declassified"
299
- expect(@ability.can?(:read, "declassified")).to be(true)
300
- expect(@ability.can?(:read, "classified")).to be(false)
301
- end
302
-
303
- it "does not stop at cannot definition when comparing class" do
304
- @ability.can :read, Range
305
- @ability.cannot :read, Range, :begin => 1
306
- expect(@ability.can?(:read, 2..5)).to be(true)
307
- expect(@ability.can?(:read, 1..5)).to be(false)
308
- expect(@ability.can?(:read, Range)).to be(true)
309
- end
310
-
311
- it "stops at cannot definition when no hash is present" do
312
- @ability.can :read, :all
313
- @ability.cannot :read, Range
314
- expect(@ability.can?(:read, 1..5)).to be(false)
315
- expect(@ability.can?(:read, Range)).to be(false)
316
- end
317
-
318
- it "allows to check ability for Module" do
319
- module B; end
320
- class A; include B; end
321
- @ability.can :read, B
322
- expect(@ability.can?(:read, A)).to be(true)
323
- expect(@ability.can?(:read, A.new)).to be(true)
324
- end
325
-
326
- it "passes nil to a block for ability on Module when no instance is passed" do
327
- module B; end
328
- class A; include B; end
329
- @ability.can :read, B do |sym|
330
- expect(sym).to be_nil
331
- true
332
- end
333
- expect(@ability.can?(:read, B)).to be(true)
334
- expect(@ability.can?(:read, A)).to be(true)
335
- end
336
-
337
- it "checks permissions through association when passing a hash of subjects" do
338
- @ability.can :read, Range, :string => {:length => 3}
339
-
340
- expect(@ability.can?(:read, "foo" => Range)).to be(true)
341
- expect(@ability.can?(:read, "foobar" => Range)).to be(false)
342
- expect(@ability.can?(:read, 123 => Range)).to be(true)
343
- expect(@ability.can?(:read, {:any => [{"foo" => Range}, {"foobar" => Range}]})).to be(true)
344
- expect(@ability.can?(:read, {:any => [{"food" => Range}, {"foobar" => Range}]})).to be(false)
345
- end
346
-
347
- it "checks permissions correctly when passing a hash of subjects with multiple definitions" do
348
- @ability.can :read, Range, :string => {:length => 4}
349
- @ability.can [:create, :read], Range, :string => {:upcase => 'FOO'}
350
-
351
- expect(@ability.can?(:read, "foo" => Range)).to be(true)
352
- expect(@ability.can?(:read, "foobar" => Range)).to be(false)
353
- expect(@ability.can?(:read, 1234 => Range)).to be(true)
354
- expect(@ability.can?(:read, {:any => [{"foo" => Range}, {"foobar" => Range}]})).to be(true)
355
- expect(@ability.can?(:read, {:any => [{"foo.bar" => Range}, {"foobar" => Range}]})).to be(false)
356
- end
357
-
358
- it "allows to check ability on Hash-like object" do
359
- class Container < Hash; end
360
- @ability.can :read, Container
361
- expect(@ability.can?(:read, Container.new)).to be(true)
362
- end
363
-
364
- it "has initial attributes based on hash conditions of 'new' action" do
365
- @ability.can :manage, Range, :foo => "foo", :hash => {:skip => "hashes"}
366
- @ability.can :create, Range, :bar => 123, :array => %w[skip arrays]
367
- @ability.can :new, Range, :baz => "baz", :range => 1..3
368
- @ability.cannot :new, Range, :ignore => "me"
369
- expect(@ability.attributes_for(:new, Range)).to eq({:foo => "foo", :bar => 123, :baz => "baz"})
370
- end
371
-
372
- it "raises access denied exception if ability us unauthorized to perform a certain action" do
373
- begin
374
- @ability.authorize! :read, :foo, 1, 2, 3, :message => "Access denied!"
375
- rescue CanCan::AccessDenied => e
376
- expect(e.message).to eq("Access denied!")
377
- expect(e.action).to eq(:read)
378
- expect(e.subject).to eq(:foo)
379
- else
380
- fail "Expected CanCan::AccessDenied exception to be raised"
381
- end
382
- end
383
-
384
- it "does not raise access denied exception if ability is authorized to perform an action and return subject" do
385
- @ability.can :read, :foo
386
- expect {
387
- expect(@ability.authorize!(:read, :foo)).to eq(:foo)
388
- }.to_not raise_error
389
- end
390
-
391
- it "knows when block is used in conditions" do
392
- @ability.can :read, :foo
393
- expect(@ability).to_not have_block(:read, :foo)
394
- @ability.can :read, :foo do |foo|
395
- false
396
- end
397
- expect(@ability).to have_block(:read, :foo)
398
- end
399
-
400
- it "knows when raw sql is used in conditions" do
401
- @ability.can :read, :foo
402
- expect(@ability).to_not have_raw_sql(:read, :foo)
403
- @ability.can :read, :foo, 'false'
404
- expect(@ability).to have_raw_sql(:read, :foo)
405
- end
406
-
407
- it "raises access denied exception with default message if not specified" do
408
- begin
409
- @ability.authorize! :read, :foo
410
- rescue CanCan::AccessDenied => e
411
- e.default_message = "Access denied!"
412
- expect(e.message).to eq("Access denied!")
413
- else
414
- fail "Expected CanCan::AccessDenied exception to be raised"
415
- end
416
- end
417
-
418
- it "determines model adapterO class by asking AbstractAdapter" do
419
- adapter_class, model_class = double, double
420
- allow(CanCan::ModelAdapters::AbstractAdapter).to receive(:adapter_class).with(model_class) { adapter_class }
421
- allow(adapter_class).to receive(:new).with(model_class, []) { :adapter_instance }
422
- expect(@ability.model_adapter(model_class, :read)).to eq(:adapter_instance)
423
- end
424
-
425
- it "raises an error when attempting to use a block with a hash condition since it's not likely what they want" do
426
- expect {
427
- @ability.can :read, Array, :published => true do
428
- false
429
- end
430
- }.to raise_error(CanCan::Error, "You are not able to supply a block with a hash of conditions in read Array ability. Use either one.")
431
- end
432
-
433
- describe "unauthorized message" do
434
- after(:each) do
435
- I18n.backend = nil
436
- end
437
-
438
- it "uses action/subject in i18n" do
439
- I18n.backend.store_translations :en, :unauthorized => {:update => {:array => "foo"}}
440
- expect(@ability.unauthorized_message(:update, Array)).to eq("foo")
441
- expect(@ability.unauthorized_message(:update, [1, 2, 3])).to eq("foo")
442
- expect(@ability.unauthorized_message(:update, :missing)).to be_nil
443
- end
444
-
445
- it "uses symbol as subject directly" do
446
- I18n.backend.store_translations :en, :unauthorized => {:has => {:cheezburger => "Nom nom nom. I eated it."}}
447
- expect(@ability.unauthorized_message(:has, :cheezburger)).to eq("Nom nom nom. I eated it.")
448
- end
449
-
450
- it "falls back to 'manage' and 'all'" do
451
- I18n.backend.store_translations :en, :unauthorized => {
452
- :manage => {:all => "manage all", :array => "manage array"},
453
- :update => {:all => "update all", :array => "update array"}
454
- }
455
- expect(@ability.unauthorized_message(:update, Array)).to eq("update array")
456
- expect(@ability.unauthorized_message(:update, Hash)).to eq("update all")
457
- expect(@ability.unauthorized_message(:foo, Array)).to eq("manage array")
458
- expect(@ability.unauthorized_message(:foo, Hash)).to eq("manage all")
459
- end
460
-
461
- it "follows aliased actions" do
462
- I18n.backend.store_translations :en, :unauthorized => {:modify => {:array => "modify array"}}
463
- @ability.alias_action :update, :to => :modify
464
- expect(@ability.unauthorized_message(:update, Array)).to eq("modify array")
465
- expect(@ability.unauthorized_message(:edit, Array)).to eq("modify array")
466
- end
467
-
468
- it "has variables for action and subject" do
469
- I18n.backend.store_translations :en, :unauthorized => {:manage => {:all => "%{action} %{subject}"}} # old syntax for now in case testing with old I18n
470
- expect(@ability.unauthorized_message(:update, Array)).to eq("update array")
471
- expect(@ability.unauthorized_message(:update, ArgumentError)).to eq("update argument error")
472
- expect(@ability.unauthorized_message(:edit, 1..3)).to eq("edit range")
473
- end
474
- end
475
-
476
- describe "#merge" do
477
- it "adds the rules from the given ability" do
478
- @ability.can :use, :tools
479
- (another_ability = double).extend(CanCan::Ability)
480
- another_ability.can :use, :search
481
-
482
- @ability.merge(another_ability)
483
- expect(@ability.can?(:use, :search)).to be(true)
484
- expect(@ability.send(:rules).size).to eq(2)
485
- end
486
- end
487
- end
@@ -1,141 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CanCan::ControllerAdditions do
4
- before(:each) do
5
- @controller_class = Class.new
6
- @controller = @controller_class.new
7
- allow(@controller).to receive(:params) { {} }
8
- allow(@controller).to receive(:current_user) { :current_user }
9
- expect(@controller_class).to receive(:helper_method).with(:can?, :cannot?, :current_ability)
10
- @controller_class.send(:include, CanCan::ControllerAdditions)
11
- end
12
-
13
- it "raises ImplementationRemoved when attempting to call 'unauthorized!' on a controller" do
14
- expect { @controller.unauthorized! }.to raise_error(CanCan::ImplementationRemoved)
15
- end
16
-
17
- it "authorize! assigns @_authorized instance variable and pass args to current ability" do
18
- allow(@controller.current_ability).to receive(:authorize!).with(:foo, :bar)
19
- @controller.authorize!(:foo, :bar)
20
- expect(@controller.instance_variable_get(:@_authorized)).to be(true)
21
- end
22
-
23
- it "has a current_ability method which generates an ability for the current user" do
24
- expect(@controller.current_ability).to be_kind_of(Ability)
25
- end
26
-
27
- it "provides a can? and cannot? methods which go through the current ability" do
28
- expect(@controller.current_ability).to be_kind_of(Ability)
29
- expect(@controller.can?(:foo, :bar)).to be(false)
30
- expect(@controller.cannot?(:foo, :bar)).to be(true)
31
- end
32
-
33
- it "load_and_authorize_resource setups a before filter which passes call to ControllerResource" do
34
- expect(cancan_resource_class = double).to receive(:load_and_authorize_resource)
35
- allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class }
36
- expect(@controller_class).to receive(:before_filter).with({}) { |options, &block| block.call(@controller) }
37
- @controller_class.load_and_authorize_resource :foo => :bar
38
- end
39
-
40
- it "load_and_authorize_resource properly passes first argument as the resource name" do
41
- expect(cancan_resource_class = double).to receive(:load_and_authorize_resource)
42
- allow(CanCan::ControllerResource).to receive(:new).with(@controller, :project, :foo => :bar) {cancan_resource_class}
43
- expect(@controller_class).to receive(:before_filter).with({}) { |options, &block| block.call(@controller) }
44
- @controller_class.load_and_authorize_resource :project, :foo => :bar
45
- end
46
-
47
- it "load_and_authorize_resource with :prepend prepends the before filter" do
48
- expect(@controller_class).to receive(:prepend_before_filter).with({})
49
- @controller_class.load_and_authorize_resource :foo => :bar, :prepend => true
50
- end
51
-
52
- it "authorize_resource setups a before filter which passes call to ControllerResource" do
53
- expect(cancan_resource_class = double).to receive(:authorize_resource)
54
- allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class}
55
- expect(@controller_class).to receive(:before_filter).with(:except => :show, :if => true) { |options, &block| block.call(@controller) }
56
- @controller_class.authorize_resource :foo => :bar, :except => :show, :if => true
57
- end
58
-
59
- it "load_resource setups a before filter which passes call to ControllerResource" do
60
- expect(cancan_resource_class = double).to receive(:load_resource)
61
- allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class}
62
- expect(@controller_class).to receive(:before_filter).with(:only => [:show, :index], :unless => false) { |options, &block| block.call(@controller) }
63
- @controller_class.load_resource :foo => :bar, :only => [:show, :index], :unless => false
64
- end
65
-
66
- it "skip_authorization_check setups a before filter which sets @_authorized to true" do
67
- expect(@controller_class).to receive(:before_filter).with(:filter_options) { |options, &block| block.call(@controller) }
68
- @controller_class.skip_authorization_check(:filter_options)
69
- expect(@controller.instance_variable_get(:@_authorized)).to be(true)
70
- end
71
-
72
- it "check_authorization triggers AuthorizationNotPerformed in after filter" do
73
- expect(@controller_class).to receive(:after_filter).with(:only => [:test]) { |options, &block| block.call(@controller) }
74
- expect {
75
- @controller_class.check_authorization(:only => [:test])
76
- }.to raise_error(CanCan::AuthorizationNotPerformed)
77
- end
78
-
79
- it "check_authorization does not trigger AuthorizationNotPerformed when :if is false" do
80
- allow(@controller).to receive(:check_auth?) { false }
81
- allow(@controller_class).to receive(:after_filter).with({}) { |options, &block| block.call(@controller) }
82
- expect {
83
- @controller_class.check_authorization(:if => :check_auth?)
84
- }.not_to raise_error
85
- end
86
-
87
- it "check_authorization does not trigger AuthorizationNotPerformed when :unless is true" do
88
- allow(@controller).to receive(:engine_controller?) { true }
89
- expect(@controller_class).to receive(:after_filter).with({}) { |options, &block| block.call(@controller) }
90
- expect {
91
- @controller_class.check_authorization(:unless => :engine_controller?)
92
- }.not_to raise_error
93
- end
94
-
95
- it "check_authorization does not raise error when @_authorized is set" do
96
- @controller.instance_variable_set(:@_authorized, true)
97
- expect(@controller_class).to receive(:after_filter).with(:only => [:test]) { |options, &block| block.call(@controller) }
98
- expect {
99
- @controller_class.check_authorization(:only => [:test])
100
- }.not_to raise_error
101
- end
102
-
103
- it "cancan_resource_class is ControllerResource by default" do
104
- expect(@controller.class.cancan_resource_class).to eq(CanCan::ControllerResource)
105
- end
106
-
107
- it "cancan_resource_class is InheritedResource when class includes InheritedResources::Actions" do
108
- allow(@controller.class).to receive(:ancestors) { ["InheritedResources::Actions"] }
109
- expect(@controller.class.cancan_resource_class).to eq(CanCan::InheritedResource)
110
- end
111
-
112
- it "cancan_skipper is an empty hash with :authorize and :load options and remember changes" do
113
- expect(@controller_class.cancan_skipper).to eq({:authorize => {}, :load => {}})
114
- @controller_class.cancan_skipper[:load] = true
115
- expect(@controller_class.cancan_skipper[:load]).to be(true)
116
- end
117
-
118
- it "skip_authorize_resource adds itself to the cancan skipper with given model name and options" do
119
- @controller_class.skip_authorize_resource(:project, :only => [:index, :show])
120
- expect(@controller_class.cancan_skipper[:authorize][:project]).to eq({:only => [:index, :show]})
121
- @controller_class.skip_authorize_resource(:only => [:index, :show])
122
- expect(@controller_class.cancan_skipper[:authorize][nil]).to eq({:only => [:index, :show]})
123
- @controller_class.skip_authorize_resource(:article)
124
- expect(@controller_class.cancan_skipper[:authorize][:article]).to eq({})
125
- end
126
-
127
- it "skip_load_resource adds itself to the cancan skipper with given model name and options" do
128
- @controller_class.skip_load_resource(:project, :only => [:index, :show])
129
- expect(@controller_class.cancan_skipper[:load][:project]).to eq({:only => [:index, :show]})
130
- @controller_class.skip_load_resource(:only => [:index, :show])
131
- expect(@controller_class.cancan_skipper[:load][nil]).to eq({:only => [:index, :show]})
132
- @controller_class.skip_load_resource(:article)
133
- expect(@controller_class.cancan_skipper[:load][:article]).to eq({})
134
- end
135
-
136
- it "skip_load_and_authore_resource adds itself to the cancan skipper with given model name and options" do
137
- @controller_class.skip_load_and_authorize_resource(:project, :only => [:index, :show])
138
- expect(@controller_class.cancan_skipper[:load][:project]).to eq({:only => [:index, :show]})
139
- expect(@controller_class.cancan_skipper[:authorize][:project]).to eq({:only => [:index, :show]})
140
- end
141
- end