Skip to content

Commit 1b8ff4e

Browse files
authored
Merge pull request #394 from Optum/master
R0.8.0
2 parents c954829 + d9cfd56 commit 1b8ff4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+7190
-2666
lines changed

api-docs.yml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,70 @@ paths:
279279
items:
280280
$ref: '#/components/schemas/RRPair'
281281
description: successful response
282+
patch:
283+
tags:
284+
- services
285+
requestBody:
286+
description: An RR pair to add to this service
287+
content:
288+
application/json:
289+
schema:
290+
description: the service to update
291+
$ref: '#/components/schemas/RRPair'
292+
responses:
293+
200:
294+
description: successful response
295+
content:
296+
application/json:
297+
schema:
298+
type: array
299+
items:
300+
$ref: '#/components/schemas/RRPair'
301+
description: successful response
302+
/services/{id}/recorded:
303+
get:
304+
description: Gets all recorded pairs from Live Invocation recording for this service
305+
tags:
306+
- services
307+
responses:
308+
200:
309+
description: successful response
310+
content:
311+
application/json:
312+
schema:
313+
type: array
314+
items:
315+
$ref: '#/components/schemas/RRPair'
316+
description: successful response
317+
/services/{id}/recorded/{rrPaidId}:
318+
patch:
319+
description: Merges a recorded RR pair into the service
320+
tags:
321+
- services
322+
responses:
323+
200:
324+
description: successful response
325+
content:
326+
application/json:
327+
schema:
328+
type: array
329+
items:
330+
$ref: '#/components/schemas/RRPair'
331+
description: successful response
332+
delete:
333+
description: Deletes a recorded RR pair
334+
tags:
335+
- services
336+
responses:
337+
200:
338+
description: successful response
339+
content:
340+
application/json:
341+
schema:
342+
type: array
343+
items:
344+
$ref: '#/components/schemas/RRPair'
345+
description: successful response
282346

283347
/services/fromSpec/upload:
284348
post:
@@ -701,6 +765,55 @@ paths:
701765
items:
702766
$ref: '#/components/schemas/Recording'
703767
description: successful response
768+
/recording/{id}/stop:
769+
patch:
770+
description: Stops a recorder. A stopped recorder will not be deleted, but will not accept any more incoming requests.
771+
parameters:
772+
- name: id
773+
in: path
774+
description: id of Recording
775+
required: true
776+
style: simple
777+
explode: false
778+
schema:
779+
type: string
780+
tags:
781+
- recordings
782+
responses:
783+
200:
784+
description: successful response
785+
content:
786+
application/json:
787+
schema:
788+
type: array
789+
items:
790+
$ref: '#/components/schemas/Recording'
791+
description: successful response
792+
/recording/{id}/start:
793+
794+
patch:
795+
parameters:
796+
- name: id
797+
in: path
798+
description: id of Recording
799+
required: true
800+
style: simple
801+
explode: false
802+
schema:
803+
type: string
804+
description: Start a recorder, and make it accept incoming requests again.
805+
tags:
806+
- recordings
807+
responses:
808+
200:
809+
description: successful response
810+
content:
811+
application/json:
812+
schema:
813+
type: array
814+
items:
815+
$ref: '#/components/schemas/Recording'
816+
description: successful response
704817

705818
/systems:
706819
get:

