contrast-agent 4.9.1 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/.rspec_parallel +6 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +0 -1
- data/ext/cs__contrast_patch/cs__contrast_patch.h +0 -2
- data/lib/contrast/agent/assess/contrast_event.rb +0 -1
- data/lib/contrast/agent/assess/finalizers/hash.rb +0 -1
- data/lib/contrast/agent/assess/policy/patcher.rb +0 -1
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -2
- data/lib/contrast/agent/assess/policy/preshift.rb +8 -5
- data/lib/contrast/agent/assess/policy/propagation_method.rb +100 -57
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +0 -2
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +31 -11
- data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -0
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +0 -1
- data/lib/contrast/agent/assess/policy/source_method.rb +13 -17
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +0 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +59 -83
- data/lib/contrast/agent/assess/property/evented.rb +2 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +0 -1
- data/lib/contrast/agent/disable_reaction.rb +1 -1
- data/lib/contrast/agent/exclusion_matcher.rb +0 -4
- data/lib/contrast/agent/inventory/database_config.rb +117 -0
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +5 -4
- data/lib/contrast/agent/inventory/policy/datastores.rb +2 -2
- data/lib/contrast/agent/middleware.rb +1 -0
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +18 -12
- data/lib/contrast/agent/patching/policy/module_policy.rb +2 -4
- data/lib/contrast/agent/patching/policy/patch.rb +5 -0
- data/lib/contrast/agent/patching/policy/patch_status.rb +3 -7
- data/lib/contrast/agent/patching/policy/patcher.rb +8 -8
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -53
- data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +137 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +7 -70
- data/lib/contrast/agent/reaction_processor.rb +1 -1
- data/lib/contrast/agent/request.rb +5 -2
- data/lib/contrast/agent/request_context.rb +19 -22
- data/lib/contrast/agent/static_analysis.rb +1 -1
- data/lib/contrast/agent/tracepoint_hook.rb +6 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +12 -6
- data/lib/contrast/api/communication/service_lifecycle.rb +4 -1
- data/lib/contrast/api/communication/socket_client.rb +4 -4
- data/lib/contrast/api/decorators/agent_startup.rb +4 -4
- data/lib/contrast/api/decorators/application_startup.rb +6 -5
- data/lib/contrast/api/decorators/route_coverage.rb +24 -1
- data/lib/contrast/components/agent.rb +5 -2
- data/lib/contrast/components/assess.rb +6 -3
- data/lib/contrast/components/base.rb +2 -2
- data/lib/contrast/components/config.rb +1 -0
- data/lib/contrast/components/contrast_service.rb +4 -2
- data/lib/contrast/components/logger.rb +13 -8
- data/lib/contrast/components/scope.rb +9 -28
- data/lib/contrast/config/base_configuration.rb +14 -6
- data/lib/contrast/configuration.rb +19 -15
- data/lib/contrast/extension/assess/array.rb +1 -11
- data/lib/contrast/extension/assess/eval_trigger.rb +0 -20
- data/lib/contrast/extension/assess/fiber.rb +0 -11
- data/lib/contrast/extension/assess/hash.rb +0 -10
- data/lib/contrast/extension/assess/kernel.rb +1 -10
- data/lib/contrast/extension/assess/marshal.rb +3 -11
- data/lib/contrast/extension/assess/regexp.rb +0 -11
- data/lib/contrast/extension/assess/string.rb +1 -26
- data/lib/contrast/extension/extension.rb +61 -0
- data/lib/contrast/extension/protect/kernel.rb +0 -10
- data/lib/contrast/framework/grape/support.rb +174 -0
- data/lib/contrast/framework/manager.rb +42 -6
- data/lib/contrast/framework/rack/support.rb +1 -1
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +0 -1
- data/lib/contrast/framework/rails/patch/support.rb +6 -3
- data/lib/contrast/framework/rails/railtie.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +1 -0
- data/lib/contrast/framework/rails/support.rb +60 -13
- data/lib/contrast/framework/sinatra/support.rb +1 -1
- data/lib/contrast/logger/log.rb +89 -15
- data/lib/contrast/utils/io_util.rb +1 -1
- data/lib/contrast/utils/ruby_ast_rewriter.rb +16 -13
- data/lib/contrast/utils/tag_util.rb +2 -1
- data/resources/assess/policy.json +197 -2
- data/resources/deadzone/policy.json +10 -0
- data/ruby-agent.gemspec +10 -1
- metadata +78 -12
- data/lib/contrast/utils/inventory_util.rb +0 -113
@@ -106,7 +106,7 @@ module Contrast
|
|
106
106
|
def _route_recurse controller, method, route
|
107
107
|
return if controller.nil? || controller.cs__class == NilClass
|
108
108
|
|
109
|
-
route_patterns = controller.routes.fetch(method
|
109
|
+
route_patterns = controller.routes.fetch(method) { [] }.map(&:first)
|
110
110
|
route_pattern = route_patterns&.find do |matcher|
|
111
111
|
matcher.params(route) # ::Mustermann::Sinatra match.
|
112
112
|
end
|
data/lib/contrast/logger/log.rb
CHANGED
@@ -13,6 +13,75 @@ require 'contrast/logger/time'
|
|
13
13
|
require 'contrast/components/config'
|
14
14
|
|
15
15
|
module Contrast
|
16
|
+
# This module allows us to dynamically weave timing into our code, so that only when the time is actually needed do
|
17
|
+
# we pay the penalty for that timing block
|
18
|
+
module TraceTiming
|
19
|
+
def methods_to_time
|
20
|
+
@_methods_to_time ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
# Store info about methods for later patching.
|
24
|
+
METHOD_INFO = Struct.new(:clazz, :method_name, :custom_msg, :aliased)
|
25
|
+
|
26
|
+
# Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
|
27
|
+
# logger set to TRACE.
|
28
|
+
#
|
29
|
+
# @params: clazz [Class] the class of the method to time.
|
30
|
+
# @params: method [Symbol] the method to time.
|
31
|
+
# @params: method [String] optional custom logging message.
|
32
|
+
def add_method_to_trace_timing clazz, method, msg = nil
|
33
|
+
methods_to_time.append(METHOD_INFO.new(clazz, method, msg, false))
|
34
|
+
enable_trace_timing if logger.level == ::Ougai::Logging::TRACE
|
35
|
+
end
|
36
|
+
|
37
|
+
# Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
|
38
|
+
# logger set to TRACE.
|
39
|
+
#
|
40
|
+
# @params: method_spec [METHOD_INFO] specs about the method to be timed.
|
41
|
+
# @params: class_method [Boolean] whether this is or isn't a class/module method.
|
42
|
+
def trace_time_class_method meth_spec, class_method
|
43
|
+
untimed_func_symbol = "untimed_#{ meth_spec.method_name }".to_sym
|
44
|
+
send_to = class_method ? meth_spec.clazz.cs__singleton_class : meth_spec.clazz
|
45
|
+
meth_spec.clazz.class_eval do
|
46
|
+
include Contrast::Components::Logger::InstanceMethods
|
47
|
+
extend Contrast::Components::Logger::InstanceMethods
|
48
|
+
|
49
|
+
send_to.send(:alias_method, untimed_func_symbol, meth_spec.method_name)
|
50
|
+
meth_spec.aliased = true
|
51
|
+
|
52
|
+
log_message = "Elapsed time for #{ meth_spec.method_name }."
|
53
|
+
log_message = meth_spec.custom_message if meth_spec.custom_msg
|
54
|
+
|
55
|
+
send_to.send(:define_method, meth_spec.method_name) do |*args, **kwargs, &block| # rubocop:disable Performance/Kernel/DefineMethod
|
56
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
57
|
+
rv = if kwargs.empty?
|
58
|
+
send(untimed_func_symbol, *args, &block)
|
59
|
+
else
|
60
|
+
send(untimed_func_symbol, *args, **kwargs, &block)
|
61
|
+
end
|
62
|
+
delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
63
|
+
logger.trace(log_message, elapsed: delta * 1000)
|
64
|
+
rv
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Enable trace timing of methods specified in @_methods_to_time via aliasing.
|
70
|
+
def enable_trace_timing
|
71
|
+
methods_to_time.each do |meth_spec|
|
72
|
+
next if meth_spec.aliased
|
73
|
+
|
74
|
+
is_class_method = meth_spec.clazz.singleton_methods(false).include?(meth_spec.method_name)
|
75
|
+
trace_time_class_method meth_spec, is_class_method
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module Contrast
|
82
|
+
# Used as a wrapper around our logging. The module option specifically adds in a new method for error that raises the
|
83
|
+
# logged exception, used in testing so that we can see if anything unexpected happens without it being swallowed
|
84
|
+
# while still providing safe options for customers.
|
16
85
|
module Logger
|
17
86
|
# For development set following env var to raise logged exceptions instead of just logging.
|
18
87
|
if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
|
@@ -20,22 +89,22 @@ module Contrast
|
|
20
89
|
alias_method :cs__error, :error
|
21
90
|
alias_method :cs__warn, :warn
|
22
91
|
|
23
|
-
def error
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
raise exc if exc && exc.cs__class < Exception
|
92
|
+
def error *args, **kwargs
|
93
|
+
if kwargs.empty?
|
94
|
+
cs__error(*args)
|
95
|
+
else
|
96
|
+
cs__error(*args, **kwargs)
|
97
|
+
end
|
98
|
+
args.each { |arg| raise arg if arg && arg.cs__class < Exception }
|
31
99
|
end
|
32
100
|
end
|
33
101
|
end
|
34
102
|
|
35
|
-
# This class functions to serve as a wrapper around our logging, as we need
|
36
|
-
#
|
103
|
+
# This class functions to serve as a wrapper around our logging, as we need to be able to dynamically update
|
104
|
+
# level based on updates to TeamServer.
|
37
105
|
class Log
|
38
106
|
include Singleton
|
107
|
+
include ::Contrast::TraceTiming
|
39
108
|
|
40
109
|
DEFAULT_NAME = 'contrast.log'
|
41
110
|
DEFAULT_LEVEL = ::Ougai::Logging::Severity::INFO
|
@@ -49,8 +118,8 @@ module Contrast
|
|
49
118
|
update
|
50
119
|
end
|
51
120
|
|
52
|
-
# Given new settings from TeamServer, update our logging to use the new
|
53
|
-
#
|
121
|
+
# Given new settings from TeamServer, update our logging to use the new file and level, assuming they weren't
|
122
|
+
# set by local configuration.
|
54
123
|
#
|
55
124
|
# @param log_file [String] the file to which to log, as provided by TeamServer settings
|
56
125
|
# @param log_level [String] the level at which to log, as provided by TeamServer settings
|
@@ -67,6 +136,8 @@ module Contrast
|
|
67
136
|
@previous_path = current_path
|
68
137
|
@previous_level = current_level_const
|
69
138
|
|
139
|
+
enable_trace_timing if current_level_const == ::Ougai::Logging::TRACE
|
140
|
+
|
70
141
|
@_logger = build(path: current_path, level_const: current_level_const)
|
71
142
|
# If we're logging to a new path, then let's start it w/ our helpful
|
72
143
|
# data gathering messages
|
@@ -76,6 +147,9 @@ module Contrast
|
|
76
147
|
logger.error('Unable to process update to LoggerManager.', e)
|
77
148
|
else
|
78
149
|
puts 'Unable to process update to LoggerManager.'
|
150
|
+
raise e if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
|
151
|
+
|
152
|
+
puts e.message
|
79
153
|
puts e.backtrace.join("\n")
|
80
154
|
end
|
81
155
|
end
|
@@ -158,7 +232,8 @@ module Contrast
|
|
158
232
|
# @return [::Ougai::Logging::Severity] the level at which to log
|
159
233
|
def find_valid_level log_level
|
160
234
|
config = ::Contrast::CONFIG.root.agent.logger
|
161
|
-
config_level = config
|
235
|
+
config_level = config&.level&.length&.positive? ? config.level : nil
|
236
|
+
|
162
237
|
valid_level(config_level || log_level)
|
163
238
|
end
|
164
239
|
|
@@ -174,8 +249,7 @@ module Contrast
|
|
174
249
|
DEFAULT_LEVEL
|
175
250
|
end
|
176
251
|
|
177
|
-
# Log that the Agent log has changed and include some default information
|
178
|
-
# at the start of the log.
|
252
|
+
# Log that the Agent log has changed and include some default information at the start of the log.
|
179
253
|
def log_update
|
180
254
|
logger.debug('Initialized new contrast agent logger')
|
181
255
|
logger.debug_with_time('middleware: log environment') do
|
@@ -6,7 +6,7 @@ require 'contrast/components/logger'
|
|
6
6
|
module Contrast
|
7
7
|
module Utils
|
8
8
|
# Util for information about an IO
|
9
|
-
|
9
|
+
module IOUtil
|
10
10
|
extend Contrast::Components::Logger::InstanceMethods
|
11
11
|
|
12
12
|
# We're only going to call rewind on things that we believe are safe to
|
@@ -36,36 +36,39 @@ module Contrast
|
|
36
36
|
# the replace within the given node.
|
37
37
|
def on_dstr node
|
38
38
|
return if node.children.all? { |child_node| child_node.type == :str }
|
39
|
-
|
40
39
|
new_content = +'('
|
41
|
-
|
40
|
+
idx = 0
|
41
|
+
while idx < node.children.size
|
42
|
+
#node.children.each_with_index do |child_node, index|
|
43
|
+
child_node = node.children[idx]
|
42
44
|
# A begin node looks like #{some_code} in ruby, we do a substring
|
43
45
|
# from [2...-1] to get rid of the #{ & trailing }.
|
44
46
|
if child_node.type == :begin
|
45
47
|
code = child_node.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
location.
|
49
|
+
expression.
|
50
|
+
source_buffer.
|
51
|
+
source[child_node.location.begin.begin_pos...child_node.location.end.end_pos]
|
50
52
|
code = code[2...-1]
|
51
53
|
new_content += "((#{ code }).to_s)"
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
# For interpolations that use class, instance, or global variables,
|
56
|
+
# those are NOT within a begin block, but instead are a ivar, cvar,
|
57
|
+
# or gvar node, not stripping of interpolation markers required.
|
56
58
|
elsif VARIABLES.include?(child_node.type)
|
57
59
|
variable = child_node.children.first
|
58
60
|
new_content << "((#{ variable }).to_s)"
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
# When interpolation includes strings before or after an
|
63
|
+
# interpolation they are simple :str nodes, in order to preserve
|
64
|
+
# escaping we need to do a dump of the string value.
|
63
65
|
elsif child_node.type == :str
|
64
66
|
literal_value = child_node.children.first
|
65
67
|
literal_value = literal_value.dump[1...-1]
|
66
68
|
new_content << "\"#{ literal_value }\""
|
67
69
|
end
|
68
|
-
new_content << ' + ' unless
|
70
|
+
new_content << ' + ' unless idx == node.children.length - 1
|
71
|
+
idx += 1
|
69
72
|
end
|
70
73
|
new_content << ')'
|
71
74
|
if node.location.cs__respond_to?(:heredoc_body)
|
@@ -8,7 +8,8 @@ module Contrast
|
|
8
8
|
class << self
|
9
9
|
# Determine if the given array of tags is covered by the other
|
10
10
|
#
|
11
|
-
# @param remaining_ranges [Array<Contrast::Agent::Assess::Tag>] the tags left that haven't been covered by
|
11
|
+
# @param remaining_ranges [Array<Contrast::Agent::Assess::Tag>] the tags left that haven't been covered by
|
12
|
+
# those given
|
12
13
|
# @param ranges Array<Contrast::Agent::Assess::Tag> the tags that are covering the first
|
13
14
|
def covered? remaining_ranges, ranges
|
14
15
|
return true unless remaining_ranges&.any?
|
@@ -34,6 +34,23 @@
|
|
34
34
|
"type": "BODY",
|
35
35
|
"tags":["NO_NEWLINES", "CROSS_SITE"]
|
36
36
|
}, {
|
37
|
+
"class_name":"ActionDispatch::Request",
|
38
|
+
"instance_method": true,
|
39
|
+
"method_visibility": "public",
|
40
|
+
"method_name": "body",
|
41
|
+
"source": "P0",
|
42
|
+
"target": "R",
|
43
|
+
"type": "BODY",
|
44
|
+
"tags":["NO_NEWLINES", "CROSS_SITE"]
|
45
|
+
}, {
|
46
|
+
"class_name":"ActionDispatch::Cookies::CookieJar",
|
47
|
+
"instance_method": true,
|
48
|
+
"method_visibility": "public",
|
49
|
+
"method_name": "[]",
|
50
|
+
"target": "R",
|
51
|
+
"type": "COOKIE",
|
52
|
+
"tags":["NO_NEWLINES", "CROSS_SITE"]
|
53
|
+
}, {
|
37
54
|
"class_name":"Rack::Request::Helpers",
|
38
55
|
"instance_method": true,
|
39
56
|
"method_visibility": "public",
|
@@ -129,10 +146,45 @@
|
|
129
146
|
"target":"R",
|
130
147
|
"type":"PARAMETER",
|
131
148
|
"tags":["CROSS_SITE"]
|
149
|
+
}, {
|
150
|
+
"class_name":"Grape::Env",
|
151
|
+
"instance_method": true,
|
152
|
+
"method_visibility": "public",
|
153
|
+
"method_name":"[]",
|
154
|
+
"source": "P0",
|
155
|
+
"target":"R",
|
156
|
+
"type":"HEADER",
|
157
|
+
"tags":["CROSS_SITE"]
|
158
|
+
}, {
|
159
|
+
"class_name":"Grape::Request",
|
160
|
+
"instance_method": true,
|
161
|
+
"method_visibility": "public",
|
162
|
+
"method_name":"headers",
|
163
|
+
"source": "P0",
|
164
|
+
"target":"R",
|
165
|
+
"type":"HEADER",
|
166
|
+
"tags":["NO_NEWLINES", "CROSS_SITE"]
|
167
|
+
}, {
|
168
|
+
"class_name":"Grape::Request",
|
169
|
+
"instance_method": true,
|
170
|
+
"method_visibility": "public",
|
171
|
+
"method_name":"body",
|
172
|
+
"target":"R",
|
173
|
+
"type":"BODY",
|
174
|
+
"tags":["CROSS_SITE"]
|
175
|
+
}, {
|
176
|
+
"class_name":"Grape::Validations::Base",
|
177
|
+
"instance_method": true,
|
178
|
+
"method_visibility": "public",
|
179
|
+
"method_name":"validate!",
|
180
|
+
"source": "P0",
|
181
|
+
"target":"R",
|
182
|
+
"type":"PARAMETER",
|
183
|
+
"tags":["CROSS_SITE"]
|
132
184
|
}
|
133
185
|
],
|
134
186
|
"propagators":[
|
135
|
-
|
187
|
+
{
|
136
188
|
"class_name":"String",
|
137
189
|
"instance_method": true,
|
138
190
|
"method_visibility": "public",
|
@@ -140,7 +192,7 @@
|
|
140
192
|
"source":"O",
|
141
193
|
"target":"R",
|
142
194
|
"action":"KEEP"
|
143
|
-
},
|
195
|
+
}, {
|
144
196
|
"class_name": "String",
|
145
197
|
"instance_method": true,
|
146
198
|
"method_visibility": "public",
|
@@ -722,6 +774,24 @@
|
|
722
774
|
"patch_method": "select_tagger",
|
723
775
|
"source": "O",
|
724
776
|
"target": "R"
|
777
|
+
},{
|
778
|
+
"class_name":"CGI::Util",
|
779
|
+
"method_name":"unescape",
|
780
|
+
"instance_method": true,
|
781
|
+
"method_visibility": "public",
|
782
|
+
"source":"P0",
|
783
|
+
"target":"R",
|
784
|
+
"action":"SPLAT",
|
785
|
+
"tags":[],
|
786
|
+
"untags":[]
|
787
|
+
}, {
|
788
|
+
"class_name":"StringIO",
|
789
|
+
"instance_method": true,
|
790
|
+
"method_visibility": "public",
|
791
|
+
"method_name": "read",
|
792
|
+
"source": "O",
|
793
|
+
"target": "R",
|
794
|
+
"action": "SPLAT"
|
725
795
|
}, {
|
726
796
|
"class_name":"CGI::Util",
|
727
797
|
"method_name":"escapeHTML",
|
@@ -742,6 +812,16 @@
|
|
742
812
|
"action":"SPLAT",
|
743
813
|
"tags":["HTML_ENCODED"],
|
744
814
|
"untags":["HTML_DECODED"]
|
815
|
+
}, {
|
816
|
+
"class_name":"Rack::Utils",
|
817
|
+
"method_name":"escape_html",
|
818
|
+
"instance_method": false,
|
819
|
+
"method_visibility": "public",
|
820
|
+
"source":"P0",
|
821
|
+
"target":"R",
|
822
|
+
"action":"SPLAT",
|
823
|
+
"tags":["HTML_ENCODED"],
|
824
|
+
"untags":["HTML_DECODED"]
|
745
825
|
}, {
|
746
826
|
"class_name":"CGI::Util",
|
747
827
|
"method_name":"h",
|
@@ -1287,6 +1367,18 @@
|
|
1287
1367
|
"instance_method": true,
|
1288
1368
|
"method_visibility": "public",
|
1289
1369
|
"source":"P0"
|
1370
|
+
}, {
|
1371
|
+
"class_name":"Rack::Response",
|
1372
|
+
"method_name":"body=",
|
1373
|
+
"instance_method": true,
|
1374
|
+
"method_visibility": "public",
|
1375
|
+
"source":"P0"
|
1376
|
+
}, {
|
1377
|
+
"class_name":"Rack::Response",
|
1378
|
+
"method_name":"write",
|
1379
|
+
"instance_method": true,
|
1380
|
+
"method_visibility": "public",
|
1381
|
+
"source":"P0"
|
1290
1382
|
}, {
|
1291
1383
|
"class_name":"Sinatra::Helpers",
|
1292
1384
|
"method_name":"body",
|
@@ -1347,12 +1439,108 @@
|
|
1347
1439
|
"method_visibility": "public",
|
1348
1440
|
"method_name":"async_exec",
|
1349
1441
|
"source":"P0"
|
1442
|
+
}, {
|
1443
|
+
"class_name":"ActiveRecord::Relation::Calculations",
|
1444
|
+
"instance_method": true,
|
1445
|
+
"method_visibility": "public",
|
1446
|
+
"method_name":"calculate",
|
1447
|
+
"source":"P0"
|
1448
|
+
}, {
|
1449
|
+
"class_name":"ActiveRecord::FinderMethods",
|
1450
|
+
"instance_method": true,
|
1451
|
+
"method_visibility": "public",
|
1452
|
+
"method_name":"exists?",
|
1453
|
+
"source":"P0"
|
1454
|
+
}, {
|
1455
|
+
"class_name":"ActiveRecord::FinderMethods",
|
1456
|
+
"instance_method": true,
|
1457
|
+
"method_visibility": "public",
|
1458
|
+
"method_name":"find_by",
|
1459
|
+
"source":"P0"
|
1350
1460
|
}, {
|
1351
1461
|
"class_name":"ActiveRecord::Querying",
|
1352
1462
|
"instance_method": false,
|
1353
1463
|
"method_visibility": "public",
|
1354
1464
|
"method_name":"select",
|
1355
1465
|
"source":"P0"
|
1466
|
+
}, {
|
1467
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1468
|
+
"instance_method": true,
|
1469
|
+
"method_visibility": "public",
|
1470
|
+
"method_name":"from",
|
1471
|
+
"source":"P0"
|
1472
|
+
}, {
|
1473
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1474
|
+
"instance_method": true,
|
1475
|
+
"method_visibility": "public",
|
1476
|
+
"method_name":"group",
|
1477
|
+
"source":"P0"
|
1478
|
+
}, {
|
1479
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1480
|
+
"instance_method": true,
|
1481
|
+
"method_visibility": "public",
|
1482
|
+
"method_name":"having",
|
1483
|
+
"source":"P0"
|
1484
|
+
}, {
|
1485
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1486
|
+
"instance_method": true,
|
1487
|
+
"method_visibility": "public",
|
1488
|
+
"method_name":"joins",
|
1489
|
+
"source":"P0"
|
1490
|
+
}, {
|
1491
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1492
|
+
"instance_method": true,
|
1493
|
+
"method_visibility": "public",
|
1494
|
+
"method_name":"lock",
|
1495
|
+
"source":"P0"
|
1496
|
+
}, {
|
1497
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1498
|
+
"instance_method": true,
|
1499
|
+
"method_visibility": "public",
|
1500
|
+
"method_name":"select",
|
1501
|
+
"source":"P0"
|
1502
|
+
}, {
|
1503
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1504
|
+
"instance_method": true,
|
1505
|
+
"method_visibility": "public",
|
1506
|
+
"method_name":"reselect",
|
1507
|
+
"source":"P0"
|
1508
|
+
}, {
|
1509
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1510
|
+
"instance_method": true,
|
1511
|
+
"method_visibility": "public",
|
1512
|
+
"method_name":"where",
|
1513
|
+
"source":"P0"
|
1514
|
+
}, {
|
1515
|
+
"class_name":"ActiveRecord::QueryMethods",
|
1516
|
+
"instance_method": true,
|
1517
|
+
"method_visibility": "public",
|
1518
|
+
"method_name":"rewhere",
|
1519
|
+
"source":"P0"
|
1520
|
+
}, {
|
1521
|
+
"class_name":"ActiveRecord::QueryMethods::WhereChain",
|
1522
|
+
"instance_method": true,
|
1523
|
+
"method_visibility": "public",
|
1524
|
+
"method_name":"not",
|
1525
|
+
"source":"P0"
|
1526
|
+
}, {
|
1527
|
+
"class_name":"ActiveRecord::Relation",
|
1528
|
+
"instance_method": true,
|
1529
|
+
"method_visibility": "public",
|
1530
|
+
"method_name":"delete_by",
|
1531
|
+
"source":"P0"
|
1532
|
+
}, {
|
1533
|
+
"class_name":"ActiveRecord::Relation",
|
1534
|
+
"instance_method": true,
|
1535
|
+
"method_visibility": "public",
|
1536
|
+
"method_name":"destroy_by",
|
1537
|
+
"source":"P0"
|
1538
|
+
}, {
|
1539
|
+
"class_name":"ActiveRecord::Relation",
|
1540
|
+
"instance_method": true,
|
1541
|
+
"method_visibility": "public",
|
1542
|
+
"method_name":"update_all",
|
1543
|
+
"source":"P0"
|
1356
1544
|
}
|
1357
1545
|
]
|
1358
1546
|
}, {
|
@@ -1685,6 +1873,13 @@
|
|
1685
1873
|
"method_visibility": "public",
|
1686
1874
|
"method_name": "redirect_to",
|
1687
1875
|
"source": "P0"
|
1876
|
+
},
|
1877
|
+
{
|
1878
|
+
"class_name": "Grape::DSL::InsideRoute",
|
1879
|
+
"instance_method": true,
|
1880
|
+
"method_visibility": "public",
|
1881
|
+
"method_name": "redirect",
|
1882
|
+
"source": "P0"
|
1688
1883
|
}
|
1689
1884
|
]
|
1690
1885
|
}, {
|