Skip to content

Commit

Permalink
Merge pull request #394 from Optum/master
Browse files Browse the repository at this point in the history
R0.8.0
  • Loading branch information
jdweeks authored Mar 11, 2019
2 parents c954829 + d9cfd56 commit 1b8ff4e
Show file tree
Hide file tree
Showing 60 changed files with 7,190 additions and 2,666 deletions.
113 changes: 113 additions & 0 deletions api-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,70 @@ paths:
items:
$ref: '#/components/schemas/RRPair'
description: successful response
patch:
tags:
- services
requestBody:
description: An RR pair to add to this service
content:
application/json:
schema:
description: the service to update
$ref: '#/components/schemas/RRPair'
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/RRPair'
description: successful response
/services/{id}/recorded:
get:
description: Gets all recorded pairs from Live Invocation recording for this service
tags:
- services
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/RRPair'
description: successful response
/services/{id}/recorded/{rrPaidId}:
patch:
description: Merges a recorded RR pair into the service
tags:
- services
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/RRPair'
description: successful response
delete:
description: Deletes a recorded RR pair
tags:
- services
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/RRPair'
description: successful response

/services/fromSpec/upload:
post:
Expand Down Expand Up @@ -701,6 +765,55 @@ paths:
items:
$ref: '#/components/schemas/Recording'
description: successful response
/recording/{id}/stop:
patch:
description: Stops a recorder. A stopped recorder will not be deleted, but will not accept any more incoming requests.
parameters:
- name: id
in: path
description: id of Recording
required: true
style: simple
explode: false
schema:
type: string
tags:
- recordings
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Recording'
description: successful response
/recording/{id}/start:

patch:
parameters:
- name: id
in: path
description: id of Recording
required: true
style: simple
explode: false
schema:
type: string
description: Start a recorder, and make it accept incoming requests again.
tags:
- recordings
responses:
200:
description: successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Recording'
description: successful response

