lib/brakeman/tracker/model.rb
require 'brakeman/tracker/collection'
module Brakeman
module ModelMethods
attr_reader :associations, :attr_accessible, :role_accessible
def initialize_model
@associations = {}
@role_accessible = []
@attr_accessible = nil
end
def association? method_name
@associations.each do |name, args|
args.each do |arg|
if symbol? arg and arg.value == method_name
return true
end
end
end
false
end
def unprotected_model?
@attr_accessible.nil? and !parent_classes_protected? and ancestor?(:"ActiveRecord::Base")
end
# go up the chain of parent classes to see if any have attr_accessible
def parent_classes_protected? seen={}
seen[self.name] = true
if @attr_accessible or self.includes.include? :"ActiveModel::ForbiddenAttributesProtection"
true
elsif parent = tracker.models[self.parent] and !seen[self.parent]
parent.parent_classes_protected? seen
else
false
end
end
def set_attr_accessible exp = nil
if exp
args = []
exp.each_arg do |e|
if node_type? e, :lit
args << e.value
elsif hash? e
@role_accessible.concat args
end
end
@attr_accessible ||= []
@attr_accessible.concat args
else
@attr_accessible ||= []
end
end
def set_attr_protected exp
add_option :attr_protected, exp
end
def attr_protected
@options[:attr_protected]
end
end
class Model < Brakeman::Collection
include ModelMethods
ASSOCIATIONS = Set[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
def initialize name, parent, file_name, src, tracker
super
initialize_model
@collection = tracker.models
end
def add_option name, exp
if ASSOCIATIONS.include? name
@associations[name] ||= []
@associations[name].concat exp.args
else
super name, exp.arglist.line(exp.line)
end
end
end
end