moesif_rack 1.4.19 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/moesif_rack/app_config.rb +76 -113
- data/lib/moesif_rack/client_ip.rb +61 -102
- data/lib/moesif_rack/governance_rules.rb +480 -0
- data/lib/moesif_rack/moesif_helpers.rb +33 -6
- data/lib/moesif_rack/moesif_middleware.rb +159 -148
- 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 +57 -107
- data/moesif_capture_outgoing/httplog.rb +2 -2
- data/test/config_example.json +1473 -0
- data/test/govrule_example.json +20 -0
- data/test/test_governance_rules.rb +213 -0
- data/test/{moesif_rack_test.rb → test_moesif_rack.rb} +18 -16
- metadata +30 -6
@@ -0,0 +1,480 @@
|
|
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, _context = api_controller.get_rules
|
113
|
+
|
114
|
+
generate_rules_caching(rules)
|
115
|
+
rescue MoesifApi::APIException => e
|
116
|
+
if e.response_code.between?(401, 403)
|
117
|
+
@moesif_helpers.log_debug 'Unauthorized access getting application configuration. Please check your Appplication Id.'
|
118
|
+
end
|
119
|
+
@moesif_helpers.log_debug 'Error getting application configuration, with status code:'
|
120
|
+
@moesif_helpers.log_debug e.response_code
|
121
|
+
rescue StandardError => e
|
122
|
+
@moesif_helpers.log_debug e.to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
def generate_rules_caching(rules)
|
126
|
+
@rules = rules
|
127
|
+
@regex_rules = []
|
128
|
+
@user_rules = {}
|
129
|
+
@unidentified_user_rules = []
|
130
|
+
@company_rules = {}
|
131
|
+
@unidentified_company_rules = []
|
132
|
+
if !rules.nil? && !rules.empty?
|
133
|
+
rules.each do |rule|
|
134
|
+
rule_id = rule['_id']
|
135
|
+
case rule['type']
|
136
|
+
when RULE_TYPES::USER
|
137
|
+
@user_rules[rule_id] = rule
|
138
|
+
@unidentified_user_rules.push(rule) if rule.fetch('applied_to_unidentified', false)
|
139
|
+
when RULE_TYPES::COMPANY
|
140
|
+
@company_rules[rule_id] = rule
|
141
|
+
@unidentified_company_rules.push(rule) if rule.fetch('applied_to_unidentified', false)
|
142
|
+
when RULE_TYPES::REGEX
|
143
|
+
@regex_rules.push(rule)
|
144
|
+
else
|
145
|
+
@moesif_helpers.log_debug 'rule type not found for id ' + rule_id
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
# @moesif_helpers.log_debug('user_rules processed ' + @user_rules.to_s)
|
150
|
+
# @moesif_helpers.log_debug('unidentified_user_rules' + @unidentified_user_rules.to_s);
|
151
|
+
# @moesif_helpers.log_debug('regex_rules' + @regex_rules.to_s);
|
152
|
+
rescue StandardError => e
|
153
|
+
@moesif_helpers.log_debug e.to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
def has_rules
|
157
|
+
return false if @rules.nil?
|
158
|
+
|
159
|
+
@rules.length >= 1
|
160
|
+
end
|
161
|
+
|
162
|
+
# TODO
|
163
|
+
def convert_uri_to_route(uri)
|
164
|
+
# TODO: for now just return uri
|
165
|
+
uri
|
166
|
+
end
|
167
|
+
|
168
|
+
def prepare_request_fields_based_on_regex_config(_env, event_model, request_body)
|
169
|
+
operation_name = request_body.fetch('operationName', nil) unless request_body.nil?
|
170
|
+
{
|
171
|
+
'request.verb' => event_model.request.verb,
|
172
|
+
'request.ip_address' => event_model.request.ip_address,
|
173
|
+
'request.route' => convert_uri_to_route(event_model.request.uri),
|
174
|
+
'request.body.operationName' => operation_name
|
175
|
+
}
|
176
|
+
end
|
177
|
+
|
178
|
+
def get_field_value_for_path(path, request_fields, request_body)
|
179
|
+
if path && path.start_with?('request.body.') && request_body
|
180
|
+
body_key = path.sub('request.body.', '')
|
181
|
+
return request_body.fetch(body_key, nil)
|
182
|
+
end
|
183
|
+
request_fields.fetch(path, nil)
|
184
|
+
end
|
185
|
+
|
186
|
+
def check_request_with_regex_match(regex_configs, request_fields, request_body)
|
187
|
+
# since there is no regex config, customer must only care about cohort criteria, we assume regex matched
|
188
|
+
return true if regex_configs.nil? || regex_configs.empty?
|
189
|
+
|
190
|
+
array_to_or = regex_configs.map do |or_group_of_regex_rule|
|
191
|
+
conditions = or_group_of_regex_rule.fetch('conditions', [])
|
192
|
+
|
193
|
+
conditions.reduce(true) do |all_match, condition|
|
194
|
+
return false unless all_match
|
195
|
+
|
196
|
+
path = condition.fetch('path', nil)
|
197
|
+
|
198
|
+
field_value = get_field_value_for_path(path, request_fields, request_body)
|
199
|
+
reg_ex = Regexp.new condition.fetch('value', nil)
|
200
|
+
|
201
|
+
if path.nil? || field_value.nil? || reg_ex.nil?
|
202
|
+
false
|
203
|
+
else
|
204
|
+
field_value =~ reg_ex
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
array_to_or.reduce(false) { |anysofar, curr| anysofar || curr }
|
210
|
+
rescue StandardError => e
|
211
|
+
@moesif_helpers.log_debug('checking regex failed, possible malformed regex ' + e.to_s)
|
212
|
+
false
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_applicable_regex_rules(request_fields, request_body)
|
216
|
+
@regex_rules.select do |rule|
|
217
|
+
regex_configs = rule['regex_config']
|
218
|
+
@moesif_helpers.log_debug('checking regex_configs')
|
219
|
+
@moesif_helpers.log_debug(regex_configs.to_s)
|
220
|
+
if regex_configs.nil?
|
221
|
+
true
|
222
|
+
else
|
223
|
+
@moesif_helpers.log_debug('checking regex_configs')
|
224
|
+
@moesif_helpers.log_debug(regex_configs.to_s)
|
225
|
+
check_request_with_regex_match(regex_configs, request_fields, request_body)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def get_applicable_user_rules_for_unidentified_user(request_fields, request_body)
|
231
|
+
@unidentified_user_rules.select do |rule|
|
232
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
233
|
+
|
234
|
+
@moesif_helpers.log_debug('regexmatched for unidetnfied_user rule ' + rule.to_json) if regex_matched
|
235
|
+
regex_matched
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
240
|
+
applicable_rules_list = []
|
241
|
+
|
242
|
+
rule_ids_hash_that_is_in_cohort = {}
|
243
|
+
|
244
|
+
# handle uses where user_id is in ARLEADY in the cohort of the rules.
|
245
|
+
# if user is in a cohorot of the rule, it will come from config user rule values array, which is
|
246
|
+
# config.user_rules.user_id.[]
|
247
|
+
unless config_user_rules_values.nil?
|
248
|
+
config_user_rules_values.each do |entry|
|
249
|
+
rule_id = entry['rules']
|
250
|
+
# this is user_id matched cohort set in the rule.
|
251
|
+
rule_ids_hash_that_is_in_cohort[rule_id] = true unless rule_id.nil?
|
252
|
+
# rule_ids_hash_that_I_am_in_cohot{629847be77e75b13635aa868: true}
|
253
|
+
|
254
|
+
found_rule = @user_rules[rule_id]
|
255
|
+
if found_rule.nil?
|
256
|
+
@moesif_helpers.log_debug('rule for not foun for ' + rule_id.to_s)
|
257
|
+
next
|
258
|
+
end
|
259
|
+
|
260
|
+
@moesif_helpers.log_debug('found rule in cached user rules' + rule_id)
|
261
|
+
|
262
|
+
regex_matched = check_request_with_regex_match(found_rule.fetch('regex_config', nil), request_fields,
|
263
|
+
request_body)
|
264
|
+
|
265
|
+
unless regex_matched
|
266
|
+
@moesif_helpers.log_debug('regex not matched, skipping ' + rule_id.to_s)
|
267
|
+
next
|
268
|
+
end
|
269
|
+
|
270
|
+
if found_rule['applied_to'] == 'not_matching'
|
271
|
+
# mean not matching, i.e. we do not apply the rule since current user is in cohort.
|
272
|
+
@moesif_helpers.log_debug('applied to is not matching to users in this cohort, so skipping add this rule')
|
273
|
+
else
|
274
|
+
# since applied_to is matching, we are in the cohort, we apply the rule by adding it to the list.
|
275
|
+
@moesif_helpers.log_debug('applied to is matching' + found_rule['applied_to'])
|
276
|
+
applicable_rules_list.push(found_rule)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# now user id is NOT associated with any cohort rule so we have to add user rules that is "Not matching"
|
282
|
+
@user_rules.each do |_rule_id, rule|
|
283
|
+
# we want to apply to any "not_matching" rules.
|
284
|
+
# we want to make sure user is not in the cohort of the rule.
|
285
|
+
next unless rule['applied_to'] == 'not_matching' && !rule_ids_hash_that_is_in_cohort[_rule_id]
|
286
|
+
|
287
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
288
|
+
applicable_rules_list.push(rule) if regex_matched
|
289
|
+
end
|
290
|
+
|
291
|
+
applicable_rules_list
|
292
|
+
end
|
293
|
+
|
294
|
+
def get_applicable_company_rules_for_unidentified_company(request_fields, request_body)
|
295
|
+
@unidentified_company_rules.select do |rule|
|
296
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
297
|
+
|
298
|
+
regex_matched
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def get_applicable_company_rules(request_fields, request_body, config_company_rules_values)
|
303
|
+
applicable_rules_list = []
|
304
|
+
|
305
|
+
@moesif_helpers.log_debug('get applicable company rules for identifed company using these config values: ' + config_company_rules_values.to_s)
|
306
|
+
|
307
|
+
rule_ids_hash_that_is_in_cohort = {}
|
308
|
+
|
309
|
+
# handle where company_id is in the cohort of the rules.
|
310
|
+
unless config_company_rules_values.nil?
|
311
|
+
config_company_rules_values.each do |entry|
|
312
|
+
rule_id = entry['rules']
|
313
|
+
# this is company_id matched cohort set in the rule.
|
314
|
+
rule_ids_hash_that_is_in_cohort[rule_id] = true unless rule_id.nil?
|
315
|
+
|
316
|
+
found_rule = @company_rules[rule_id]
|
317
|
+
|
318
|
+
if found_rule.nil?
|
319
|
+
@moesif_helpers.log_debug('company rule for not found for ' + rule_id.to_s)
|
320
|
+
next
|
321
|
+
end
|
322
|
+
|
323
|
+
regex_matched = check_request_with_regex_match(found_rule.fetch('regex_config', nil), request_fields,
|
324
|
+
request_body)
|
325
|
+
|
326
|
+
unless regex_matched
|
327
|
+
@moesif_helpers.log_debug('regex not matched, skipping ' + rule_id.to_s)
|
328
|
+
next
|
329
|
+
end
|
330
|
+
|
331
|
+
if found_rule['applied_to'] == 'not_matching'
|
332
|
+
# mean not matching, i.e. we do not apply the rule since current user is in cohort.
|
333
|
+
@moesif_helpers.log_debug('applied to is companies not in this cohort, so skipping add this rule')
|
334
|
+
else
|
335
|
+
# since applied_to is matching, we are in the cohort, we apply the rule by adding it to the list.
|
336
|
+
@moesif_helpers.log_debug('applied to is matching' + found_rule['applied_to'])
|
337
|
+
applicable_rules_list.push(found_rule)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# handle is NOT in the cohort of rule so we have to apply rules that are "Not matching"
|
343
|
+
@company_rules.each do |_rule_id, rule|
|
344
|
+
# we want to apply to any "not_matching" rules.
|
345
|
+
next unless rule['applied_to'] == 'not_matching' && !rule_ids_hash_that_is_in_cohort[_rule_id]
|
346
|
+
|
347
|
+
regex_matched = check_request_with_regex_match(rule.fetch('regex_config', nil), request_fields, request_body)
|
348
|
+
applicable_rules_list.push(rule) if regex_matched
|
349
|
+
end
|
350
|
+
applicable_rules_list
|
351
|
+
end
|
352
|
+
|
353
|
+
def replace_merge_tag_values(template_obj_or_val, mergetag_values, variables_from_rules)
|
354
|
+
# take the template, either headers or body, and replace with mergetag_values
|
355
|
+
# recursively
|
356
|
+
return template_obj_or_val if variables_from_rules.nil? || variables_from_rules.empty?
|
357
|
+
|
358
|
+
if template_obj_or_val.nil?
|
359
|
+
template_obj_or_val
|
360
|
+
elsif template_obj_or_val.is_a?(String)
|
361
|
+
temp_val = template_obj_or_val
|
362
|
+
variables_from_rules.each do |variable|
|
363
|
+
variable_name = variable['name']
|
364
|
+
variable_value = mergetag_values.nil? ? 'UNKNOWN' : mergetag_values.fetch(variable_name, 'UNKNOWN')
|
365
|
+
temp_val = temp_val.sub('{{' + variable_name + '}}', variable_value)
|
366
|
+
end
|
367
|
+
temp_val
|
368
|
+
elsif template_obj_or_val.is_a?(Array)
|
369
|
+
tempplate_obj_or_val.map { |entry| replace_merge_tag_values(entry, mergetag_values, variables_from_rules) }
|
370
|
+
elsif template_obj_or_val.is_a?(Hash)
|
371
|
+
result_hash = {}
|
372
|
+
template_obj_or_val.each do |key, entry|
|
373
|
+
result_hash[key] = replace_merge_tag_values(entry, mergetag_values, variables_from_rules)
|
374
|
+
end
|
375
|
+
result_hash
|
376
|
+
else
|
377
|
+
template_obj_or_val
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
def modify_response_for_applicable_rule(rule, response, mergetag_values)
|
382
|
+
# For matched rule, we can now modify the response
|
383
|
+
# response is a hash with :status, :headers and :body or nil
|
384
|
+
@moesif_helpers.log_debug('about to modify response ' + mergetag_values.to_s)
|
385
|
+
new_headers = response[:headers].clone
|
386
|
+
rule_variables = rule['variables']
|
387
|
+
# headers are always merged togethe
|
388
|
+
rule_headers = replace_merge_tag_values(rule.dig('response', 'headers'), mergetag_values, rule_variables)
|
389
|
+
# insersion of rule headers, we do not replace all headers.
|
390
|
+
rule_headers.each { |key, entry| new_headers[key] = entry } unless rule_headers.nil?
|
391
|
+
|
392
|
+
response[:headers] = new_headers
|
393
|
+
|
394
|
+
# only replace status and body if it is blocking.
|
395
|
+
if rule['block']
|
396
|
+
@moesif_helpers.log_debug('rule is block' + rule.to_s)
|
397
|
+
response[:status] = rule.dig('response', 'status') || response[:status]
|
398
|
+
new_body = replace_merge_tag_values(rule.dig('response', 'body'), mergetag_values, rule_variables)
|
399
|
+
response[:body] = new_body
|
400
|
+
response[:block_rule_id] = rule['_id']
|
401
|
+
end
|
402
|
+
|
403
|
+
response
|
404
|
+
rescue StandardError => e
|
405
|
+
@moesif_helpers.log_debug('failed to apply rule ' + rule.to_json + ' for ' + response.to_s + ' error: ' + e.to_s)
|
406
|
+
response
|
407
|
+
end
|
408
|
+
|
409
|
+
def apply_rules_list(applicable_rules, response, config_rule_values)
|
410
|
+
return response if applicable_rules.nil? || applicable_rules.empty?
|
411
|
+
|
412
|
+
# config_rule_values if exists should be from config for a particular user for an list of rules.
|
413
|
+
# [
|
414
|
+
# {
|
415
|
+
# "rules": "629847be77e75b13635aa868",
|
416
|
+
# "values": {
|
417
|
+
# "1": "viewer-Float(online)-nd",
|
418
|
+
# "2": "[\"62984b17715c450ba6ad46b2\"]",
|
419
|
+
# "3": "[\"user cohort created at 6/1, 10:31 PM\"]",
|
420
|
+
# "4": "viewer-Float(online)-nd"
|
421
|
+
# }
|
422
|
+
# }
|
423
|
+
# ]
|
424
|
+
|
425
|
+
applicable_rules.reduce(response) do |prev_response, rule|
|
426
|
+
unless config_rule_values.nil?
|
427
|
+
found_rule_value_pair = config_rule_values.find { |rule_value_pair| rule_value_pair['rules'] == rule['_id'] }
|
428
|
+
mergetag_values = found_rule_value_pair['values'] unless found_rule_value_pair.nil?
|
429
|
+
end
|
430
|
+
modify_response_for_applicable_rule(rule, prev_response, mergetag_values)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def govern_request(config, env, event_model, status, headers, body)
|
435
|
+
# we can skip if rules does not exist or config does not exist
|
436
|
+
return if @rules.nil? || @rules.empty?
|
437
|
+
|
438
|
+
if event_model
|
439
|
+
request_body = event_model.request.body
|
440
|
+
request_fields = prepare_request_fields_based_on_regex_config(env, event_model, request_body)
|
441
|
+
end
|
442
|
+
|
443
|
+
user_id = event_model.user_id
|
444
|
+
company_id = event_model.company_id
|
445
|
+
|
446
|
+
# apply in reverse order of priority.
|
447
|
+
# Priority is user rule, company rule, and regex.
|
448
|
+
# by apply in reverse order, the last rule become highest priority.
|
449
|
+
|
450
|
+
new_response = {
|
451
|
+
status: status,
|
452
|
+
headers: headers,
|
453
|
+
body: body
|
454
|
+
}
|
455
|
+
|
456
|
+
applicable_regex_rules = get_applicable_regex_rules(request_fields, request_body)
|
457
|
+
new_response = apply_rules_list(applicable_regex_rules, new_response, nil)
|
458
|
+
|
459
|
+
if company_id.nil?
|
460
|
+
company_rules = get_applicable_company_rules_for_unidentified_company(request_fields, request_body)
|
461
|
+
new_response = apply_rules_list(company_rules, new_response, nil)
|
462
|
+
else
|
463
|
+
config_rule_values = config.dig('company_rules', company_id) unless config.nil?
|
464
|
+
company_rules = get_applicable_company_rules(request_fields, request_body, config_rule_values)
|
465
|
+
new_response = apply_rules_list(company_rules, new_response, config_rule_values)
|
466
|
+
end
|
467
|
+
|
468
|
+
if user_id.nil?
|
469
|
+
user_rules = get_applicable_user_rules_for_unidentified_user(request_fields, request_body)
|
470
|
+
new_response = apply_rules_list(user_rules, new_response, nil)
|
471
|
+
else
|
472
|
+
config_rule_values = config.dig('user_rules', user_id) unless config.nil?
|
473
|
+
user_rules = get_applicable_user_rules(request_fields, request_body, config_rule_values)
|
474
|
+
new_response = apply_rules_list(user_rules, new_response, config_rule_values)
|
475
|
+
end
|
476
|
+
new_response
|
477
|
+
rescue StandardError => e
|
478
|
+
@moesif_helpers.log_debug 'error try to govern request:' + e.to_s + 'for event' + event_model.to_s
|
479
|
+
end
|
480
|
+
end
|
@@ -1,14 +1,41 @@
|
|
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 format_replacement_body(replacement_body, original_body)
|
16
|
+
# replacement_body is an hash or array json in this case.
|
17
|
+
# but original body could be in chunks already. we want to follow suit.
|
18
|
+
return original_body if replacement_body.nil?
|
19
|
+
|
20
|
+
if original_body.instance_of?(Hash) || original_body.instance_of?(Array)
|
21
|
+
log_debug 'original_body is a hash or array return as is'
|
22
|
+
return replacement_body
|
7
23
|
end
|
8
24
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
25
|
+
if original_body.is_a? String
|
26
|
+
log_debug 'original_body is a string, return a string format'
|
27
|
+
return replacement_body.to_json.to_s
|
13
28
|
end
|
29
|
+
|
30
|
+
if original_body.respond_to?(:each) && original_body.respond_to?(:inject)
|
31
|
+
# we know it is an chunks
|
32
|
+
log_debug 'original_body respond to iterator, must likely chunks'
|
33
|
+
[replacement_body.to_json.to_s]
|
34
|
+
end
|
35
|
+
|
36
|
+
[replacement_body.to_json.to_s]
|
37
|
+
rescue StandardError => e
|
38
|
+
log_debug 'failed to convert replacement body ' + e.to_s
|
39
|
+
[replacement_body.to_json.to_s]
|
40
|
+
end
|
14
41
|
end
|