Skip to content
This repository
Browse code

mass_assignment_security moved from AR to AMo, and minor test cleanup

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information...
commit 4b66aab00fa0ea6bcc6ec81df19e44de34fd7864 1 parent 7c86e8e
Josh Kalderimis authored July 08, 2010 josevalim committed July 08, 2010
1  activemodel/lib/active_model.rb
@@ -38,6 +38,7 @@ module ActiveModel
38 38
   autoload :EachValidator, 'active_model/validator'
39 39
   autoload :Errors
40 40
   autoload :Lint
  41
+  autoload :MassAssignmentSecurity
41 42
   autoload :Name, 'active_model/naming'
42 43
   autoload :Naming
43 44
   autoload :Observer, 'active_model/observing'
11  ...ord/lib/active_record/mass_assignment_security.rb → ...odel/lib/active_model/mass_assignment_security.rb
... ...
@@ -1,6 +1,7 @@
1  
-require 'active_record/mass_assignment_security/permission_set'
  1
+require 'active_support/core_ext/class/attribute.rb'
  2
+require 'active_model/mass_assignment_security/permission_set'
2 3
 
3  
-module ActiveRecord
  4
+module ActiveModel
4 5
   # = Active Record Mass-Assignment Security
5 6
   module MassAssignmentSecurity
6 7
     extend ActiveSupport::Concern
@@ -112,11 +113,13 @@ def attr_accessible(*names)
112 113
       end
113 114
 
114 115
       def protected_attributes
115  
-        self._protected_attributes ||= BlackList.new(attributes_protected_by_default).tap { |w| w.logger = logger }
  116
+        self._protected_attributes ||= BlackList.new(attributes_protected_by_default).tap do |w|
  117
+          w.logger = self.logger if self.respond_to?(:logger)
  118
+        end
116 119
       end
117 120
 
118 121
       def accessible_attributes
119  
-        self._accessible_attributes ||= WhiteList.new.tap { |w| w.logger = logger }
  122
+        self._accessible_attributes ||= WhiteList.new.tap { |w| w.logger = self.logger if self.respond_to?(:logger) }
120 123
       end
121 124
 
122 125
       def active_authorizer
4  ...record/mass_assignment_security/permission_set.rb → ..._model/mass_assignment_security/permission_set.rb
... ...
@@ -1,6 +1,6 @@
1  
-require 'active_record/mass_assignment_security/sanitizer'
  1
+require 'active_model/mass_assignment_security/sanitizer'
2 2
 
3  
-module ActiveRecord
  3
+module ActiveModel
4 4
   module MassAssignmentSecurity
5 5
 
6 6
     class PermissionSet < Set
6  ...tive_record/mass_assignment_security/sanitizer.rb → ...ctive_model/mass_assignment_security/sanitizer.rb
... ...
@@ -1,4 +1,4 @@
1  
-module ActiveRecord
  1
+module ActiveModel
2 2
   module MassAssignmentSecurity
3 3
     module Sanitizer
4 4
 
@@ -17,11 +17,11 @@ def debug_protected_attribute_removal(attributes, sanitized_attributes)
17 17
         end
18 18
 
19 19
         def debug?
20  
-          logger.present?
  20
+          self.logger.present?
21 21
         end
22 22
 
23 23
         def warn!(attrs)
24  
-          logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}"
  24
+          self.logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}"
25 25
         end
26 26
 
27 27
     end
4  ...cases/mass_assignment_security/black_list_test.rb → ...cases/mass_assignment_security/black_list_test.rb
... ...
@@ -1,9 +1,9 @@
1 1
 require "cases/helper"
2 2
 
3  
-class BlackListTest < ActiveRecord::TestCase
  3
+class BlackListTest < ActiveModel::TestCase
4 4
 
5 5
   def setup
6  
-    @black_list   = ActiveRecord::MassAssignmentSecurity::BlackList.new
  6
+    @black_list   = ActiveModel::MassAssignmentSecurity::BlackList.new
7 7
     @included_key = 'admin'
8 8
     @black_list  += [ @included_key ]
9 9
   end
4  ...s/mass_assignment_security/permission_set_test.rb → ...s/mass_assignment_security/permission_set_test.rb
... ...
@@ -1,9 +1,9 @@
1 1
 require "cases/helper"