/systems:
get:
Expand Down
19 changes: 17 additions & 2 deletions assets/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ <h2>Register</h2>
} if (errorHint == 'SE') {
document.getElementById("errMsg").innerHTML = "<strong>*Oops! Something went wrong.</strong>";
}
var ck_email = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i
var ck_uname = /^[a-zA-Z0-9]{4,10}$/;
var ck_email = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
var ck_pword = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,}$/;
function validate(form) {
var uname = form.username.value;
Expand All @@ -87,6 +88,9 @@ <h2>Register</h2>
if (uname != '' && uname.length < 4) {
errors[errors.length] = "Username length must be a minimum of 4 characteres.";
}
if (uname != '' && !ck_uname.test(uname)) {
errors[errors.length] = "Username length must be between 4 & 10. Username shouldn't contain special Character and should start with alphanumeric.";
}
if (!ck_email.test(email)) {
errors[errors.length] = "You must enter a valid email address.";
}
Expand All @@ -100,7 +104,18 @@ <h2>Register</h2>
reportErrors(errors);
return false;
}
return true;
var obj = { username: uname, mail: email, password: password };
var formData = JSON.stringify(obj);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.status == 302) {
window.location.href=window.location.origin+xhr.getResponseHeader('redirectUrl');
}
};
xhr.open('post', '/register', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(formData);
return false;
}
var errList = [];
function reportErrors(errors) {
Expand Down
199 changes: 199 additions & 0 deletions controllers/matchTemplateController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
const xml2js = require('xml2js');
const debug = require('debug')('matching');

/**
* Applies all template options to a response string. E.g. puts out map values
* @param {*} response
* @param {*} templateOptions
*/
function applyTemplateOptionsToResponse(response,templateOptions){

if(templateOptions.map){
for(let key in templateOptions.map){
response = response.replace("{{" + key + "}}",templateOptions.map[key]);
}
}
return response;
}



/**
* Merges a newly returned options object from processCondition() into the existing options
* @param {*} oldOptions Old options- this gets mut'd!
* @param {*} newOptions new options
*/
function mergeInOptions(oldOptions,newOptions){
if(typeof newOptions == 'object'){
for(let key1 in newOptions){
if(oldOptions[key1]){
if(Array.isArray(oldOptions[key1])){
oldOptions[key1] = oldOptions[key1].concat(newOptions[key1]);
}else if(typeof oldOptions == 'object'){
for(let key2 in newOptions[key1]){
oldOptions[key1][key2] = newOptions[key1][key2];
}
}else{
oldOptions[key1] = newOptions[key1];
}
}else{
oldOptions[key1] = newOptions[key1];
}
}
}
}


/**
* Given a condition string, process this condition.
* @param {string} field Flattened field name (e.g. "params.person.firstName")
* @param {string} conditionString The condition string (e.g. map:firstName)
* @param {object} flatPayload Flattened payload
* @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!
*/
function processCondition(field,conditionString,flatPayload){
let split = conditionString.split(":",2);
let condNum, payloadNum;
try{
switch(split[0]){
case "map":
var map = {};
if(flatPayload[field] === undefined)
return false;
map[split[1]] = flatPayload[field] || '';
return {map};
case "lt":
if(flatPayload[field] === undefined)
return false;
condNum = parseFloat(split[1]);
payloadNum = parseFloat(flatPayload[field]);
return payloadNum < condNum;
case "gt":
if(flatPayload[field] === undefined)
return false;
condNum = parseFloat(split[1]);
payloadNum = parseFloat(flatPayload[field]);
return payloadNum > condNum;

case "any":
return flatPayload[field] !== undefined;
case "regex":
var reg = new RegExp(split[1]);
return flatPayload[field].match(reg) !== null;
default:
return {};
}
}catch(e){
console.log(e);
debug(e);
return false;
}
}


/**
* Iterates through multiple ; separated conditions
* @param {*} field
* @param {*} conditionString
* @param {*} flatPayload
*/
function preProcessCondition(field,conditionString,flatPayload){
if(typeof conditionString != "string"){
return false;
}
var split = conditionString.split(";");
var opts = {};
for(let splString of split){
let newOpts = processCondition(field,splString,flatPayload);
if(newOpts === false)
return false;
mergeInOptions(opts,newOpts);
}
return opts;
}


/**
* Tests a payload against a request using a template. Returns any template options that were parsed (e.g. mapping vars)
* @param {*} flatTemplate The flattened template
* @param {*} rrpair RR Pair in question
* @param {*} flatPayload Flattened payload
* @param {*} flatReqData Flattened reqData from RR pair
* @param {*} path Path of this req (for debug logging)
*/
function matchOnTemplate(flatTemplate,rrpair,flatPayload,flatReqData,path){
var returnOptions = {};
const trimmedPayload = {}; const trimmedReqData = {};
var hasBlank = false;
for (let field in flatTemplate) {

//If we have a condition here, handle its special properties
if(flatTemplate[field]){
var ret = preProcessCondition(field,flatTemplate[field],flatPayload);
if(ret !== false){
mergeInOptions(returnOptions,ret);
}else{
return false;
}
//Otherwise add this to the list to get literal equals'd
}else{
hasBlank = true;
trimmedPayload[field] = flatPayload[field];
trimmedReqData[field] = flatReqData[field];
}
}

logEvent(path, rrpair.label, 'received payload (from template): ' + JSON.stringify(trimmedPayload, null, 2));
logEvent(path, rrpair.label, 'expected payload (from template): ' + JSON.stringify(trimmedReqData, null, 2));

if(hasBlank && !deepEquals(trimmedPayload, trimmedReqData)){
return false;
}

// make sure we're not comparing {} == {}
if (hasBlank && JSON.stringify(trimmedPayload) === '{}') {
return false;
}
return returnOptions;
}


/**
* Given a template and the payload type, parse this template and flatten it.
* @param {*} template
* @param {*} payloadType
* @return Flattened template, or false if parsing fails.
*/
function parseAndFlattenTemplate(template,payloadType){
if (payloadType === 'XML') {
let ret = false;
xml2js.parseString(template, function(err, xmlTemplate) {
if (err) {
logEvent(err);
ret = false;
}
ret = flattenObject(xmlTemplate);
});
return ret;
}
else if (payloadType === 'JSON') {
try {
return flattenObject(JSON.parse(template));
}
catch(e) {
debug(e);
return false;
}
}else{
return false;
}

}


module.exports = {
matchOnTemplate : matchOnTemplate,
applyTemplateOptionsToResponse:applyTemplateOptionsToResponse,
preProcessCondition:preProcessCondition,
parseAndFlattenTemplate: parseAndFlattenTemplate
}
Loading

0 comments on commit 1b8ff4e

Please sign in to comment.