mercredi 22 mars 2017

Overriding assign_attributes breaks Active:ModelForbiddenAttirbutesError exceptions and allows for mass attribute assignment

I have a module that was being used in a Rails 3 application to clean up bad characters from user form submissions. This worked fine under Rails 3 using attr_accessible in the models to prevent mass attr assignment, but with Strong Parameters in both Rails 3 and Rails 4 this is somehow bypassing Active:ModelForbiddenAttributesError exceptions so they never get raised and any params can be saved without first being permitted.

The module I'm using looks like this

module AttributeAssignmentCleaner
  def assign_attributes(new_attributes, opt= {})
    new_attributes = new_attributes.merge(opt)
    new_attributes = ris_attribute_cleaner(new_attributes)
    super(new_attributes)
  end

  def attributes=(new_attributes)
    new_attributes = ris_attribute_cleaner(new_attributes)
    super
  end

  def ris_attribute_cleaner(new_attributes)
    return new_attributes if new_attributes.nil?
    lookup = {
        "‘" => "'",
        "‛" => "'",
        "’" => "'",
        "“" => '"',
        "‟" => '"',
        "”" => '"',
        " " => '-',
        "‐" => '-',
        "‑" => '-',
        "‒" => '-',
        "–" => '-',
        "—" => '-',
        "―" => '-',
        "﹣" => '-',
        "-" => '-',
        "_" => '_',
        "︱" => '|',
        "︲" => '|',
        "•" => '*', }

    convert_char = Proc.new do |x|
      if lookup.has_key?(x)
        lookup[x]
      else
        ''
      end

    end
    new_attributes = new_attributes.inject({}) do |h, (key, val)|
      h[key] = case
                 when val == ''
                   nil
                 when val.is_a?(String) && val.ascii_only? == false

                   val = ActiveSupport::Multibyte::Chars.new(val).normalize(:kd).to_s
                   val = val.force_encoding("UTF-8").encode(
                       "us-ascii",
                       :fallback => convert_char
                   ).encode("UTF-8")

                 else
                   val
               end
      h
    end
  end
end

I would have expected this to work correctly as it calls super at the end; I would think the exceptions would get raised then, but this is not the case.

Aucun commentaire:

Enregistrer un commentaire