aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/forbidden_attributes_protection.rb14
-rw-r--r--activemodel/test/cases/forbidden_attributes_protection_test.rb32
-rw-r--r--activemodel/test/models/mass_assignment_specific.rb7
4 files changed, 54 insertions, 0 deletions
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index d1cc19ec6b..f8b2b79906 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -34,6 +34,7 @@ module ActiveModel
autoload :Conversion
autoload :Dirty
autoload :EachValidator, 'active_model/validator'
+ autoload :ForbiddenAttributesProtection
autoload :Lint
autoload :MassAssignmentSecurity
autoload :Model
diff --git a/activemodel/lib/active_model/forbidden_attributes_protection.rb b/activemodel/lib/active_model/forbidden_attributes_protection.rb
new file mode 100644
index 0000000000..39f1a20734
--- /dev/null
+++ b/activemodel/lib/active_model/forbidden_attributes_protection.rb
@@ -0,0 +1,14 @@
+module ActiveModel
+ class ForbiddenAttributes < StandardError
+ end
+
+ module ForbiddenAttributesProtection
+ def sanitize_for_mass_assignment(new_attributes, options = {})
+ if !new_attributes.respond_to?(:permitted?) || (new_attributes.respond_to?(:permitted?) && new_attributes.permitted?)
+ super
+ else
+ raise ActiveModel::ForbiddenAttributes
+ end
+ end
+ end
+end
diff --git a/activemodel/test/cases/forbidden_attributes_protection_test.rb b/activemodel/test/cases/forbidden_attributes_protection_test.rb
new file mode 100644
index 0000000000..d3088b4fc2
--- /dev/null
+++ b/activemodel/test/cases/forbidden_attributes_protection_test.rb
@@ -0,0 +1,32 @@
+require 'cases/helper'
+require 'models/mass_assignment_specific'
+
+class ActiveModelMassUpdateProtectionTest < ActiveSupport::TestCase
+ test "forbidden attributes cannot be used for mass updating" do
+ params = { "a" => "b" }
+ class << params
+ define_method(:permitted?) { false }
+ end
+ assert_raises(ActiveModel::ForbiddenAttributes) do
+ SpecialPerson.new.sanitize_for_mass_assignment(params)
+ end
+ end
+
+ test "permitted attributes can be used for mass updating" do
+ params = { "a" => "b" }
+ class << params
+ define_method(:permitted?) { true }
+ end
+ assert_nothing_raised do
+ assert_equal({ "a" => "b" },
+ SpecialPerson.new.sanitize_for_mass_assignment(params))
+ end
+ end
+
+ test "regular attributes should still be allowed" do
+ assert_nothing_raised do
+ assert_equal({ a: "b" },
+ SpecialPerson.new.sanitize_for_mass_assignment(a: "b"))
+ end
+ end
+end
diff --git a/activemodel/test/models/mass_assignment_specific.rb b/activemodel/test/models/mass_assignment_specific.rb
index 1d123fa58c..1bf828ad43 100644
--- a/activemodel/test/models/mass_assignment_specific.rb
+++ b/activemodel/test/models/mass_assignment_specific.rb
@@ -20,6 +20,13 @@ class Person
public :sanitize_for_mass_assignment
end
+class SpecialPerson
+ include ActiveModel::MassAssignmentSecurity
+ include ActiveModel::ForbiddenAttributesProtection
+
+ public :sanitize_for_mass_assignment
+end
+
class Account
include ActiveModel::MassAssignmentSecurity
attr_accessible :name, :email, :as => [:default, :admin]