Improve logging of ActiveModel::MassAssignmentSecurity::Sanitizer

This commit is contained in:
Naoto Takai 2012-05-17 06:55:14 +09:00
parent 78b6fdd89f
commit 80a2c9e5db
4 changed files with 28 additions and 15 deletions

@ -229,7 +229,7 @@ def accessible_attributes_configs
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)

@ -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 @@ def logger?
@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 @@ def initialize(target = nil)
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 @@ def insensitive_attributes
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

@ -19,7 +19,7 @@ def setup
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 @@ def setup
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 @@ def setup
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

@ -4,7 +4,7 @@
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
def process_removed_attributes(attrs)
def process_removed_attributes(klass, attrs)
raise StandardError
end