protected_attributes 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +17 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +111 -0
  6. data/Rakefile +11 -0
  7. data/lib/action_controller/accessible_params_wrapper.rb +29 -0
  8. data/lib/active_model/mass_assignment_security.rb +353 -0
  9. data/lib/active_model/mass_assignment_security/permission_set.rb +40 -0
  10. data/lib/active_model/mass_assignment_security/sanitizer.rb +74 -0
  11. data/lib/active_record/mass_assignment_security.rb +23 -0
  12. data/lib/active_record/mass_assignment_security/associations.rb +116 -0
  13. data/lib/active_record/mass_assignment_security/attribute_assignment.rb +88 -0
  14. data/lib/active_record/mass_assignment_security/core.rb +27 -0
  15. data/lib/active_record/mass_assignment_security/inheritance.rb +18 -0
  16. data/lib/active_record/mass_assignment_security/nested_attributes.rb +148 -0
  17. data/lib/active_record/mass_assignment_security/persistence.rb +81 -0
  18. data/lib/active_record/mass_assignment_security/reflection.rb +9 -0
  19. data/lib/active_record/mass_assignment_security/relation.rb +47 -0
  20. data/lib/active_record/mass_assignment_security/validations.rb +24 -0
  21. data/lib/protected_attributes.rb +14 -0
  22. data/lib/protected_attributes/railtie.rb +18 -0
  23. data/lib/protected_attributes/version.rb +3 -0
  24. data/protected_attributes.gemspec +26 -0
  25. data/test/abstract_unit.rb +156 -0
  26. data/test/accessible_params_wrapper_test.rb +76 -0
  27. data/test/ar_helper.rb +67 -0
  28. data/test/attribute_sanitization_test.rb +929 -0
  29. data/test/mass_assignment_security/black_list_test.rb +20 -0
  30. data/test/mass_assignment_security/permission_set_test.rb +36 -0
  31. data/test/mass_assignment_security/sanitizer_test.rb +50 -0
  32. data/test/mass_assignment_security/white_list_test.rb +19 -0
  33. data/test/mass_assignment_security_test.rb +118 -0
  34. data/test/models/company.rb +105 -0
  35. data/test/models/keyboard.rb +3 -0
  36. data/test/models/mass_assignment_specific.rb +76 -0
  37. data/test/models/person.rb +82 -0
  38. data/test/models/subscriber.rb +5 -0
  39. data/test/models/task.rb +5 -0
  40. data/test/test_helper.rb +3 -0
  41. metadata +199 -0
