aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model/mass_assignment_security.rb2
-rw-r--r--activemodel/lib/active_model/mass_assignment_security/sanitizer.rb31
-rw-r--r--activemodel/lib/active_model/validations.rb6
-rw-r--r--activemodel/test/cases/mass_assignment_security/sanitizer_test.rb8
-rw-r--r--activemodel/test/cases/mass_assignment_security_test.rb2
-rw-r--r--activemodel/test/cases/validations_test.rb15
6 files changed, 49 insertions, 15 deletions
diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb
index 5e5405fe27..893fbf92c3 100644
--- a/activemodel/lib/active_model/mass_assignment_security.rb
+++ b/activemodel/lib/active_model/mass_assignment_security.rb
@@ -229,7 +229,7 @@ module ActiveModel
protected
def sanitize_for_mass_assignment(attributes, role = nil)
- _mass_assignment_sanitizer.sanitize(attributes, mass_assignment_authorizer(role))
+ _mass_assignment_sanitizer.sanitize(self.class, attributes, mass_assignment_authorizer(role))
end
def mass_assignment_authorizer(role)
diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
index 4491e07a72..44ce5a489d 100644
--- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
+++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
@@ -2,18 +2,18 @@ module ActiveModel
module MassAssignmentSecurity
class Sanitizer
# Returns all attributes not denied by the authorizer.
- def sanitize(attributes, authorizer)
+ def sanitize(klass, attributes, authorizer)
rejected = []
sanitized_attributes = attributes.reject do |key, value|
rejected << key if authorizer.deny?(key)
end
- process_removed_attributes(rejected) unless rejected.empty?
+ process_removed_attributes(klass, rejected) unless rejected.empty?
sanitized_attributes
end
protected
- def process_removed_attributes(attrs)
+ def process_removed_attributes(klass, attrs)
raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten"
end
end
@@ -32,8 +32,21 @@ module ActiveModel
@target.respond_to?(:logger) && @target.logger
end
- def process_removed_attributes(attrs)
- logger.warn "Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger?
+ def backtrace
+ if defined? Rails
+ Rails.backtrace_cleaner.clean(caller)
+ else
+ caller
+ end
+ end
+
+ def process_removed_attributes(klass, attrs)
+ if logger?
+ logger.warn do
+ "WARNING: Can't mass-assign protected attributes for #{klass.name}: #{attrs.join(', ')}\n" +
+ backtrace.map { |trace| "\t#{trace}" }.join("\n")
+ end
+ end
end
end
@@ -42,9 +55,9 @@ module ActiveModel
super()
end
- def process_removed_attributes(attrs)
+ def process_removed_attributes(klass, attrs)
return if (attrs - insensitive_attributes).empty?
- raise ActiveModel::MassAssignmentSecurity::Error.new(attrs)
+ raise ActiveModel::MassAssignmentSecurity::Error.new(klass, attrs)
end
def insensitive_attributes
@@ -53,8 +66,8 @@ module ActiveModel
end
class Error < StandardError
- def initialize(attrs)
- super("Can't mass-assign protected attributes: #{attrs.join(', ')}")
+ def initialize(klass, attrs)
+ super("Can't mass-assign protected attributes for #{klass.name}: #{attrs.join(', ')}")
end
end
end
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 3ed72bae3b..611e9ffd55 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -178,6 +178,12 @@ module ActiveModel
end
end
+ # Clean the +Errors+ object if instance is duped
+ def initialize_dup(other) # :nodoc:
+ @errors = nil
+ super
+ end
+
# Returns the +Errors+ object that holds all information about attribute error messages.
def errors
@errors ||= Errors.new(self)
diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
index 3660b9b1e5..418a24294a 100644
--- a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
@@ -19,7 +19,7 @@ class SanitizerTest < ActiveModel::TestCase
test "sanitize attributes" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
- attributes = @logger_sanitizer.sanitize(original_attributes, @authorizer)
+ attributes = @logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
assert !attributes.key?('admin'), "Denied key should be rejected"
@@ -29,14 +29,14 @@ class SanitizerTest < ActiveModel::TestCase
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
log = StringIO.new
self.logger = ActiveSupport::Logger.new(log)
- @logger_sanitizer.sanitize(original_attributes, @authorizer)
+ @logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}")
end
test "debug mass assignment removal with StrictSanitizer" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
assert_raise ActiveModel::MassAssignmentSecurity::Error do
- @strict_sanitizer.sanitize(original_attributes, @authorizer)
+ @strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
end
end
@@ -44,7 +44,7 @@ class SanitizerTest < ActiveModel::TestCase
original_attributes = {'id' => 1, 'first_name' => 'allowed'}
assert_nothing_raised do
- @strict_sanitizer.sanitize(original_attributes, @authorizer)
+ @strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
end
end
diff --git a/activemodel/test/cases/mass_assignment_security_test.rb b/activemodel/test/cases/mass_assignment_security_test.rb
index a197dbe748..0c6352cd71 100644
--- a/activemodel/test/cases/mass_assignment_security_test.rb
+++ b/activemodel/test/cases/mass_assignment_security_test.rb
@@ -4,7 +4,7 @@ require 'models/mass_assignment_specific'
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
- def process_removed_attributes(attrs)
+ def process_removed_attributes(klass, attrs)
raise StandardError
end
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index a716d0896e..1f5023bf76 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -344,4 +344,19 @@ class ValidationsTest < ActiveModel::TestCase
Topic.validates :title, options
assert_equal({ :presence => true }, options)
end
+
+ def test_dup_validity_is_independent
+ Topic.validates_presence_of :title
+ topic = Topic.new("title" => "Litterature")
+ topic.valid?
+
+ duped = topic.dup
+ duped.title = nil
+ assert duped.invalid?
+
+ topic.title = nil
+ duped.title = 'Mathematics'
+ assert topic.invalid?
+ assert duped.valid?
+ end
end