2 2
 
3  
-class PermissionSetTest < ActiveRecord::TestCase
  3
+class PermissionSetTest < ActiveModel::TestCase
4 4
 
5 5
   def setup
6  
-    @permission_list = ActiveRecord::MassAssignmentSecurity::PermissionSet.new
  6
+    @permission_list = ActiveModel::MassAssignmentSecurity::PermissionSet.new
7 7
   end
8 8
 
9 9
   test "+ stringifies added collection values" do
5  .../cases/mass_assignment_security/sanitizer_test.rb → .../cases/mass_assignment_security/sanitizer_test.rb
... ...
@@ -1,9 +1,10 @@
1 1
 require "cases/helper"
  2
+require 'logger'
2 3
 
3  
-class SanitizerTest < ActiveRecord::TestCase
  4
+class SanitizerTest < ActiveModel::TestCase
4 5
 
5 6
   class SanitizingAuthorizer
6  
-    include ActiveRecord::MassAssignmentSecurity::Sanitizer
  7
+    include ActiveModel::MassAssignmentSecurity::Sanitizer
7 8
 
8 9
     attr_accessor :logger
9 10
 
4  ...cases/mass_assignment_security/white_list_test.rb → ...cases/mass_assignment_security/white_list_test.rb
... ...
@@ -1,9 +1,9 @@
1 1
 require "cases/helper"
2 2
 
3  
-class WhiteListTest < ActiveRecord::TestCase
  3
+class WhiteListTest < ActiveModel::TestCase
4 4
 
5 5
   def setup
6  
-    @white_list   = ActiveRecord::MassAssignmentSecurity::WhiteList.new
  6
+    @white_list   = ActiveModel::MassAssignmentSecurity::WhiteList.new
7 7
     @included_key = 'first_name'
8 8
     @white_list  += [ @included_key ]
9 9
   end
52  activemodel/test/cases/mass_assignment_security_test.rb
... ...
@@ -0,0 +1,52 @@
  1
+require "cases/helper"
  2
+require 'models/mass_assignment_specific'
  3
+
  4
+class MassAssignmentSecurityTest < ActiveModel::TestCase
  5
+
  6
+  def test_attribute_protection
  7
+    user = User.new
  8
+    expected = { "name" => "John Smith", "email" => "john@smith.com" }
  9
+    sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
  10
+    assert_equal expected, sanitized
  11
+  end
  12
+
  13
+  def test_attributes_accessible
  14
+    user = Person.new
  15
+    expected = { "name" => "John Smith", "email" => "john@smith.com" }
  16
+    sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true))
  17
+    assert_equal expected, sanitized
  18
+  end
  19
+
  20
+  def test_attributes_protected_by_default
  21
+    firm = Firm.new
  22
+    expected = { }
  23
+    sanitized = firm.sanitize_for_mass_assignment({ "type" => "Client" })
  24
+    assert_equal expected, sanitized
  25
+  end
  26
+
  27
+  def test_mass_assignment_protection_inheritance
  28
+    assert LoosePerson.accessible_attributes.blank?
  29
+    assert_equal Set.new([ 'credit_rating', 'administrator']), LoosePerson.protected_attributes
  30
+
  31
+    assert LooseDescendant.accessible_attributes.blank?
  32
+    assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number']), LooseDescendant.protected_attributes
  33
+
  34
+    assert LooseDescendantSecond.accessible_attributes.blank?
  35
+    assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name']), LooseDescendantSecond.protected_attributes,
  36
+      'Running attr_protected twice in one class should merge the protections'
  37
+
  38
+    assert (TightPerson.protected_attributes - TightPerson.attributes_protected_by_default).blank?
  39
+    assert_equal Set.new([ 'name', 'address' ]), TightPerson.accessible_attributes
  40
+
  41
+    assert (TightDescendant.protected_attributes - TightDescendant.attributes_protected_by_default).blank?
  42
+    assert_equal Set.new([ 'name', 'address', 'phone_number' ]), TightDescendant.accessible_attributes
  43
+  end
  44
+
  45
+  def test_mass_assignment_multiparameter_protector
  46
+    task = Task.new
  47
+    attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
  48
