diff options
3 files changed, 32 insertions, 29 deletions
diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index e3c9097646..c97420bc03 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -12,12 +12,8 @@ module ActiveModel class_attribute :_protected_attributes class_attribute :_active_authorizer - class_attribute :mass_assignment_sanitizer, :mass_assignment_sanitizers + class_attribute :_mass_assignment_sanitizer self.mass_assignment_sanitizer = :logger - self.mass_assignment_sanitizers = { - :logger => LoggerSanitizer.new(self.respond_to?(:logger) && self.logger), - :strict => StrictSanitizer.new - } end # Mass assignment security provides an interface for protecting attributes @@ -172,7 +168,7 @@ module ActiveModel options = args.extract_options! role = options[:as] || :default - self._accessible_attributes = accessible_attributes_configs.dup + self._accessible_attributes = accessible_attributes_configs.dup self._accessible_attributes[role] = self.accessible_attributes(role) + args self._active_authorizer = self._accessible_attributes @@ -195,19 +191,25 @@ module ActiveModel [] end + def mass_assignment_sanitizer=(value) + self._mass_assignment_sanitizer = if value.is_a?(Symbol) + const_get(:"#{value.to_s.camelize}Sanitizer").new(self) + else + value + end + end + private def protected_attributes_configs self._protected_attributes ||= begin - default_black_list = BlackList.new(attributes_protected_by_default) - Hash.new(default_black_list) + Hash.new { |h,k| h[k] = BlackList.new(attributes_protected_by_default) } end end def accessible_attributes_configs self._accessible_attributes ||= begin - default_white_list = WhiteList.new - Hash.new(default_white_list) + Hash.new { |h,k| h[k] = WhiteList.new } end end end @@ -215,13 +217,7 @@ module ActiveModel protected def sanitize_for_mass_assignment(attributes, role = :default) - sanitizer = case mass_assignment_sanitizer - when Symbol - self.mass_assignment_sanitizers[mass_assignment_sanitizer] - else - mass_assignment_sanitizer - end - sanitizer.sanitize(attributes, mass_assignment_authorizer(role)) + _mass_assignment_sanitizer.sanitize(attributes, mass_assignment_authorizer(role)) end def mass_assignment_authorizer(role = :default) diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb index 4dfff050a8..ee43a6694f 100644 --- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb +++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb @@ -1,6 +1,11 @@ +require 'active_support/core_ext/module/delegation' + module ActiveModel module MassAssignmentSecurity class Sanitizer + def initialize(target=nil) + end + # Returns all attributes not denied by the authorizer. def sanitize(attributes, authorizer) sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) } @@ -18,19 +23,22 @@ module ActiveModel def process_removed_attributes(attrs) raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten" end - end + class LoggerSanitizer < Sanitizer + delegate :logger, :to => :@target - attr_accessor :logger + def initialize(target) + @target = target + super + end - def initialize(logger = nil) - self.logger = logger - super() + def logger? + @target.respond_to?(:logger) && @target.logger end - + def process_removed_attributes(attrs) - self.logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if self.logger + logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? end end @@ -42,6 +50,5 @@ module ActiveModel class Error < StandardError end - end end diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb index e9e7eee0bd..62a6ec9c9b 100644 --- a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb +++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb @@ -3,7 +3,7 @@ require 'logger' require 'active_support/core_ext/object/inclusion' class SanitizerTest < ActiveModel::TestCase - + attr_accessor :logger class Authorizer < ActiveModel::MassAssignmentSecurity::PermissionSet def deny?(key) @@ -12,8 +12,8 @@ class SanitizerTest < ActiveModel::TestCase end def setup - @logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new - @strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new + @logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new(self) + @strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new(self) @authorizer = Authorizer.new end @@ -28,7 +28,7 @@ class SanitizerTest < ActiveModel::TestCase test "debug mass assignment removal with LoggerSanitizer" do original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' } log = StringIO.new - @logger_sanitizer.logger = Logger.new(log) + self.logger = Logger.new(log) @logger_sanitizer.sanitize(original_attributes, @authorizer) assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}") end |