moesif_rack 1.4.18 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/lib/moesif_rack/app_config.rb +87 -120
- data/lib/moesif_rack/client_ip.rb +61 -102
- data/lib/moesif_rack/governance_rules.rb +483 -0
- data/lib/moesif_rack/moesif_helpers.rb +57 -6
- data/lib/moesif_rack/moesif_middleware.rb +178 -140
- data/lib/moesif_rack/regex_config_helper.rb +96 -104
- data/lib/moesif_rack/update_company.rb +44 -48
- data/lib/moesif_rack/update_user.rb +44 -48
- data/moesif_capture_outgoing/httplog/adapters/net_http.rb +18 -21
- data/moesif_capture_outgoing/httplog/http_log.rb +54 -85
- data/moesif_capture_outgoing/httplog.rb +2 -2
- data/test/config_example.json +1477 -0
- data/test/govrule_example.json +20 -0
- data/test/test_governance_rules.rb +212 -0
- metadata +8 -4
@@ -0,0 +1,483 @@
|
|
1
|
+
require 'moesif_api'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
require 'zlib'
|
5
|
+
require 'stringio'
|
6
|
+
require_relative './moesif_helpers'
|
7
|
+
require_relative './regex_config_helper'
|
8
|
+
|
9
|
+
# rule refereence
|
10
|
+
# {
|
11
|
+
# "_id": "649b64ea96d5e2384e3cece6",
|
12
|
+
# "created_at": "2023-06-27T22:38:34.405",
|
13
|
+
# "type": "regex",
|
14
|
+
# "state": 2,
|
15
|
+
# "org_id": "688:25",
|
16
|
+
# "app_id": "768:74",
|
17
|
+
# "name": "teset govern rule. ",
|
18
|
+
# "block": true,
|
19
|
+
# "applied_to": "matching",
|
20
|
+
# "applied_to_unidentified": false,
|
21
|
+
# "response": {
|
22
|
+
# "status": 205,
|
23
|
+
# "headers": {
|
24
|
+
# "X-Test": "12423"
|
25
|
+
# },
|
26
|
+
# "body": {
|
27
|
+
# "hello": "there"
|
28
|
+
# }
|
29
|
+
# },
|
30
|
+
# "regex_config": [
|
31
|
+
# {
|
32
|
+
# "conditions": [
|
33
|
+
# {
|
34
|
+
# "path": "request.route",
|
35
|
+
# "value": "test"
|
36
|
+
# },
|
37
|
+
# {
|
38
|
+
# "path": "request.verb",
|
39
|
+
# "value": "test"
|
40
|
+
# }
|
41
|
+
# ]
|
42
|
+
# },
|
43
|
+
# {
|
44
|
+
# "conditions": [
|
45
|
+
# {
|
46
|
+
# "path": "request.ip_address",
|
47
|
+
# "value": "teset"
|
48
|
+
# },
|
49
|
+
# {
|
50
|
+
# "path": "request.verb",
|
51
|
+
# "value": "5"
|
52
|
+
# }
|
53
|
+
# ]
|
54
|
+
# }
|
55
|
+
# ]
|
56
|
+
# }
|
57
|
+
|
58
|
+
# user rule reference.
|
59
|
+
|
60
|
+
# {
|
61
|
+
# "_id": "649b65d83a5a0131fd035427",
|
62
|
+
# "created_at": "2023-06-27T22:42:32.301",
|
63
|
+
# "type": "user",
|
64
|
+
# "state": 2,
|
65
|
+
# "org_id": "688:25",
|
66
|
+
# "app_id": "768:74",
|
67
|
+
# "name": "test user rule",
|
68
|
+
# "block": false,
|
69
|
+
# "applied_to": "matching",
|
70
|
+
# "applied_to_unidentified": true,
|
71
|
+
# "response": {
|
72
|
+
# "status": 200,
|
73
|
+
# "headers": {
|
74
|
+
# "teset": "test"
|
75
|
+
# }
|
76
|
+
# },
|
77
|
+
# "cohorts": [
|
78
|
+
# {
|
79
|
+
# "id": "645c3793cba73323bb0760e6"
|
80
|
+
# }
|
81
|
+
# ],
|
82
|
+
# "regex_config": [
|
83
|
+
# {
|
84
|
+
# "conditions": [
|
85
|
+
# {
|
86
|
+
# "path": "request.verb",
|
87
|
+
# "value": "get"
|
88
|
+
# }
|
89
|
+
# ]
|
90
|
+
# }
|
91
|
+
# ]
|
92
|
+
# }
|
93
|
+
|
94
|
+
module RULE_TYPES
|
95
|
+
USER = 'user'
|
96
|
+
COMPANY = 'company'
|
97
|
+
REGEX = 'regex'
|
98
|
+
end
|
99
|
+
|
100
|
+
class GovernanceRules
|
101
|
+
def initialize(debug)
|
102
|
+
@debug = debug
|
103
|
+
@moesif_helpers = MoesifHelpers.new(debug)
|
104
|
+
@regex_config_helper = RegexConfigHelper.new(debug)
|
105
|
+
@last_fetch = Time.at(0)
|
106
|
+
end
|
107
|
+
|
108
|
+
def load_rules(api_controller)
|
109
|
+
# Get Application Config
|
110
|
+
@last_fetch = Time.now.utc
|
111
|
+
@moesif_helpers.log_debug('starting downlaoding rules')
|
112
|
+
rules_response = api_controller.get_rules
|
113
|
+
rules = @moesif_helpers.decompress_gzip_body(rules_response)
|
114
|
+
@moesif_helpers.log_debug('new rules downloaded')
|
115
|
+
@moesif_helpers.log_debug(rules.to_json)
|
116
|
+
|
117
|
+
generate_rules_caching(rules)
|
118
|
+
rescue MoesifApi::APIException => e
|
119
|
+
if e.response_code.between?(401, 403)
|
120
|
+
@moesif_helpers.log_debug 'Unauthorized access getting application configuration. Please check your Appplication Id.'
|
121
|
+
end
|
122
|
+
@moesif_helpers.log_debug 'Error getting application configuration, with status code:'
|
123
|
+
@moesif_helpers.log_debug e.response_code
|
124
|
+
rescue StandardError => e
|
125
|
+
@moesif_helpers.log_debug e.to_s
|
126
|
+
end
|
127
|
+
|
128
|
+
def generate_rules_caching(rules)
|
129
|
+
@rules = rules
|
130
|
+
@regex_rules = []
|
131
|
+
@user_rules = {}
|
132
|
+
@unidentified_user_rules = []
|
133
|
+
@company_rules = {}
|
134
|
+
@unidentified_company_rules = []
|
135
|
+
if !rules.nil? && !rules.empty?
|
136
|
+
rules.each do |rule|
|
137
|
+
rule_id = rule['_id']
|
138
|
+
case rule['type']
|
139
|
+
when RULE_TYPES::USER
|
140
|
+
@user_rules[rule_id] = rule
|
141
|
+
@unidentified_user_rules.push(rule) if rule.fetch('applied_to_unidentified', false)
|
142
|
+
when RULE_TYPES::COMPANY
|
143
|
+
@company_rules[rule_id] = rule
|
144
|
+
@unidentified_company_rules.push(rule) if rule.fetch('applied_to_unidentified', false)
|
145
|
+
when RULE_TYPES::REGEX
|
146
|
+
@regex_rules.push(rule)
|
147
|
+
else
|
148
|
+
@moesif_helpers.log_debug 'rule type not found for id ' + rule_id
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
# @moesif_helpers.log_debug('user_rules processed ' + @user_rules.to_s)
|
153
|
+
# @moesif_helpers.log_debug('unidentified_user_rules' + @unidentified_user_rules.to_s);
|
154
|
+
# @moesif_helpers.log_debug('regex_rules' + @regex_rules.to_s);
|
155
|
+
rescue StandardError => e
|
156
|
+
@moesif_helpers.log_debug e.to_s
|
157
|
+
end
|
158
|
+
|
159
|
+
def has_rules
|
160
|
+
return false if @rules.nil?
|
161
|
+
|
162
|
+
@rules.length >= 1
|
163
|
+
end
|
164
|
+
|
165
|
+
# TODO
|
166
|
+
def convert_uri_to_route(uri)
|
167
|
+
# TODO: for now just return uri
|
168
|
+
uri
|
169
|
+
end
|
170
|
+
|
171
|
+
def prepare_request_fields_based_on_regex_config(_env, event_model, request_body)
|
172
|
+
operation_name = request_body.fetch('operationName', nil) unless request_body.nil?
|
173
|
+
{
|
174
|
+
'request.verb' => event_model.request.verb,
|
175
|
+
'request.ip_address' => event_model.request.ip_address,
|
176
|
+
'request.route' => convert_uri_to_route(event_model.request.uri),
|
177
|
+
'request.body.operationName' => operation_name
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_field_value_for_path(path, request_fields, request_body)
|
182
|
+
if path && path.start_with?('request.body.') && request_body
|
183
|
+
body_key = path.sub('request.body.', '')
|
184
|
+
return request_body.fetch(body_key, nil)
|
185
|
+
end
|
186
|
+
request_fields.fetch(path, nil)
|
187
|
+
end
|
188
|
+
|
189
|
+
def check_request_with_regex_match(regex_configs, request_fields, request_body)
|
190
|
+
# since there is no regex config, customer must only care about cohort criteria, we assume regex matched
|
191
|
+
return true if regex_configs.nil? || regex_configs.empty?
|
192
|
+
|
193
|
+
array_to_or = regex_configs.map do |or_group_of_regex_rule|
|
194
|
+
conditions = or_group_of_regex_rule.fetch('conditions', [])
|
195
|
+
|
196
|
+
conditions.reduce(true) do |all_match, condition|
|
197
|
+
return false unless all_match
|
198
|
+
|
199
|
+
path = condition.fetch('path', nil)
|
200
|
+
|
201
|
+
field_value = get_field_value_for_path(path, request_fields, request_body)
|
202
|
+
reg_ex = Regexp.new condition.fetch('value', nil)
|
203
|
+
|
204
|
+
if path.nil? || field_value.nil? || reg_ex.nil?
|
205
|
+
false
|
206
|
+
else
|
207
|
+
field_value =~ reg_ex
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
array_to_or.reduce(false) { |anysofar, curr| anysofar || curr }
|
213
|
+
rescue StandardError => e
|
214
|
+
@moesif_helpers.log_debug('checking regex failed, possible malformed regex ' + e.to_s)
|
215
|
+
false
|
216
|
+
end
|
217
|
+
|
218
|
+
def get_applicable_regex_rules(request_fields, request_body)
|
219
|
+
@regex_rules.select do |rule|
|
220
|
+
regex_configs = rule['regex_config']
|
221
|
+
@moesif_helpers.log_debug('checking regex_configs')
|
222
|
+
@moesif_helpers.log_debug(regex_configs.to_s)
|
223
|
+
if regex_configs.nil?
|
224
|
+
true
|
225
|
+
else
|
226
|
+
@moesif_helpers.log_debug('checking regex_configs')
|
227
|
+
@moesif_helpers.log_debug(regex_configs.to_s)
|
228
|
+
check_request_with_regex_match(regex_configs, request_fields, request_body)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def get_applicable_user_rules_for_unidentified_user(request_fields, request_body)
|
234
|
+
@unidentified_user_rules.select do |rule|
|
235
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
236
|
+
|
237
|
+
@moesif_helpers.log_debug('regexmatched for unidetnfied_user rule ' + rule.to_json) if regex_matched
|
238
|
+
regex_matched
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
243
|
+
applicable_rules_list = []
|
244
|
+
|
245
|
+
rule_ids_hash_that_is_in_cohort = {}
|
246
|
+
|
247
|
+
# handle uses where user_id is in ARLEADY in the cohort of the rules.
|
248
|
+
# if user is in a cohorot of the rule, it will come from config user rule values array, which is
|
249
|
+
# config.user_rules.user_id.[]
|
250
|
+
unless config_user_rules_values.nil?
|
251
|
+
config_user_rules_values.each do |entry|
|
252
|
+
rule_id = entry['rules']
|
253
|
+
# this is user_id matched cohort set in the rule.
|
254
|
+
rule_ids_hash_that_is_in_cohort[rule_id] = true unless rule_id.nil?
|
255
|
+
# rule_ids_hash_that_I_am_in_cohot{629847be77e75b13635aa868: true}
|
256
|
+
|
257
|
+
found_rule = @user_rules[rule_id]
|
258
|
+
if found_rule.nil?
|
259
|
+
@moesif_helpers.log_debug('rule for not foun for ' + rule_id.to_s)
|
260
|
+
next
|
261
|
+
end
|
262
|
+
|
263
|
+
@moesif_helpers.log_debug('found rule in cached user rules' + rule_id)
|
264
|
+
|
265
|
+
regex_matched = check_request_with_regex_match(found_rule.fetch('regex_config', nil), request_fields,
|
266
|
+
request_body)
|
267
|
+
|
268
|
+
unless regex_matched
|
269
|
+
@moesif_helpers.log_debug('regex not matched, skipping ' + rule_id.to_s)
|
270
|
+
next
|
271
|
+
end
|
272
|
+
|
273
|
+
if found_rule['applied_to'] == 'not_matching'
|
274
|
+
# mean not matching, i.e. we do not apply the rule since current user is in cohort.
|
275
|
+
@moesif_helpers.log_debug('applied to is not matching to users in this cohort, so skipping add this rule')
|
276
|
+
else
|
277
|
+
# since applied_to is matching, we are in the cohort, we apply the rule by adding it to the list.
|
278
|
+
@moesif_helpers.log_debug('applied to is matching' + found_rule['applied_to'])
|
279
|
+
applicable_rules_list.push(found_rule)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# now user id is NOT associated with any cohort rule so we have to add user rules that is "Not matching"
|
285
|
+
@user_rules.each do |_rule_id, rule|
|
286
|
+
# we want to apply to any "not_matching" rules.
|
287
|
+
# we want to make sure user is not in the cohort of the rule.
|
288
|
+
next unless rule['applied_to'] == 'not_matching' && !rule_ids_hash_that_is_in_cohort[_rule_id]
|
289
|
+
|
290
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
291
|
+
applicable_rules_list.push(rule) if regex_matched
|
292
|
+
end
|
293
|
+
|
294
|
+
applicable_rules_list
|
295
|
+
end
|
296
|
+
|
297
|
+
def get_applicable_company_rules_for_unidentified_company(request_fields, request_body)
|
298
|
+
@unidentified_company_rules.select do |rule|
|
299
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
300
|
+
|
301
|
+
regex_matched
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def get_applicable_company_rules(request_fields, request_body, config_company_rules_values)
|
306
|
+
applicable_rules_list = []
|
307
|
+
|
308
|
+
@moesif_helpers.log_debug('get applicable company rules for identifed company using these config values: ' + config_company_rules_values.to_s)
|
309
|
+
|
310
|
+
rule_ids_hash_that_is_in_cohort = {}
|
311
|
+
|
312
|
+
# handle where company_id is in the cohort of the rules.
|
313
|
+
unless config_company_rules_values.nil?
|
314
|
+
config_company_rules_values.each do |entry|
|
315
|
+
rule_id = entry['rules']
|
316
|
+
# this is company_id matched cohort set in the rule.
|
317
|
+
rule_ids_hash_that_is_in_cohort[rule_id] = true unless rule_id.nil?
|
318
|
+
|
319
|
+
found_rule = @company_rules[rule_id]
|
320
|
+
|
321
|
+
if found_rule.nil?
|
322
|
+
@moesif_helpers.log_debug('company rule for not found for ' + rule_id.to_s)
|
323
|
+
next
|
324
|
+
end
|
325
|
+
|
326
|
+
regex_matched = check_request_with_regex_match(found_rule.fetch('regex_config', nil), request_fields,
|
327
|
+
request_body)
|
328
|
+
|
329
|
+
unless regex_matched
|
330
|
+
@moesif_helpers.log_debug('regex not matched, skipping ' + rule_id.to_s)
|
331
|
+
next
|
332
|
+
end
|
333
|
+
|
334
|
+
if found_rule['applied_to'] == 'not_matching'
|
335
|
+
# mean not matching, i.e. we do not apply the rule since current user is in cohort.
|
336
|
+
@moesif_helpers.log_debug('applied to is companies not in this cohort, so skipping add this rule')
|
337
|
+
else
|
338
|
+
# since applied_to is matching, we are in the cohort, we apply the rule by adding it to the list.
|
339
|
+
@moesif_helpers.log_debug('applied to is matching' + found_rule['applied_to'])
|
340
|
+
applicable_rules_list.push(found_rule)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# handle is NOT in the cohort of rule so we have to apply rules that are "Not matching"
|
346
|
+
@company_rules.each do |_rule_id, rule|
|
347
|
+
# we want to apply to any "not_matching" rules.
|
348
|
+
next unless rule['applied_to'] == 'not_matching' && !rule_ids_hash_that_is_in_cohort[_rule_id]
|
349
|
+
|
350
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
351
|
+
applicable_rules_list.push(rule) if regex_matched
|
352
|
+
end
|
353
|
+
applicable_rules_list
|
354
|
+
end
|
355
|
+
|
356
|
+
def replace_merge_tag_values(template_obj_or_val, mergetag_values, variables_from_rules)
|
357
|
+
# take the template, either headers or body, and replace with mergetag_values
|
358
|
+
# recursively
|
359
|
+
return template_obj_or_val if variables_from_rules.nil? || variables_from_rules.empty?
|
360
|
+
|
361
|
+
if template_obj_or_val.nil?
|
362
|
+
template_obj_or_val
|
363
|
+
elsif template_obj_or_val.is_a?(String)
|
364
|
+
temp_val = template_obj_or_val
|
365
|
+
variables_from_rules.each do |variable|
|
366
|
+
variable_name = variable['name']
|
367
|
+
variable_value = mergetag_values.nil? ? 'UNKNOWN' : mergetag_values.fetch(variable_name, 'UNKNOWN')
|
368
|
+
temp_val = temp_val.sub('{{' + variable_name + '}}', variable_value)
|
369
|
+
end
|
370
|
+
temp_val
|
371
|
+
elsif template_obj_or_val.is_a?(Array)
|
372
|
+
tempplate_obj_or_val.map { |entry| replace_merge_tag_values(entry, mergetag_values, variables_from_rules) }
|
373
|
+
elsif template_obj_or_val.is_a?(Hash)
|
374
|
+
result_hash = {}
|
375
|
+
template_obj_or_val.each do |key, entry|
|
376
|
+
result_hash[key] = replace_merge_tag_values(entry, mergetag_values, variables_from_rules)
|
377
|
+
end
|
378
|
+
result_hash
|
379
|
+
else
|
380
|
+
template_obj_or_val
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def modify_response_for_applicable_rule(rule, response, mergetag_values)
|
385
|
+
# For matched rule, we can now modify the response
|
386
|
+
# response is a hash with :status, :headers and :body or nil
|
387
|
+
@moesif_helpers.log_debug('about to modify response ' + mergetag_values.to_s)
|
388
|
+
new_headers = response[:headers].clone
|
389
|
+
rule_variables = rule['variables']
|
390
|
+
# headers are always merged togethe
|
391
|
+
rule_headers = replace_merge_tag_values(rule.dig('response', 'headers'), mergetag_values, rule_variables)
|
392
|
+
# insersion of rule headers, we do not replace all headers.
|
393
|
+
rule_headers.each { |key, entry| new_headers[key] = entry } unless rule_headers.nil?
|
394
|
+
|
395
|
+
response[:headers] = new_headers
|
396
|
+
|
397
|
+
# only replace status and body if it is blocking.
|
398
|
+
if rule['block']
|
399
|
+
@moesif_helpers.log_debug('rule is block' + rule.to_s)
|
400
|
+
response[:status] = rule.dig('response', 'status') || response[:status]
|
401
|
+
new_body = replace_merge_tag_values(rule.dig('response', 'body'), mergetag_values, rule_variables)
|
402
|
+
response[:body] = new_body
|
403
|
+
response[:block_rule_id] = rule['_id']
|
404
|
+
end
|
405
|
+
|
406
|
+
response
|
407
|
+
rescue StandardError => e
|
408
|
+
@moesif_helpers.log_debug('failed to apply rule ' + rule.to_json + ' for ' + response.to_s + ' error: ' + e.to_s)
|
409
|
+
response
|
410
|
+
end
|
411
|
+
|
412
|
+
def apply_rules_list(applicable_rules, response, config_rule_values)
|
413
|
+
return response if applicable_rules.nil? || applicable_rules.empty?
|
414
|
+
|
415
|
+
# config_rule_values if exists should be from config for a particular user for an list of rules.
|
416
|
+
# [
|
417
|
+
# {
|
418
|
+
# "rules": "629847be77e75b13635aa868",
|
419
|
+
# "values": {
|
420
|
+
# "1": "viewer-Float(online)-nd",
|
421
|
+
# "2": "[\"62984b17715c450ba6ad46b2\"]",
|
422
|
+
# "3": "[\"user cohort created at 6/1, 10:31 PM\"]",
|
423
|
+
# "4": "viewer-Float(online)-nd"
|
424
|
+
# }
|
425
|
+
# }
|
426
|
+
# ]
|
427
|
+
|
428
|
+
applicable_rules.reduce(response) do |prev_response, rule|
|
429
|
+
unless config_rule_values.nil?
|
430
|
+
found_rule_value_pair = config_rule_values.find { |rule_value_pair| rule_value_pair['rules'] == rule['_id'] }
|
431
|
+
mergetag_values = found_rule_value_pair['values'] unless found_rule_value_pair.nil?
|
432
|
+
end
|
433
|
+
modify_response_for_applicable_rule(rule, prev_response, mergetag_values)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def govern_request(config, env, event_model, status, headers, body)
|
438
|
+
# we can skip if rules does not exist or config does not exist
|
439
|
+
return if @rules.nil? || @rules.empty?
|
440
|
+
|
441
|
+
if event_model
|
442
|
+
request_body = event_model.request.body
|
443
|
+
request_fields = prepare_request_fields_based_on_regex_config(env, event_model, request_body)
|
444
|
+
end
|
445
|
+
|
446
|
+
user_id = event_model.user_id
|
447
|
+
company_id = event_model.company_id
|
448
|
+
|
449
|
+
# apply in reverse order of priority.
|
450
|
+
# Priority is user rule, company rule, and regex.
|
451
|
+
# by apply in reverse order, the last rule become highest priority.
|
452
|
+
|
453
|
+
new_response = {
|
454
|
+
status: status,
|
455
|
+
headers: headers,
|
456
|
+
body: body
|
457
|
+
}
|
458
|
+
|
459
|
+
applicable_regex_rules = get_applicable_regex_rules(request_fields, request_body)
|
460
|
+
new_response = apply_rules_list(applicable_regex_rules, new_response, nil)
|
461
|
+
|
462
|
+
if company_id.nil?
|
463
|
+
company_rules = get_applicable_company_rules_for_unidentified_company(request_fields, request_body)
|
464
|
+
new_response = apply_rules_list(company_rules, new_response, nil)
|
465
|
+
else
|
466
|
+
config_rule_values = config.dig('company_rules', company_id) unless config.nil?
|
467
|
+
company_rules = get_applicable_company_rules(request_fields, request_body, config_rule_values)
|
468
|
+
new_response = apply_rules_list(company_rules, new_response, config_rule_values)
|
469
|
+
end
|
470
|
+
|
471
|
+
if user_id.nil?
|
472
|
+
user_rules = get_applicable_user_rules_for_unidentified_user(request_fields, request_body)
|
473
|
+
new_response = apply_rules_list(user_rules, new_response, nil)
|
474
|
+
else
|
475
|
+
config_rule_values = config.dig('user_rules', user_id) unless config.nil?
|
476
|
+
user_rules = get_applicable_user_rules(request_fields, request_body, config_rule_values)
|
477
|
+
new_response = apply_rules_list(user_rules, new_response, config_rule_values)
|
478
|
+
end
|
479
|
+
new_response
|
480
|
+
rescue StandardError => e
|
481
|
+
@moesif_helpers.log_debug 'error try to govern request:' + e.to_s + 'for event' + event_model.to_s
|
482
|
+
end
|
483
|
+
end
|
@@ -1,14 +1,65 @@
|
|
1
1
|
require 'time'
|
2
|
+
require 'rack'
|
2
3
|
|
3
4
|
class MoesifHelpers
|
5
|
+
def initialize(debug)
|
6
|
+
@debug = debug
|
7
|
+
end
|
4
8
|
|
5
|
-
|
6
|
-
|
9
|
+
def log_debug(message)
|
10
|
+
return unless @debug
|
11
|
+
|
12
|
+
puts("#{Time.now} [Moesif Middleware] PID #{Process.pid} TID #{Thread.current.object_id} #{message}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def decompress_gzip_body(moesif_api_response)
|
16
|
+
# Decompress gzip response body
|
17
|
+
|
18
|
+
# Check if the content-encoding header exist and is of type zip
|
19
|
+
if moesif_api_response.headers.key?(:content_encoding) && moesif_api_response.headers[:content_encoding].eql?('gzip')
|
20
|
+
|
21
|
+
# Create a GZipReader object to read data
|
22
|
+
gzip_reader = Zlib::GzipReader.new(StringIO.new(moesif_api_response.raw_body.to_s))
|
23
|
+
|
24
|
+
# Read the body
|
25
|
+
uncompressed_string = gzip_reader.read
|
26
|
+
|
27
|
+
# Return the parsed body
|
28
|
+
JSON.parse(uncompressed_string)
|
29
|
+
else
|
30
|
+
@moesif_helpers.log_debug 'Content Encoding is of type other than gzip, returning nil'
|
31
|
+
nil
|
7
32
|
end
|
33
|
+
rescue StandardError => e
|
34
|
+
@moesif_helpers.log_debug 'Error while decompressing the response body'
|
35
|
+
@moesif_helpers.log_debug e.to_s
|
36
|
+
nil
|
37
|
+
end
|
8
38
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
39
|
+
def format_replacement_body(replacement_body, original_body)
|
40
|
+
# replacement_body is an hash or array json in this case.
|
41
|
+
# but original body could be in chunks already. we want to follow suit.
|
42
|
+
return original_body if replacement_body.nil?
|
43
|
+
|
44
|
+
if original_body.instance_of?(Hash) || original_body.instance_of?(Array)
|
45
|
+
log_debug 'original_body is a hash or array return as is'
|
46
|
+
return replacement_body
|
47
|
+
end
|
48
|
+
|
49
|
+
if original_body.is_a? String
|
50
|
+
log_debug 'original_body is a string, return a string format'
|
51
|
+
return replacement_body.to_json.to_s
|
13
52
|
end
|
53
|
+
|
54
|
+
if original_body.respond_to?(:each) && original_body.respond_to?(:inject)
|
55
|
+
# we know it is an chunks
|
56
|
+
log_debug 'original_body respond to iterator, must likely chunks'
|
57
|
+
[replacement_body.to_json.to_s]
|
58
|
+
end
|
59
|
+
|
60
|
+
[replacement_body.to_json.to_s]
|
61
|
+
rescue StandardError => e
|
62
|
+
log_debug 'failed to convert replacement body ' + e.to_s
|
63
|
+
[replacement_body.to_json.to_s]
|
64
|
+
end
|
14
65
|
end
|