Class: Spektr::Checks::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/spektr/checks/base.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, target) ⇒ Base

Returns a new instance of Base.



5
6
7
8
9
# File 'lib/spektr/checks/base.rb', line 5

def initialize(app, target)
  @app = app
  @target = target
  @targets = []
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



3
4
5
# File 'lib/spektr/checks/base.rb', line 3

def name
  @name
end

Instance Method Details

#app_version_between?(a, b) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/spektr/checks/base.rb', line 142

def app_version_between?(a, b)
  version_between?(a, b, @app.rails_version)
end

#dupe?(path, location, message) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
41
42
# File 'lib/spektr/checks/base.rb', line 36

def dupe?(path, location, message)
  @app.warnings.find do |w|
    w.path == path &&
      (w.location.nil? || w.location&.line == location&.line) &&
      w.message == message
  end
end

#model_attribute?(item) ⇒ Boolean

TODO: this doesn’t work properly

Returns:

  • (Boolean)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/spektr/checks/base.rb', line 104

def model_attribute?(item)
  model_names = @app.models.collect(&:name)
  case item.type
  when :ivar, :lvar
    # TODO: handle helpers here too
    if ["Spektr::Targets::Controller", "Spektr::Targets::View"].include?(@target.class.name)
      actions = []
      @app.controllers.each do |controller|
        actions = actions.concat controller.actions.select { |action|
          action.template == @target.view_path if @target.respond_to? :view_path
        }
      end
      actions.each do |action|
        action.body.each do |exp|
          return exp.user_input? if exp.is_a?(Exp::Ivasign) && exp.name == item.name
        end
      end
    end
  when :send
    ast = item.is_a?(Parser::AST::Node) ? item : item.ast
    _send = Exp::Send.new(ast)
    return true if _send.receiver && model_names.include?(_send.receiver.name)
  when :const
    return true if model_names.include? item.name
  when :block, :pair, :hash, :array, :if, :or
    item.children.each do |child|
      next unless child.is_a?(Parser::AST::Node)
      return true if model_attribute?(child)
    end
  when :dstr
    # TODO: implement this
  when :sym, :str, :nil, :yield
    # do nothing
  else
    raise "Unknown argument type #{item.type}"
  end
end

#runObject



11
12
13
14
# File 'lib/spektr/checks/base.rb', line 11

def run
  ::Spektr.logger.debug "Running #{self.class.name} on #{@target.path}"
  target_affected? && should_run?
end

#should_run?Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
26
# File 'lib/spektr/checks/base.rb', line 20

def should_run?
  if version_affected && @app.rails_version
    version_affected > @app.rails_version
  else
    true
  end
end

#target_affected?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/spektr/checks/base.rb', line 16

def target_affected?
  @targets.include?(@target.class.name)
end

#user_input?(type, name, ast = nil, object = nil) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/spektr/checks/base.rb', line 46

def user_input?(type, name, ast = nil, object = nil)
  case type
  when :ivar, :lvar
    # TODO: handle helpers here too
    return false unless @target.instance_of?(Spektr::Targets::View)

    actions = []
    @app.controllers.each do |controller|
      actions = actions.concat controller.actions.select { |action|
        action.template == @target.view_path
      }
    end
    actions.each do |action|
      action.body.each do |exp|
        return exp.user_input? if exp.is_a?(Exp::Ivasign) && exp.name == name
      end
    end
    false
  when :send
    if ast.children.first&.type == :send
      child = ast.children.first
      return user_input?(child.type, child.children.last, child)
    end
    return true if %i[params cookies request].include? name
  when :xstr, :begin
    ast.children.each do |child|
      next unless child.is_a?(Parser::AST::Node)
      return true if user_input?(child.type, child.children.last, child)
    end
  when :dstr
    object&.children&.each do |child|
      if child.is_a?(Parser::AST::Node)
        name = nil
        ast = child
      else
        name = child.name
        ast = child.ast
      end
      return true if user_input?(child.type, name, ast)
    end
  when :lvasgn
    ast.children.each do |child|
      next unless child.is_a?(Parser::AST::Node)
      return true if user_input?(child.type, child.children.last, child)
    end
  when :block, :pair, :hash, :array, :if, :or
    ast.children.each do |child|
      next unless child.is_a?(Parser::AST::Node)
      return true if user_input?(child.type, child.children.last, child)
    end
  when :sym, :str, :const, :int, :cbase, :true, :self, :args, :nil, :yield
    # do nothing
  else
    raise "Unknown argument type #{type} #{name} #{ast.inspect}"
  end
end

#version_affectedObject



44
# File 'lib/spektr/checks/base.rb', line 44

def version_affected; end

#version_between?(a, b, version) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
# File 'lib/spektr/checks/base.rb', line 146

def version_between?(a, b, version)
  version = Gem::Version.new(version) unless version.is_a? Gem::Version
  version >= Gem::Version.new(a) && version <= Gem::Version.new(b)
end

#warn!(target, check, location, message, confidence = :high) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/spektr/checks/base.rb', line 28

def warn!(target, check, location, message, confidence = :high)
  full_path = target.is_a?(String) ? target : target.path
  path = full_path.gsub(@app.root, "")
  return if dupe?(path, location, message)

  @app.warnings << Warning.new(path, full_path, check, location, message, confidence)
end