protected_attributes 1.0.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 (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