+    sanitized = task.sanitize_for_mass_assignment(attributes)
  49
+    assert_equal sanitized, { }
  50
+  end
  51
+
  52
+end
57  activemodel/test/models/mass_assignment_specific.rb
... ...
@@ -0,0 +1,57 @@
  1
+class User
  2
+  include ActiveModel::MassAssignmentSecurity
  3
+  attr_protected :admin
  4
+
  5
+  public :sanitize_for_mass_assignment
  6
+end
  7
+
  8
+class Person
  9
+  include ActiveModel::MassAssignmentSecurity
  10
+  attr_accessible :name, :email
  11
+
  12
+  public :sanitize_for_mass_assignment
  13
+end
  14
+
  15
+class Firm
  16
+  include ActiveModel::MassAssignmentSecurity
  17
+
  18
+  public :sanitize_for_mass_assignment
  19
+
  20
+  def self.attributes_protected_by_default
  21
+    ["type"]
  22
+  end
  23
+end
  24
+
  25
+class Task
  26
+  include ActiveModel::MassAssignmentSecurity
  27
+  attr_protected :starting
  28
+
  29
+  public :sanitize_for_mass_assignment
  30
+end
  31
+
  32
+class LoosePerson
  33
+  include ActiveModel::MassAssignmentSecurity
  34
+  attr_protected :credit_rating, :administrator
  35
+end
  36
+
  37
+class LooseDescendant < LoosePerson
  38
+  attr_protected :phone_number
  39
+end
  40
+
  41
+class LooseDescendantSecond< LoosePerson
  42
+  attr_protected :phone_number
  43
+  attr_protected :name
  44
+end
  45
+
  46
+class TightPerson
  47
+  include ActiveModel::MassAssignmentSecurity
  48
+  attr_accessible :name, :address
  49
+
  50
+  def self.attributes_protected_by_default
  51
+    ["mobile_number"]
  52
+  end
  53
+end
  54
+
  55
+class TightDescendant < TightPerson
  56
+  attr_accessible :phone_number
  57
+end
1  activerecord/lib/active_record.rb
@@ -64,7 +64,6 @@ module ActiveRecord
64 64
     autoload :CounterCache
65 65
     autoload :DynamicFinderMatch
66 66
     autoload :DynamicScopeMatch
67  
-    autoload :MassAssignmentSecurity
68 67
     autoload :Migration
69 68
     autoload :Migrator, 'active_record/migration'
70 69
     autoload :NamedScope
2  activerecord/lib/active_record/base.rb
@@ -1797,7 +1797,7 @@ def object_from_yaml(string)
1797 1797
     include AttributeMethods::PrimaryKey
1798 1798
     include AttributeMethods::TimeZoneConversion
1799 1799
     include AttributeMethods::Dirty
1800  
-    include MassAssignmentSecurity
  1800
+    include ActiveModel::MassAssignmentSecurity
1801 1801
     include Callbacks, ActiveModel::Observing, Timestamp
1802 1802
     include Associations, AssociationPreload, NamedScope
1803 1803
 
2  activerecord/test/cases/base_test.rb
@@ -17,7 +17,7 @@
17 17
 require 'models/minimalistic'
18 18
 require 'models/warehouse_thing'
19 19
 require 'models/parrot'
20  
-require 'models/mass_assignment_specific'
  20
+require 'models/loose_person'
21 21
 require 'rexml/document'
22 22
 require 'active_support/core_ext/exception'
23 23
 
71  activerecord/test/cases/mass_assignment_security_test.rb
... ...
@@ -1,28 +1,11 @@
1 1
 require "cases/helper"
2  
-require 'models/reply'
3 2
 require 'models/company'
4 3
 require 'models/subscriber'
5 4
 require 'models/keyboard'
6  
-require 'models/mass_assignment_specific'
  5
+require 'models/task'
7 6
 
8 7
 class MassAssignmentSecurityTest < ActiveRecord::TestCase
9 8
 