assets/register.html

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ <h2>Register</h2>
7474
} if (errorHint == 'SE') {
7575
document.getElementById("errMsg").innerHTML = "<strong>*Oops! Something went wrong.</strong>";
7676
}
77-
var ck_email = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i
77+
var ck_uname = /^[a-zA-Z0-9]{4,10}$/;
78+
var ck_email = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
7879
var ck_pword = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,}$/;
7980
function validate(form) {
8081
var uname = form.username.value;
@@ -87,6 +88,9 @@ <h2>Register</h2>
8788
if (uname != '' && uname.length < 4) {
8889
errors[errors.length] = "Username length must be a minimum of 4 characteres.";
8990
}
91+
if (uname != '' && !ck_uname.test(uname)) {
92+
errors[errors.length] = "Username length must be between 4 & 10. Username shouldn't contain special Character and should start with alphanumeric.";
93+
}
9094
if (!ck_email.test(email)) {
9195
errors[errors.length] = "You must enter a valid email address.";
9296
}
@@ -100,7 +104,18 @@ <h2>Register</h2>
100104
reportErrors(errors);
101105
return false;
102106
}
103-
return true;
107+
var obj = { username: uname, mail: email, password: password };
108+
var formData = JSON.stringify(obj);
109+
var xhr = new XMLHttpRequest();
110+
xhr.onreadystatechange = function() {
111+
if (this.status == 302) {
112+
window.location.href=window.location.origin+xhr.getResponseHeader('redirectUrl');
113+
}
114+
};
115+
xhr.open('post', '/register', true);
116+
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
117+
xhr.send(formData);
118+
return false;
104119
}
105120
var errList = [];
106121
function reportErrors(errors) {
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
const xml2js = require('xml2js');
2+
const debug = require('debug')('matching');
3+
4+
/**
5+
* Applies all template options to a response string. E.g. puts out map values
6+
* @param {*} response
7+
* @param {*} templateOptions
8+
*/
9+
function applyTemplateOptionsToResponse(response,templateOptions){
10+
11+
if(templateOptions.map){
12+
for(let key in templateOptions.map){
13+
response = response.replace("{{" + key + "}}",templateOptions.map[key]);
14+
}
15+
}
16+
return response;
17+
}
18+
19+
20+
21+
/**
22+
* Merges a newly returned options object from processCondition() into the existing options
23+
* @param {*} oldOptions Old options- this gets mut'd!
24+
* @param {*} newOptions new options
25+
*/
26+
function mergeInOptions(oldOptions,newOptions){
27+
if(typeof newOptions == 'object'){
28+
for(let key1 in newOptions){
29+
if(oldOptions[key1]){
30+
if(Array.isArray(oldOptions[key1])){
31+
oldOptions[key1] = oldOptions[key1].concat(newOptions[key1]);
32+
}else if(typeof oldOptions == 'object'){
33+
for(let key2 in newOptions[key1]){
34+
oldOptions[key1][key2] = newOptions[key1][key2];
35+
}
36+
}else{
37+
oldOptions[key1] = newOptions[key1];
38+
}
39+
}else{
40+
oldOptions[key1] = newOptions[key1];
41+
}
42+
}
43+
}
44+
}
45+
46+
47+
/**
48+
* Given a condition string, process this condition.
49+
* @param {string} field Flattened field name (e.g. "params.person.firstName")
50+
* @param {string} conditionString The condition string (e.g. map:firstName)
51+
* @param {object} flatPayload Flattened payload
52+
* @return Returns either an object that contains new options for the template, OR false if the condition is considered failed. ONLY false is considered a failure- {} or null is a pass!
53+
*/
54+
function processCondition(field,conditionString,flatPayload){
55+
let split = conditionString.split(":",2);
56+
let condNum, payloadNum;
57+
try{
58+
switch(split[0]){
59+
case "map":
60+
var map = {};
61+
if(flatPayload[field] === undefined)
62+
return false;
63+
map[split[1]] = flatPayload[field] || '';
64+
return {map};
65+
case "lt":
66+
if(flatPayload[field] === undefined)
67+
return false;
68+
condNum = parseFloat(split[1]);
69+
payloadNum = parseFloat(flatPayload[field]);
70+
return payloadNum < condNum;
71+
case "gt":
72+
if(flatPayload[field] === undefined)
73+
return false;
74+
condNum = parseFloat(split[1]);
75+
payloadNum = parseFloat(flatPayload[field]);
76+
return payloadNum > condNum;
77+
78+
case "any":
79+
return flatPayload[field] !== undefined;
80+
case "regex":
81+
var reg = new RegExp(split[1]);
82+
return flatPayload[field].match(reg) !== null;
83+
default:
84+
return {};
85+
}
86+
}catch(e){
87+
console.log(e);
88+
debug(e);
89+
return false;
90+
}
91+
}
92+
93+
94+
/**
95+
* Iterates through multiple ; separated conditions
96+
* @param {*} field
97+
* @param {*} conditionString
98+
* @param {*} flatPayload
99+
*/
100+
function preProcessCondition(field,conditionString,flatPayload){
101+
if(typeof conditionString != "string"){
102+
return false;
103+
}
104+
var split = conditionString.split(";");
105+
var opts = {};
106+
for(let splString of split){
107+
let newOpts = processCondition(field,splString,flatPayload);
108+
if(newOpts === false)
109+
return false;
110+
mergeInOptions(opts,newOpts);
111+
}
112+
return opts;
113+
}
114+
115+
116+
/**
117+
* Tests a payload against a request using a template. Returns any template options that were parsed (e.g. mapping vars)
118+
* @param {*} flatTemplate The flattened template
119+
* @param {*} rrpair RR Pair in question
120+
* @param {*} flatPayload Flattened payload
121+
* @param {*} flatReqData Flattened reqData from RR pair
122+
* @param {*} path Path of this req (for debug logging)
123+
*/
124+
function matchOnTemplate(flatTemplate,rrpair,flatPayload,flatReqData,path){
125+
var returnOptions = {};
126+
const trimmedPayload = {}; const trimmedReqData = {};
127+
var hasBlank = false;
128+
for (let field in flatTemplate) {
129+
130+
//If we have a condition here, handle its special properties
131+
if(flatTemplate[field]){
132+
var ret = preProcessCondition(field,flatTemplate[field],flatPayload);
133+
if(ret !== false){
134+
mergeInOptions(returnOptions,ret);
135+
}else{
136+
return false;
137+
}
138+
//Otherwise add this to the list to get literal equals'd
139+
}else{
140+
hasBlank = true;
141+
trimmedPayload[field] = flatPayload[field];
142+
trimmedReqData[field] = flatReqData[field];
143+
}
144+
}
145+
146+
logEvent(path, rrpair.label, 'received payload (from template): ' + JSON.stringify(trimmedPayload, null, 2));
147+
logEvent(path, rrpair.label, 'expected payload (from template): ' + JSON.stringify(trimmedReqData, null, 2));
148+
149+
if(hasBlank && !deepEquals(trimmedPayload, trimmedReqData)){
150+
return false;
151+
}
152+
153+
// make sure we're not comparing {} == {}
154+
if (hasBlank && JSON.stringify(trimmedPayload) === '{}') {
155+
return false;
156+
}
157+
return returnOptions;
158+
}
159+
160+
161+
/**
162+
* Given a template and the payload type, parse this template and flatten it.
163+
* @param {*} template
164+
* @param {*} payloadType
165+
* @return Flattened template, or false if parsing fails.
166+
*/
167+
function parseAndFlattenTemplate(template,payloadType){
168+
if (payloadType === 'XML') {
169+
let ret = false;
170+
xml2js.parseString(template, function(err, xmlTemplate) {
171+
if (err) {
172+
logEvent(err);
173+
ret = false;
174+
}
175+
ret = flattenObject(xmlTemplate);
176+
});
177+
return ret;
178+
}
179+
else if (payloadType === 'JSON') {
180+
try {
181+
return flattenObject(JSON.parse(template));
182+
}
183+
catch(e) {
184+
debug(e);
185+
return false;
186+
}
187+
}else{
188+
return false;
189+
}
190+
191+
}
192+
193+
194+
module.exports = {
195+
matchOnTemplate : matchOnTemplate,
196+
applyTemplateOptionsToResponse:applyTemplateOptionsToResponse,
197+
preProcessCondition:preProcessCondition,
198+
parseAndFlattenTemplate: parseAndFlattenTemplate
199+
}

0 commit comments

Comments
 (0)