data/test/ar_helper.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'active_record'
2
+
3
+ ActiveSupport::Deprecation.silence do
4
+ require 'active_record/test_case'
5
+ end
6
+
7
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
8
+
9
+ ActiveRecord::Schema.verbose = false
10
+ ActiveRecord::Schema.define do
11
+
12
+ create_table :accounts, :force => true do |t|
13
+ t.integer :firm_id
14
+ t.string :firm_name
15
+ t.integer :credit_limit
16
+ end
17
+
18
+
19
+ create_table :companies, :force => true do |t|
20
+ t.string :type
21
+ t.integer :firm_id
22
+ t.string :firm_name
23
+ t.string :name
24
+ t.integer :client_of
25
+ t.integer :rating, :default => 1
26
+ t.integer :account_id
27
+ t.string :description, :default => ""
28
+ end
29
+
30
+ add_index :companies, [:firm_id, :type, :rating], :name => "company_index"
31
+ add_index :companies, [:firm_id, :type], :name => "company_partial_index", :where => "rating > 10"
32
+
33
+
34
+ create_table :keyboards, :force => true, :id => false do |t|
35
+ t.primary_key :key_number
36
+ t.string :name
37
+ end
38
+
39
+
40
+ create_table :people, :force => true do |t|
41
+ t.string :first_name, :null => false
42
+ t.references :primary_contact
43
+ t.string :gender, :limit => 1
44
+ t.references :number1_fan
45
+ t.integer :lock_version, :null => false, :default => 0
46
+ t.string :comments
47
+ t.integer :followers_count, :default => 0
48
+ t.references :best_friend
49
+ t.references :best_friend_of
50
+ t.timestamps
51
+ end
52
+
53
+
54
+ create_table :subscribers, :force => true, :id => false do |t|
55
+ t.string :nick, :null => false
56
+ t.string :name
57
+ end
58
+ add_index :subscribers, :nick, :unique => true
59
+
60
+
61
+ create_table :tasks, :force => true do |t|
62
+ t.datetime :starting
63
+ t.datetime :ending
64
+ end
65
+ end
66
+
67
+ QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
@@ -0,0 +1,929 @@
1
+ require 'test_helper'
2
+ require 'ar_helper'
3
+ require 'active_record/mass_assignment_security'
4
+ require 'models/company'
5
+ require 'models/subscriber'
6
+ require 'models/keyboard'
7
+ require 'models/task'
8
+ require 'models/person'
9
+
10
+ module MassAssignmentTestHelpers
11
+ def teardown
12
+ ActiveRecord::Base.send(:descendants).each do |klass|
13
+ begin
14
+ klass.delete_all
15
+ rescue
16
+ end
17
+ end
18
+ end
19
+
20
+ def attributes_hash
21
+ {
22
+ :id => 5,
23
+ :first_name => 'Josh',
24
+ :gender => 'm',
25
+ :comments => 'rides a sweet bike'
26
+ }
27
+ end
28
+
29
+ def assert_default_attributes(person, create = false)
30
+ unless create
31
+ assert_nil person.id
32
+ else
33
+ assert !!person.id
34
+ end
35
+ assert_equal 'Josh', person.first_name
36
+ assert_equal 'm', person.gender
37
+ assert_nil person.comments
38
+ end
39
+
40
+ def assert_admin_attributes(person, create = false)
41
+ unless create
42
+ assert_nil person.id
43
+ else
44
+ assert !!person.id
45
+ end
46
+ assert_equal 'Josh', person.first_name
47
+ assert_equal 'm', person.gender
48
+ assert_equal 'rides a sweet bike', person.comments
49
+ end
50
+
51
+ def assert_all_attributes(person)
52
+ assert_equal 5, person.id
53
+ assert_equal 'Josh', person.first_name
54
+ assert_equal 'm', person.gender
55
+ assert_equal 'rides a sweet bike', person.comments
56
+ end
57
+
58
+ def with_strict_sanitizer
59
+ ActiveRecord::Base.mass_assignment_sanitizer = :strict
60
+ yield
61
+ ensure
62
+ ActiveRecord::Base.mass_assignment_sanitizer = :logger
63
+ end
64
+ end
65
+
66
+ module MassAssignmentRelationTestHelpers
67
+ def setup
68
+ super
69
+ @person = LoosePerson.create(attributes_hash)
70
+ end
71
+ end
72
+
73
+ class AttributeSanitizationTest < ActiveSupport::TestCase
74
+ include MassAssignmentTestHelpers
75
+
76
+ def test_customized_primary_key_remains_protected
77
+ subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
78
+ assert_nil subscriber.id
79
+
80
+ keyboard = Keyboard.new(:key_number => 9, :name => 'nice try')
81
+ assert_nil keyboard.id
82
+ end
83
+
84
+ def test_customized_primary_key_remains_protected_when_referred_to_as_id
85
+ subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try')
86
+ assert_nil subscriber.id
87
+
88
+ keyboard = Keyboard.new(:id => 9, :name => 'nice try')
89
+ assert_nil keyboard.id
90
+ end
91
+
92
+ def test_mass_assigning_invalid_attribute
93
+ firm = Firm.new
94
+
95
+ assert_raise(ActiveRecord::UnknownAttributeError) do
96
+ firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 }
97
+ end
98
+ end
99
+
100
+ def test_mass_assigning_does_not_choke_on_nil
101
+ assert_nil Firm.new.assign_attributes(nil)
102
+ end
103
+
104
+ def test_mass_assigning_does_not_choke_on_empty_hash
105
+ assert_nil Firm.new.assign_attributes({})
106
+ end
107
+
108
+ def test_assign_attributes_uses_default_role_when_no_role_is_provided
109
+ p = LoosePerson.new
110
+ p.assign_attributes(attributes_hash)
111
+
112
+ assert_default_attributes(p)
113
+ end
114
+
115
+ def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used
116
+ p = LoosePerson.new
117
+ p.assign_attributes(attributes_hash, :without_protection => true)
118
+
119
+ assert_all_attributes(p)
120
+ end
121
+
122
+ def test_assign_attributes_with_default_role_and_attr_protected_attributes
123
+ p = LoosePerson.new
124
+ p.assign_attributes(attributes_hash, :as => :default)
125
+
126
+ assert_default_attributes(p)
127
+ end
128
+
129
+ def test_assign_attributes_with_admin_role_and_attr_protected_attributes
130
+ p = LoosePerson.new
131
+ p.assign_attributes(attributes_hash, :as => :admin)
132
+
133
+ assert_admin_attributes(p)
134
+ end
135
+
136
+ def test_assign_attributes_with_default_role_and_attr_accessible_attributes
137
+ p = TightPerson.new
138
+ p.assign_attributes(attributes_hash, :as => :default)
139
+
140
+ assert_default_attributes(p)
141
+ end
142
+
143
+ def test_assign_attributes_with_admin_role_and_attr_accessible_attributes
144
+ p = TightPerson.new
145
+ p.assign_attributes(attributes_hash, :as => :admin)
146
+
147
+ assert_admin_attributes(p)
148
+ end
149
+
150
+ def test_new_with_attr_accessible_attributes
151
+ p = TightPerson.new(attributes_hash)
152
+
153
+ assert_default_attributes(p)
154
+ end
155
+
156
+ def test_new_with_attr_protected_attributes
157
+ p = LoosePerson.new(attributes_hash)
158
+
159
+ assert_default_attributes(p)
160
+ end
161
+
162
+ def test_create_with_attr_accessible_attributes
163
+ p = TightPerson.create(attributes_hash)
164
+
165
+ assert_default_attributes(p, true)
166
+ end
167
+
168
+ def test_create_with_attr_protected_attributes
169
+ p = LoosePerson.create(attributes_hash)
170
+
171
+ assert_default_attributes(p, true)
172
+ end
173
+
174
+ def test_new_with_admin_role_with_attr_accessible_attributes
175
+ p = TightPerson.new(attributes_hash, :as => :admin)
176
+
177
+ assert_admin_attributes(p)
178
+ end
179
+
180
+ def test_new_with_admin_role_with_attr_protected_attributes
181
+ p = LoosePerson.new(attributes_hash, :as => :admin)
182
+
183
+ assert_admin_attributes(p)
184
+ end
185
+
186
+ def test_create_with_admin_role_with_attr_accessible_attributes
187
+ p = TightPerson.create(attributes_hash, :as => :admin)
188
+
189
+ assert_admin_attributes(p, true)
190
+ end
191
+
192
+ def test_create_with_admin_role_with_attr_protected_attributes
193
+ p = LoosePerson.create(attributes_hash, :as => :admin)
194
+
195
+ assert_admin_attributes(p, true)
196
+ end
197
+
198
+ def test_create_with_bang_with_admin_role_with_attr_accessible_attributes
199
+ p = TightPerson.create!(attributes_hash, :as => :admin)
200
+
201
+ assert_admin_attributes(p, true)
202
+ end
203
+
204
+ def test_create_with_bang_with_admin_role_with_attr_protected_attributes
205
+ p = LoosePerson.create!(attributes_hash, :as => :admin)
206
+
207
+ assert_admin_attributes(p, true)
208
+ end
209
+
210
+ def test_new_with_without_protection_with_attr_accessible_attributes
211
+ p = TightPerson.new(attributes_hash, :without_protection => true)
212
+
213
+ assert_all_attributes(p)
214
+ end
215
+
216
+ def test_new_with_without_protection_with_attr_protected_attributes
217
+ p = LoosePerson.new(attributes_hash, :without_protection => true)
218
+
219
+ assert_all_attributes(p)
220
+ end
221
+
222
+ def test_create_with_without_protection_with_attr_accessible_attributes
223
+ p = TightPerson.create(attributes_hash, :without_protection => true)
224
+
225
+ assert_all_attributes(p)
226
+ end
227
+
228
+ def test_create_with_without_protection_with_attr_protected_attributes
229
+ p = LoosePerson.create(attributes_hash, :without_protection => true)
230
+
231
+ assert_all_attributes(p)
232
+ end
233
+
234
+ def test_create_with_bang_with_without_protection_with_attr_accessible_attributes
235
+ p = TightPerson.create!(attributes_hash, :without_protection => true)
236
+
237
+ assert_all_attributes(p)
238
+ end
239
+
240
+ def test_create_with_bang_with_without_protection_with_attr_protected_attributes
241
+ p = LoosePerson.create!(attributes_hash, :without_protection => true)
242
+
243
+ assert_all_attributes(p)
244
+ end
245
+
246
+ def test_protection_against_class_attribute_writers
247
+ [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names,
248
+ :default_timezone, :schema_format, :lock_optimistically, :timestamped_migrations, :default_scopes,
249
+ :connection_handler, :nested_attributes_options, :_attr_readonly, :attribute_types_cached_by_default,
250
+ :attribute_method_matchers, :time_zone_aware_attributes, :skip_time_zone_conversion_for_attributes].each do |method|
251
+ assert_respond_to Task, method
252
+ assert_respond_to Task, "#{method}="
253
+ assert_respond_to Task.new, method
254
+ assert !Task.new.respond_to?("#{method}=")
255
+ end
256
+ end
257
+
258
+ def test_new_with_protected_inheritance_column
259
+ firm = Company.new(type: "Firm")
260
+ assert_equal firm.class, Company
261
+ end
262
+
263
+ def test_new_with_accessible_inheritance_column
264
+ corporation = Corporation.new(type: "SpecialCorporation")
265
+ assert_equal corporation.class, SpecialCorporation
266
+ end
267
+
268
+ def test_new_with_invalid_inheritance_column_class
269
+ assert_raise(ActiveRecord::SubclassNotFound) { Corporation.new(type: "InvalidCorporation") }
270
+ end
271
+
272
+ def test_new_with_unrelated_inheritance_column_class
273
+ assert_raise(ActiveRecord::SubclassNotFound) { Corporation.new(type: "Person") }
274
+ end
275
+ end
276
+
277
+
278
+ # This class should be deleted when we remove activerecord-deprecated_finders as a
279
+ # dependency.
280
+ class MassAssignmentSecurityDeprecatedFindersTest < ActiveRecord::TestCase
281
+ include MassAssignmentTestHelpers
282
+
283
+ def setup
284
+ super
285
+ @deprecation_behavior = ActiveSupport::Deprecation.behavior
286
+ ActiveSupport::Deprecation.behavior = :silence
287
+ end
288
+
289
+ def teardown
290
+ super
291
+ ActiveSupport::Deprecation.behavior = @deprecation_behavior
292
+ end
293
+
294
+ def test_find_or_initialize_by_with_attr_accessible_attributes
295
+ p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash)
296
+
297
+ assert_default_attributes(p)
298
+ end
299
+
300
+ def test_find_or_initialize_by_with_admin_role_with_attr_accessible_attributes
301
+ p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin)
302
+
303
+ assert_admin_attributes(p)
304
+ end
305
+
306
+ def test_find_or_initialize_by_with_attr_protected_attributes
307
+ p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash)
308
+
309
+ assert_default_attributes(p)
310
+ end
311
+
312
+ def test_find_or_initialize_by_with_admin_role_with_attr_protected_attributes
313
+ p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin)
314
+
315
+ assert_admin_attributes(p)
316
+ end
317
+
318
+ def test_find_or_create_by_with_attr_accessible_attributes
319
+ p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash)
320
+
321
+ assert_default_attributes(p, true)
322
+ end
323
+
324
+ def test_find_or_create_by_with_admin_role_with_attr_accessible_attributes
325
+ p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin)
326
+
327
+ assert_admin_attributes(p, true)
328
+ end
329
+
330
+ def test_find_or_create_by_with_attr_protected_attributes
331
+ p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash)
332
+
333
+ assert_default_attributes(p, true)
334
+ end
335
+
336
+ def test_find_or_create_by_with_admin_role_with_attr_protected_attributes
337
+ p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin)
338
+
339
+ assert_admin_attributes(p, true)
340
+ end
341
+
342
+ end
343
+
344
+
345
+ class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase
346
+ include MassAssignmentTestHelpers
347
+ include MassAssignmentRelationTestHelpers
348
+
349
+ # build
350
+
351
+ def test_has_one_build_with_attr_protected_attributes
352
+ best_friend = @person.build_best_friend(attributes_hash)
353
+ assert_default_attributes(best_friend)
354
+ end
355
+
356
+ def test_has_one_build_with_attr_accessible_attributes
357
+ best_friend = @person.build_best_friend(attributes_hash)
358
+ assert_default_attributes(best_friend)
359
+ end
360
+
361
+ def test_has_one_build_with_admin_role_with_attr_protected_attributes
362
+ best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
363
+ assert_admin_attributes(best_friend)
364
+ end
365
+
366
+ def test_has_one_build_with_admin_role_with_attr_accessible_attributes
367
+ best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
368
+ assert_admin_attributes(best_friend)
369
+ end
370
+
371
+ def test_has_one_build_without_protection
372
+ best_friend = @person.build_best_friend(attributes_hash, :without_protection => true)
373
+ assert_all_attributes(best_friend)
374
+ end
375
+
376
+ def test_has_one_build_with_strict_sanitizer
377
+ with_strict_sanitizer do
378
+ best_friend = @person.build_best_friend(attributes_hash.except(:id, :comments))
379
+ assert_equal @person.id, best_friend.best_friend_id
380
+ end
381
+ end
382
+
383
+ # create
384
+
385
+ def test_has_one_create_with_attr_protected_attributes
386
+ best_friend = @person.create_best_friend(attributes_hash)
387
+ assert_default_attributes(best_friend, true)
388
+ end
389
+
390
+ def test_has_one_create_with_attr_accessible_attributes
391
+ best_friend = @person.create_best_friend(attributes_hash)
392
+ assert_default_attributes(best_friend, true)
393
+ end
394
+
395
+ def test_has_one_create_with_admin_role_with_attr_protected_attributes
396
+ best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
397
+ assert_admin_attributes(best_friend, true)
398
+ end
399
+
400
+ def test_has_one_create_with_admin_role_with_attr_accessible_attributes
401
+ best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
402
+ assert_admin_attributes(best_friend, true)
403
+ end
404
+
405
+ def test_has_one_create_without_protection
406
+ best_friend = @person.create_best_friend(attributes_hash, :without_protection => true)
407
+ assert_all_attributes(best_friend)
408
+ end
409
+
410
+ def test_has_one_create_with_strict_sanitizer
411
+ with_strict_sanitizer do
412
+ best_friend = @person.create_best_friend(attributes_hash.except(:id, :comments))
413
+ assert_equal @person.id, best_friend.best_friend_id
414
+ end
415
+ end
416
+
417
+ # create!
418
+
419
+ def test_has_one_create_with_bang_with_attr_protected_attributes
420
+ best_friend = @person.create_best_friend!(attributes_hash)
421
+ assert_default_attributes(best_friend, true)
422
+ end
423
+
424
+ def test_has_one_create_with_bang_with_attr_accessible_attributes
425
+ best_friend = @person.create_best_friend!(attributes_hash)
426
+ assert_default_attributes(best_friend, true)
427
+ end
428
+
429
+ def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
430
+ best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
431
+ assert_admin_attributes(best_friend, true)
432
+ end
433
+
434
+ def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
435
+ best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
436
+ assert_admin_attributes(best_friend, true)
437
+ end
438
+
439
+ def test_has_one_create_with_bang_without_protection
440
+ best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true)
441
+ assert_all_attributes(best_friend)
442
+ end
443
+
444
+ def test_has_one_create_with_bang_with_strict_sanitizer
445
+ with_strict_sanitizer do
446
+ best_friend = @person.create_best_friend!(attributes_hash.except(:id, :comments))
447
+ assert_equal @person.id, best_friend.best_friend_id
448
+ end
449
+ end
450
+
451
+ end
452
+
453
+
454
+ class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase
455
+ include MassAssignmentTestHelpers
456
+ include MassAssignmentRelationTestHelpers
457
+
458
+ # build
459
+
460
+ def test_belongs_to_build_with_attr_protected_attributes
461
+ best_friend = @person.build_best_friend_of(attributes_hash)
462
+ assert_default_attributes(best_friend)
463
+ end
464
+
465
+ def test_belongs_to_build_with_attr_accessible_attributes
466
+ best_friend = @person.build_best_friend_of(attributes_hash)
467
+ assert_default_attributes(best_friend)
468
+ end
469
+
470
+ def test_belongs_to_build_with_admin_role_with_attr_protected_attributes
471
+ best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
472
+ assert_admin_attributes(best_friend)
473
+ end
474
+
475
+ def test_belongs_to_build_with_admin_role_with_attr_accessible_attributes
476
+ best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
477
+ assert_admin_attributes(best_friend)
478
+ end
479
+
480
+ def test_belongs_to_build_without_protection
481
+ best_friend = @person.build_best_friend_of(attributes_hash, :without_protection => true)
482
+ assert_all_attributes(best_friend)
483
+ end
484
+
485
+ # create
486
+
487
+ def test_belongs_to_create_with_attr_protected_attributes
488
+ best_friend = @person.create_best_friend_of(attributes_hash)
489
+ assert_default_attributes(best_friend, true)
490
+ end
491
+
492
+ def test_belongs_to_create_with_attr_accessible_attributes
493
+ best_friend = @person.create_best_friend_of(attributes_hash)
494
+ assert_default_attributes(best_friend, true)
495
+ end
496
+
497
+ def test_belongs_to_create_with_admin_role_with_attr_protected_attributes
498
+ best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
499
+ assert_admin_attributes(best_friend, true)
500
+ end
501
+
502
+ def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes
503
+ best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
504
+ assert_admin_attributes(best_friend, true)
505
+ end
506
+
507
+ def test_belongs_to_create_without_protection
508
+ best_friend = @person.create_best_friend_of(attributes_hash, :without_protection => true)
509
+ assert_all_attributes(best_friend)
510
+ end
511
+
512
+ def test_belongs_to_create_with_strict_sanitizer
513
+ with_strict_sanitizer do
514
+ best_friend = @person.create_best_friend_of(attributes_hash.except(:id, :comments))
515
+ assert_equal best_friend.id, @person.best_friend_of_id
516
+ end
517
+ end
518
+
519
+ # create!
520
+
521
+ def test_belongs_to_create_with_bang_with_attr_protected_attributes
522
+ best_friend = @person.create_best_friend!(attributes_hash)
523
+ assert_default_attributes(best_friend, true)
524
+ end
525
+
526
+ def test_belongs_to_create_with_bang_with_attr_accessible_attributes
527
+ best_friend = @person.create_best_friend!(attributes_hash)
528
+ assert_default_attributes(best_friend, true)
529
+ end
530
+
531
+ def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes
532
+ best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
533
+ assert_admin_attributes(best_friend, true)
534
+ end
535
+
536
+ def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes
537
+ best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
538
+ assert_admin_attributes(best_friend, true)
539
+ end
540
+
541
+ def test_belongs_to_create_with_bang_without_protection
542
+ best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true)
543
+ assert_all_attributes(best_friend)
544
+ end
545
+
546
+ def test_belongs_to_create_with_bang_with_strict_sanitizer
547
+ with_strict_sanitizer do
548
+ best_friend = @person.create_best_friend_of!(attributes_hash.except(:id, :comments))
549
+ assert_equal best_friend.id, @person.best_friend_of_id
550
+ end
551
+ end
552
+
553
+ end
554
+
555
+
556
+ class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase
557
+ include MassAssignmentTestHelpers
558
+ include MassAssignmentRelationTestHelpers
559
+
560
+ # build
561
+
562
+ def test_has_many_build_with_attr_protected_attributes
563
+ best_friend = @person.best_friends.build(attributes_hash)
564
+ assert_default_attributes(best_friend)
565
+ end
566
+
567
+ def test_has_many_build_with_attr_accessible_attributes
568
+ best_friend = @person.best_friends.build(attributes_hash)
569
+ assert_default_attributes(best_friend)
570
+ end
571
+
572
+ def test_has_many_build_with_admin_role_with_attr_protected_attributes
573
+ best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
574
+ assert_admin_attributes(best_friend)
575
+ end
576
+
577
+ def test_has_many_build_with_admin_role_with_attr_accessible_attributes
578
+ best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
579
+ assert_admin_attributes(best_friend)
580
+ end
581
+
582
+ def test_has_many_build_without_protection
583
+ best_friend = @person.best_friends.build(attributes_hash, :without_protection => true)
584
+ assert_all_attributes(best_friend)
585
+ end
586
+
587
+ def test_has_many_build_with_strict_sanitizer
588
+ with_strict_sanitizer do
589
+ best_friend = @person.best_friends.build(attributes_hash.except(:id, :comments))
590
+ assert_equal @person.id, best_friend.best_friend_id
591
+ end
592
+ end
593
+
594
+ # create
595
+
596
+ def test_has_many_create_with_attr_protected_attributes
597
+ best_friend = @person.best_friends.create(attributes_hash)
598
+ assert_default_attributes(best_friend, true)
599
+ end
600
+
601
+ def test_has_many_create_with_attr_accessible_attributes
602
+ best_friend = @person.best_friends.create(attributes_hash)
603
+ assert_default_attributes(best_friend, true)
604
+ end
605
+
606
+ def test_has_many_create_with_admin_role_with_attr_protected_attributes
607
+ best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
608
+ assert_admin_attributes(best_friend, true)
609
+ end
610
+
611
+ def test_has_many_create_with_admin_role_with_attr_accessible_attributes
612
+ best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
613
+ assert_admin_attributes(best_friend, true)
614
+ end
615
+
616
+ def test_has_many_create_without_protection
617
+ best_friend = @person.best_friends.create(attributes_hash, :without_protection => true)
618
+ assert_all_attributes(best_friend)
619
+ end
620
+
621
+ def test_has_many_create_with_strict_sanitizer
622
+ with_strict_sanitizer do
623
+ best_friend = @person.best_friends.create(attributes_hash.except(:id, :comments))
624
+ assert_equal @person.id, best_friend.best_friend_id
625
+ end
626
+ end
627
+
628
+ # create!
629
+
630
+ def test_has_many_create_with_bang_with_attr_protected_attributes
631
+ best_friend = @person.best_friends.create!(attributes_hash)
632
+ assert_default_attributes(best_friend, true)
633
+ end
634
+
635
+ def test_has_many_create_with_bang_with_attr_accessible_attributes
636
+ best_friend = @person.best_friends.create!(attributes_hash)
637
+ assert_default_attributes(best_friend, true)
638
+ end
639
+
640
+ def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes
641
+ best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
642
+ assert_admin_attributes(best_friend, true)
643
+ end
644
+
645
+ def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes
646
+ best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
647
+ assert_admin_attributes(best_friend, true)
648
+ end
649
+
650
+ def test_has_many_create_with_bang_without_protection
651
+ best_friend = @person.best_friends.create!(attributes_hash, :without_protection => true)
652
+ assert_all_attributes(best_friend)
653
+ end
654
+
655
+ def test_has_many_create_with_bang_with_strict_sanitizer
656
+ with_strict_sanitizer do
657
+ best_friend = @person.best_friends.create!(attributes_hash.except(:id, :comments))
658
+ assert_equal @person.id, best_friend.best_friend_id
659
+ end
660
+ end
661
+
662
+ end
663
+
664
+
665
+ class MassAssignmentSecurityNestedAttributesTest < ActiveRecord::TestCase
666
+ include MassAssignmentTestHelpers
667
+
668
+ def nested_attributes_hash(association, collection = false, except = [:id])
669
+ if collection
670
+ { :first_name => 'David' }.merge(:"#{association}_attributes" => [attributes_hash.except(*except)])
671
+ else
672
+ { :first_name => 'David' }.merge(:"#{association}_attributes" => attributes_hash.except(*except))
673
+ end
674
+ end
675
+
676
+ # build
677
+
678
+ def test_has_one_new_with_attr_protected_attributes
679
+ person = LoosePerson.new(nested_attributes_hash(:best_friend))
680
+ assert_default_attributes(person.best_friend)
681
+ end
682
+
683
+ def test_has_one_new_with_attr_accessible_attributes
684
+ person = TightPerson.new(nested_attributes_hash(:best_friend))
685
+ assert_default_attributes(person.best_friend)
686
+ end
687
+
688
+ def test_has_one_new_with_admin_role_with_attr_protected_attributes
689
+ person = LoosePerson.new(nested_attributes_hash(:best_friend), :as => :admin)
690
+ assert_admin_attributes(person.best_friend)
691
+ end
692
+
693
+ def test_has_one_new_with_admin_role_with_attr_accessible_attributes
694
+ person = TightPerson.new(nested_attributes_hash(:best_friend), :as => :admin)
695
+ assert_admin_attributes(person.best_friend)
696
+ end
697
+
698
+ def test_has_one_new_without_protection
699
+ person = LoosePerson.new(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
700
+ assert_all_attributes(person.best_friend)
701
+ end
702
+
703
+ def test_belongs_to_new_with_attr_protected_attributes
704
+ person = LoosePerson.new(nested_attributes_hash(:best_friend_of))
705
+ assert_default_attributes(person.best_friend_of)
706
+ end
707
+
708
+ def test_belongs_to_new_with_attr_accessible_attributes
709
+ person = TightPerson.new(nested_attributes_hash(:best_friend_of))
710
+ assert_default_attributes(person.best_friend_of)
711
+ end
712
+
713
+ def test_belongs_to_new_with_admin_role_with_attr_protected_attributes
714
+ person = LoosePerson.new(nested_attributes_hash(:best_friend_of), :as => :admin)
715
+ assert_admin_attributes(person.best_friend_of)
716
+ end
717
+
718
+ def test_belongs_to_new_with_admin_role_with_attr_accessible_attributes
719
+ person = TightPerson.new(nested_attributes_hash(:best_friend_of), :as => :admin)
720
+ assert_admin_attributes(person.best_friend_of)
721
+ end
722
+
723
+ def test_belongs_to_new_without_protection
724
+ person = LoosePerson.new(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
725
+ assert_all_attributes(person.best_friend_of)
726
+ end
727
+
728
+ def test_has_many_new_with_attr_protected_attributes
729
+ person = LoosePerson.new(nested_attributes_hash(:best_friends, true))
730
+ assert_default_attributes(person.best_friends.first)
731
+ end
732
+
733
+ def test_has_many_new_with_attr_accessible_attributes
734
+ person = TightPerson.new(nested_attributes_hash(:best_friends, true))
735
+ assert_default_attributes(person.best_friends.first)
736
+ end
737
+
738
+ def test_has_many_new_with_admin_role_with_attr_protected_attributes
739
+ person = LoosePerson.new(nested_attributes_hash(:best_friends, true), :as => :admin)
740
+ assert_admin_attributes(person.best_friends.first)
741
+ end
742
+
743
+ def test_has_many_new_with_admin_role_with_attr_accessible_attributes
744
+ person = TightPerson.new(nested_attributes_hash(:best_friends, true), :as => :admin)
745
+ assert_admin_attributes(person.best_friends.first)
746
+ end
747
+
748
+ def test_has_many_new_without_protection
749
+ person = LoosePerson.new(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
750
+ assert_all_attributes(person.best_friends.first)
751
+ end
752
+
753
+ # create
754
+
755
+ def test_has_one_create_with_attr_protected_attributes
756
+ person = LoosePerson.create(nested_attributes_hash(:best_friend))
757
+ assert_default_attributes(person.best_friend, true)
758
+ end
759
+
760
+ def test_has_one_create_with_attr_accessible_attributes
761
+ person = TightPerson.create(nested_attributes_hash(:best_friend))
762
+ assert_default_attributes(person.best_friend, true)
763
+ end
764
+
765
+ def test_has_one_create_with_admin_role_with_attr_protected_attributes
766
+ person = LoosePerson.create(nested_attributes_hash(:best_friend), :as => :admin)
767
+ assert_admin_attributes(person.best_friend, true)
768
+ end
769
+
770
+ def test_has_one_create_with_admin_role_with_attr_accessible_attributes
771
+ person = TightPerson.create(nested_attributes_hash(:best_friend), :as => :admin)
772
+ assert_admin_attributes(person.best_friend, true)
773
+ end
774
+
775
+ def test_has_one_create_without_protection
776
+ person = LoosePerson.create(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
777
+ assert_all_attributes(person.best_friend)
778
+ end
779
+
780
+ def test_belongs_to_create_with_attr_protected_attributes
781
+ person = LoosePerson.create(nested_attributes_hash(:best_friend_of))
782
+ assert_default_attributes(person.best_friend_of, true)
783
+ end
784
+
785
+ def test_belongs_to_create_with_attr_accessible_attributes
786
+ person = TightPerson.create(nested_attributes_hash(:best_friend_of))
787
+ assert_default_attributes(person.best_friend_of, true)
788
+ end
789
+
790
+ def test_belongs_to_create_with_admin_role_with_attr_protected_attributes
791
+ person = LoosePerson.create(nested_attributes_hash(:best_friend_of), :as => :admin)
792
+ assert_admin_attributes(person.best_friend_of, true)
793
+ end
794
+
795
+ def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes
796
+ person = TightPerson.create(nested_attributes_hash(:best_friend_of), :as => :admin)
797
+ assert_admin_attributes(person.best_friend_of, true)
798
+ end
799
+
800
+ def test_belongs_to_create_without_protection
801
+ person = LoosePerson.create(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
802
+ assert_all_attributes(person.best_friend_of)
803
+ end
804
+
805
+ def test_has_many_create_with_attr_protected_attributes
806
+ person = LoosePerson.create(nested_attributes_hash(:best_friends, true))
807
+ assert_default_attributes(person.best_friends.first, true)
808
+ end
809
+
810
+ def test_has_many_create_with_attr_accessible_attributes
811
+ person = TightPerson.create(nested_attributes_hash(:best_friends, true))
812
+ assert_default_attributes(person.best_friends.first, true)
813
+ end
814
+
815
+ def test_has_many_create_with_admin_role_with_attr_protected_attributes
816
+ person = LoosePerson.create(nested_attributes_hash(:best_friends, true), :as => :admin)
817
+ assert_admin_attributes(person.best_friends.first, true)
818
+ end
819
+
820
+ def test_has_many_create_with_admin_role_with_attr_accessible_attributes
821
+ person = TightPerson.create(nested_attributes_hash(:best_friends, true), :as => :admin)
822
+ assert_admin_attributes(person.best_friends.first, true)
823
+ end
824
+
825
+ def test_has_many_create_without_protection
826
+ person = LoosePerson.create(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
827
+ assert_all_attributes(person.best_friends.first)
828
+ end
829
+
830
+ # create!
831
+
832
+ def test_has_one_create_with_bang_with_attr_protected_attributes
833
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend))
834
+ assert_default_attributes(person.best_friend, true)
835
+ end
836
+
837
+ def test_has_one_create_with_bang_with_attr_accessible_attributes
838
+ person = TightPerson.create!(nested_attributes_hash(:best_friend))
839
+ assert_default_attributes(person.best_friend, true)
840
+ end
841
+
842
+ def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
843
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend), :as => :admin)
844
+ assert_admin_attributes(person.best_friend, true)
845
+ end
846
+
847
+ def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
848
+ person = TightPerson.create!(nested_attributes_hash(:best_friend), :as => :admin)
849
+ assert_admin_attributes(person.best_friend, true)
850
+ end
851
+
852
+ def test_has_one_create_with_bang_without_protection
853
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
854
+ assert_all_attributes(person.best_friend)
855
+ end
856
+
857
+ def test_belongs_to_create_with_bang_with_attr_protected_attributes
858
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend_of))
859
+ assert_default_attributes(person.best_friend_of, true)
860
+ end
861
+
862
+ def test_belongs_to_create_with_bang_with_attr_accessible_attributes
863
+ person = TightPerson.create!(nested_attributes_hash(:best_friend_of))
864
+ assert_default_attributes(person.best_friend_of, true)
865
+ end
866
+
867
+ def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes
868
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin)
869
+ assert_admin_attributes(person.best_friend_of, true)
870
+ end
871
+
872
+ def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes
873
+ person = TightPerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin)
874
+ assert_admin_attributes(person.best_friend_of, true)
875
+ end
876
+
877
+ def test_belongs_to_create_with_bang_without_protection
878
+ person = LoosePerson.create!(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
879
+ assert_all_attributes(person.best_friend_of)
880
+ end
881
+
882
+ def test_has_many_create_with_bang_with_attr_protected_attributes
883
+ person = LoosePerson.create!(nested_attributes_hash(:best_friends, true))
884
+ assert_default_attributes(person.best_friends.first, true)
885
+ end
886
+
887
+ def test_has_many_create_with_bang_with_attr_accessible_attributes
888
+ person = TightPerson.create!(nested_attributes_hash(:best_friends, true))
889
+ assert_default_attributes(person.best_friends.first, true)
890
+ end
891
+
892
+ def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes
893
+ person = LoosePerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin)
894
+ assert_admin_attributes(person.best_friends.first, true)
895
+ end
896
+
897
+ def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes
898
+ person = TightPerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin)
899
+ assert_admin_attributes(person.best_friends.first, true)
900
+ end
901
+
902
+ def test_has_many_create_with_bang_without_protection
903
+ person = LoosePerson.create!(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
904
+ assert_all_attributes(person.best_friends.first)
905
+ end
906
+
907
+ def test_mass_assignment_options_are_reset_after_exception
908
+ person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin)
909
+ person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin)
910
+
911
+ attributes = { :best_friend_attributes => { :comments => 'rides a sweet bike' } }
912
+ assert_raises(RuntimeError) { person.assign_attributes(attributes, :as => :admin) }
913
+ assert_equal 'm', person.best_friend.gender
914
+
915
+ person.best_friend_attributes = { :gender => 'f' }
916
+ assert_equal 'm', person.best_friend.gender
917
+ end
918
+
919
+ def test_mass_assignment_options_are_nested_correctly
920
+ person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin)
921
+ person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin)
922
+
923
+ attributes = { :best_friend_first_name => 'Josh', :best_friend_attributes => { :gender => 'f' } }
924
+ person.assign_attributes(attributes, :as => :admin)
925
+ assert_equal 'Josh', person.best_friend.first_name
926
+ assert_equal 'f', person.best_friend.gender
927
+ end
928
+
929
+ end