10  
-  def test_mass_assignment_protection
11  
-    firm = Firm.new
12  
-    firm.attributes = { "name" => "Next Angle", "rating" => 5 }
13  
-    assert_equal 1, firm.rating
14  
-  end
15  
-
16  
-  def test_mass_assignment_protection_against_class_attribute_writers
17  
-    [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names,
18  
-     :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method|
19  
-      assert_respond_to  Task, method
20  
-      assert_respond_to  Task, "#{method}="
21  
-      assert_respond_to  Task.new, method
22  
-      assert !Task.new.respond_to?("#{method}=")
23  
-    end
24  
-  end
25  
-
26 9
   def test_customized_primary_key_remains_protected
27 10
     subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
28 11
     assert_nil subscriber.id
@@ -47,50 +30,14 @@ def test_mass_assigning_invalid_attribute
47 30
     end
48 31
   end
49 32
 
50  
-  def test_mass_assignment_protection_on_defaults
51  
-    firm = Firm.new
52  
-    firm.attributes = { "id" => 5, "type" => "Client" }
53  
-    assert_nil firm.id
54  
-    assert_equal "Firm", firm[:type]
55  
-  end
56  
-
57  
-  def test_mass_assignment_accessible
58  
-    reply = Reply.new("title" => "hello", "content" => "world", "approved" => true)
59  
-    reply.save
60  
-
61  
-    assert reply.approved?
62  
-
63  
-    reply.approved = false
64  
-    reply.save
65  
-
66  
-    assert !reply.approved?
67  
-  end
68  
-
69  
-  def test_mass_assignment_protection_inheritance
70  
-    assert LoosePerson.accessible_attributes.blank?
71  
-    assert_equal Set.new([ 'credit_rating', 'administrator', *LoosePerson.attributes_protected_by_default ]), LoosePerson.protected_attributes
72  
-
73  
-    assert LooseDescendant.accessible_attributes.blank?
74  
-    assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', *LoosePerson.attributes_protected_by_default ]), LooseDescendant.protected_attributes
75  
-
76  
-    assert LooseDescendantSecond.accessible_attributes.blank?
77  
-    assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name', *LoosePerson.attributes_protected_by_default ]),
78  
-      LooseDescendantSecond.protected_attributes, 'Running attr_protected twice in one class should merge the protections'
79  
-
80  
-    assert (TightPerson.protected_attributes - TightPerson.attributes_protected_by_default).blank?
81  
-    assert_equal Set.new([ 'name', 'address' ]), TightPerson.accessible_attributes
82  
-
83  
-    assert (TightDescendant.protected_attributes - TightDescendant.attributes_protected_by_default).blank?
84  
-    assert_equal Set.new([ 'name', 'address', 'phone_number' ]), TightDescendant.accessible_attributes
85  
-  end
86  
-
87  
-  def test_mass_assignment_multiparameter_protector
88  
-    task = Task.new
89  
-    time = Time.mktime(2000, 1, 1, 1)
90  
-    task.starting = time
91  
-    attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
92  
-    task.attributes = attributes
93  
-    assert_equal time, task.starting
  33
+  def test_protection_against_class_attribute_writers
  34
+    [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names,
  35
+     :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method|
  36
+      assert_respond_to  Task, method
  37
+      assert_respond_to  Task, "#{method}="
  38
+      assert_respond_to  Task.new, method
  39
+      assert !Task.new.respond_to?("#{method}=")
  40
+    end
94 41
   end
95 42
 
96 43
 end
10  activerecord/test/models/mass_assignment_specific.rb → activerecord/test/models/loose_person.rb
... ...
@@ -1,6 +1,7 @@
1 1
 class LoosePerson < ActiveRecord::Base
2 2
   self.table_name = 'people'
3 3
   self.abstract_class = true
  4
+
4 5
   attr_protected :credit_rating, :administrator
5 6
 end
6 7
 
@@ -20,13 +21,4 @@ class TightPerson < ActiveRecord::Base
20 21
 
21 22
 class TightDescendant < TightPerson
22 23
   attr_accessible :phone_number
23  
-end
24  
-
25  
-class Task < ActiveRecord::Base
26  
-  attr_protected :starting
27  
-end
28  
-
29  
-class TopicWithProtectedContent < ActiveRecord::Base
30  
-  self.table_name = 'topics'
31  
-  attr_protected  :content
32 24
 end

0 notes on commit 4b66aab

Please sign in to comment.
Something went wrong with that request. Please try again.