require 'brakeman/checks/base_check'

#Check if mass assignment is used with models
#which inherit from ActiveRecord::Base.
#
#If tracker.options[:collapse_mass_assignment] is +true+ (default), all models 
#which do not use attr_accessible will be reported in a single warning
class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
  Brakeman::Checks.add self

  @description = "Reports models which do not use attr_restricted and warns on models that use attr_protected"

  def run_check
    return if mass_assign_disabled?

    #Roll warnings into one warning for all models
    if tracker.options[:collapse_mass_assignment]
      no_accessible_names = []
      protected_names = []

      check_models do |name, model|
        if model[:options][:attr_protected].nil?
          no_accessible_names << name.to_s
        elsif not tracker.options[:ignore_attr_protected]
          protected_names << name.to_s
        end
      end

      unless no_accessible_names.empty?
        warn :model => no_accessible_names.sort.join(", "),
          :warning_type => "Attribute Restriction",
          :message => "Mass assignment is not restricted using attr_accessible",
          :confidence => CONFIDENCE[:high]
      end

      unless protected_names.empty?
        warn :model => protected_names.sort.join(", "),
          :warning_type => "Attribute Restriction",
          :message => "attr_accessible is recommended over attr_protected",
          :confidence => CONFIDENCE[:low]
      end
    else #Output one warning per model

      check_models do |name, model|
        if model[:options][:attr_protected].nil?
          warn :model => name,
            :file => model[:file],
            :warning_type => "Attribute Restriction",
            :message => "Mass assignment is not restricted using attr_accessible",
            :confidence => CONFIDENCE[:high]
        elsif not tracker.options[:ignore_attr_protected]
          warn :model => name,
            :file => model[:file],
            :line => model[:options][:attr_protected].first.line,
            :warning_type => "Attribute Restriction",
            :message => "attr_accessible is recommended over attr_protected",
            :confidence => CONFIDENCE[:low]
        end
      end
    end
  end

  def check_models
    tracker.models.each do |name, model|
      if unprotected_model? model
        yield name, model
      end
    end
  end
end