cancancan 1.10.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +5 -5
  2. data/cancancan.gemspec +19 -21
  3. data/init.rb +2 -0
  4. data/lib/cancan/ability/actions.rb +93 -0
  5. data/lib/cancan/ability/rules.rb +96 -0
  6. data/lib/cancan/ability/strong_parameter_support.rb +41 -0
  7. data/lib/cancan/ability.rb +114 -146
  8. data/lib/cancan/class_matcher.rb +30 -0
  9. data/lib/cancan/conditions_matcher.rb +147 -0
  10. data/lib/cancan/config.rb +101 -0
  11. data/lib/cancan/controller_additions.rb +38 -41
  12. data/lib/cancan/controller_resource.rb +59 -215
  13. data/lib/cancan/controller_resource_builder.rb +26 -0
  14. data/lib/cancan/controller_resource_finder.rb +42 -0
  15. data/lib/cancan/controller_resource_loader.rb +120 -0
  16. data/lib/cancan/controller_resource_name_finder.rb +23 -0
  17. data/lib/cancan/controller_resource_sanitizer.rb +32 -0
  18. data/lib/cancan/exceptions.rb +25 -5
  19. data/lib/cancan/matchers.rb +17 -3
  20. data/lib/cancan/model_adapters/abstract_adapter.rb +30 -9
  21. data/lib/cancan/model_adapters/active_record_4_adapter.rb +43 -15
  22. data/lib/cancan/model_adapters/active_record_5_adapter.rb +61 -0
  23. data/lib/cancan/model_adapters/active_record_adapter.rb +157 -82
  24. data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
  25. data/lib/cancan/model_adapters/conditions_normalizer.rb +49 -0
  26. data/lib/cancan/model_adapters/default_adapter.rb +2 -0
  27. data/lib/cancan/model_adapters/sti_normalizer.rb +47 -0
  28. data/lib/cancan/model_adapters/strategies/base.rb +40 -0
  29. data/lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb +93 -0
  30. data/lib/cancan/model_adapters/strategies/joined_alias_exists_subquery.rb +31 -0
  31. data/lib/cancan/model_adapters/strategies/left_join.rb +11 -0
  32. data/lib/cancan/model_adapters/strategies/subquery.rb +18 -0
  33. data/lib/cancan/model_additions.rb +6 -3
  34. data/lib/cancan/parameter_validators.rb +9 -0
  35. data/lib/cancan/relevant.rb +29 -0
  36. data/lib/cancan/rule.rb +79 -91
  37. data/lib/cancan/rules_compressor.rb +23 -0
  38. data/lib/cancan/sti_detector.rb +12 -0
  39. data/lib/cancan/unauthorized_message_resolver.rb +24 -0
  40. data/lib/cancan/version.rb +3 -1
  41. data/lib/cancan.rb +16 -12
  42. data/lib/cancancan.rb +2 -0
  43. data/lib/generators/cancan/ability/ability_generator.rb +4 -2
  44. data/lib/generators/cancan/ability/templates/ability.rb +9 -9
  45. metadata +82 -93
  46. data/.gitignore +0 -15
  47. data/.rspec +0 -1
  48. data/.travis.yml +0 -48
  49. data/Appraisals +0 -135
  50. data/CHANGELOG.rdoc +0 -495
  51. data/CONTRIBUTING.md +0 -23
  52. data/Gemfile +0 -3
  53. data/LICENSE +0 -22
  54. data/README.md +0 -197
  55. data/Rakefile +0 -9
  56. data/gemfiles/activerecord_3.0.gemfile +0 -18
  57. data/gemfiles/activerecord_3.1.gemfile +0 -20
  58. data/gemfiles/activerecord_3.2.gemfile +0 -20
  59. data/gemfiles/activerecord_4.0.gemfile +0 -17
  60. data/gemfiles/activerecord_4.1.gemfile +0 -17
  61. data/gemfiles/activerecord_4.2.gemfile +0 -17
  62. data/gemfiles/datamapper_1.x.gemfile +0 -14
  63. data/gemfiles/mongoid_2.x.gemfile +0 -20
  64. data/gemfiles/sequel_3.x.gemfile +0 -20
  65. data/lib/cancan/inherited_resource.rb +0 -20
  66. data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
  67. data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
  68. data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
  69. data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
  70. data/spec/README.rdoc +0 -27
  71. data/spec/cancan/ability_spec.rb +0 -487
  72. data/spec/cancan/controller_additions_spec.rb +0 -141
  73. data/spec/cancan/controller_resource_spec.rb +0 -648
  74. data/spec/cancan/exceptions_spec.rb +0 -58
  75. data/spec/cancan/inherited_resource_spec.rb +0 -71
  76. data/spec/cancan/matchers_spec.rb +0 -29
  77. data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -40
  78. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
  79. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
  80. data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
  81. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
  82. data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
  83. data/spec/cancan/rule_spec.rb +0 -52
  84. data/spec/matchers.rb +0 -13
  85. data/spec/spec.opts +0 -2
  86. data/spec/spec_helper.rb +0 -27
  87. 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