diff --git a/api-docs.yml b/api-docs.yml index 85097178..e1f5db50 100644 --- a/api-docs.yml +++ b/api-docs.yml @@ -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: @@ -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: diff --git a/assets/register.html b/assets/register.html index c9d89c1e..485fef06 100644 --- a/assets/register.html +++ b/assets/register.html @@ -74,7 +74,8 @@

Register

} if (errorHint == 'SE') { document.getElementById("errMsg").innerHTML = "*Oops! Something went wrong."; } - 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; @@ -87,6 +88,9 @@

Register

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."; } @@ -100,7 +104,18 @@

Register

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) { diff --git a/controllers/matchTemplateController.js b/controllers/matchTemplateController.js new file mode 100644 index 00000000..eb500a40 --- /dev/null +++ b/controllers/matchTemplateController.js @@ -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 +} \ No newline at end of file diff --git a/controllers/recorderController.js b/controllers/recorderController.js index a32d4e0e..65995ed2 100644 --- a/controllers/recorderController.js +++ b/controllers/recorderController.js @@ -2,59 +2,138 @@ const requestNode = require('request'); const Recording = require('../models/http/Recording'); const routing = require('../routes/recording'); const manager = require('../lib/pm2/manager'); +const constants = require('../lib/util/constants'); var activeRecorders = {}; -function escapeRegExp(string) { - return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string - } + /** * Recorder object * * This object is created whenever a new recording session is started. the recording router will route all appropriate transactions to this object + * Can instead pass an ID to a Recording document to 'name', and create an instance based on that recorder. */ -var Recorder = function(name,path,sut,remoteHost,remotePort,protocol,headerMask,ssl){ - this.path = path; - - //Ensure path starts with / - if(this.path.substring(0,1) != "/") - this.path = "/" + this.path; - - this.model = Recording.create({ - sut : {name:sut}, - path : path, - remoteHost : remoteHost, - protocol : protocol || 'REST', - remotePort : remotePort || 80, - headerMask : headerMask || ['Content-Type'], - service : { - basePath : path.substring(1), - sut:{name:sut}, - name:name, - type:protocol - }, - name: name, - ssl:ssl - },(function(err,newModel){ - this.model = newModel; - - if(!(this.model.headerMask)) - this.model.headerMask = []; - - if(!(this.model.headerMask['Content-Type'])) - this.model.headerMask.push('Content-Type'); +var Recorder = function(name,path,sut,remoteHost,remotePort,protocol,headerMask,ssl,filters,creator, rsp){ - this.model.save(function(err){ - if(err) console.log(err); + var rec = this; + + //If passed ID for Recording document... + if(arguments.length == 1){ + rec.model = new Promise(function(resolve,reject){ + Recording.findById(name,function(err,doc){ + if(err){ + reject(err); + }else{ + doc.running = true; + doc.save(function(err,doc){ + if(err){ + reject(err); + }else if(doc){ + rec.model = doc; + syncWorkersToNewRecorder(rec); + resolve(doc); + }else{ + reject(new Error("doc save failed")); + } + }); + } + + }); }); - syncWorkersToNewRecorder(this); - }).bind(this)); + }else{ + + this.path = path; + + //Ensure path starts with / + if(this.path.substring(0,1) != "/") + this.path = "/" + this.path; + + //Make sure it starts with ONLY one / + this.path.replace(/^\/+/,"/"); + this.model = Recording.create({ + sut : {name:sut}, + path : path, + remoteHost : remoteHost, + protocol : protocol || 'REST', + remotePort : remotePort || 80, + headerMask : headerMask || ['Content-Type'], + service : { + basePath : path, + sut:{name:sut}, + name:name, + type:protocol + }, + name: name, + ssl:ssl, + filters:filters + },(function(err,newModel){ + if(err) { + handleBackEndValidationsAndErrors(err, rsp); + return; + } + this.model = newModel; + + if(!(this.model.headerMask)) + this.model.headerMask = []; + + if(!(this.model.headerMask['Content-Type'])) + this.model.headerMask.push('Content-Type'); + + this.model.save(function(err, recording){ + if(err) { + handleBackEndValidationsAndErrors(err, rsp); + return; + } + }); + syncWorkersToNewRecorder(this); + }).bind(this)); + } }; +/** + * This function handle mongoose validation Errors or any other error at backend. + * @param {*} err err Object contains error from backEnd. + * @param {*} res response Object required to send response error code. + * @returns blank to stop further processing and sends 400(bad request from mongoose validations) or 500(internal error) to clients. + */ +/* To Do:- This below function is used in both serviceController and recorderController. We + should keep this functiona at common place and should be call from ther at both places. */ + function handleBackEndValidationsAndErrors(err, res) { + { + switch (err.name) { + case 'ValidationError': + LOOP1: + for (let field in err.errors) { + switch (err.errors[field].kind) { + case 'required': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'user defined': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'enum': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'Number': + handleError(err.errors[field].message, res, 400); + break LOOP1; + default: + handleError(err.errors[field].message, res, 400); + break LOOP1; + } + } + break; + default: + handleError(err, res, 500); + } + return; + } + } + function registerRecorder(recorder){ activeRecorders[recorder.model._id] = recorder; routing.bindRecorderToPath("/" + recorder.model.sut.name + recorder.model.path + "*",recorder); @@ -113,6 +192,7 @@ function stripRRPairForReq(rrpair) { myRRPair.reqData = JSON.parse(req.body); }catch(err){ myRRPair.reqData = req.body; + myRRPair.payloadType = "PLAIN"; } } else @@ -180,6 +260,7 @@ function stripRRPairForReq(rrpair) { myRRPair.resData = JSON.parse(body); }catch(err){ myRRPair.resData = body; + myRRPair.payloadType = "PLAIN"; } }else{ myRRPair.resData = body; @@ -197,8 +278,46 @@ function stripRRPairForReq(rrpair) { break; } } + + + //Check our filters + var filters = this.model.filters; + var addThisRRPair = true; + var filteredReason = null; + if(filters && filters.enabled && body){ + if(filters.bodyStrings.length){ + for(let i = 0; i < filters.bodyStrings.length; i++){ + if(body.includes(filters.bodyStrings[i])){ + addThisRRPair = false; + filteredReason = 'Found string "' + filters.bodyStrings[i] + '" in response body.' + break; + } + } + } + if(addThisRRPair && filters.statuses.length){ + for(let i = 0; i < filters.statuses.length; i++){ + if(remoteRsp.statusCode == filters.statuses[i]){ + addThisRRPair = false; + filteredReason = 'Found status code "' + filters.statuses[i] + '" in response.' + break; + } + } + } + if(addThisRRPair && filters.headers.length){ + for(let i = 0; i < filters.headers.length; i++){ + let header = filters.headers[i]; + if(remoteRsp.headers[header.key] && remoteRsp.headers[header.key] == header.value){ + addThisRRPair = false; + filteredReason = 'Found header "' + header.key + '" with value "' + header.value + '" in response headers.' + break; + } + } + } + } + + //Push RRPair to model, then update our local model - if(!duplicate){ + if(!duplicate && addThisRRPair){ Recording.update({_id : this.model._id} , {$push: {"service.rrpairs":myRRPair} @@ -211,6 +330,11 @@ function stripRRPairForReq(rrpair) { //Send back response to user rsp.status(remoteRsp.statusCode); var headers = remoteRsp.headers; + + //Add reason for filtered, if filtered + if(!addThisRRPair && filteredReason){ + headers['_mockiato-filtered-reason'] = filteredReason; + } if(headers['content-type']){ rsp.type(headers['content-type']) delete headers['content-type']; @@ -268,6 +392,28 @@ function getRecordingById(req,rsp){ }); } +/** + * API call to get a specific recording based on SUT + * @param {*} req express req + * @param {*} rsp express rsp + */ +function getRecordingBySystem(req,rsp){ + let allRecorders = []; + + const query = { 'sut.name': req.params.name }; + + Recording.find(query,function(err,docs){ + if(err){ + handleError(err,rsp,500); + return; + } + console.log("Found Recorder with SUT",docs); + allRecorders = docs; + return rsp.json(allRecorders); + + }); +} + /** * API call to get RR pairs for a recorder after a certain index, for use in active update/polling * @param {*} req express req @@ -320,8 +466,8 @@ function findDuplicateRecorder(sut,path){ * @param {string} dataType XML/JSON/etc * @param {array{string}} headerMask array of headers to save */ -function beginRecordingSession(label,path,sut,remoteHost,remotePort,protocol,headerMask,ssl){ - var newRecorder = new Recorder(label,path,sut,remoteHost,remotePort,protocol,headerMask,ssl); +function beginRecordingSession(label,path,sut,remoteHost,remotePort,protocol,headerMask,ssl,filters,creator, rsp){ + var newRecorder = new Recorder(label,path,sut,remoteHost,remotePort,protocol,headerMask,ssl,filters,creator, rsp); return newRecorder; } @@ -356,6 +502,28 @@ function removeRecorder(req,rsp){ } +/** + * API call to stop a recorder based on ID. + * @param {*} req express req + * @param {*} rsp express rsp + */ +function stopRecorder(req,rsp){ + var recorder = activeRecorders[req.params.id]; + if(recorder){ + recorder.model.running = false; + recorder.model.save(function(err,doc){ + rsp.status(200); + rsp.json(doc); + deregisterRecorder(recorder); + + }); + + }else{ + handleError(new Error("No recorder found for that ID or recorder is already stopped."),rsp,404); + } + +} + function deregisterRecorder(recorder){ routing.unbindRecorder(recorder); if(activeRecorders[recorder.model._id]) @@ -372,13 +540,23 @@ function deregisterRecorder(recorder){ */ function addRecorder(req,rsp){ var body = req.body; + if (body.sut === undefined){ + handleError(constants.REQUIRED_SUT_PARAMS_ERR, rsp, 400); + return; + } + if(body.basePath === undefined){ + handleError(constants.REQUIRED_BASEPATH_ERR, rsp, 400); + return; + } if(body.type == "SOAP") body.payloadType = "XML"; if(findDuplicateRecorder(body.sut,body.basePath)){ - handleError("OverlappingRecorderPathError",rsp,500); + handleError(constants.DUP_RECORDER_PATH_BODY,rsp,400); + return; } else{ - var newRecorder = beginRecordingSession(body.name,body.basePath,body.sut,body.remoteHost,body.remotePort,body.type,body.headerMask,body.ssl); + //need to refactor this..just pasa body and not so much parameters to beginRecordingSession function. + var newRecorder = beginRecordingSession(body.name,body.basePath,body.sut,body.remoteHost,body.remotePort,body.type,body.headerMask,body.ssl,body.filters,body.creator, rsp); newRecorder.model.then(function(doc){ rsp.json(doc); }).catch(function(err){ @@ -389,6 +567,29 @@ function addRecorder(req,rsp){ } + /** + * Starts an existing Recording into a Recorder object. + * @param {string} recorderId + * @return {Recorder} recorder object instantiated from Recording doc + */ + function startRecorderFromId(recorderId){ + return new Recorder(recorderId); +} + +/** + * API call to start a recorder. :id is the id to a Recording document. Starts up a Recorder based on the Recording doc. + * @param {*} req express req + * @param {*} rsp express rsp + */ +function startRecorder(req,rsp){ + startRecorderFromId(req.params.id).model.then(function(doc){ + rsp.json(doc); + }).catch(function(err){ + handleError(err,rsp,500); + }); +} + + module.exports = { Recorder: Recorder, @@ -398,6 +599,20 @@ function addRecorder(req,rsp){ getRecorderRRPairsAfter : getRecorderRRPairsAfter, removeRecorder: removeRecorder, registerRecorder: registerRecorder, - deregisterRecorder: deregisterRecorder + deregisterRecorder: deregisterRecorder, + startRecorder : startRecorder, + stopRecorder : stopRecorder, + getRecordingBySystem : getRecordingBySystem }; + +//On startup, start all recorders that should be active. +Recording.find({running:true},function(err,docs){ + if(docs){ + docs.forEach(function(doc){ + new Recorder(doc); + }); + }else if(err){ + debug('error initializing recorders'); + } +}); \ No newline at end of file diff --git a/controllers/rrpairController.js b/controllers/rrpairController.js index a461deb2..04bc750e 100644 --- a/controllers/rrpairController.js +++ b/controllers/rrpairController.js @@ -1,8 +1,7 @@ const Service = require('../models/http/Service'); const MQService = require('../models/mq/MQService'); -const xml2js = require('xml2js'); -const xmlBuilder = new xml2js.Builder(); + function getPairsByServiceId(req, res) { Service.findById(req.params.serviceId, function(err, service) { @@ -27,41 +26,6 @@ function getPairsByServiceId(req, res) { }); } -function trimRequestData(template, rrpair) { - if (!template || !rrpair) { - return; - } - - xml2js.parseString(template, function(err, xmlTemplate) { - if (err) { - debug(err); - return; - } - template = xmlTemplate; - }); - - let reqData; - xml2js.parseString(rrpair.reqData, function(err, data) { - reqData = data; - }); - - // flatten request data - const flatTemplate = flattenObject(template); - const flatReqData = flattenObject(reqData); - const trimmedReqData = {}; - - // pull out the fields specified in the template - for (let field in flatTemplate) { - trimmedReqData[field] = flatReqData[field]; - } - - // unflatten the trimmed request data - const unflatReqData = unflattenObject(trimmedReqData); - - return xmlBuilder.buildObject(unflatReqData); -} - module.exports = { - getPairsByServiceId: getPairsByServiceId, - trimRequestData: trimRequestData + getPairsByServiceId: getPairsByServiceId }; diff --git a/controllers/serviceController.js b/controllers/serviceController.js index 944d4eae..8903178a 100644 --- a/controllers/serviceController.js +++ b/controllers/serviceController.js @@ -15,6 +15,84 @@ const unzip = require('unzip2'); const YAML = require('yamljs'); const invoke = require('../routes/invoke'); const System = require('../models/common/System'); +const systemController = require('./systemController'); +const constants = require('../lib/util/constants'); + +/** + * Given a User object and a service's id, return a promise that resolves if this user can edit the service, and rejects otherwise + * @param {User} user + * @param {string} serviceId + */ +function canUserEditServiceById(user,serviceId){ + return new Promise(function(resolve,reject){ + Service.findById(serviceId,function(err,doc){ + if(err) + reject(err) + else + if(doc){ + systemController.isUserMemberOfGroup(user,doc.sut).then((bool)=>{resolve(bool)},(err)=>{reject(err)}); + }else{ + reject("No Service Found"); + } + }); + }); +} + + + + + +/** + * Wrapper function for (MQ)Service.create. If req is provided, will also check against current logged in user's permissions first. + * @param {object} serv An object containing the info to create a service + * @param {*} req Express request. + * @return A promise from creating the service. Resolves to the new service. Rejects with error from mongoose OR error from lack of group permission. + */ +function createService(serv,req){ + return new Promise(function(resolve,reject){ + if(req){ + var user = req.decoded; + serv.lastUpdateUser = user; + var authed = false; + + //Get our system + systemController.getSystemIfMember(user.uid,serv.sut.name).exec(function(err,system){ + if(err){ + reject(err); + }else if(system){ + serv.sut = system; //Make sure service has full system info, including proper ID! + performCreate(); + }else{ + reject(new Error(constants.USER_NOT_AUTHORIZED_ERR)); + } + }); + + }else{ + performCreate(); + } + function performCreate(){ + if(serv.type == "MQ"){ + MQService.create(serv,function(err,service){ + if(err) + reject(err); + else + resolve(service); + }); + }else{ + Service.create(serv,function(err,service){ + if(err) + reject(err); + else + resolve(service); + }); + } + } + + + + }); + +} /** * Helper function for search. Trims down an HTTP service for return, and filters + trims rrpairs. @@ -390,7 +468,7 @@ function getServicesArchiveBySystem(req, res) { let allServices = []; const query = { $or: [ { 'service.sut.name': req.params.name }, { 'mqservice.sut.name': req.params.name } ] }; - +console.log(query); Archive.find(query, function(err, services) { if (err) { handleError(err, res, 500); @@ -453,27 +531,31 @@ function getServicesByQuery(req, res) { } function getArchiveServices(req, res) { - const sut = req.query.sut; - const user = req.query.user; + //const query = {}; - const query = { $or: [ { 'service.sut.name': sut }, { 'mqservice.sut.name': sut },{ 'service.user.uid': user }, - { 'mqservice.user.uid': user } ] }; + const sut = req.query.sut; + const user = req.query.user; - Archive.find(query, function(err, services) { - if (err) { - handleError(err, res, 500); - return; - } - return res.json(services); - }); + const query = { $and :[ {$or: [ { 'service.sut.name': sut }, { 'mqservice.sut.name': sut }] },{$or : [{ 'service.user.uid': user }, + { 'mqservice.user.uid': user } ]}] }; + + Archive.find(query, function(err, services) { + if (err) { + handleError(err, res, 500); + return; + } + return res.json(services); + }); } function getDraftServices(req, res) { + // const query = {}; + const sut = req.query.sut; const user = req.query.user; - const query = { $or: [ { 'service.sut.name': sut }, { 'mqservice.sut.name': sut },{ 'service.user.uid': user }, - { 'mqservice.user.uid': user } ] }; + const query = { $and :[ {$or: [ { 'service.sut.name': sut }, { 'mqservice.sut.name': sut }] },{$or : [{ 'service.user.uid': user }, + { 'mqservice.user.uid': user } ]}] }; DraftService.find(query, function(err, services) { if (err) { @@ -491,20 +573,20 @@ function searchDuplicate(service, next) { basePath: service.basePath }; - const query = { + const dupCheckQuery = { name: service.name, basePath: service.basePath }; - Service.findOne(query2ServDiffNmSmBP, function (err, sameNmDupBP) { + Service.findOne(query2ServDiffNmSmBP, function (err, diffNmSameBP) { if (err) { handleError(err, res, 500); return; } - else if (sameNmDupBP) + else if (diffNmSameBP) next({ twoServDiffNmSmBP: true }); else { - Service.findOne(query, function (err, duplicate) { + Service.findOne(dupCheckQuery, function (err, duplicate) { if (err) { handleError(err, res, 500); return; @@ -532,7 +614,7 @@ function stripRRPair(rrpair) { // function to merge req / res pairs of duplicate services function mergeRRPairs(original, second) { - for (let rrpair2 of second.rrpairs) { + for (let rrpair2 of second.rrpairs) { let hasAlready = false; let rr2 = stripRRPair(new RRPair(rrpair2)); @@ -583,8 +665,21 @@ function syncWorkers(service, action) { } function addService(req, res) { - const type = req.body.type; + /* validating sut here because code doesn't reach to mongoose validation check. we are using sut.name to calculate base path before mongoose + validations. even if sut present but name or members not present in req data. unautorize error message is thrown which is not correct.*/ + if (!req.body.sut || !req.body.sut.name){ + handleError(constants.REQUIRED_SUT_PARAMS_ERR, res, 400); + return; + } + + /* This check is mandatory for basePath validation because basePath is created using groupName. so mongoose validation will + not throw an error. This is the case when user may forget to put mandatory field 'basePath' in request for REST/SOAP type service.*/ + if (!req.body.basePath && (req.body.type === 'REST' || req.body.type === 'SOAP')){ + handleError(constants.REQUIRED_BASEPATH_ERR, res, 400); + return; + } + const type = req.body.type; let serv = { sut: req.body.sut, user: req.decoded, @@ -594,8 +689,7 @@ function addService(req, res) { delayMax: req.body.delayMax, basePath: '/' + req.body.sut.name + req.body.basePath, matchTemplates: req.body.matchTemplates, - rrpairs: req.body.rrpairs, - lastUpdateUser: req.decoded + rrpairs: req.body.rrpairs }; //Save req and res data string cache @@ -615,15 +709,18 @@ function addService(req, res) { if (type === 'MQ') { serv.connInfo = req.body.connInfo; - MQService.create(serv, + createService(serv,req).then( + function(service){ + res.json(service); + }, // handler for db call - function(err, service) { + function(err) { if (err) { - handleError(err, res, 500); - return; - } + handleBackEndValidationsAndErrors(err, res); + return; + } // respond with the newly created resource - res.json(service); + }); } else { @@ -632,39 +729,87 @@ function addService(req, res) { searchDuplicate(serv, function(duplicate) { if (duplicate && duplicate.twoServDiffNmSmBP){ - res.json({"error":"twoSeviceDiffNameSameBasePath"}); + handleError(constants.SERVICES_DIFFNAME_SAMEBASEPATH_ERR, res, 400); return; } - else if (duplicate) { - // merge services - mergeRRPairs(duplicate, serv); - // save merged service - duplicate.save(function(err, newService) { - if (err) { - handleError(err, res, 500); + else if (duplicate) { + //only merge if both service type is same othwise throw error 409. + if(duplicate.type == serv.type){ + if(!serv.rrpairs){ + handleError(constants.REQUST_NO_RRPAIR, res, 400); return; } - res.json(newService); - - syncWorkers(newService, 'register'); - }); + // merge services + mergeRRPairs(duplicate, serv); + // save merged service + duplicate.save(function(err, newService) { + if (err) { + handleBackEndValidationsAndErrors(err, res); + return; + } + res.json(newService); + syncWorkers(newService, 'register'); + }); + }else{ + handleError(constants.DIFF_TYPE_SERV_ERR, res, 409); + return; + } } else { - Service.create(serv, - function(err, service) { - if (err) { - handleError(err, res, 500); + createService(serv, req).then( + function (service) { + res.json(service); + + syncWorkers(service, 'register'); + }, function (err) { + handleBackEndValidationsAndErrors(err, res); return; } - res.json(service); - - syncWorkers(service, 'register'); - }); + ); } }); } } +/** + * This function handle mongoose validation Errors or any other error at backend. + * @param {*} err err Object contains error from backEnd. + * @param {*} res response Object required to send response error code. + * @returns blank to stop further processing and sends 400(bad request from mongoose validations) or 500(internal error) to clients. + */ +/* To Do:- This below function is used in both serviceController and recorderController. We + should keep this functiona at common place and should be call from ther at both places. */ +function handleBackEndValidationsAndErrors(err, res) { + { + switch (err.name) { + case 'ValidationError': + LOOP1: + for (let field in err.errors) { + switch (err.errors[field].kind) { + case 'required': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'user defined': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'enum': + handleError(err.errors[field].message, res, 400); + break LOOP1; + case 'Number': + handleError(err.errors[field].message, res, 400); + break LOOP1; + default: + handleError(err.errors[field].message, res, 400); + break LOOP1; + } + } + break; + default: + handleError(err, res, 500); + } + return; + } +} function addServiceAsDraft(req, res) { const type = req.body.type; @@ -721,8 +866,6 @@ function addServiceAsDraft(req, res) { return; } res.json(service); - - syncWorkers(service, 'register'); }); } } @@ -755,6 +898,9 @@ function updateService(req, res) { }); } if(req.body.liveInvocation){ + if(service.liveInvocation && service.liveInvocation.recordedRRPairs){ + req.body.liveInvocation.recordedRRPairs = service.liveInvocation.recordedRRPairs; + } service.liveInvocation = req.body.liveInvocation; } if (req.body.matchTemplates) { @@ -776,7 +922,7 @@ function updateService(req, res) { // save updated service in DB service.save(function (err, newService) { if (err) { - handleError(err, res, 500); + handleBackEndValidationsAndErrors(err, res); return; } @@ -793,8 +939,12 @@ function updateService(req, res) { return; } if(draftservice.service){ - addService(req, res); + var reg = new RegExp("/" + draftservice.service.sut.name,"i"); + var basePath = draftservice.service.basePath.replace(reg,""); + req.body.basePath = basePath; } + addService(req, res); + }); } }); @@ -808,8 +958,6 @@ function updateService(req, res) { handleError(err, res, 500); return; } - // if (draftservice.service) { - console.log('Inside updateServiceAsDraft: ' + draftservice); if(draftservice.service){ // don't let consumer alter name, base path, etc. @@ -969,6 +1117,7 @@ function restoreService(req, res) { } if (archive.service) { let newService = { + _id:archive.service._id, sut: archive.service.sut, user: archive.service.user, name: archive.service.name, @@ -982,7 +1131,8 @@ function restoreService(req, res) { rrpairs: archive.service.rrpairs, lastUpdateUser: archive.service.lastUpdateUser }; - Service.create(newService, function (err, callback) { + createService(newService,req).then(function(service){}, + function (err) { if (err) { handleError(err, res, 500); } @@ -1000,7 +1150,7 @@ function restoreService(req, res) { rrpairs: archive.mqservice.rrpairs, connInfo: archive.mqservice.connInfo }; - MQService.create(newMQService, function (err, callback) { + createService(newMQService,req).then( function(serv) {},function (err) { if (err) { handleError(err, res, 500); } @@ -1090,44 +1240,60 @@ function publishExtractedRRPairs(req, res) { serv.user = req.decoded; if (type === 'MQ') { - MQService.create(serv, + createService(serv,req).then( + function(service){ + res.json(service); + }, // handler for db call - function(err, service) { + function(err) { if (err) { - handleError(err, res, 500); + handleBackEndValidationsAndErrors(err, res); return; } // respond with the newly created resource - res.json(service); + }); } else { searchDuplicate(serv, function(duplicate) { if (duplicate && duplicate.twoServDiffNmSmBP){ - res.json({"error":"twoSeviceDiffNameSameBasePath"}); + handleError(constants.SERVICES_DIFFNAME_SAMEBASEPATH_ERR, res, 400); return; } - else if (duplicate) { + else if (duplicate) { + //only merge if both service type is same othwise do nothing. + if(duplicate.type == serv.type){ + if(!serv.rrpairs){ + handleError(constants.REQUST_NO_RRPAIR, res, 400); + return; + } // merge services mergeRRPairs(duplicate, serv); // save merged service duplicate.save(function(err, newService) { if (err) { - handleError(err, res, 500); + handleBackEndValidationsAndErrors(err, res); return; } res.json(newService); - syncWorkers(newService, 'register'); }); + }else{ + handleError(constants.DIFF_TYPE_SERV_ERR, res, 400); + return; } + } else { - Service.create(serv, function (err, service) { + createService(serv,req).then( + function(service){ + res.json(service); + syncWorkers(service , 'register'); + }, + function (err, service) { if (err) { - handleError(err, res, 500); + handleBackEndValidationsAndErrors(err, res); + return; } - res.json(service); - syncWorkers(service , 'register'); }); } }); @@ -1191,29 +1357,41 @@ function publishUploadedSpec(req, res) { searchDuplicate(serv, function(duplicate) { if (duplicate && duplicate.twoServDiffNmSmBP){ - res.json({"error":"twoSeviceDiffNameSameBasePath"}); + handleError(constants.SERVICES_DIFFNAME_SAMEBASEPATH_ERR, res, 400); return; } - else if (duplicate) { + else if (duplicate) { + //only merge if both service type is same othwise do nothing. + if(duplicate.type == serv.type){ + if(!serv.rrpairs){ + handleError(constants.REQUST_NO_RRPAIR, res, 400); + return; + } // merge services mergeRRPairs(duplicate, serv); // save merged service duplicate.save(function(err, newService) { if (err) { - handleError(err, res, 500); + handleBackEndValidationsAndErrors(err, res); return; } res.json(newService); - - syncWorkers(newService, 'register'); + syncWorkers(newService, 'register'); }); + }else{ + handleError(constants.DIFF_TYPE_SERV_ERR, res, 400); + return; } + } else { - Service.create(serv, function (err, service) { - if (err) handleError(err, res, 500); - + createService(serv,req).then( function(service){ res.json(service); syncWorkers(service, 'register'); + },function (err) { + if (err) { + handleBackEndValidationsAndErrors(err, res); + return; + } }); } }); @@ -1264,6 +1442,117 @@ function deleteDraftService(req, res) { }); } + + +/** + * API Call to delete a specific recorded RR pair from liveInvocation + * @param {*} req Express req + * @param {*} res Express rsp + */ +function deleteRecordedRRPair(req,res){ + var serviceId = req.params.id; + var rrPairId = req.params.rrpairId; + canUserEditServiceById(req.decoded,serviceId).then((bool)=>{ + Service.findOneAndUpdate({_id:serviceId},{$pull:{"liveInvocation.recordedRRPairs":{_id:rrPairId}}},function(err,doc){ + if(err) + handleError(err,res,500); + else + res.json(doc); + + }); + },(err)=>{ + handleError(err,res,500); + }); + +} + +/** + * API call to get just the recorded RR pairs from a service + * @param {*} req express req + * @param {*} res express rsp + */ +function getServiceRecordedRRPairs(req,res){ + var serviceId = req.params.id; + Service.findById(serviceId).select("liveInvocation.recordedRRPairs").exec(function(err,doc){ + if(err) + handleError(err,res,500); + else + res.json(doc); + }); +} + +/** + * API call to take one recorded pair and merge it into RRPairs with no edit + * @param {*} req express req + * @param {*} res express rsp + */ +function mergeRecordedRRPair(req,res){ + var serviceId = req.params.id; + var rrPairId = req.params.rrpairId; + canUserEditServiceById(req.decoded,serviceId).then((bool)=>{ + Service.findOne({_id:serviceId,'liveInvocation.recordedRRPairs':{$elemMatch:{_id:rrPairId}}}).exec(function(err,doc){ + if(err){ + handleError(err,res,500); + }else if(doc){ + for(let i = 0; i < doc.liveInvocation.recordedRRPairs.length; i++){ + var rrpair = doc.liveInvocation.recordedRRPairs[i]; + if(rrpair._id == rrPairId){ + var rrPairWrapper = {rrpairs:[rrpair]}; + mergeRRPairs(doc,rrPairWrapper); + doc.liveInvocation.recordedRRPairs.splice(i,1); + doc.save(function(err,newDoc){ + res.json(newDoc); + syncWorkers(newDoc, 'register'); + }); + break; + } + } + }else{ + res.status(404); + res.json({}); + } + }); + },(err)=>{ + handleError(err,res,500); + }); +} + +/** + * API call to add an RRPair to a service + * @param {*} req express req + * @param {*} res express rsp + */ +function addRRPair(req,res){ + var serviceId = req.params.id; + canUserEditServiceById(req.decoded,serviceId).then((bool)=>{ + var rrPair = req.body; + Service.findById(serviceId,function(err,doc){ + if(err) + handleError(err,res,500); + else if(doc){ + mergeRRPairs(doc,{rrpairs:[rrPair]}); + doc.save(function(err,newDoc){ + if(err){ + handleError(err,res,500); + }else{ + res.json(newDoc); + } + }) + }else{ + res.status(404); + res.end(); + } + }); + + },(err)=>{ + if(err == "No Service Found") + handleError(err,res,404); + else + handleError(err,res,401); + }); +} + + module.exports = { getServiceById: getServiceById, getArchiveServiceInfo: getArchiveServiceInfo, @@ -1290,27 +1579,12 @@ module.exports = { deleteDraftService: deleteDraftService, getDraftServicesByUser: getDraftServicesByUser, addServiceAsDraft: addServiceAsDraft, - updateServiceAsDraft: updateServiceAsDraft + updateServiceAsDraft: updateServiceAsDraft, + deleteRecordedRRPair: deleteRecordedRRPair, + canUserEditServiceById: canUserEditServiceById, + getServiceRecordedRRPairs: getServiceRecordedRRPairs, + mergeRecordedRRPair: mergeRecordedRRPair, + addRRPair: addRRPair }; -//Add resDataString and rspDataString to every existing service on boot, if they do not already have it -Service.find({'rrpairs.resDataString':{$exists:false},'rrpairs.reqDataString':{$exists:false}},function(err,docs){ - if(err){ - console.log(err); - }else{ - if(docs){ - docs.forEach(function(doc){ - if(doc.rrpairs){ - doc.rrpairs.forEach(function(rrpair){ - if(rrpair.reqData) - rrpair.reqDataString = typeof rrpair.reqData == 'string' ? rrpair.reqData : JSON.stringify(rrpair.reqData); - if(rrpair.resData) - rrpair.resDataString = typeof rrpair.resData == 'string' ? rrpair.resData : JSON.stringify(rrpair.resData); - }); - } - doc.save(); - }); - } - } -}); \ No newline at end of file diff --git a/controllers/systemController.js b/controllers/systemController.js index 2d31250c..f5ca7ef9 100644 --- a/controllers/systemController.js +++ b/controllers/systemController.js @@ -1,6 +1,7 @@ const System = require('../models/common/System'); const debug = require('debug')('default'); const _ = require('lodash/array'); +const constants = require('../lib/util/constants'); function getSystems(req, res) { System.find({}, function(err, systems) { @@ -53,6 +54,17 @@ function updateGroup(req, res){ } function addSystem(req, res) { + + /** + * In case user import template with no sut key(by mistake) in .json file. In this case req.body may be empty. + * It is handled in service creation using validation of mandatory fields and showing proper error message on UI. + * So it needs to handle here. Otherwise application will not show what is problem with template. + */ + if(!req.body) { + res.json(constants.SUT_NOT_PRESENT_ERR_MSG); + return; + } + if (!req.body.members) req.body.members = []; //adds super user to all groups created @@ -112,10 +124,52 @@ function delSystem(req, res) { }); } +/** + * Helper function to get all SUTs this user is a member of + * @param {string} user uid for user of interest + * @return mongoose query + */ +function findSystemsForUser(user){ + return System.find({members:user}); +} + + +/** + * Get a system if and ONLY if the given user is a member of that system. Otherwise return null. + * @param {string} user User uid + * @param {string} system System name + * @return mongoose query + */ +function getSystemIfMember(user,system){ + return System.findOne({members:user,name:system}); +} + +/** + * Tests if user is a member of this group. returns a promise. Resolves to true if they are, rejects with error otherwise. + * @param {User} user + * @param {System} system + */ +function isUserMemberOfGroup(user,system){ + return new Promise(function(resolve,reject){ + System.findOne({name:system.name,members:user.uid},function(err,doc){ + if(err){ + reject(err); + }else if(doc){ + resolve(true); + }else{ + reject(new Error("User " + user.uid + " not member of group " + system.name)); + } + }) + }); +} + module.exports = { getSystems: getSystems, addSystem: addSystem, delSystem: delSystem, getOneSystem: getOneSystem, - updateGroup: updateGroup + updateGroup: updateGroup, + findSystemsForUser: findSystemsForUser, + getSystemIfMember : getSystemIfMember, + isUserMemberOfGroup: isUserMemberOfGroup }; \ No newline at end of file diff --git a/controllers/userController.js b/controllers/userController.js index f9f5972b..11712c2f 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -22,7 +22,6 @@ function delUser(req, res) { } function getAdminUser(req, res) { - console.log('here'); res.json(process.env.MOCKIATO_ADMIN); } diff --git a/lib/auth/local.js b/lib/auth/local.js index 007f6ae3..95101796 100644 --- a/lib/auth/local.js +++ b/lib/auth/local.js @@ -1,5 +1,4 @@ const mongoose = require('mongoose'); -const debug = require('debug')('default'); const fs = require('fs'); const express = require('express'); const passport = require('passport'); @@ -15,16 +14,20 @@ router.post('/', function (req, res) { if (err) { var errName = err.name; if (errName == 'UserExistsError') { - console.log(err); - res.redirect('/register?ErrHint=' + encodeURIComponent('DU')); + res.append('redirectUrl', '/register?ErrHint=' + encodeURIComponent('DU')); + res.status(302); + res.send('Error : This username already exist.'); }else{ - console.log(err); - res.redirect('/register?ErrHint=' + encodeURIComponent('SE')); + res.append('redirectUrl', '/register?ErrHint=' + encodeURIComponent('SE')); + res.status(302); + res.send('Something went wrong.'); } } - passport.authenticate('local')(req, res, function () { - res.redirect('/#regS'); - }); + else { + res.append('redirectUrl', '/#regS'); + res.status(302); + res.send('User Registration Successful!'); + } }); }); diff --git a/lib/rrpair/parser.js b/lib/rrpair/parser.js index 863bc07f..78762389 100644 --- a/lib/rrpair/parser.js +++ b/lib/rrpair/parser.js @@ -40,7 +40,7 @@ function parse(path, type) { var bulkUpload = function (newPath, newFiles, type, message) { var serv; var rr; var req; var res; var fileCounter = 0; var filesNameJson = {}; var isMacZip = false; if (type === 'MQ') {serv = new MQService();rr = new MQPair();} else {serv = new Service();rr = new RRPair();} - var restMethods = constants.ALL_REST_METHODS; var numberOfFiles = newFiles.length; + var restMethods = constants.ALL_REST_METHODS; var numberOfFiles = newFiles.length; var labelCounter = 0; //removing Mac related files/directory. if (newFiles.includes("__MACOSX")) { @@ -93,6 +93,7 @@ var bulkUpload = function (newPath, newFiles, type, message) { var match = onlyFileNameRegx.exec(filename); if (match[1].endsWith(constants.REQ_FILE_END)) { req = true; + rr.label = 'RRPair'+ ++labelCounter; if (type === constants.REST) { var firstWord = content.substr(0, content.indexOf(constants.SPACE)); if (!restMethods.includes(firstWord)) { diff --git a/lib/util/constants.js b/lib/util/constants.js index 939e2146..8ac0ef7e 100644 --- a/lib/util/constants.js +++ b/lib/util/constants.js @@ -1,5 +1,4 @@ module.exports = Object.freeze({ - //below constants for bulk upload parser.js SPACE: ' ', HTTP: 'HTTP', SOAP: 'SOAP', @@ -25,6 +24,44 @@ module.exports = Object.freeze({ TEXT_XML: 'text/xml', APPLICATION_JSON: 'application/json', TEXT_PLAIN: 'text/plain', - //below constants for app.js of express framework. ORG_USR_REGISTER_VIEW: 'Mockiato ☕


You are using Mockiato in your organziation. Please login with your organization credentials.


', + ALL_SERVICE_TYPE: '["REST", "SOAP", "MQ"]', + REST_SOAP_REQUIREDFIELD_ERRMSG: 'Required fields (Group, Name, Base Path, Request/Response Pair) is not present.', + MQ_REQUIREDFIELD_ERRMSG: 'Required fields (Group, Name, Request/Response Pair) is not present.', + SOAP_MQ_RRPAIR_REQFIELD_ERRMSG: 'Required fields (Request Payload, Response Payload) not present in Request/Response Pairs.', + REST_RRPAIR_REQFIELD_ERRMSG: 'Required fields (HTTP Method, Payload Type) not present in Request/Response Pairs.', + REST_RRPAIR_REQRESDATA_FORMAT: 'Request or Response is not in correct Json format.', + SOAP_MQ_RRPAIR_REQRESDATA_FORMAT: 'Request or Response is not in correct xml format.', + ALL_PAYLOAD_TYPE: ['JSON', 'XML', 'PLAIN'], + SUT_NOT_PRESENT_ERR_MSG: 'Error: sut not present in imported Template', + MQ_VALID_XML_REQ_ERR: 'Request is not a valid xml.', + MQ_VALID_XML_RES_ERR: 'Response is not a valid xml.', + REQUIRED_REQUEST_PAYLOAD_ERR: 'Required field Request Payload (rrpairs.reqData) is not present in request.', + REQUIRED_RESPONSE_PAYLOAD_ERR: 'Required field Response Payload (rrpairs.resData) is not present in request.', + REQUIRED_SUT_ERR: 'Required field Group (sut) is not present in request.', + REQUIRED_SUT_PARAMS_ERR: 'Required field Group (sut or sut/name) is not present in request.', + REQURIED_SUT_NAME_ERR: 'Required field Gruop name (sut.name) is not present in request.', + REQUIRED_SUT_MEMBERS_ERR: 'Required field Gruop members (sut.members) is not present in request.', + REQUIRED_BASEPATH_ERR: 'Required field Base Path (basePath) is not present in request.', + REQUIRED_SERVICE_NAME_ERR: 'Required field Service Name (name) is not present in request.', + REQUIRED_SERVICE_TYPE_ERR: 'Required field Service Type (type) is not present in request.', + REQUIRED_RRPAIRS_ERR: 'Required field Request/Response Pair (rrpairs) is not present in request.', + REQUIRED_HTTP_METHOD_ERR: 'Required field HTTP Method (rrpairs.verb) is not present in request.', + REQUIRED_RRPAIRS_PAYLOADTYPE_ERR: 'Required field Payload Type (rrpairs.payloadType) is not present in request.', + SERVICETYPE_PAYLAODTYPE_COMBINATION_ERR: 'Service Type and Payload Type (payloadType in rrpairs) combination is incorrect.', + PAYLOADTYPE_REQDATA_NOMATCH_ERR: 'Syntax of Request Payload (reqData) is invalid. It don\'t match with given Payload Type.', + PAYLOADTYPE_RESDATA_NOMATCH_ERR: 'Syntax of Response Payload (resData) is invalid. It don\'t match with given Payload Type.', + NOT_VALID_VERB:' is not a valid Http Method' , + NOT_VALID_PAYLOADTYPE:' is not a valid PayLoad Type ', + USER_NOT_AUTHORIZED_ERR: 'User not authorized to create on this group.', + REQUST_NO_RRPAIR: 'Request don\'t contain rrpairs', + DIFF_TYPE_SERV_ERR: 'There is already a different type(Rest/Soap) of service available with same name and basepath.', + SERVICES_DIFFNAME_SAMEBASEPATH_ERR: 'There is another service already exist in our system with same basepath.', + LIVE_OR_VIRTUAL_NOT_ERR: 'You must choose between "Live first" or "Virtual first" for a Live Invocation.', + REMOTE_HOST_NOT_ERR: 'Please provide remote host', + REMOTE_PORT_NOT_ERR: 'please provide remote port', + REQUIRED_SERVICE_ERR : 'There is no Service in this recorder creation request.', + REQUIRED_RECORDER_SERVICE_NAME_ERR: 'Record Service name is mandatory. Please provide.', + DUP_RECORDER_PATH_BODY: 'This recorder\'s group and path overlap with an active recorder.', + NOT_VALID_INTEGER: ' is not a valid Positive Integer Number for ' }); \ No newline at end of file diff --git a/lib/util/index.js b/lib/util/index.js index 232cfd55..f0c58897 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -2,6 +2,7 @@ const fs = require('fs'); const jwt = require('jsonwebtoken'); const assert = require('assert'); const debug = require('debug')('default'); +const logger = require('../../winston'); // function for responding with errors global.handleError = function(e, res, stat) { @@ -159,4 +160,19 @@ if (!Object.entries) return resArray; }; + +global.logEvent = function(path, label, msg) { + debug(path, label, msg); + + let event = {}; + event.path = path; + event.label = label; + event.msg = msg; + + logger.info(event); +} + +global.escapeRegExp = function(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; \ No newline at end of file diff --git a/models/common/System.js b/models/common/System.js index 43f23f39..a80971f6 100644 --- a/models/common/System.js +++ b/models/common/System.js @@ -1,8 +1,15 @@ const mongoose = require('mongoose'); +const constants = require('../../lib/util/constants'); const sutSchema = new mongoose.Schema({ - name: String, - members: {type : Array, "default" : [] } + name: { + type : String, + required: [true, constants.REQURIED_SUT_NAME_ERR] + }, + members: { + type : Array, + default : [] + } }); module.exports = mongoose.model('SUT', sutSchema); diff --git a/models/http/RRPair.js b/models/http/RRPair.js index 856401b7..4e328d6a 100644 --- a/models/http/RRPair.js +++ b/models/http/RRPair.js @@ -1,13 +1,82 @@ const mongoose = require('mongoose'); +const xml2js = require("xml2js"); +const constants = require('../../lib/util/constants'); const rrSchema = new mongoose.Schema({ - verb: String, + verb: { + type: String, + required: [ function () { + return this.parent().type === 'REST'; + }, + constants.REQUIRED_HTTP_METHOD_ERR + ], + validate: { + validator: function (v) { + if (this.parent().type === 'REST' && !constants.ALL_REST_METHODS.includes(v)) + return false; + else return true; + }, + message: '{VALUE}'+constants.NOT_VALID_VERB+'({PATH}).' + } + }, + path: String, - payloadType: String, + payloadType: { + type: String, + required: [true, constants.REQUIRED_RRPAIRS_PAYLOADTYPE_ERR], + enum: { + values: constants.ALL_PAYLOAD_TYPE, + message: '{VALUE}'+constants.NOT_VALID_PAYLOADTYPE+'({PATH}).' + }, + validate: { + validator: function (v) { + if (this.parent().type === 'SOAP' && v === 'XML') + return true; + else if (this.parent().type === 'REST' && (v === 'XML' || v === 'JSON' || v === 'PLAIN')) + return true; + else return false; + }, + message: constants.SERVICETYPE_PAYLAODTYPE_COMBINATION_ERR + } + }, // use schema-less data-types queries: mongoose.Schema.Types.Mixed, reqHeaders: mongoose.Schema.Types.Mixed, - reqData: mongoose.Schema.Types.Mixed, + reqData: { + type: mongoose.Schema.Types.Mixed, + validate: { + validator: function (v) { + /* Making validation true in case of DraftService. + In other cases, apply normal validations. */ + try { + if (this.parent().parent().constructor.modelName === 'DraftService') return true; //else continue validations. + } catch (e) {/* Not a draft service so continue below validations*/ } + if (this.payloadType === 'JSON') { + try { + JSON.parse(JSON.stringify(v)); + return true; + } catch (e) { + return false; + } + } else if (this.payloadType === 'XML') { + try{ + xml2js.parseString(v, function (err, result) { + if(err) throw err; + }); + return true; + }catch(e){return false;} + } else { + return true; + } + }, + message: constants.PAYLOADTYPE_REQDATA_NOMATCH_ERR + }, + required: [function () { + return this.parent().type === 'SOAP'; + }, + constants.REQUIRED_REQUEST_PAYLOAD_ERR + ] + }, reqDataString: String, resStatus: { // force integer only @@ -17,7 +86,41 @@ const rrSchema = new mongoose.Schema({ set: function(v) { return Math.round(v); } }, resHeaders: mongoose.Schema.Types.Mixed, - resData: mongoose.Schema.Types.Mixed, + resData: { + type: mongoose.Schema.Types.Mixed, + validate: { + validator: function (v) { + /* Making validation true in case of DraftService. + In other cases, apply normal validations. */ + try { + if (this.parent().parent().constructor.modelName === 'DraftService') return true; //else continue validations. + } catch (e) {/* Not a draft service so continue below validations*/ } + if (this.payloadType === 'JSON') { + try { + JSON.parse(JSON.stringify(v)); + return true; + } catch (e) { + return false; + } + } else if (this.payloadType === 'XML') { + try{ + xml2js.parseString(v, function (err, result) { + if(err) throw err; + }); + return true; + }catch(e){return false;} + } else { + return true; + } + }, + message: constants.PAYLOADTYPE_RESDATA_NOMATCH_ERR + }, + required: [function () { + return this.parent().type === 'SOAP'; + }, + constants.REQUIRED_RESPONSE_PAYLOAD_ERR + ] + }, resDataString: String, label: String }); diff --git a/models/http/Recording.js b/models/http/Recording.js index 909f0c09..4ac01d40 100644 --- a/models/http/Recording.js +++ b/models/http/Recording.js @@ -1,19 +1,51 @@ const mongoose = require('mongoose'); const Service = require('./Service'); const System = require('../common/System'); +const constants = require('../../lib/util/constants'); const recordingSchema = new mongoose.Schema({ - service: Service.schema, - sut : System.schema, - path : String, - remoteHost : String, - remotePort : Number, + service: { + type: Service.schema, + required: [true, constants.REQUIRED_SERVICE_ERR] + }, + sut: { + type: System.schema, + required: [true, constants.REQUIRED_SUT_ERR] + }, + path : { + type: String, + required: [true, constants.REQUIRED_BASEPATH_ERR] + }, + remoteHost : { + type: String, + required: [true, constants.REMOTE_HOST_NOT_ERR] + }, + remotePort : { + type: Number, + required: [true, constants.REMOTE_PORT_NOT_ERR] + }, payloadType : String, protocol : String, headerMask : Array, - name : String, + name: { + type: String, + required: [true, constants.REQUIRED_RECORDER_SERVICE_NAME_ERR] + }, active : Boolean, - ssl : Boolean + ssl : Boolean, + running: { + type: Boolean, + default: true + }, + filters:{ + enabled : { + type: Boolean, + default : false + }, + bodyStrings : [String], + headers : [{key:String,value:String}], + statuses : [Number] + } }); recordingSchema.set('usePushEach', true); diff --git a/models/http/Service.js b/models/http/Service.js index 4e99ba7f..71ca5e19 100644 --- a/models/http/Service.js +++ b/models/http/Service.js @@ -3,34 +3,58 @@ const mongoose = require('mongoose'); const User = require('../common/User'); const System = require('../common/System'); const RRPair = require('./RRPair'); +const constants = require('../../lib/util/constants'); const serviceSchema = new mongoose.Schema({ - sut: System.schema, + sut: { + type: System.schema, + required: [true, constants.REQUIRED_SUT_ERR] + }, user: User.schema, name: { - type: String, + type: String, + required: [true, constants.REQUIRED_SERVICE_NAME_ERR], index: true }, - type: String, + type: { + type: String, + required: [true, constants.REQUIRED_SERVICE_TYPE_ERR] + }, basePath: { - type: String, + type: String, + required: [true, constants.REQUIRED_BASEPATH_ERR], index: true }, matchTemplates: [mongoose.Schema.Types.Mixed], - rrpairs: [RRPair.schema], + rrpairs: { + type: [RRPair.schema] + //required: [true, constants.REQUIRED_RRPAIRS_ERR] + }, delay: { // force integer only type: Number, default: 0, - get: function(v) { return Math.round(v); }, - set: function(v) { return Math.round(v); } + validate: { + validator: function (v) { + if (Number.isInteger(v) && v >= 0) + return true; + else return false; + }, + message: '{VALUE}'+constants.NOT_VALID_INTEGER+'({PATH}).' + } }, delayMax: { // force integer only type: Number, default: 0, - get: function(v) { return Math.round(v); }, - set: function(v) { return Math.round(v); } + validate: { + validator: function (v) { + if (Number.isInteger(v) && v >= 0) + return true; + else return false; + }, + message: '{VALUE}'+constants.NOT_VALID_INTEGER+'({PATH}).' + } }, txnCount: { type: Number, @@ -44,17 +68,136 @@ const serviceSchema = new mongoose.Schema({ }, lastUpdateUser:{ type: User.schema - },liveInvocation:{ + }, liveInvocation: { enabled: Boolean, - liveFirst: Boolean, - remoteHost : String, - remotePort : Number, - remoteBasePath : String, - failStatusCodes : [Number], - failStrings : [String], - ssl: Boolean + liveFirst: { + type: Boolean, + required: [function () { + return this.liveInvocation.enabled; + }, + constants.LIVE_OR_VIRTUAL_NOT_ERR + ] + }, + remoteHost: { + type: String, + required: [function () { + return this.liveInvocation.enabled; + }, + constants.REMOTE_HOST_NOT_ERR + ] + }, + remotePort: { + type: Number, + required: [function () { + return this.liveInvocation.enabled; + }, + constants.REMOTE_PORT_NOT_ERR + ] + }, + remoteBasePath: String, + failStatusCodes: [Number], + failStrings: [String], + ssl: Boolean, + record : { + type: Boolean, + default: false + }, + recordedRRPairs:[RRPair.schema] } },{timestamps:{createdAt:'createdAt',updatedAt:'updatedAt'}}); +/** + * Strips down an RRPair for quick logical comparison + * @param {RRPair} rrpair + */ +function stripRRPair(rrpair) { + return { + verb: rrpair.verb || '', + path: rrpair.path || '', + payloadType: rrpair.payloadType || '', + queries: rrpair.queries || {}, + reqHeaders: rrpair.reqHeaders || {}, + reqData: rrpair.reqData || {}, + resStatus: rrpair.resStatus || 200, + resData: rrpair.resData || {} + }; +} + +/** + * Goes through liveinvocation.recordedRRPairs and strips out all duplicates before saving the service + * @param {Service} service + */ +function filterDuplicateRecordedPairs(service){ + + //This check probably looks excessive- it is necessary because service can be null, the live invo group can be null, the recorded section can be null, and recorded can be 0 length! + //Not checking makes the entire app grind to a half if any of those are null. + if(service && service.liveInvocation && service.liveInvocation.recordedRRPairs && service.liveInvocation.recordedRRPairs.length){ + var pairs = service.liveInvocation.recordedRRPairs; + var keepThisRRPair = []; + var strippedPairs = []; + for(let i = 0; i < pairs.length; i++){ + keepThisRRPair.push(true); + strippedPairs[i] = stripRRPair(pairs[i]); + } + + //iterate over all RR pairs, calling them i. + for(let i = 0; i < strippedPairs.length; i++){ + + //If i has not already been eliminated... + if(keepThisRRPair[i]){ + + //Then compare it against all RRPairs further down the list than i, calling each one j + for(let j = i+1; j < strippedPairs.length;j++){ + + //If i and j are duplicates, mark off j (but not i) to NOT include in the trimmed list. + if(deepEquals(strippedPairs[i],strippedPairs[j])){ + keepThisRRPair[j] = false; + } + } + } + } + //Extract only the rrpairs we want to + var rrPairs = []; + for(let i = 0; i < pairs.length; i++){ + if(keepThisRRPair[i]){ + rrPairs.push(pairs[i]); + } + } + + //if changes were made, save them + if(rrPairs.length != pairs.length){ + service.liveInvocation.recordedRRPairs = rrPairs; + logEvent("","Mongoose","Saving modified pairs. Old count:" + pairs.length + " New count: " + rrPairs.length); + service.save(function(err){ + logEvent("","Mongoose",err); + }); + } + + } + + return service; +} + + + +/** + * The below hooks hook on every find or findOne call made to the Service schema. On each call, every service will be checked for duplicate recorded RRPairs under liveInvocation.recordedRRPairs. + * Any duplicates will be stripped (except the original pair recorded) from the list of recordedRRPairs. This will happen before Mockiato receives the result of the query, and this change will be saved immediately. + */ + +serviceSchema.post('findOne',function(result){ + filterDuplicateRecordedPairs(result); +}); + +serviceSchema.post('find',function(results){ + results.forEach(function(result){ + filterDuplicateRecordedPairs(result); + }) +}); + + + + + serviceSchema.set('usePushEach', true); module.exports = mongoose.model('Service', serviceSchema); \ No newline at end of file diff --git a/models/mq/MQPair.js b/models/mq/MQPair.js index 4ffb7c11..8b84d769 100644 --- a/models/mq/MQPair.js +++ b/models/mq/MQPair.js @@ -1,9 +1,49 @@ const mongoose = require('mongoose'); +xml2js = require("xml2js"); +const constants = require('../../lib/util/constants'); const pairSchema = new mongoose.Schema({ label: String, - reqData: mongoose.Schema.Types.Mixed, - resData: mongoose.Schema.Types.Mixed + reqData: { + type: mongoose.Schema.Types.Mixed, + validate: { + validator: function (v) { + /* Making validation true in case of DraftService. + In other cases, apply normal validations. */ + try{ + if (this.parent().parent().constructor.modelName === 'DraftService') return true; //else continue validations. + } catch (e) {/* Not a draft service so continue below validations*/ } + try{ + xml2js.parseString(v, function (err, result) { + if(err) throw err; + }); + return true; + }catch(e){return false;} + }, + message: constants.MQ_VALID_XML_REQ_ERR + }, + required: [true, constants.REQUIRED_REQUEST_PAYLOAD_ERR] + }, + resData: { + type: mongoose.Schema.Types.Mixed, + validate: { + validator: function (v) { + /* Making validation true in case of DraftService. + In other cases, apply normal validations. */ + try{ + if (this.parent().parent().constructor.modelName === 'DraftService') return true; //else continue validations. + } catch (e) {/* Not a draft service so continue below validations*/ } + try{ + xml2js.parseString(v, function (err, result) { + if(err) throw err; + }); + return true; + }catch(e){return false;} + }, + message: constants.MQ_VALID_XML_RES_ERR + }, + required: [true, constants.REQUIRED_RESPONSE_PAYLOAD_ERR] + }, }); module.exports = mongoose.model('MQPair', pairSchema); \ No newline at end of file diff --git a/models/mq/MQService.js b/models/mq/MQService.js index b0ef9fbe..ead2750b 100644 --- a/models/mq/MQService.js +++ b/models/mq/MQService.js @@ -5,18 +5,29 @@ const System = require('../common/System'); const MQPair = require('./MQPair'); const MQInfo = require('./MQInfo'); +const constants = require('../../lib/util/constants'); const mqSchema = new mongoose.Schema({ - sut: System.schema, + sut: { + type: System.schema, + required: [true, constants.REQUIRED_SUT_ERR] + }, user: User.schema, name: { - type: String, + type: String, + required: [true, constants.REQUIRED_SERVICE_NAME_ERR], index: true }, - type: String, + type: { + type: String, + required: [true, constants.REQUIRED_SERVICE_TYPE_ERR] + }, matchTemplates: [mongoose.Schema.Types.Mixed], connInfo: MQInfo.schema, - rrpairs: [MQPair.schema], + rrpairs: { + type: [MQPair.schema], + required: [true, constants.REQUIRED_RRPAIRS_ERR] + }, running: { type: Boolean, default: true diff --git a/package.json b/package.json index b8a5fb2c..427d18f1 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,14 @@ "scripts": { "start": "node ./bin/www", "serve": "pm2 start ./bin/www -i ${MOCKIATO_NODES:=1} --name app --no-daemon", - "test": "nyc --reporter=text mocha tests --exit" + "test": "nyc --reporter=text --reporter=html mocha tests --exit" }, "nyc": { "exclude": [ "tests", "lib/pm2", - "lib/remove-route" + "lib/remove-route", + "winston.js" ] }, "dependencies": { diff --git a/public/index.html b/public/index.html index f0807484..61a7f51c 100644 --- a/public/index.html +++ b/public/index.html @@ -55,7 +55,7 @@ @@ -86,10 +86,7 @@ - + @@ -204,8 +201,8 @@ - - + diff --git a/public/js/app/app.js b/public/js/app/app.js index ec90ade1..388cec65 100644 --- a/public/js/app/app.js +++ b/public/js/app/app.js @@ -33,7 +33,21 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' }] } }) - + .when("/update/:id/recorded", { + templateUrl: "partials/recordedInvokePairs.html", + controller: "mergeRecordedController", + resolve: { + auth: ['$q', 'authService', function($q, authService) { + var userInfo = authService.getUserInfo(); + + if (userInfo) { + return $q.when(userInfo); + } else { + return $q.reject({ authenticated: false }); + } + }] + } + }) .when("/update/:id/:frmWher", { templateUrl: "partials/updateForm.html", controller: "updateController", @@ -49,7 +63,7 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' }] } }) - + .when("/showArchiveService/:id/:frmWher", { templateUrl: "partials/updateForm.html", controller: "showArchiveController", @@ -66,21 +80,21 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' } }) - // .when("/showDraftService/:id/:frmWher", { - // templateUrl: "partials/updateForm.html", - // controller: "showDraftController", - // resolve: { - // auth: ['$q', 'authService', function($q, authService) { - // var userInfo = authService.getUserInfo(); - - // if (userInfo) { - // return $q.when(userInfo); - // } else { - // return $q.reject({ authenticated: false }); - // } - // }] - // } - // }) + .when("/showDraftService/:id/:frmWher", { + templateUrl: "partials/updateForm.html", + controller: "showDraftController", + resolve: { + auth: ['$q', 'authService', function($q, authService) { + var userInfo = authService.getUserInfo(); + + if (userInfo) { + return $q.when(userInfo); + } else { + return $q.reject({ authenticated: false }); + } + }] + } + }) .when("/addTemplate", { templateUrl: "partials/templateForm.html", @@ -98,9 +112,10 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' } }) - .when("/fetchservices", { + .when("/fetchservices/:sut?/:user?", { templateUrl: "partials/servicehistory.html", controller: "serviceHistoryController", + reloadOnUrl: false, resolve: { auth: ['$q', 'authService', function($q, authService) { var userInfo = authService.getUserInfo(); @@ -114,9 +129,27 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' } }) - .when("/fetchDeletedServices", { + .when("/fetchDeletedServices/:sut?/:user?", { templateUrl: "partials/deletedServices.html", controller: "deletedServiceController", + reloadOnUrl: false, + resolve: { + auth: ['$q', 'authService', function($q, authService) { + var userInfo = authService.getUserInfo(); + + if (userInfo) { + return $q.when(userInfo); + } else { + return $q.reject({ authenticated: false }); + } + }] + } + }) + + .when("/fetchDraftServices/:sut?/:user?", { + templateUrl: "partials/draftServices.html", + controller: "draftServiceController", + reloadOnUrl: false, resolve: { auth: ['$q', 'authService', function($q, authService) { var userInfo = authService.getUserInfo(); @@ -130,23 +163,7 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' } }) - // .when("/fetchDraftServices", { - // templateUrl: "partials/draftServices.html", - // controller: "draftServiceController", - // resolve: { - // auth: ['$q', 'authService', function($q, authService) { - // var userInfo = authService.getUserInfo(); - - // if (userInfo) { - // return $q.when(userInfo); - // } else { - // return $q.reject({ authenticated: false }); - // } - // }] - // } - // }) - - .when("/selectService", { + .when("/selectService/:id", { templateUrl: "partials/selectService.html", controller: "selectServiceController", resolve: { @@ -262,7 +279,7 @@ var mockapp = angular.module('mockapp',['mockapp.controllers','mockapp.services' } }) .otherwise({ - redirectTo: "/selectService" + redirectTo: "/selectService/home" }); }]); diff --git a/public/js/app/controllers.js b/public/js/app/controllers.js index fbe7d9e6..51ab2f02 100644 --- a/public/js/app/controllers.js +++ b/public/js/app/controllers.js @@ -1,10 +1,10 @@ -var ctrl = angular.module("mockapp.controllers",['mockapp.services','mockapp.factories','ngFileSaver']) +var ctrl = angular.module("mockapp.controllers", ['mockapp.services', 'mockapp.factories', 'ngFileSaver']) - .controller('authController', ['$scope','authService', - function($scope,authService) { - $scope.loginUser = function(credentials) { - authService.login(credentials.username, credentials.password); - }; + .controller('authController', ['$scope', 'authService', + function ($scope, authService) { + $scope.loginUser = function (credentials) { + authService.login(credentials.username, credentials.password); + }; }]) .controller("templateController", ['$scope', 'templateService', 'ctrlConstants', @@ -27,366 +27,389 @@ var ctrl = angular.module("mockapp.controllers",['mockapp.services','mockapp.fac }; }]) - .controller("myMenuAppController", ['$scope', 'apiHistoryService', 'sutService', 'authService', 'suggestionsService', 'helperFactory', 'ctrlConstants', - function ($scope, apiHistoryService, sutService,authService,suggestionsService,helperFactory,ctrlConstants){ - $scope.myUser = authService.getUserInfo().username; - $scope.sutlist = sutService.getGroupsByUser($scope.myUser); - $scope.servicevo = {}; - $scope.servicevo.matchTemplates = [{ id: 0, val: '' }]; - $scope.servicevo.failStatuses = [{ id: 0, val: '' }]; - $scope.servicevo.failStrings = [{ id: 0, val: '' }]; - $scope.servicevo.rawpairs = [{ - id: 0, - queriesArr: [{ - id: 0 - }], - reqHeadersArr: [{ - id: 0, - }], - resHeadersArr: [{ - id: 0 - }] - }]; - - $scope.statusCodes = suggestionsService.getStatusCodes(); - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - - $scope.addFailStatus = function(){ - $scope.servicevo.failStatuses.push({val:''}); - } - $scope.removeFailStatus= function(index){ - $scope.servicevo.failStatuses.splice(index,1); - } - $scope.addFailString = function(){ - $scope.servicevo.failStrings.push({val:''}); - } - $scope.removeFailString= function(index){ - $scope.servicevo.failStrings.splice(index,1); - } - $scope.addTemplate = function() { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - }; + .controller("myMenuAppController", ['$scope', 'apiHistoryService', 'sutService', 'authService', 'suggestionsService', 'helperFactory', 'ctrlConstants','modalService', + function ($scope, apiHistoryService, sutService, authService, suggestionsService, helperFactory, ctrlConstants,modalService) { + $scope.myUser = authService.getUserInfo().username; + $scope.sutlist = sutService.getGroupsByUser($scope.myUser); + $scope.servicevo = {}; + $scope.servicevo.matchTemplates = [{ id: 0, val: '' }]; + $scope.servicevo.failStatuses = [{ id: 0, val: '' }]; + $scope.servicevo.failStrings = [{ id: 0, val: '' }]; + $scope.servicevo.rawpairs = [{ + id: 0, + queriesArr: [{ + id: 0 + }], + reqHeadersArr: [{ + id: 0, + }], + resHeadersArr: [{ + id: 0 + }] + }]; + + $scope.statusCodes = suggestionsService.getStatusCodes(); + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + + $scope.addFailStatus = function () { + $scope.servicevo.failStatuses.push({ val: '' }); + } + $scope.removeFailStatus = function (index) { + $scope.servicevo.failStatuses.splice(index, 1); + } + $scope.addFailString = function () { + $scope.servicevo.failStrings.push({ val: '' }); + } + $scope.removeFailString = function (index) { + $scope.servicevo.failStrings.splice(index, 1); + } + $scope.addTemplate = function () { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + }; - $scope.removeTemplate = function(index) { - $scope.servicevo.matchTemplates.splice(index, 1); - }; + $scope.removeTemplate = function (index) { + $scope.servicevo.matchTemplates.splice(index, 1); + }; - $scope.addNewRRPair = function() { - var newItemNo = $scope.servicevo.rawpairs.length; - $scope.servicevo.rawpairs.push({ - id: newItemNo, - queriesArr: [{ - id: 0 - }], - reqHeadersArr: [{ - id: 0 - }], - resHeadersArr: [{ - id: 0 - }] - }); - }; + $scope.addNewRRPair = function () { + var newItemNo = $scope.servicevo.rawpairs.length; + $scope.servicevo.rawpairs.push({ + id: newItemNo, + queriesArr: [{ + id: 0 + }], + reqHeadersArr: [{ + id: 0 + }], + resHeadersArr: [{ + id: 0 + }] + }); + }; - $scope.removeRRPair = function(index) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $scope.rrPairNo = index; - $('#modal-btn-yes').on("click", function () { - $scope.servicevo.rawpairs.splice($scope.rrPairNo,1); - $scope.$apply(); - }); - }; + $scope.removeRRPair = function (index) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $scope.rrPairNo = index; + $('#modal-btn-yes').on("click", function () { + $scope.servicevo.rawpairs.splice($scope.rrPairNo, 1); + $scope.$apply(); + }); + }; - $scope.addNewReqHeader = function(rr) { - var newItemNo = rr.reqHeadersArr.length; - rr.reqHeadersArr.push({'id':newItemNo}); - }; + $scope.addNewReqHeader = function (rr) { + var newItemNo = rr.reqHeadersArr.length; + rr.reqHeadersArr.push({ 'id': newItemNo }); + }; - $scope.removeReqHeader = function(rr) { - var lastItem = rr.reqHeadersArr.length-1; - rr.reqHeadersArr.splice(lastItem); - }; + $scope.removeReqHeader = function (rr, index) { + rr.reqHeadersArr.splice(index, 1); + }; - $scope.addNewResHeader = function(rr) { - var newItemNo = rr.resHeadersArr.length; - rr.resHeadersArr.push({'id':newItemNo}); - }; + $scope.addNewResHeader = function (rr) { + var newItemNo = rr.resHeadersArr.length; + rr.resHeadersArr.push({ 'id': newItemNo }); + }; - $scope.removeResHeader = function(rr) { - var lastItem = rr.resHeadersArr.length-1; - rr.resHeadersArr.splice(lastItem); - }; + $scope.removeResHeader = function (rr, index) { + rr.resHeadersArr.splice(index, 1); + }; - $scope.addQuery = function(rr) { - var newItemNo = rr.queriesArr.length; - rr.queriesArr.push({'id':newItemNo}); - }; + $scope.addQuery = function (rr) { + var newItemNo = rr.queriesArr.length; + rr.queriesArr.push({ 'id': newItemNo }); + }; - $scope.removeQuery = function(rr) { - var lastItem = rr.queriesArr.length-1; - rr.queriesArr.splice(lastItem); - }; + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; - $scope.setContentType = function(rr, type) { - if (!rr) - rr = $scope.servicevo.rawpairs[0]; - - if (rr.reqHeadersArr.length < 2) - $scope.addNewReqHeader(rr); - - if (rr.resHeadersArr.length < 2) - $scope.addNewResHeader(rr); - - // set values - rr.reqHeadersArr[0].v = type; - rr.resHeadersArr[0].v = type; - - rr.reqHeadersArr[0].k = 'Content-Type'; - rr.resHeadersArr[0].k = 'Content-Type'; - - $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); - $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); - }; - - $scope.publishservice = function (servicevo) { - try { - if (helperFactory.isDuplicateReq(servicevo)) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } else { - apiHistoryService.publishServiceToAPI(servicevo); - } - } - catch (e) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_SERV_SAVE_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.PUB_FAIL_SERV_SAVE_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - // $('#modal-btn-yes').on("click", function () { - // apiHistoryService.saveServiceAsDraft(servicevo, false); - // }); - } - }; - }]) + $scope.setContentType = function (rr, type) { + if (!rr) + rr = $scope.servicevo.rawpairs[0]; - .controller("createRecorderController", ['$scope', 'apiHistoryService', 'sutService', 'authService', 'suggestionsService', 'helperFactory', 'ctrlConstants', - function($scope,apiHistoryService,sutService,authService,suggestionsService,helperFactory,ctrlConstants){ - $scope.myUser = authService.getUserInfo().username; - $scope.sutlist = sutService.getGroupsByUser($scope.myUser); - $scope.servicevo = {}; - $scope.servicevo.matchTemplates = [{ id: 0, val: '' }]; - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - $scope.servicevo.reqHeadersArr = [{id:0}]; - - $scope.showRecorderHelp = function(){ - $('#recordingHelp-modal').modal('toggle'); - } - $scope.addNewReqHeader = function(service) { - var newItemNo = service.reqHeadersArr.length; - service.reqHeadersArr.push({'id':newItemNo}); - }; + if (rr.reqHeadersArr.length < 2) + $scope.addNewReqHeader(rr); - $scope.removeReqHeader = function(service) { - var lastItem = service.reqHeadersArr.length-1; - service.reqHeadersArr.splice(lastItem); - }; + if (rr.resHeadersArr.length < 2) + $scope.addNewResHeader(rr); - $scope.createRecorder = function (servicevo) { - apiHistoryService.publishRecorderToAPI(servicevo); - }; + // set values + rr.reqHeadersArr[0].v = type; + rr.resHeadersArr[0].v = type; - }]) - .controller("viewRecorderController", ['$scope', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', '$timeout', - function($scope, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants,$timeout){ - $scope.statusCodes = suggestionsService.getStatusCodes(); - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - var totalRRPairs = 0; - - - - function processRRPairs(rrpairs){ - var rrpairsRaw = []; - var rrid = 0; - rrpairs.forEach(function(rr){ - rr.id = rrid++; - console.log(rr); - rr.queriesArr = []; - rr.reqHeadersArr = []; - rr.resHeadersArr = []; - rr.method = rr.verb; - - if (rr.payloadType === 'JSON') { - rr.requestpayload = JSON.stringify(rr.reqData); - rr.responsepayload = JSON.stringify(rr.resData); + rr.reqHeadersArr[0].k = 'Content-Type'; + rr.resHeadersArr[0].k = 'Content-Type'; - //Handle empty JSON object- stringify surrounds in "" - if(rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\""){ - rr.responsepayload = rr.responsepayload.substring(1,3); - } - } - else { - rr.requestpayload = rr.reqData; - rr.responsepayload = rr.resData; - } + $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); + $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); + }; - // map object literals to arrays for Angular view - if (rr.reqHeaders) { - var reqHeads = Object.entries(rr.reqHeaders); - var reqHeadId = 0; - reqHeads.forEach(function(elem){ - var head = {}; + $scope.publishservice = function (servicevo) { + try { + if (helperFactory.isDuplicateReq(servicevo)) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } else { + apiHistoryService.publishServiceToAPI(servicevo); + } + } + catch (e) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_SERV_SAVE_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.PUB_FAIL_SERV_SAVE_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.saveServiceAsDraft(servicevo, false); + }); + } + }; + $scope.showTemplateHelp = function(){ + modalService.showTemplateHelp(); + + } + }]) - head.id = reqHeadId; - head.k = elem[0]; - head.v = elem[1]; + .controller("createRecorderController", ['$scope', 'apiHistoryService', 'sutService', 'authService', 'suggestionsService', 'helperFactory', 'ctrlConstants', + function ($scope, apiHistoryService, sutService, authService, suggestionsService, helperFactory, ctrlConstants) { + $scope.orderByField = 'name'; + $scope.reverseSort = false; + $scope.myUser = authService.getUserInfo().username; + $scope.sutlist = sutService.getGroupsByUser($scope.myUser); + $scope.servicevo = {}; + $scope.servicevo.matchTemplates = [{ id: 0, val: '' }]; + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + $scope.servicevo.reqHeadersArr = [{ id: 0 }]; + $scope.servicevo.filterStatusCodes = [{ id: 0, v: '' }]; + $scope.servicevo.filterStrings = [{ id: 0, v: '' }]; + $scope.servicevo.filterHeaders = [{ id: 0, k: '', v: '' }]; + $scope.servicevo.currentUser = authService.getUserInfo().username; + + $scope.showRecorderHelp = function () { + $('#recordingHelp-modal').modal('toggle'); + } + $scope.addNewReqHeader = function (service) { + var newItemNo = service.reqHeadersArr.length; + service.reqHeadersArr.push({ 'id': newItemNo }); + }; + $scope.addNewStatusCode = function (service) { + service.filterStatusCodes.push({ 'id': service.filterStatusCodes.length }); + } + $scope.removeStatusCode = function (service) { + service.filterStatusCodes.splice(service.filterStatusCodes.length - 1); + } + $scope.addNewString = function (service) { + service.filterStrings.push({ 'id': service.filterStrings.length }); + } + $scope.removeString = function (service) { + service.filterStrings.splice(service.filterStrings.length - 1); + } + $scope.addNewFilterHeader = function (service) { + service.filterHeaders.push({ 'id': service.filterHeaders.length }); + } + $scope.removeFilterHeader = function (service) { + service.filterHeaders.splice(service.filterHeaders.length - 1); + } + + $scope.removeReqHeader = function (service, index) { + service.reqHeadersArr.splice(index, 1); + }; - rr.reqHeadersArr.push(head); - reqHeadId++; - }); - } - else { - rr.reqHeadersArr.push({ id: 0 }); - } + $scope.createRecorder = function (servicevo) { + apiHistoryService.publishRecorderToAPI(servicevo); + }; - if (rr.resHeaders) { - var resHeads = Object.entries(rr.resHeaders); - var resHeadId = 0; - resHeads.forEach(function(elem){ - var head = {}; - head.id = resHeadId; - head.k = elem[0]; - head.v = elem[1]; - rr.resHeadersArr.push(head); - resHeadId++; - }); - } - else { - rr.resHeadersArr.push({ id: 0 }); + }]) + .controller("viewRecorderController", ['$scope', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', '$timeout', + function ($scope, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, $timeout) { + $scope.statusCodes = suggestionsService.getStatusCodes(); + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + var totalRRPairs = 0; + + + + function processRRPairs(rrpairs) { + var rrpairsRaw = []; + var rrid = 0; + rrpairs.forEach(function (rr) { + rr.id = rrid++; + console.log(rr); + rr.queriesArr = []; + rr.reqHeadersArr = []; + rr.resHeadersArr = []; + rr.method = rr.verb; + + if (rr.payloadType === 'JSON') { + rr.requestpayload = JSON.stringify(rr.reqData); + rr.responsepayload = JSON.stringify(rr.resData); + + //Handle empty JSON object- stringify surrounds in "" + if (rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\"") { + rr.responsepayload = rr.responsepayload.substring(1, 3); } + } + else { + rr.requestpayload = rr.reqData; + rr.responsepayload = rr.resData; + } - if (rr.queries) { - var qs = Object.entries(rr.queries); - var qId = 0; - qs.forEach(function(elem){ - var q = {}; + // map object literals to arrays for Angular view + if (rr.reqHeaders) { + var reqHeads = Object.entries(rr.reqHeaders); + var reqHeadId = 0; + reqHeads.forEach(function (elem) { + var head = {}; - q.id = qId; - q.k = elem[0]; - q.v = elem[1]; + head.id = reqHeadId; + head.k = elem[0]; + head.v = elem[1]; - rr.queriesArr.push(q); - qId++; - }); - } - else { - rr.queriesArr.push({ id: 0 }); - } + rr.reqHeadersArr.push(head); + reqHeadId++; + }); + } + else { + rr.reqHeadersArr.push({ id: 0 }); + } - rrpairsRaw.push(rr); - }); - return rrpairsRaw; - } + if (rr.resHeaders) { + var resHeads = Object.entries(rr.resHeaders); + var resHeadId = 0; + resHeads.forEach(function (elem) { + var head = {}; - //Polls for new data + applies every X millis - function pollForNewRRPair(delay){ - $timeout(function(){ - apiHistoryService.getRecordingRRPairsWithIndex($routeParams.id,totalRRPairs).then(function(response){ - if(response.data.length){ - console.log(response.data); - var rrpairs = processRRPairs(response.data); - rrpairs.forEach(function(rr){ - rr.id = totalRRPairs++; - - }); - $scope.servicevo.rawpairs = $scope.servicevo.rawpairs.concat(rrpairs); - console.log(rrpairs); - } - if($routeParams.id) - pollForNewRRPair(delay); - }).catch(function(err){ - if($routeParams.id) - pollForNewRRPair(delay); + head.id = resHeadId; + head.k = elem[0]; + head.v = elem[1]; + + rr.resHeadersArr.push(head); + resHeadId++; }); } - - ,delay); + else { + rr.resHeadersArr.push({ id: 0 }); + } - } + if (rr.queries) { + var qs = Object.entries(rr.queries); + var qId = 0; + qs.forEach(function (elem) { + var q = {}; - $scope.removeRRPair = function(index) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $scope.rrPairNo = index; - $('#modal-btn-yes').on("click", function () { - $scope.servicevo.rawpairs.splice($scope.rrPairNo,1); - $scope.$apply(); + q.id = qId; + q.k = elem[0]; + q.v = elem[1]; + + rr.queriesArr.push(q); + qId++; }); - }; - - $scope.addTemplate = function() { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - }; + } + else { + rr.queriesArr.push({ id: 0 }); + } - $scope.removeTemplate = function(index) { - $scope.servicevo.matchTemplates.splice(index, 1); - }; + rrpairsRaw.push(rr); + }); + return rrpairsRaw; + } + + //Polls for new data + applies every X millis + function pollForNewRRPair(delay) { + $timeout(function () { + apiHistoryService.getRecordingRRPairsWithIndex($routeParams.id, totalRRPairs).then(function (response) { + if (response.data.length) { + console.log(response.data); + var rrpairs = processRRPairs(response.data); + rrpairs.forEach(function (rr) { + rr.id = totalRRPairs++; - $scope.addNewRRPair = function() { - var newItemNo = $scope.servicevo.rawpairs.length; - $scope.servicevo.rawpairs.push({ - id: newItemNo, - queriesArr: [{ - id: 0 - }], - reqHeadersArr: [{ - id: 0 - }], - resHeadersArr: [{ - id: 0 - }] + }); + $scope.servicevo.rawpairs = $scope.servicevo.rawpairs.concat(rrpairs); + console.log(rrpairs); + } + if ($routeParams.id) + pollForNewRRPair(delay); + }).catch(function (err) { + if ($routeParams.id) + pollForNewRRPair(delay); }); - }; + } - $scope.removeReqHeader = function(rr) { - var lastItem = rr.reqHeadersArr.length-1; - rr.reqHeadersArr.splice(lastItem); - }; + , delay); - $scope.addNewResHeader = function(rr) { - var newItemNo = rr.resHeadersArr.length; - rr.resHeadersArr.push({'id':newItemNo}); - }; + } - $scope.addNewReqHeader = function(rr) { - var newItemNo = rr.reqHeadersArr.length; - rr.reqHeadersArr.push({'id':newItemNo}); - }; - - $scope.removeResHeader = function(rr) { - var lastItem = rr.resHeadersArr.length-1; - rr.resHeadersArr.splice(lastItem); - }; + $scope.removeRRPair = function (index) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $scope.rrPairNo = index; + $('#modal-btn-yes').on("click", function () { + $scope.servicevo.rawpairs.splice($scope.rrPairNo, 1); + $scope.$apply(); + }); + }; - $scope.addQuery = function(rr) { - var newItemNo = rr.queriesArr.length; - rr.queriesArr.push({'id':newItemNo}); - }; + $scope.addTemplate = function () { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + }; - $scope.removeQuery = function(rr) { - var lastItem = rr.queriesArr.length-1; - rr.queriesArr.splice(lastItem); - }; - //Get this recorder's data - apiHistoryService.getRecordingById($routeParams.id) - .then(function(response) { + $scope.removeTemplate = function (index) { + $scope.servicevo.matchTemplates.splice(index, 1); + }; + + $scope.addNewRRPair = function () { + var newItemNo = $scope.servicevo.rawpairs.length; + $scope.servicevo.rawpairs.push({ + id: newItemNo, + queriesArr: [{ + id: 0 + }], + reqHeadersArr: [{ + id: 0 + }], + resHeadersArr: [{ + id: 0 + }] + }); + }; + + $scope.removeReqHeader = function (rr, index) { + rr.reqHeadersArr.splice(index, 1); + }; + + $scope.addNewResHeader = function (rr) { + var newItemNo = rr.resHeadersArr.length; + rr.resHeadersArr.push({ 'id': newItemNo }); + }; + + $scope.addNewReqHeader = function (rr) { + var newItemNo = rr.reqHeadersArr.length; + rr.reqHeadersArr.push({ 'id': newItemNo }); + }; + + $scope.removeResHeader = function (rr, index) { + rr.resHeadersArr.splice(index, 1); + }; + + $scope.addQuery = function (rr) { + var newItemNo = rr.queriesArr.length; + rr.queriesArr.push({ 'id': newItemNo }); + }; + + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; + //Get this recorder's data + apiHistoryService.getRecordingById($routeParams.id) + .then(function (response) { console.log(response); var recorder = response.data; var service = recorder.service; @@ -395,1408 +418,1805 @@ var ctrl = angular.module("mockapp.controllers",['mockapp.services','mockapp.fac sut: service.sut, name: service.name, type: service.type, - basePath: service.basePath + basePath: service.basePath.substring(0,1) == "/" ? service.basePath.substring(1) : service.basePath + }; $scope.servicevo.matchTemplates = [{ id: 0, val: '' }]; $scope.servicevo.rawpairs = processRRPairs(service.rrpairs); totalRRPairs = service.rrpairs.length; - + pollForNewRRPair(3000); }); - $scope.publishService = function(servicevo) { - try { - if (helperFactory.isDuplicateReq(servicevo)) { + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + var newsutlist = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + newsutlist.push(sut.name); + } + }); + }); + $scope.canEdit = function () { + if (newsutlist.includes($scope.servicevo.sut.name)) { + return true; + } + else { + + return false; + } + }; + }) + + .catch(function (err) { + console.log(err); + }); + + $scope.publishService = function (servicevo) { + try { + if (helperFactory.isDuplicateReq(servicevo)) { $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); $('#genricMsg-dialog').modal('toggle'); - } else { - apiHistoryService.publishServiceToAPI(servicevo, false,true); + } else { + apiHistoryService.publishServiceToAPI(servicevo, false, true); - } - } - catch(e) { - console.log(e); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); } - }; + } + catch (e) { + console.log(e); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } + }; }]) - - .controller("showArchiveController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', - function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService) { - - $scope.statusCodes = suggestionsService.getStatusCodes(); - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - - this.getService = function() { - apiHistoryService.getArchiveServiceById($routeParams.id) - .then(function(response) { - var service; - if(response.data.service) service = response.data.service; - if(response.data.mqservice) service = response.data.mqservice; - console.log(service); - $scope.servicevo = { - id: service._id, - sut: service.sut, - name: service.name, - type: service.type, - delay: service.delay, - delayMax: service.delayMax, - txnCount: service.txnCount, - basePath: service.basePath, - - }; - - $scope.myUser = authService.getUserInfo().username; - - //returning a promise from factory didnt seem to work with .then() function here, alternative solution - $http.get('/api/systems') - .then(function (response) { - var newsutlist = []; - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sut.members.forEach(function (memberlist) { - if (memberlist.includes($scope.myUser)) { - newsutlist.push(sut.name); - } - }); - }); - $scope.canEdit = function () { - return false; - }; - }) - - .catch(function (err) { - console.log(err); - }); - - if(service.lastUpdateUser){ - $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; - } - if(service.createdAt){ - $scope.servicevo.createdAt = service.createdAt; - } - if(service.updatedAt){ - $scope.servicevo.updatedAt = service.updatedAt; - } - - $scope.servicevo.matchTemplates = []; - $scope.servicevo.rawpairs = []; - - if (service.matchTemplates && service.matchTemplates.length) { - service.matchTemplates.forEach(function(template, index) { - $scope.servicevo.matchTemplates.push({ id: index, val: template }); - }); - } - else { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - } - - var rrid = 0; - service.rrpairs.forEach(function(rr){ - rr.id = rrid; - rr.queriesArr = []; - rr.reqHeadersArr = []; - rr.resHeadersArr = []; - rr.method = rr.verb; - - if (rr.payloadType === 'JSON') { - rr.requestpayload = JSON.stringify(rr.reqData, null, 4); - rr.responsepayload = JSON.stringify(rr.resData, null, 4); - - //Handle empty JSON object- stringify surrounds in "" - if(rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\""){ - rr.responsepayload = rr.responsepayload.substring(1,3); - } - } - else { - rr.requestpayload = rr.reqData; - rr.responsepayload = rr.resData; - } - - // map object literals to arrays for Angular view - if (rr.reqHeaders) { - var reqHeads = Object.entries(rr.reqHeaders); - var reqHeadId = 0; - reqHeads.forEach(function(elem){ - var head = {}; - - head.id = reqHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.reqHeadersArr.push(head); - reqHeadId++; - }); - } - else { - rr.reqHeadersArr.push({ id: 0 }); - } - - if (rr.resHeaders) { - var resHeads = Object.entries(rr.resHeaders); - var resHeadId = 0; - resHeads.forEach(function(elem){ - var head = {}; - - head.id = resHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.resHeadersArr.push(head); - resHeadId++; - }); - } - else { - rr.resHeadersArr.push({ id: 0 }); - } - - if (rr.queries) { - var qs = Object.entries(rr.queries); - var qId = 0; - qs.forEach(function(elem){ - var q = {}; - - q.id = qId; - q.k = elem[0]; - q.v = elem[1]; - - rr.queriesArr.push(q); - qId++; - }); - } - else { - rr.queriesArr.push({ id: 0 }); - } - - $scope.servicevo.rawpairs.push(rr); - rrid++; - }); - }) - - .catch(function(err) { - console.log(err); - }); - }; - this.getService(); - }]) - .controller("showDraftController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', - function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService) { - - $scope.statusCodes = suggestionsService.getStatusCodes(); - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - - this.getService = function() { - apiHistoryService.getDraftServiceById($routeParams.id) - - .then(function(response) { - var service; - if(response.data.service) service = response.data.service; - if(response.data.mqservice) service = response.data.mqservice; - - console.log(service); - $scope.servicevo = { - id: service._id, - sut: service.sut, - name: service.name, - type: service.type, - delay: service.delay, - delayMax: service.delayMax, - txnCount: service.txnCount, - basePath: service.basePath - }; - - if(service.liveInvocation){ - - $scope.servicevo.remoteHost = service.liveInvocation.remoteHost; - $scope.servicevo.remotePort = service.liveInvocation.remotePort; - $scope.servicevo.remotePath = service.liveInvocation.remoteBasePath; - $scope.servicevo.liveInvocationCheck = service.liveInvocation.enabled; - $scope.servicevo.invokeSSL = service.liveInvocation.ssl; - //Extract and build out codes/strings for failures - var failStatusCodes = service.liveInvocation.failStatusCodes; - var failStrings = service.liveInvocation.failStrings; - $scope.servicevo.failStatuses = []; - $scope.servicevo.failStrings = []; - for(var i = 0; i < failStatusCodes.length; i++){ - $scope.servicevo.failStatuses[i] = {'id': i, 'val' : failStatusCodes[i]}; - - } - for(var i = 0; i < failStrings.length; i++){ - $scope.servicevo.failStrings[i] = {'id': i, 'val' : failStrings[i]}; - } - if(!$scope.servicevo.failStatuses.length){ - $scope.servicevo.failStatuses[0] = {'id': 0,val:''}; - } - if(!$scope.servicevo.failStrings.length){ - $scope.servicevo.failStrings[0] = {'id': 0,val:''}; - } - //Select correct radio - if(service.liveInvocation.liveFirst) - $scope.servicevo.liveInvokePrePost = 'PRE'; - else - $scope.servicevo.liveInvokePrePost = 'POST'; - - }else{ - $scope.servicevo.failStatuses = []; - $scope.servicevo.failStrings = []; - $scope.servicevo.failStatuses[0] = {'id': 0,val:''}; - $scope.servicevo.failStrings[0] = {'id': 0,val:''}; - } - console.log($scope.servicevo); - - $scope.myUser = authService.getUserInfo().username; - - //returning a promise from factory didnt seem to work with .then() function here, alternative solution - $http.get('/api/systems') - .then(function (response) { - var newsutlist = []; - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sut.members.forEach(function (memberlist) { - if (memberlist.includes($scope.myUser)) { - newsutlist.push(sut.name); - } - }); - }); - - $scope.canEdit = function () { - if (newsutlist.includes($scope.servicevo.sut.name )) { - return true; - } - else { - return false; - } - }; - }) - - .catch(function (err) { - console.log(err); - }); - - if(service.lastUpdateUser){ - $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; - } - if(service.createdAt){ - $scope.servicevo.createdAt = service.createdAt; - } - if(service.updatedAt){ - $scope.servicevo.updatedAt = service.updatedAt; - } + .controller("showArchiveController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', + function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService) { + + $scope.statusCodes = suggestionsService.getStatusCodes(); + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + + this.getService = function () { + apiHistoryService.getArchiveServiceById($routeParams.id) + .then(function (response) { + var service; + if (response.data.service) service = response.data.service; + if (response.data.mqservice) service = response.data.mqservice; + console.log(service); + $scope.servicevo = { + id: service._id, + sut: service.sut, + name: service.name, + type: service.type, + delay: service.delay, + delayMax: service.delayMax, + txnCount: service.txnCount, + basePath: service.basePath, - $scope.servicevo.matchTemplates = []; - $scope.servicevo.rawpairs = []; + }; + $scope.myUser = authService.getUserInfo().username; - if (service.matchTemplates && service.matchTemplates.length) { - service.matchTemplates.forEach(function(template, index) { - $scope.servicevo.matchTemplates.push({ id: index, val: template }); - }); + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + var newsutlist = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + newsutlist.push(sut.name); } - else { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - } - - var rrid = 0; - service.rrpairs.forEach(function(rr){ - rr.id = rrid; - rr.queriesArr = []; - rr.reqHeadersArr = []; - rr.resHeadersArr = []; - rr.method = rr.verb; - - if (rr.payloadType === 'JSON') { - rr.requestpayload = JSON.stringify(rr.reqData, null, 4); - rr.responsepayload = JSON.stringify(rr.resData, null, 4); - - //Handle empty JSON object- stringify surrounds in "" - if(rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\""){ - rr.responsepayload = rr.responsepayload.substring(1,3); - } - } - else { - rr.requestpayload = rr.reqData; - rr.responsepayload = rr.resData; - } - - // map object literals to arrays for Angular view - if (rr.reqHeaders) { - var reqHeads = Object.entries(rr.reqHeaders); - var reqHeadId = 0; - reqHeads.forEach(function(elem){ - var head = {}; - - head.id = reqHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.reqHeadersArr.push(head); - reqHeadId++; - }); - } - else { - rr.reqHeadersArr.push({ id: 0 }); - } - - if (rr.resHeaders) { - var resHeads = Object.entries(rr.resHeaders); - var resHeadId = 0; - resHeads.forEach(function(elem){ - var head = {}; - - head.id = resHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.resHeadersArr.push(head); - resHeadId++; - }); - } - else { - rr.resHeadersArr.push({ id: 0 }); - } - - if (rr.queries) { - var qs = Object.entries(rr.queries); - var qId = 0; - qs.forEach(function(elem){ - var q = {}; - - q.id = qId; - q.k = elem[0]; - q.v = elem[1]; - - rr.queriesArr.push(q); - qId++; - }); - } - else { - rr.queriesArr.push({ id: 0 }); - } - - $scope.servicevo.rawpairs.push(rr); - rrid++; - }); - }) - - .catch(function(err) { - console.log(err); + }); }); - }; - this.getService(); + }) + .catch(function (err) { + console.log(err); + }); - $scope.addFailStatus = function(){ - $scope.servicevo.failStatuses.push({val:''}); + $scope.canEdit = function () { + return false; + }; + + if ($routeParams.frmWher == 'frmArchive') { + $scope.isFrmArchive = true; } - $scope.removeFailStatus= function(index){ - $scope.servicevo.failStatuses.splice(index,1); + if (service.lastUpdateUser) { + $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; } - $scope.addFailString = function(){ - $scope.servicevo.failStrings.push({val:''}); + if (service.createdAt) { + $scope.servicevo.createdAt = service.createdAt; } - $scope.removeFailString= function(index){ - $scope.servicevo.failStrings.splice(index,1); + if (service.updatedAt) { + $scope.servicevo.updatedAt = service.updatedAt; } - $scope.addTemplate = function() { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - }; - $scope.removeTemplate = function(index) { - $scope.servicevo.matchTemplates.splice(index, 1); - }; + $scope.servicevo.matchTemplates = []; + $scope.servicevo.rawpairs = []; - $scope.addNewRRPair = function() { - var newItemNo = $scope.servicevo.rawpairs.length; - $scope.servicevo.rawpairs.push({ - id: newItemNo, - queriesArr: [{ - id: 0 - }], - reqHeadersArr: [{ - id: 0 - }], - resHeadersArr: [{ - id: 0 - }] + if (service.matchTemplates && service.matchTemplates.length) { + service.matchTemplates.forEach(function (template, index) { + $scope.servicevo.matchTemplates.push({ id: index, val: template }); }); - }; - - $scope.removeRRPair = function(index) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $scope.rrPairNo = index; - $('#modal-btn-yes').on("click", function () { - $scope.servicevo.rawpairs.splice($scope.rrPairNo,1); - $scope.$apply(); - }); - }; + } + else { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + } - $scope.addNewReqHeader = function(rr) { - var newItemNo = rr.reqHeadersArr.length; - rr.reqHeadersArr.push({'id':newItemNo}); - }; + var rrid = 0; + service.rrpairs.forEach(function (rr) { + rr.id = rrid; + rr.queriesArr = []; + rr.reqHeadersArr = []; + rr.resHeadersArr = []; + rr.method = rr.verb; + + if (rr.payloadType === 'JSON') { + rr.requestpayload = JSON.stringify(rr.reqData, null, 4); + rr.responsepayload = JSON.stringify(rr.resData, null, 4); + + //Handle empty JSON object- stringify surrounds in "" + if (rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\"") { + rr.responsepayload = rr.responsepayload.substring(1, 3); + } + } + else { + rr.requestpayload = rr.reqData; + rr.responsepayload = rr.resData; + } - $scope.removeReqHeader = function(rr) { - var lastItem = rr.reqHeadersArr.length-1; - rr.reqHeadersArr.splice(lastItem); - }; + // map object literals to arrays for Angular view + if (rr.reqHeaders) { + var reqHeads = Object.entries(rr.reqHeaders); + var reqHeadId = 0; + reqHeads.forEach(function (elem) { + var head = {}; - $scope.addNewResHeader = function(rr) { - var newItemNo = rr.resHeadersArr.length; - rr.resHeadersArr.push({'id':newItemNo}); - }; + head.id = reqHeadId; + head.k = elem[0]; + head.v = elem[1]; - $scope.removeResHeader = function(rr) { - var lastItem = rr.resHeadersArr.length-1; - rr.resHeadersArr.splice(lastItem); - }; + rr.reqHeadersArr.push(head); + reqHeadId++; + }); + } + else { + rr.reqHeadersArr.push({ id: 0 }); + } - $scope.addQuery = function(rr) { - var newItemNo = rr.queriesArr.length; - rr.queriesArr.push({'id':newItemNo}); - }; + if (rr.resHeaders) { + var resHeads = Object.entries(rr.resHeaders); + var resHeadId = 0; + resHeads.forEach(function (elem) { + var head = {}; - $scope.removeQuery = function(rr) { - var lastItem = rr.queriesArr.length-1; - rr.queriesArr.splice(lastItem); - }; + head.id = resHeadId; + head.k = elem[0]; + head.v = elem[1]; - $scope.updateService = function(servicevo) { - try { - if (helperFactory.isDuplicateReq(servicevo)) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } else { - apiHistoryService.publishServiceToAPI(servicevo, true); - } - } - catch(e) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_SERV_SAVE_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.PUB_FAIL_SERV_SAVE_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $('#modal-btn-yes').on("click", function() { - apiHistoryService.saveServiceAsDraft(servicevo, true); + rr.resHeadersArr.push(head); + resHeadId++; }); } - }; + else { + rr.resHeadersArr.push({ id: 0 }); + } - $scope.serviceInfo = function() { - console.log($routeParams.id); - $http.get('/api/services/draft/' + $routeParams.id) - - .then(function(response) { - var data; - if(response.data.mqservice) - data = response.data.mqservice; - else - data = response.data.service; - console.log(data); - feedbackService.displayServiceInfo(data); - $('#serviceInfo-modal').modal('toggle'); - }) + if (rr.queries) { + var qs = Object.entries(rr.queries); + var qId = 0; + qs.forEach(function (elem) { + var q = {}; - .catch(function(err) { - console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.SERV_SAVE_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.SERV_INFO_NOT_FOUND); - $('#genricMsg-dialog').modal('toggle'); - }); - }; + q.id = qId; + q.k = elem[0]; + q.v = elem[1]; - $scope.setContentType = function(rr, type) { - if (rr.reqHeadersArr.length < 2) - $scope.addNewReqHeader(rr); + rr.queriesArr.push(q); + qId++; + }); + } + else { + rr.queriesArr.push({ id: 0 }); + } - if (rr.resHeadersArr.length < 2) - $scope.addNewResHeader(rr); + $scope.servicevo.rawpairs.push(rr); + rrid++; + }); + }) - // set values - rr.reqHeadersArr[0].v = type; - rr.resHeadersArr[0].v = type; - - rr.reqHeadersArr[0].k = 'Content-Type'; - rr.resHeadersArr[0].k = 'Content-Type'; + .catch(function (err) { + console.log(err); + }); + }; + this.getService(); + }]) - $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); - $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); + .controller("showDraftController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', + function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService) { + + $scope.statusCodes = suggestionsService.getStatusCodes(); + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + + this.getService = function () { + apiHistoryService.getDraftServiceById($routeParams.id) + + .then(function (response) { + var service; + if (response.data.service) service = response.data.service; + if (response.data.mqservice) service = response.data.mqservice; + + console.log(service); + $scope.servicevo = { + id: service._id, + sut: service.sut, + name: service.name, + type: service.type, + delay: service.delay, + delayMax: service.delayMax, + txnCount: service.txnCount, + basePath: service.basePath }; - $scope.totalDisplayed = 10; - - $scope.loadMore = function () { - $scope.totalDisplayed += 10; - }; - - }]) + if (service.liveInvocation) { + + $scope.servicevo.remoteHost = service.liveInvocation.remoteHost; + $scope.servicevo.remotePort = service.liveInvocation.remotePort; + $scope.servicevo.remotePath = service.liveInvocation.remoteBasePath; + $scope.servicevo.liveInvocationCheck = service.liveInvocation.enabled; + $scope.servicevo.invokeSSL = service.liveInvocation.ssl; + //Extract and build out codes/strings for failures + var failStatusCodes = service.liveInvocation.failStatusCodes; + var failStrings = service.liveInvocation.failStrings; + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + for (var i = 0; i < failStatusCodes.length; i++) { + $scope.servicevo.failStatuses[i] = { 'id': i, 'val': failStatusCodes[i] }; - - .controller("updateController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', - function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService) { - - $scope.statusCodes = suggestionsService.getStatusCodes(); - $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); - - this.getService = function() { - apiHistoryService.getServiceById($routeParams.id) - - .then(function(response) { - var service = response.data; - console.log(service); - $scope.servicevo = { - id: service._id, - sut: service.sut, - name: service.name, - type: service.type, - delay: service.delay, - delayMax: service.delayMax, - txnCount: service.txnCount, - basePath: service.basePath, - - - }; - - if(service.liveInvocation){ - - $scope.servicevo.remoteHost = service.liveInvocation.remoteHost; - $scope.servicevo.remotePort = service.liveInvocation.remotePort; - $scope.servicevo.remotePath = service.liveInvocation.remoteBasePath; - $scope.servicevo.liveInvocationCheck = service.liveInvocation.enabled; - $scope.servicevo.invokeSSL = service.liveInvocation.ssl; - //Extract and build out codes/strings for failures - var failStatusCodes = service.liveInvocation.failStatusCodes; - var failStrings = service.liveInvocation.failStrings; - $scope.servicevo.failStatuses = []; - $scope.servicevo.failStrings = []; - for(var i = 0; i < failStatusCodes.length; i++){ - $scope.servicevo.failStatuses[i] = {'id': i, 'val' : failStatusCodes[i]}; - - } - for(var i = 0; i < failStrings.length; i++){ - $scope.servicevo.failStrings[i] = {'id': i, 'val' : failStrings[i]}; - } - if(!$scope.servicevo.failStatuses.length){ - $scope.servicevo.failStatuses[0] = {'id': 0,val:''}; - } - if(!$scope.servicevo.failStrings.length){ - $scope.servicevo.failStrings[0] = {'id': 0,val:''}; - } - //Select correct radio - if(service.liveInvocation.liveFirst) - $scope.servicevo.liveInvokePrePost = 'PRE'; - else - $scope.servicevo.liveInvokePrePost = 'POST'; - - }else{ - $scope.servicevo.failStatuses = []; - $scope.servicevo.failStrings = []; - $scope.servicevo.failStatuses[0] = {'id': 0,val:''}; - $scope.servicevo.failStrings[0] = {'id': 0,val:''}; - } - console.log($scope.servicevo); - - - $scope.myUser = authService.getUserInfo().username; - - //returning a promise from factory didnt seem to work with .then() function here, alternative solution - $http.get('/api/systems') - .then(function (response) { - var newsutlist = []; - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sut.members.forEach(function (memberlist) { - if (memberlist.includes($scope.myUser)) { - newsutlist.push(sut.name); - } - }); - }); - $scope.canEdit = function () { - if (newsutlist.includes($scope.servicevo.sut.name )) { - return true; - } - else { - return false; - } - }; - }) - - .catch(function (err) { - console.log(err); - }); - - if(service.lastUpdateUser){ - $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; - } - if(service.createdAt){ - $scope.servicevo.createdAt = service.createdAt; - } - if(service.updatedAt){ - $scope.servicevo.updatedAt = service.updatedAt; - } + } + for (var i = 0; i < failStrings.length; i++) { + $scope.servicevo.failStrings[i] = { 'id': i, 'val': failStrings[i] }; + } + if (!$scope.servicevo.failStatuses.length) { + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + } + if (!$scope.servicevo.failStrings.length) { + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + //Select correct radio + if (service.liveInvocation.liveFirst) + $scope.servicevo.liveInvokePrePost = 'PRE'; + else + $scope.servicevo.liveInvokePrePost = 'POST'; - $scope.servicevo.matchTemplates = []; - $scope.servicevo.rawpairs = []; + } else { + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + console.log($scope.servicevo); + $scope.myUser = authService.getUserInfo().username; - if (service.matchTemplates && service.matchTemplates.length) { - service.matchTemplates.forEach(function(template, index) { - $scope.servicevo.matchTemplates.push({ id: index, val: template }); - }); - } - else { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + var newsutlist = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + newsutlist.push(sut.name); } - - var rrid = 0; - service.rrpairs.forEach(function(rr){ - rr.id = rrid; - rr.queriesArr = []; - rr.reqHeadersArr = []; - rr.resHeadersArr = []; - rr.method = rr.verb; - - if (rr.payloadType === 'JSON') { - rr.requestpayload = JSON.stringify(rr.reqData, null, 4); - rr.responsepayload = JSON.stringify(rr.resData, null, 4); - - //Handle empty JSON object- stringify surrounds in "" - if(rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\""){ - rr.responsepayload = rr.responsepayload.substring(1,3); - } - } - else { - rr.requestpayload = rr.reqData; - rr.responsepayload = rr.resData; - } - - // map object literals to arrays for Angular view - if (rr.reqHeaders) { - var reqHeads = Object.entries(rr.reqHeaders); - var reqHeadId = 0; - reqHeads.forEach(function(elem){ - var head = {}; - - head.id = reqHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.reqHeadersArr.push(head); - reqHeadId++; - }); - } - else { - rr.reqHeadersArr.push({ id: 0 }); - } - - if (rr.resHeaders) { - var resHeads = Object.entries(rr.resHeaders); - var resHeadId = 0; - resHeads.forEach(function(elem){ - var head = {}; - - head.id = resHeadId; - head.k = elem[0]; - head.v = elem[1]; - - rr.resHeadersArr.push(head); - resHeadId++; - }); - } - else { - rr.resHeadersArr.push({ id: 0 }); - } - - if (rr.queries) { - var qs = Object.entries(rr.queries); - var qId = 0; - qs.forEach(function(elem){ - var q = {}; - - q.id = qId; - q.k = elem[0]; - q.v = elem[1]; - - rr.queriesArr.push(q); - qId++; - }); - } - else { - rr.queriesArr.push({ id: 0 }); - } - - $scope.servicevo.rawpairs.push(rr); - rrid++; - }); - }) - - .catch(function(err) { - console.log(err); + }); }); - }; - this.getService(); + $scope.canEdit = function () { + if (newsutlist.includes($scope.servicevo.sut.name)) { + return true; + } + else { + return false; + } + }; + }) - $scope.addFailStatus = function(){ - $scope.servicevo.failStatuses.push({val:''}); - } - $scope.removeFailStatus= function(index){ - $scope.servicevo.failStatuses.splice(index,1); + .catch(function (err) { + console.log(err); + }); + + if (service.lastUpdateUser) { + $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; } - $scope.addFailString = function(){ - $scope.servicevo.failStrings.push({val:''}); + if (service.createdAt) { + $scope.servicevo.createdAt = service.createdAt; } - $scope.removeFailString= function(index){ - $scope.servicevo.failStrings.splice(index,1); + if (service.updatedAt) { + $scope.servicevo.updatedAt = service.updatedAt; } - $scope.addTemplate = function() { - $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); - }; - - $scope.removeTemplate = function(index) { - $scope.servicevo.matchTemplates.splice(index, 1); - }; - - $scope.addNewRRPair = function() { - var newItemNo = $scope.servicevo.rawpairs.length; - $scope.servicevo.rawpairs.push({ - id: newItemNo, - queriesArr: [{ - id: 0 - }], - reqHeadersArr: [{ - id: 0 - }], - resHeadersArr: [{ - id: 0 - }] - }); - }; - $scope.removeRRPair = function(index) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $scope.rrPairNo = index; - $('#modal-btn-yes').on("click", function () { - $scope.servicevo.rawpairs.splice($scope.rrPairNo,1); - $scope.$apply(); - }); - }; + $scope.servicevo.matchTemplates = []; + $scope.servicevo.rawpairs = []; - $scope.addNewReqHeader = function(rr) { - var newItemNo = rr.reqHeadersArr.length; - rr.reqHeadersArr.push({'id':newItemNo}); - }; - $scope.removeReqHeader = function(rr) { - var lastItem = rr.reqHeadersArr.length-1; - rr.reqHeadersArr.splice(lastItem); - }; + if (service.matchTemplates && service.matchTemplates.length) { + service.matchTemplates.forEach(function (template, index) { + $scope.servicevo.matchTemplates.push({ id: index, val: template }); + }); + } + else { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + } - $scope.addNewResHeader = function(rr) { - var newItemNo = rr.resHeadersArr.length; - rr.resHeadersArr.push({'id':newItemNo}); - }; + var rrid = 0; + service.rrpairs.forEach(function (rr) { + rr.id = rrid; + rr.queriesArr = []; + rr.reqHeadersArr = []; + rr.resHeadersArr = []; + rr.method = rr.verb; - $scope.removeResHeader = function(rr) { - var lastItem = rr.resHeadersArr.length-1; - rr.resHeadersArr.splice(lastItem); - }; + //Handle empty JSON object- stringify surrounds in "" + if (rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\"") { + rr.responsepayload = rr.responsepayload.substring(1, 3); + } + + rr.requestpayload = rr.reqData; + rr.responsepayload = rr.resData; - $scope.addQuery = function(rr) { - var newItemNo = rr.queriesArr.length; - rr.queriesArr.push({'id':newItemNo}); - }; + // map object literals to arrays for Angular view + if (rr.reqHeaders) { + var reqHeads = Object.entries(rr.reqHeaders); + var reqHeadId = 0; + reqHeads.forEach(function (elem) { + var head = {}; - $scope.removeQuery = function(rr) { - var lastItem = rr.queriesArr.length-1; - rr.queriesArr.splice(lastItem); - }; + head.id = reqHeadId; + head.k = elem[0]; + head.v = elem[1]; - $scope.updateService = function(servicevo) { - try { - if (helperFactory.isDuplicateReq(servicevo)) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } else { - apiHistoryService.publishServiceToAPI(servicevo, true); - } + rr.reqHeadersArr.push(head); + reqHeadId++; + }); } - catch(e) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); + else { + rr.reqHeadersArr.push({ id: 0 }); } - }; - $scope.setContentType = function(rr, type) { - if (rr.reqHeadersArr.length < 2) - $scope.addNewReqHeader(rr); + if (rr.resHeaders) { + var resHeads = Object.entries(rr.resHeaders); + var resHeadId = 0; + resHeads.forEach(function (elem) { + var head = {}; - if (rr.resHeadersArr.length < 2) - $scope.addNewResHeader(rr); + head.id = resHeadId; + head.k = elem[0]; + head.v = elem[1]; - // set values - rr.reqHeadersArr[0].v = type; - rr.resHeadersArr[0].v = type; - - rr.reqHeadersArr[0].k = 'Content-Type'; - rr.resHeadersArr[0].k = 'Content-Type'; - - $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); - $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); - }; - - $scope.serviceInfo = function() { - console.log($routeParams.id); - $http.get('/api/services/' + $routeParams.id) + rr.resHeadersArr.push(head); + resHeadId++; + }); + } + else { + rr.resHeadersArr.push({ id: 0 }); + } - .then(function(response) { - var data = response.data; - console.log(data); - feedbackService.displayServiceInfo(data); - $('#serviceInfo-modal').modal('toggle'); - }) + if (rr.queries) { + var qs = Object.entries(rr.queries); + var qId = 0; + qs.forEach(function (elem) { + var q = {}; - .catch(function(err) { - console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - }); - }; + q.id = qId; + q.k = elem[0]; + q.v = elem[1]; - $scope.totalDisplayed = 10; + rr.queriesArr.push(q); + qId++; + }); + } + else { + rr.queriesArr.push({ id: 0 }); + } - $scope.loadMore = function () { - $scope.totalDisplayed += 10; - }; + $scope.servicevo.rawpairs.push(rr); + rrid++; + }); + }) - //To Show Service Success Modal when a new service is created. - if($routeParams.frmWher=='frmServCreate'){ - $http.get('/api/services/' + $routeParams.id) - .then(function(response) { - var data = response.data; - console.log(data); - feedbackService.displayServiceInfo(data); - }) - .catch(function(err) { - console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - }); - $('#success-modal').modal('toggle'); - } - }]) + .catch(function (err) { + console.log(err); + }); + }; + this.getService(); + + $scope.addFailStatus = function () { + $scope.servicevo.failStatuses.push({ val: '' }); + } + $scope.removeFailStatus = function (index) { + $scope.servicevo.failStatuses.splice(index, 1); + } + $scope.addFailString = function () { + $scope.servicevo.failStrings.push({ val: '' }); + } + $scope.removeFailString = function (index) { + $scope.servicevo.failStrings.splice(index, 1); + } + $scope.addTemplate = function () { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + }; - .controller("selectServiceController", ['$scope', 'apiHistoryService','authService', - function($scope,apiHistoryService,authService){ - $scope.serviceList = []; - apiHistoryService.getRecentModifiedServices(5,authService.getUserInfo().username).then(function(response){ - var data = response.data; - $scope.serviceList = data; - console.log(data); - }); - }]) - .controller("recorderListController", ['$scope', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', - function($scope,$http,$timeout,sutService,feedbackService,apiHistoryService,userService,authService,FileSaver,Blob,ctrlConstants){ - $scope.sutlist = sutService.getAllSUT(); - $scope.userlist = userService.getAllUsers(); - $scope.recordingList = []; - apiHistoryService.getRecordings().then(function(response){ - var data = response.data; - $scope.recordingList = data; - }); + $scope.removeTemplate = function (index) { + $scope.servicevo.matchTemplates.splice(index, 1); + }; + $scope.addNewRRPair = function () { + var newItemNo = $scope.servicevo.rawpairs.length; + $scope.servicevo.rawpairs.push({ + id: newItemNo, + queriesArr: [{ + id: 0 + }], + reqHeadersArr: [{ + id: 0 + }], + resHeadersArr: [{ + id: 0 + }] + }); + }; - $scope.deleteRecording = function (recording) { + $scope.removeRRPair = function (index) { $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_REC_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); $('#genricMsg-dialog').modal('toggle'); + $scope.rrPairNo = index; $('#modal-btn-yes').on("click", function () { - apiHistoryService.deleteRecording(recording._id) - .then(function (response) { - - $scope.recordingList.forEach(function (elem, i, arr) { - if (elem._id === recording._id) - arr.splice(i, 1); - }); - }) - .catch(function (err) { - console.log(err); - }); + $scope.servicevo.rawpairs.splice($scope.rrPairNo, 1); + $scope.$apply(); }); }; + $scope.addNewReqHeader = function (rr) { + var newItemNo = rr.reqHeadersArr.length; + rr.reqHeadersArr.push({ 'id': newItemNo }); + }; - }]) + $scope.removeReqHeader = function (rr, index) { + rr.reqHeadersArr.splice(index, 1); + }; - .controller("serviceHistoryController", ['$scope', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', - function($scope,$http,$timeout,sutService,feedbackService,apiHistoryService,userService,authService,FileSaver,Blob,ctrlConstants){ - $scope.sutlist = sutService.getAllSUT(); - $scope.userlist = userService.getAllUsers(); - $scope.servicelist = []; - - //script to retroactively assign group member. not needed for the future. - $scope.script=function(){ - console.log("starting script"); - var sutnames = []; - $http.get('/api/systems') - .then(function (response) { - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sutnames.push(sut.name); - }); - }) + $scope.addNewResHeader = function (rr) { + var newItemNo = rr.resHeadersArr.length; + rr.resHeadersArr.push({ 'id': newItemNo }); + }; - .catch(function (err) { - console.log(err); - }); + $scope.removeResHeader = function (rr, index) { + rr.resHeadersArr.splice(index, 1); + }; - $http.get('/api/services') - .then(function (response) { - console.log(response.data); - for (var i = 0; i < response.data.length; i++) { - var owner = ["mockiato", response.data[i].user.uid];//change superuser name if neccesary - var sut = response.data[i].sut.name; - - if (sutnames.includes(sut)){ - console.log("------------------------------------"); - console.log("sut "+ sut + " exists"); - console.log(owner + " will be added to group: " + sut); - sutService.updateGroup(sut, owner); - } - else{ - console.log("------------------------------------"); - console.log("sut " + sut + " does not exist"); - } - } - }) + $scope.addQuery = function (rr) { + var newItemNo = rr.queriesArr.length; + rr.queriesArr.push({ 'id': newItemNo }); + }; - .catch(function (err) { - console.log(err); - }); - } - ///////////////////////////end script. to remove + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; - $scope.filtersSelected = function(sut, user) { - if (sut && !user) { - apiHistoryService.getServiceForSUT(sut.name) + $scope.updateService = function (servicevo) { + try { + if (helperFactory.isDuplicateReq(servicevo)) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } else { + apiHistoryService.publishServiceToAPI(servicevo, true); + } + } + catch (e) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_SERV_SAVE_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.PUB_FAIL_SERV_SAVE_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.saveServiceAsDraft(servicevo, true); + }); + } + }; - .then(function(response) { - var data = response.data; - console.log(data); - $scope.servicelist = data; - }) + //To Show Service Success Modal when a new service is created as draft + if ($routeParams.frmWher == 'frmCreateDraft') { + $http.get('/api/services/draft/' + $routeParams.id) + .then(function (response) { + var data; + if (response.data.mqservice) + data = response.data.mqservice; + else + data = response.data.service; + console.log(data); + feedbackService.displayServiceInfo(data); + }) + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + } + $scope.serviceInfo = function () { + console.log($routeParams.id); + $http.get('/api/services/draft/' + $routeParams.id) + + .then(function (response) { + var data; + if (response.data.mqservice) + data = response.data.mqservice; + else + data = response.data.service; + console.log(data); + feedbackService.displayServiceInfo(data); + $('#serviceInfo-modal').modal('toggle'); + }) + + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.SERV_SAVE_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.SERV_INFO_NOT_FOUND); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + }; - .catch(function(err) { - console.log(err); - }); - } + $scope.setContentType = function (rr, type) { + if (rr.reqHeadersArr.length < 2) + $scope.addNewReqHeader(rr); - else if (user && !sut) { - apiHistoryService.getServiceByUser(user.name) + if (rr.resHeadersArr.length < 2) + $scope.addNewResHeader(rr); - .then(function(response) { - var data = response.data; - console.log(data); - $scope.servicelist = data; - }) + // set values + rr.reqHeadersArr[0].v = type; + rr.resHeadersArr[0].v = type; - .catch(function(err) { - console.log(err); - }); - } + rr.reqHeadersArr[0].k = 'Content-Type'; + rr.resHeadersArr[0].k = 'Content-Type'; - else if (user && sut) { - apiHistoryService.getServicesFiltered(sut.name, user.name) + $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); + $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); + }; - .then(function(response) { - var data = response.data; - console.log(data); - $scope.servicelist = data; - }) + $scope.totalDisplayed = 10; - .catch(function(err) { - console.log(err); - }); - } + $scope.loadMore = function () { + $scope.totalDisplayed += 10; + }; - //returning a promise from factory didnt seem to work with .then() function here, alternative solution - $http.get('/api/systems') - .then(function (response) { - $scope.myUser = authService.getUserInfo().username; - $scope.myGroups = []; - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sut.members.forEach(function (memberlist) { - if (memberlist.includes($scope.myUser)) { - $scope.myGroups.push(sut.name); - } - }); - }); - }) - - .catch(function (err) { - console.log(err); - }); - }; - $scope.filtersSelected(null, { name: authService.getUserInfo().username }); + }]) - $scope.clearSelected = function() { - $scope.selectedSut = null; - $scope.selectedUser = null; - $scope.servicelist = []; - }; + .controller("mergeRecordedController", ['$scope', '$routeParams', 'apiHistoryService', 'authService', '$http', '$timeout', 'ctrlConstants', + function ($scope, $routeParams, apiHistoryService, authService, $http, $timeout, ctrlConstants) { + //Get service + update info - $scope.deleteService = function (service) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $('#modal-btn-yes').on("click", function () { - apiHistoryService.deleteServiceAPI(service) - .then(function (response) { - var data = response.data; - console.log(data); - $scope.servicelist.forEach(function (elem, i, arr) { - if (elem._id === data.id) - arr.splice(i, 1); - }); - }) - .catch(function (err) { - console.log(err); - }); - }); - }; - $scope.toggleService = function(service) { - apiHistoryService.toggleServiceAPI(service) + apiHistoryService.getServiceById($routeParams.id).then(function (response) { + var service = response.data; + $scope.servicevo = { + id: service._id, + sut: service.sut, + name: service.name, + type: service.type, + delay: service.delay, + delayMax: service.delayMax, + txnCount: service.txnCount, + basePath: service.basePath, - .then(function(response) { - var data = response.data; - console.log(data); - service.running = !service.running; - }) - .catch(function(err) { - console.log(err); - }); - }; + }; - $scope.exportService = function(serv) { - // clone the service - var service = JSON.parse(JSON.stringify(serv)); + if (service.liveInvocation) { + + $scope.servicevo.remoteHost = service.liveInvocation.remoteHost; + $scope.servicevo.remotePort = service.liveInvocation.remotePort; + $scope.servicevo.remotePath = service.liveInvocation.remoteBasePath; + $scope.servicevo.liveInvocationCheck = service.liveInvocation.enabled; + $scope.servicevo.invokeSSL = service.liveInvocation.ssl; + $scope.servicevo.liveRecordCheck = service.liveInvocation.record; + //Extract and build out codes/strings for failures + var failStatusCodes = service.liveInvocation.failStatusCodes; + var failStrings = service.liveInvocation.failStrings; + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + for (var i = 0; i < failStatusCodes.length; i++) { + $scope.servicevo.failStatuses[i] = { 'id': i, 'val': failStatusCodes[i] }; - // clean up data before export - delete service._id; - delete service.sut._id; - delete service.user; - delete service.__v; - delete service.$$hashKey; + } + for (var i = 0; i < failStrings.length; i++) { + $scope.servicevo.failStrings[i] = { 'id': i, 'val': failStrings[i] }; + } + if (!$scope.servicevo.failStatuses.length) { + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + } + if (!$scope.servicevo.failStrings.length) { + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + //Select correct radio + if (service.liveInvocation.liveFirst) + $scope.servicevo.liveInvokePrePost = 'PRE'; + else + $scope.servicevo.liveInvokePrePost = 'POST'; - if (service.basePath) { - service.basePath = service.basePath.replace('/' + service.sut.name, ''); - } - - service.rrpairs.forEach(function(rr) { - delete rr._id; - }); + } else { + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + $scope.myUser = authService.getUserInfo().username; - var data = new Blob([JSON.stringify(service, null, " ")], { type: 'application/json;charset=utf-8' }); - FileSaver.saveAs(data, service.name + '.json'); - }; - $scope.serviceInfo = function(serviceID) { - console.log('printing service id: ' + serviceID); - $http.get('/api/services/' + serviceID) - - .then(function(response) { - var data = response.data; - console.log(data); - feedbackService.displayServiceInfo(data); - $('#serviceInfo-modal').modal('toggle'); - }) - - .catch(function(err) { - console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - }); + $http.get('/api/systems') + .then(function (response) { + var newsutlist = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + newsutlist.push(sut.name); + } + }); + }); + $scope.canEdit = function () { + if (newsutlist.includes($scope.servicevo.sut.name)) { + return true; + } + else { + return false; + } }; - }]) + }) - .controller("dataGenController", ['$scope', '$parse', 'FileSaver', 'Blob', 'genDataService', 'ctrlConstants', - function($scope, $parse, FileSaver, Blob, genDataService, ctrlConstants){ - $scope.addColumn = newColumn; - $scope.numRows= 100; - $scope.gen = {}; - $scope.gen.columns = []; - - //setting some default vals - $scope.idBool = true; - $scope.fileType = 'JSON'; - $scope.rowOffset = 0; - - function mapJSON(){ - var dataArr = []; - - for(var c=0; c < $scope.numRows + 1; c++){ - if($scope.idBool){ - var id = $scope.rowOffset; - dataArr.forEach(function (newJobItem){ - newJobItem.id = id++; - }); - } + .catch(function (err) { + console.log(err); + }); + if (service.lastUpdateUser) { + $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; + } + if (service.createdAt) { + $scope.servicevo.createdAt = service.createdAt; + } + if (service.updatedAt) { + $scope.servicevo.updatedAt = service.updatedAt; + } - for(var i=0; i < $scope.gen.columns.length; i++){ - dataArr.forEach(function (hVal){ - var header = $scope.gen.columns[i].header; - var dataType = $scope.gen.columns[i].dataType; - hVal[header] = genDataService.getDataType(dataType); - }); - } - dataArr.push({}); - } + $scope.servicevo.matchTemplates = []; + $scope.servicevo.rawpairs = []; - var lastItem = dataArr.length-1; - dataArr.splice(lastItem); - return dataArr; - }; - function mapCSV(){ - var json = mapJSON() - var fields = Object.keys(json[0]) - var replacer = function(key, value) { return value === null ? '' : value } - var csv = json.map(function(row){ - return fields.map(function(fieldName){ - return JSON.stringify(row[fieldName], replacer) - }).join(',') - }) - csv.unshift(fields.join(',')) // add header column + if (service.matchTemplates && service.matchTemplates.length) { + service.matchTemplates.forEach(function (template, index) { + $scope.servicevo.matchTemplates.push({ id: index, val: template }); + }); + } + else { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + } + $scope.servicevo.rawpairs = processRRPairs(service.liveInvocation.recordedRRPairs); + }); - return csv.join('\r\n'); - }; + function processRRPairs(rrpairs) { + var rrpairsRaw = []; + var rrid = 0; + rrpairs.forEach(function (rr) { + rr.id = rrid++; + console.log(rr); + rr.queriesArr = []; + rr.reqHeadersArr = []; + rr.resHeadersArr = []; + rr.method = rr.verb; + + if (rr.payloadType === 'JSON') { + rr.requestpayload = JSON.stringify(rr.reqData); + rr.responsepayload = JSON.stringify(rr.resData); + + //Handle empty JSON object- stringify surrounds in "" + if (rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\"") { + rr.responsepayload = rr.responsepayload.substring(1, 3); + } + } + else { + rr.requestpayload = rr.reqData; + rr.responsepayload = rr.resData; + } - function map_dl_XML(){ - xmlData = genDataService.json2xml(mapJSON()); - var blob = new Blob([xmlData], {type : 'text/xml;charset=utf-8;'}); - FileSaver.saveAs(blob, 'mockiato-data.xml'); - }; + // map object literals to arrays for Angular view + if (rr.reqHeaders) { + var reqHeads = Object.entries(rr.reqHeaders); + var reqHeadId = 0; + reqHeads.forEach(function (elem) { + var head = {}; - $scope.printColumns = function() { - if($scope.numRows > 1000){ - return alert(ctrlConstants.DATAGEN_ALERT_MSG_1000ROWS); - } + head.id = reqHeadId; + head.k = elem[0]; + head.v = elem[1]; - if($scope.fileType == "JSON"){ - downloadJSON(mapJSON()); - } - else if($scope.fileType == "CSV"){ - downloadCSV(mapCSV()); - } + rr.reqHeadersArr.push(head); + reqHeadId++; + }); + } + else { + rr.reqHeadersArr.push({ id: 0 }); + } - else if($scope.fileType == "XML"){ - map_dl_XML(); - } + if (rr.resHeaders) { + var resHeads = Object.entries(rr.resHeaders); + var resHeadId = 0; + resHeads.forEach(function (elem) { + var head = {}; - else { - alert("No integration for that file type yet"); - } - }; + head.id = resHeadId; + head.k = elem[0]; + head.v = elem[1]; - function newColumn() { - $scope.gen.columns.push({}); - }; + rr.resHeadersArr.push(head); + resHeadId++; + }); + } + else { + rr.resHeadersArr.push({ id: 0 }); + } - $scope.remColumn = function() { - var lastItem = $scope.gen.columns.length-1; - $scope.gen.columns.splice(lastItem); - }; + if (rr.queries) { + var qs = Object.entries(rr.queries); + var qId = 0; + qs.forEach(function (elem) { + var q = {}; - function downloadCSV(data){ - var exportFilename = 'mockiato-data'; - var csvData = new Blob([data], {type: 'text/csv;charset=utf-8;'}); - //IE11 & Edge - if (navigator.msSaveBlob) { - navigator.msSaveBlob(csvData, exportFilename); - } else { - //In FF link must be added to DOM to be clicked - var link = document.createElement('a'); - link.href = window.URL.createObjectURL(csvData); - link.setAttribute('download', exportFilename); - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } + q.id = qId; + q.k = elem[0]; + q.v = elem[1]; - }; + rr.queriesArr.push(q); + qId++; + }); + } + else { + rr.queriesArr.push({ id: 0 }); + } - function downloadJSON(data){ - var blob = new Blob([JSON.stringify(data, null, " ")], {type : 'application/json'}); - FileSaver.saveAs(blob, 'mockiato-data.json'); - }; + rrpairsRaw.push(rr); + }); + return rrpairsRaw; + } - //setting some default vals - newColumn(); - $scope.gen.columns[0].header = 'first_name'; - $scope.gen.columns[0].dataType = 'First Name'; + $scope.deleteRRPair = function (rr) { - newColumn(); - $scope.gen.columns[1].header = 'last_name'; - $scope.gen.columns[1].dataType = 'Last Name'; + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + + $scope.performDelete(rr); + }); + } + $scope.performDelete = function (rr) { + apiHistoryService.deleteRecordedLiveRRPair($scope.servicevo.id, rr._id).then(function (rsp) { + $scope.servicevo.rawpairs.splice($scope.servicevo.rawpairs.indexOf(rr), 1); + }); + } - newColumn(); - $scope.gen.columns[2].header = 'email'; - $scope.gen.columns[2].dataType = 'Email Address'; + $scope.mergeRRPair = function (rr) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.MRG_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.MRG_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.MRG_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + if($scope.servicevo.type == "SOAP"){ + rr.payloadType = "XML"; + rr.method = "POST"; + } + apiHistoryService.addRRPairToService($scope.servicevo.id, rr).then(function (result) { + $scope.performDelete(rr); + }); + }); + } - }]) + $scope.addNewReqHeader = function (rr) { + var newItemNo = rr.reqHeadersArr.length; + rr.reqHeadersArr.push({ 'id': newItemNo }); + }; - .controller("adminController", ['$scope', 'authService', 'userService', 'sutService', 'ctrlConstants', - function ($scope, authService, userService, sutService, ctrlConstants){ - $scope.myUser = authService.getUserInfo().username; - $scope.sutlist = sutService.getGroupsByUser($scope.myUser); - $scope.userlist = userService.getAllUsers(); - $scope.selectedSut = []; - $scope.allSUT = sutService.getAllSUT(); - $scope.deleteSutList = sutService.getGroupsToBeDeleted($scope.myUser); + $scope.removeReqHeader = function (rr, index) { + rr.reqHeadersArr.splice(index, 1); + }; - $scope.checkAndAddGroup = function (createSut) { - var count = 0; - $scope.createGroupMessage = ""; - for (var i = 0; i < $scope.allSUT.length; i++) { - if ($scope.allSUT[i].name.toUpperCase() == $scope.createSut.name.toUpperCase()) { - count++; - } - } - if (count != 0) { - $scope.createGroupMessage = ctrlConstants.GRP_ALREADY_EXIST_MSG; - } - else { - sutService.addGroup($scope.createSut); - $scope.createGroupMessage = ctrlConstants.GRP_CREATED_SUCCESS_MSG; - - } - window.location.reload(true); + $scope.addNewResHeader = function (rr) { + var newItemNo = rr.resHeadersArr.length; + rr.resHeadersArr.push({ 'id': newItemNo }); }; - - $scope.removeGroup = function (deleteSut) { - sutService.deleteGroup( deleteSut); - $scope.deleteGroupMessage = ctrlConstants.GRP_DELETION_SUCCESS_MSG; - window.location.reload(true); - }; + $scope.removeResHeader = function (rr, index) { + rr.resHeadersArr.splice(index, 1); + }; + $scope.addQuery = function (rr) { + var newItemNo = rr.queriesArr.length; + rr.queriesArr.push({ 'id': newItemNo }); + }; - - $scope.$watch('selectedSut', function (newSut) { - if ($scope.selectedSut != ""){ //removes null response, saves resources - $scope.memberlist = sutService.getMembers(newSut.name); - - //disallows duplicate user add - $scope.removeMembers = function (users) { - return $scope.memberlist.indexOf(users.name) === -1; + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; + var timeoutPromise; + $scope.pollForRRPairs = function () { + timeoutPromise = $timeout(function () { + + apiHistoryService.getRecordedLiveRRPairs($routeParams.id).then(function (result) { + if (result.data.liveInvocation.recordedRRPairs) { + var newRRPairs = processRRPairs(result.data.liveInvocation.recordedRRPairs); + console.log(newRRPairs); + var rrPairs = $scope.servicevo.rawpairs; + newRRPairs.forEach(function (rr) { + var found = false; + rrPairs.forEach(function (rr2) { + if (rr._id == rr2._id) { + found = true; + } + }); + if (!found) + rrPairs.push(rr); + }); } - } - }); + }); - $scope.saveGroup = function (selectedSut) { - sutService.updateGroup(selectedSut.name, $scope.memberlist); - }; + $scope.pollForRRPairs(); - $scope.addMember = function () { - $scope.memberlist.push($scope.member.name); - $scope.saveGroup($scope.selectedSut); - } - $scope.removeMember = function (index) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_USER_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $scope.userNo = index; - $('#modal-btn-yes').on("click", function () { - $scope.memberlist.splice($scope.userNo, 1); - $scope.$apply(); - $scope.saveGroup($scope.selectedSut); + }, 3000); + }; + + $scope.$on("$destroy", function () { + $timeout.cancel(timeoutPromise); + }); + $scope.pollForRRPairs(); + }]) + .controller("updateController", ['$scope', '$q', '$http', '$routeParams', 'apiHistoryService', 'feedbackService', 'suggestionsService', 'helperFactory', 'ctrlConstants', 'sutService', 'authService', "$location",'modalService', + function ($scope, $q, $http, $routeParams, apiHistoryService, feedbackService, suggestionsService, helperFactory, ctrlConstants, sutService, authService, $location,modalService) { + + $scope.statusCodes = suggestionsService.getStatusCodes(); + $scope.possibleHeaders = suggestionsService.getPossibleHeaders(); + + this.getService = function () { + apiHistoryService.getServiceById($routeParams.id) + + .then(function (response) { + var service = response.data; + $scope.servicevo = { + id: service._id, + sut: service.sut, + name: service.name, + type: service.type, + delay: service.delay, + delayMax: service.delayMax, + txnCount: service.txnCount, + basePath: service.basePath, + + + }; + + if (service.liveInvocation) { + + $scope.servicevo.remoteHost = service.liveInvocation.remoteHost; + $scope.servicevo.remotePort = service.liveInvocation.remotePort; + $scope.servicevo.remotePath = service.liveInvocation.remoteBasePath; + $scope.servicevo.liveInvocationCheck = service.liveInvocation.enabled; + $scope.servicevo.invokeSSL = service.liveInvocation.ssl; + $scope.servicevo.liveRecordCheck = service.liveInvocation.record; + //Extract and build out codes/strings for failures + var failStatusCodes = service.liveInvocation.failStatusCodes; + var failStrings = service.liveInvocation.failStrings; + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + for (var i = 0; i < failStatusCodes.length; i++) { + $scope.servicevo.failStatuses[i] = { 'id': i, 'val': failStatusCodes[i] }; + + } + for (var i = 0; i < failStrings.length; i++) { + $scope.servicevo.failStrings[i] = { 'id': i, 'val': failStrings[i] }; + } + if (!$scope.servicevo.failStatuses.length) { + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + } + if (!$scope.servicevo.failStrings.length) { + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + //Select correct radio + if (service.liveInvocation.liveFirst) + $scope.servicevo.liveInvokePrePost = 'PRE'; + else + $scope.servicevo.liveInvokePrePost = 'POST'; + + } else { + $scope.servicevo.failStatuses = []; + $scope.servicevo.failStrings = []; + $scope.servicevo.failStatuses[0] = { 'id': 0, val: '' }; + $scope.servicevo.failStrings[0] = { 'id': 0, val: '' }; + } + + + $scope.myUser = authService.getUserInfo().username; + + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + var newsutlist = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + newsutlist.push(sut.name); + } + }); + }); + $scope.canEdit = function () { + if (newsutlist.includes($scope.servicevo.sut.name)) { + return true; + } + else { + + return false; + } + }; + }) + + .catch(function (err) { + console.log(err); + }); + + if (service.lastUpdateUser) { + $scope.servicevo.lastUpdateUser = service.lastUpdateUser.uid; + } + if (service.createdAt) { + $scope.servicevo.createdAt = service.createdAt; + } + if (service.updatedAt) { + $scope.servicevo.updatedAt = service.updatedAt; + } + + $scope.servicevo.matchTemplates = []; + $scope.servicevo.rawpairs = []; + + + if (service.matchTemplates && service.matchTemplates.length) { + service.matchTemplates.forEach(function (template, index) { + $scope.servicevo.matchTemplates.push({ id: index, val: template }); + }); + } + else { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + } + + var rrid = 0; + service.rrpairs.forEach(function (rr) { + rr.id = rrid; + rr.queriesArr = []; + rr.reqHeadersArr = []; + rr.resHeadersArr = []; + rr.method = rr.verb; + + if (rr.payloadType === 'JSON') { + rr.requestpayload = JSON.stringify(rr.reqData, null, 4); + rr.responsepayload = JSON.stringify(rr.resData, null, 4); + + //Handle empty JSON object- stringify surrounds in "" + if (rr.responsepayload == "\"[]\"" || rr.responsepayload == "\"{}\"") { + rr.responsepayload = rr.responsepayload.substring(1, 3); + } + } + else { + rr.requestpayload = rr.reqData; + rr.responsepayload = rr.resData; + } + + // map object literals to arrays for Angular view + if (rr.reqHeaders) { + var reqHeads = Object.entries(rr.reqHeaders); + var reqHeadId = 0; + reqHeads.forEach(function (elem) { + var head = {}; + + head.id = reqHeadId; + head.k = elem[0]; + head.v = elem[1]; + + rr.reqHeadersArr.push(head); + reqHeadId++; + }); + } + else { + rr.reqHeadersArr.push({ id: 0 }); + } + + if (rr.resHeaders) { + var resHeads = Object.entries(rr.resHeaders); + var resHeadId = 0; + resHeads.forEach(function (elem) { + var head = {}; + + head.id = resHeadId; + head.k = elem[0]; + head.v = elem[1]; + + rr.resHeadersArr.push(head); + resHeadId++; + }); + } + else { + rr.resHeadersArr.push({ id: 0 }); + } + + if (rr.queries) { + var qs = Object.entries(rr.queries); + var qId = 0; + qs.forEach(function (elem) { + var q = {}; + + q.id = qId; + q.k = elem[0]; + q.v = elem[1]; + + rr.queriesArr.push(q); + qId++; + }); + } + else { + rr.queriesArr.push({ id: 0 }); + } + + $scope.servicevo.rawpairs.push(rr); + rrid++; + }); + }) + + .catch(function (err) { + console.log(err); }); - }; + }; + this.getService(); + + $scope.addFailStatus = function () { + $scope.servicevo.failStatuses.push({ val: '' }); + } + $scope.removeFailStatus = function (index) { + $scope.servicevo.failStatuses.splice(index, 1); + } + $scope.addFailString = function () { + $scope.servicevo.failStrings.push({ val: '' }); + } + $scope.removeFailString = function (index) { + $scope.servicevo.failStrings.splice(index, 1); + } + $scope.addTemplate = function () { + $scope.servicevo.matchTemplates.push({ id: 0, val: '' }); + }; + + $scope.removeTemplate = function (index) { + $scope.servicevo.matchTemplates.splice(index, 1); + }; + + $scope.addNewRRPair = function () { + var newItemNo = $scope.servicevo.rawpairs.length; + $scope.servicevo.rawpairs.push({ + id: newItemNo, + queriesArr: [{ + id: 0 + }], + reqHeadersArr: [{ + id: 0 + }], + resHeadersArr: [{ + id: 0 + }] + }); + }; + + $scope.viewRecorded = function () { + $location.path("/update/" + $scope.servicevo.id + "/recorded") + } + $scope.removeRRPair = function (index) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_RRPAIR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $scope.rrPairNo = index; + $('#modal-btn-yes').on("click", function () { + $scope.servicevo.rawpairs.splice($scope.rrPairNo, 1); + $scope.$apply(); + }); + }; + + $scope.addNewReqHeader = function (rr) { + var newItemNo = rr.reqHeadersArr.length; + rr.reqHeadersArr.push({ 'id': newItemNo }); + }; + + $scope.removeReqHeader = function (rr, index) { + rr.reqHeadersArr.splice(index, 1); + }; + + $scope.addNewResHeader = function (rr) { + var newItemNo = rr.resHeadersArr.length; + rr.resHeadersArr.push({ 'id': newItemNo }); + }; + + $scope.removeResHeader = function (rr, index) { + rr.resHeadersArr.splice(index, 1); + }; + + $scope.addQuery = function (rr) { + var newItemNo = rr.queriesArr.length; + rr.queriesArr.push({ 'id': newItemNo }); + }; + + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; + + $scope.removeQuery = function (rr, index) { + rr.queriesArr.splice(index, 1); + }; + + $scope.updateService = function (servicevo) { + try { + if (helperFactory.isDuplicateReq(servicevo)) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DUP_REQ_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.DUP_REQ_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DUPLICATE_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } else { + apiHistoryService.publishServiceToAPI(servicevo, true); + } + } + catch (e) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } + }; + + $scope.setContentType = function (rr, type) { + if (rr.reqHeadersArr.length < 2) + $scope.addNewReqHeader(rr); + + if (rr.resHeadersArr.length < 2) + $scope.addNewResHeader(rr); + + // set values + rr.reqHeadersArr[0].v = type; + rr.resHeadersArr[0].v = type; + + rr.reqHeadersArr[0].k = 'Content-Type'; + rr.resHeadersArr[0].k = 'Content-Type'; + + $scope.$broadcast('angucomplete-alt:changeInput', 'req-header-0', rr.reqHeadersArr[0].k); + $scope.$broadcast('angucomplete-alt:changeInput', 'res-header-0', rr.resHeadersArr[0].k); + }; + + $scope.serviceInfo = function () { + console.log($routeParams.id); + $http.get('/api/services/' + $routeParams.id) + + .then(function (response) { + var data = response.data; + console.log(data); + feedbackService.displayServiceInfo(data); + $('#serviceInfo-modal').modal('toggle'); + }) + + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + }; + + $scope.totalDisplayed = 10; + + $scope.loadMore = function () { + $scope.totalDisplayed += 10; + }; + + $scope.showTemplateHelp = function(){ + modalService.showTemplateHelp(); + + } + //To Show Service Success Modal when a new service is created. + if ($routeParams.frmWher == 'frmServCreate') { + $http.get('/api/services/' + $routeParams.id) + .then(function (response) { + var data = response.data; + console.log(data); + feedbackService.displayServiceInfo(data); + }) + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + $('#success-modal').modal('toggle'); + } + }]) + + .controller("selectServiceController", ['$scope', '$http', '$routeParams', 'feedbackService', 'apiHistoryService','authService', 'ctrlConstants', + function($scope,$http,$routeParams,feedbackService,apiHistoryService,authService,ctrlConstants){ + $scope.serviceList = []; + apiHistoryService.getRecentModifiedServices(5, authService.getUserInfo().username).then(function (response) { + var data = response.data; + $scope.serviceList = data; + console.log(data); + }); + //To Show Service Success Modal when a new service is created from Draft. + if($routeParams.id !== 'home'){ + $http.get('/api/services/' + $routeParams.id) + .then(function(response) { + var data = response.data; + console.log(data); + feedbackService.displayServiceInfo(data); + }) + .catch(function(err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + $('#success-modal').modal('toggle'); + } + }]) + .controller("recorderListController", ['$scope', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', + function ($scope, $http, $timeout, sutService, feedbackService, apiHistoryService, userService, authService, FileSaver, Blob, ctrlConstants) { + $scope.sutlist = sutService.getAllSUT(); + $scope.userlist = userService.getAllUsers(); + $scope.recordingList = []; + apiHistoryService.getRecordings().then(function (response) { + var data = response.data; + $scope.recordingList = data; + }); + + $scope.startRecorder = function (recorder) { + apiHistoryService.startRecorder(recorder) + .then(function (response) { + + recorder.running = true; + recorder.active = true; + }) + + .catch(function (err) { + console.log(err); + }); + }; + + $scope.stopRecorder = function (recorder) { + apiHistoryService.stopRecorder(recorder) + + .then(function (response) { + recorder.running = false; + recorder.active = false; + }) + + .catch(function (err) { + //If 404, try starting, just in case. + console.log(err.status); + if (err.status == 404) + $scope.startRecorder(recorder); + + console.log(err); + }); + }; + + + $scope.deleteRecording = function (recording) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_REC_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.deleteRecording(recording._id) + .then(function (response) { + + $scope.recordingList.forEach(function (elem, i, arr) { + if (elem._id === recording._id) + arr.splice(i, 1); + }); + }) + .catch(function (err) { + console.log(err); + }); + }); + }; + + + }]) + + .controller("serviceHistoryController", ['$scope', '$location', '$routeParams', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', + function ($scope, $location, $routeParams, $http, $timeout, sutService, feedbackService, apiHistoryService, userService, authService, FileSaver, Blob, ctrlConstants) { + Promise.all([sutService.getAllSUTPromise(), userService.getAllUsersPromise()]).then(function (values) { + $scope.sutlist = values[0]; + $scope.userlist = values[1]; + if ($routeParams.user || $routeParams.sut) + performUpdateOnPathParams(); + else + $scope.filtersSelected(null, { name: authService.getUserInfo().username }); + }); + + $scope.servicelist = []; + console.log($routeParams); + + $scope.buttonHit = false; + + $scope.$watchGroup(['selectedSut', 'selectedUser'], function (newVals) { + $scope.filtersSelected(newVals[0], newVals[1]); + $scope.buttonHit = true; //bool check so function isnt called twice + }); + + + $scope.filtersSelected = function (sut, user) { + $location.path("/fetchservices/" + (sut ? sut.name : '') + "/" + (user ? user.name : '')); + + if (sut && !user) { + apiHistoryService.getServiceForSUT(sut.name) + + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist = data; + }) + + .catch(function (err) { + console.log(err); + }); + } + + else if (user && !sut) { + apiHistoryService.getServiceByUser(user.name) + + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist = data; + }) + + .catch(function (err) { + console.log(err); + }); + } + + else if (user && sut) { + apiHistoryService.getServicesFiltered(sut.name, user.name) + + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist = data; + }) + + .catch(function (err) { + console.log(err); + }); + } + $scope.orderByField = 'name'; + $scope.reverseSort = false; + }; + + function performUpdateOnPathParams() { + $scope.filtersSelected($routeParams.sut ? { name: $routeParams.sut } : null, $routeParams.user ? { name: $routeParams.user } : null); + if ($routeParams.sut) { + for (let sut of $scope.sutlist) { + if (sut.name == $routeParams.sut) { + $scope.selectedSut = sut; + break; + } + } + } else { + $scope.selectedSut = null; + } + if ($routeParams.user) { + for (let user of $scope.userlist) { + if (user.name == $routeParams.user) { + $scope.selectedUser = user; + break; + } + } + } else { + $scope.selectedUser = null; + } + } + + $scope.$on('$routeUpdate', function () { + if (!$scope.buttonHit) + performUpdateOnPathParams(); + else + $scope.buttonHit = false; + }); + $scope.clearSelected = function () { + $scope.selectedSut = null; + $scope.selectedUser = null; + $scope.servicelist = []; + }; + + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + $scope.myUser = authService.getUserInfo().username; + $scope.myGroups = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + $scope.myGroups.push(sut.name); + } + }); + }); + }) + + .catch(function (err) { + console.log(err); + }); + + $scope.deleteService = function (service) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.deleteServiceAPI(service) + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist.forEach(function (elem, i, arr) { + if (elem._id === data.id) + arr.splice(i, 1); + }); + }) + .catch(function (err) { + console.log(err); + }); + }); + }; + + $scope.toggleService = function (service) { + apiHistoryService.toggleServiceAPI(service) + + .then(function (response) { + var data = response.data; + console.log(data); + service.running = !service.running; + }) + + .catch(function (err) { + console.log(err); + }); + }; + + $scope.exportService = function (serv) { + // clone the service + var service = JSON.parse(JSON.stringify(serv)); + + // clean up data before export + delete service._id; + delete service.sut._id; + delete service.user; + delete service.__v; + delete service.$$hashKey; + + if (service.basePath) { + service.basePath = service.basePath.replace('/' + service.sut.name, ''); + } + + service.rrpairs.forEach(function (rr) { + delete rr._id; + }); + + var data = new Blob([JSON.stringify(service, null, " ")], { type: 'application/json;charset=utf-8' }); + FileSaver.saveAs(data, service.name + '.json'); + }; + + $scope.serviceInfo = function (serviceID) { + console.log('printing service id: ' + serviceID); + $http.get('/api/services/' + serviceID) + + .then(function (response) { + var data = response.data; + console.log(data); + feedbackService.displayServiceInfo(data); + $('#serviceInfo-modal').modal('toggle'); + }) + + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + }); + }; + }]) + + .controller("dataGenController", ['$scope', '$parse', 'FileSaver', 'Blob', 'genDataService', 'ctrlConstants', + function ($scope, $parse, FileSaver, Blob, genDataService, ctrlConstants) { + $scope.addColumn = newColumn; + $scope.numRows = 100; + $scope.gen = {}; + $scope.gen.columns = []; + + //setting some default vals + $scope.idBool = true; + $scope.fileType = 'JSON'; + $scope.rowOffset = 0; + + function mapJSON() { + var dataArr = []; + + for (var c = 0; c < $scope.numRows + 1; c++) { + if ($scope.idBool) { + var id = $scope.rowOffset; + dataArr.forEach(function (newJobItem) { + newJobItem.id = id++; + }); + } + + for (var i = 0; i < $scope.gen.columns.length; i++) { + dataArr.forEach(function (hVal) { + var header = $scope.gen.columns[i].header; + var dataType = $scope.gen.columns[i].dataType; + hVal[header] = genDataService.getDataType(dataType); + }); + } + dataArr.push({}); + } + + var lastItem = dataArr.length - 1; + dataArr.splice(lastItem); + return dataArr; + }; + + function mapCSV() { + var json = mapJSON() + var fields = Object.keys(json[0]) + var replacer = function (key, value) { return value === null ? '' : value } + var csv = json.map(function (row) { + return fields.map(function (fieldName) { + return JSON.stringify(row[fieldName], replacer) + }).join(',') + }) + csv.unshift(fields.join(',')) // add header column + + return csv.join('\r\n'); + }; + + function map_dl_XML() { + xmlData = genDataService.json2xml(mapJSON()); + var blob = new Blob([xmlData], { type: 'text/xml;charset=utf-8;' }); + FileSaver.saveAs(blob, 'mockiato-data.xml'); + }; + + $scope.printColumns = function () { + if ($scope.numRows > 1000) { + return alert(ctrlConstants.DATAGEN_ALERT_MSG_1000ROWS); + } + + if ($scope.fileType == "JSON") { + downloadJSON(mapJSON()); + } + else if ($scope.fileType == "CSV") { + downloadCSV(mapCSV()); + } + + else if ($scope.fileType == "XML") { + map_dl_XML(); + } + + else { + alert("No integration for that file type yet"); + } + }; + + function newColumn() { + $scope.gen.columns.push({}); + }; + + $scope.remColumn = function () { + var lastItem = $scope.gen.columns.length - 1; + $scope.gen.columns.splice(lastItem); + }; + + function downloadCSV(data) { + var exportFilename = 'mockiato-data'; + var csvData = new Blob([data], { type: 'text/csv;charset=utf-8;' }); + //IE11 & Edge + if (navigator.msSaveBlob) { + navigator.msSaveBlob(csvData, exportFilename); + } else { + //In FF link must be added to DOM to be clicked + var link = document.createElement('a'); + link.href = window.URL.createObjectURL(csvData); + link.setAttribute('download', exportFilename); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + + }; + + function downloadJSON(data) { + var blob = new Blob([JSON.stringify(data, null, " ")], { type: 'application/json' }); + FileSaver.saveAs(blob, 'mockiato-data.json'); + }; + + //setting some default vals + newColumn(); + $scope.gen.columns[0].header = 'first_name'; + $scope.gen.columns[0].dataType = 'First Name'; + + newColumn(); + $scope.gen.columns[1].header = 'last_name'; + $scope.gen.columns[1].dataType = 'Last Name'; + + newColumn(); + $scope.gen.columns[2].header = 'email'; + $scope.gen.columns[2].dataType = 'Email Address'; + + }]) + + .controller("adminController", ['$scope', 'authService', 'userService', 'sutService', 'ctrlConstants', + function ($scope, authService, userService, sutService, ctrlConstants) { + $scope.myUser = authService.getUserInfo().username; + $scope.sutlist = sutService.getGroupsByUser($scope.myUser); + $scope.userlist = userService.getAllUsers(); + $scope.selectedSut = []; + $scope.allSUT = sutService.getAllSUT(); + $scope.deleteSutList = sutService.getGroupsToBeDeleted($scope.myUser); + + $scope.checkAndAddGroup = function (createSut) { + var count = 0; + $scope.createGroupMessage = ""; + for (var i = 0; i < $scope.allSUT.length; i++) { + if ($scope.allSUT[i].name.toUpperCase() == $scope.createSut.name.toUpperCase()) { + count++; + } + } + if (count != 0) { + $scope.createGroupMessage = ctrlConstants.GRP_ALREADY_EXIST_MSG; + } + else { + sutService.addGroup($scope.createSut); + $scope.createGroupMessage = ctrlConstants.GRP_CREATED_SUCCESS_MSG; + + } + window.location.reload(true); + }; - }]) + $scope.removeGroup = function (deleteSut) { + sutService.deleteGroup(deleteSut); + $scope.deleteGroupMessage = ctrlConstants.GRP_DELETION_SUCCESS_MSG; + window.location.reload(true); + }; - .controller("mainController", ['$rootScope', '$location', 'authService', 'ctrlConstants', - function($rootScope,$location,authService,ctrlConstants){ - if (window.location.port) - $rootScope.mockiatoHost = 'http://' + window.location.hostname + ':' + window.location.port; - else - $rootScope.mockiatoHost = 'http://' + window.location.hostname; + $scope.$watch('selectedSut', function (newSut) { + if ($scope.selectedSut != "") { //removes null response, saves resources + $scope.memberlist = sutService.getMembers(newSut.name); - $rootScope.virt = { - baseUrl: '', - type: '' - }; - $rootScope.virt.operations = []; + //disallows duplicate user add + $scope.removeMembers = function (users) { + return $scope.memberlist.indexOf(users.name) === -1; + } + } + }); - $rootScope.$on("$routeChangeSuccess", function(userInfo) { - console.log(userInfo); - $rootScope.virt.operations = []; - }); + $scope.saveGroup = function (selectedSut) { + sutService.updateGroup(selectedSut.name, $scope.memberlist); + }; - $rootScope.$on("$routeChangeError", function(event, current, previous, eventObj) { - if (eventObj.authenticated === false) { - $location.path("/login"); - } - }); + $scope.addMember = function () { + $scope.memberlist.push($scope.member.name); + $scope.saveGroup($scope.selectedSut); + } - $rootScope.logout = function() { - authService.logout(); - $location.path("/login"); - }; + $scope.removeMember = function (index) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_CONFIRM_USER_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $scope.userNo = index; + $('#modal-btn-yes').on("click", function () { + $scope.memberlist.splice($scope.userNo, 1); + $scope.$apply(); + $scope.saveGroup($scope.selectedSut); + }); + }; - if (location.href.indexOf('#regS') !== -1) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.REG_SUCCESS_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.REG_SUCCESS_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.CLOSE_PRMRY_BTN_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } }]) - .controller("bulkUploadController", ['$scope', 'sutService' , 'authService', 'zipUploadAndExtractService', 'publishExtractedRRPairService', 'ctrlConstants', - function ($scope, sutService, authService, zipUploadAndExtractService, publishExtractedRRPairService, ctrlConstants) { + + .controller("mainController", ['$rootScope', '$location', 'authService', 'ctrlConstants', + function ($rootScope, $location, authService, ctrlConstants) { + if (window.location.port) + $rootScope.mockiatoHost = 'http://' + window.location.hostname + ':' + window.location.port; + else + $rootScope.mockiatoHost = 'http://' + window.location.hostname; + + $rootScope.virt = { + baseUrl: '', + type: '' + }; + $rootScope.virt.operations = []; + + $rootScope.$on("$routeChangeSuccess", function (userInfo) { + console.log(userInfo); + $rootScope.virt.operations = []; + }); + + $rootScope.$on("$routeChangeError", function (event, current, previous, eventObj) { + if (eventObj.authenticated === false) { + $location.path("/login"); + } + }); + + $rootScope.logout = function () { + authService.logout(); + $location.path("/login"); + }; + + if (location.href.indexOf('#regS') !== -1) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.REG_SUCCESS_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.REG_SUCCESS_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.CLOSE_PRMRY_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + } + }]) + + .controller("bulkUploadController", ['$scope', 'sutService', 'authService', 'zipUploadAndExtractService', 'publishExtractedRRPairService', 'ctrlConstants', + function ($scope, sutService, authService, zipUploadAndExtractService, publishExtractedRRPairService, ctrlConstants) { $scope.myUser = authService.getUserInfo().username; $scope.sutlist = sutService.getGroupsByUser($scope.myUser); $scope.bulkUpload = {}; @@ -1807,8 +2227,7 @@ var ctrl = angular.module("mockapp.controllers",['mockapp.services','mockapp.fac if ($scope.uploadRRPair) { $scope.uploadSuccessMessage = ""; $scope.uploadErrMessage = ""; - if($scope.uploadRRPair.name.endsWith(".zip")) - { + if ($scope.uploadRRPair.name.endsWith(".zip")) { zipUploadAndExtractService.zipUploadAndExtract($scope.uploadRRPair, function (file_upload_name_id) { if (file_upload_name_id) { $scope.uploadSuccessMessage = ctrlConstants.BULK_UPLOAD_SUCCESS_MSG + $scope.uploadRRPair.name; @@ -1820,525 +2239,535 @@ var ctrl = angular.module("mockapp.controllers",['mockapp.services','mockapp.fac } }); } - else{ + else { $scope.uploadErrMessage = ctrlConstants.BULK_UPLOAD_FILE_TYPE_FAILURE_MSG + $scope.uploadRRPair.name; $scope.uploadSuccessMessage = ""; } } }; $scope.publishExtractedRRPairFiles = function (bulkUpload) { - publishExtractedRRPairService.publishExtractedRRPair(bulkUpload, $scope.uploaded_file_name_id, function (message){ + publishExtractedRRPairService.publishExtractedRRPair(bulkUpload, $scope.uploaded_file_name_id, function (message) { $scope.uploadErrMessage = message; $scope.uploadSuccessMessage = ""; }); }; -}]) + }]) -.controller("specController", ['$scope','$routeParams' , 'sutService', 'authService', 'specUploadService', 'publishSpecService', 'ctrlConstants', - function($scope, $routeParams, sutService, authService, specUploadService, publishSpecService, ctrlConstants) { - $scope.myUser = authService.getUserInfo().username; - $scope.sutlist = sutService.getGroupsByUser($scope.myUser); - $scope.spec = {}; - $scope.spec.type = $routeParams.specType; - if ($scope.spec.type == 'openapi') { $scope.spec.heading = 'OpenAPI' } else if ($scope.spec.type == 'wsdl') { $scope.spec.heading = 'WSDL' } + .controller("specController", ['$scope', '$routeParams', 'sutService', 'authService', 'specUploadService', 'publishSpecService', 'ctrlConstants', + function ($scope, $routeParams, sutService, authService, specUploadService, publishSpecService, ctrlConstants) { + $scope.myUser = authService.getUserInfo().username; + $scope.sutlist = sutService.getGroupsByUser($scope.myUser); + $scope.spec = {}; + $scope.spec.type = $routeParams.specType; + if ($scope.spec.type == 'openapi') { $scope.spec.heading = 'OpenAPI' } else if ($scope.spec.type == 'wsdl') { $scope.spec.heading = 'WSDL' } - - $scope.callUploadSpec = function () { - $scope.uploadSuccessMessage = ""; - $scope.uploadErrMessage = ""; - $scope.uploaded_file_name_id = ""; - if ($scope.uploadSpec) { - $scope.uploadSuccessMessage = ""; - $scope.uploadErrMessage = ""; - if (($scope.spec.type == 'openapi' && ($scope.uploadSpec.name.endsWith(".yaml") || $scope.uploadSpec.name.endsWith(".yml") || $scope.uploadSpec.name.endsWith(".json"))) - || ($scope.spec.type == 'wsdl' && $scope.uploadSpec.name.endsWith(".wsdl"))) { - specUploadService.specUpload($scope.uploadSpec, function (uploaded_file_id) { - if (uploaded_file_id) { - $scope.uploadSuccessMessage = ctrlConstants.SPEC_UPLOAD_SUCCESS_MSG + $scope.uploadSpec.name; - $scope.uploaded_file_id = uploaded_file_id; - $scope.uploadErrMessage = ""; - } else { - $scope.uploadErrMessage = ctrlConstants.SPEC_UPLOAD_FAILURE_MSG + $scope.uploadSpec.name; - $scope.uploadSuccessMessage = ""; - } - }); - } - else { - $scope.uploadErrMessage = ctrlConstants.SPEC_FILE_TYPE_UPLOAD_ERROR + $scope.uploadSpec.name; + + $scope.callUploadSpec = function () { + $scope.uploadSuccessMessage = ""; + $scope.uploadErrMessage = ""; + $scope.uploaded_file_name_id = ""; + if ($scope.uploadSpec) { + $scope.uploadSuccessMessage = ""; + $scope.uploadErrMessage = ""; + if (($scope.spec.type == 'openapi' && ($scope.uploadSpec.name.endsWith(".yaml") || $scope.uploadSpec.name.endsWith(".yml") || $scope.uploadSpec.name.endsWith(".json"))) + || ($scope.spec.type == 'wsdl' && $scope.uploadSpec.name.endsWith(".wsdl"))) { + specUploadService.specUpload($scope.uploadSpec, function (uploaded_file_id) { + if (uploaded_file_id) { + $scope.uploadSuccessMessage = ctrlConstants.SPEC_UPLOAD_SUCCESS_MSG + $scope.uploadSpec.name; + $scope.uploaded_file_id = uploaded_file_id; + $scope.uploadErrMessage = ""; + } else { + $scope.uploadErrMessage = ctrlConstants.SPEC_UPLOAD_FAILURE_MSG + $scope.uploadSpec.name; $scope.uploadSuccessMessage = ""; } - } - }; - - $scope.publishspec = function (spec) { + }); + } + else { + $scope.uploadErrMessage = ctrlConstants.SPEC_FILE_TYPE_UPLOAD_ERROR + $scope.uploadSpec.name; $scope.uploadSuccessMessage = ""; - $scope.uploadErrMessage = ""; - $scope.flag = false; - //conditions are complex here. Any change will break validations. - Pradeep - if ((typeof spec.url !== 'undefined' && spec.url !== "" && $scope.spec.type == 'openapi' && (spec.url.endsWith(".yaml") || spec.url.endsWith(".yml") || spec.url.endsWith(".json"))) - || (typeof spec.url !== 'undefined' && spec.url !== "" && $scope.spec.type == 'wsdl' && spec.url.endsWith("?wsdl")) - || ((typeof spec.url == 'undefined' || spec.url == "") && $scope.uploadSpec && $scope.spec.type == 'openapi' && ($scope.uploadSpec.name.endsWith(".yaml") || $scope.uploadSpec.name.endsWith(".yml") || $scope.uploadSpec.name.endsWith(".json"))) - || ((typeof spec.url == 'undefined' || spec.url == "") && $scope.uploadSpec && $scope.spec.type == 'wsdl' && $scope.uploadSpec.name.endsWith(".wsdl")) - ) { - var filename; var file_id; - if ($scope.uploadSpec || $scope.uploaded_file_id) { - file_id = $scope.uploaded_file_id; - filename = $scope.uploadSpec.name; - } else { - file_id = ""; - filename = ""; - } - publishSpecService.publishSpec(spec, file_id, filename, function(message){ - if(message == 'twoSeviceDiffNameSameBasePath') - { $scope.flag= true;} - }); - } else { - $scope.uploadErrMessage = ctrlConstants.SPEC_FILE_TYPE_URL_PUBLISH_ERROR; - $scope.uploadSuccessMessage = ""; - } - }; + } + } + }; + + $scope.publishspec = function (spec) { + $scope.uploadSuccessMessage = ""; + $scope.uploadErrMessage = ""; + $scope.flag = false; + //conditions are complex here. Any change will break validations. - Pradeep + if ((typeof spec.url !== 'undefined' && spec.url !== "" && $scope.spec.type == 'openapi' && (spec.url.endsWith(".yaml") || spec.url.endsWith(".yml") || spec.url.endsWith(".json"))) + || (typeof spec.url !== 'undefined' && spec.url !== "" && $scope.spec.type == 'wsdl' && spec.url.endsWith("?wsdl")) + || ((typeof spec.url == 'undefined' || spec.url == "") && $scope.uploadSpec && $scope.spec.type == 'openapi' && ($scope.uploadSpec.name.endsWith(".yaml") || $scope.uploadSpec.name.endsWith(".yml") || $scope.uploadSpec.name.endsWith(".json"))) + || ((typeof spec.url == 'undefined' || spec.url == "") && $scope.uploadSpec && $scope.spec.type == 'wsdl' && $scope.uploadSpec.name.endsWith(".wsdl")) + ) { + var filename; var file_id; + if ($scope.uploadSpec || $scope.uploaded_file_id) { + file_id = $scope.uploaded_file_id; + filename = $scope.uploadSpec.name; + } else { + file_id = ""; + filename = ""; + } + publishSpecService.publishSpec(spec, file_id, filename, function (message) { + if (message == 'twoSeviceDiffNameSameBasePath') { $scope.flag = true; } + }); + } else { + $scope.uploadErrMessage = ctrlConstants.SPEC_FILE_TYPE_URL_PUBLISH_ERROR; + $scope.uploadSuccessMessage = ""; + } + }; }]) - .controller("deletedServiceController", ['$scope', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', - function($scope,$http,$timeout,sutService,feedbackService,apiHistoryService,userService,authService,FileSaver,Blob,ctrlConstants){ - $scope.sutlist = sutService.getAllSUT(); - $scope.userlist = userService.getAllUsers(); - $scope.servicelist = []; - - //script to retroactively assign group member. not needed for the future. - $scope.script=function(){ - console.log("starting script"); - var sutnames = []; - $http.get('/api/systems') - .then(function (response) { - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sutnames.push(sut.name); - }); - }) + .controller("deletedServiceController", ['$scope', '$location', '$routeParams', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', + function ($scope, $location, $routeParams, $http, $timeout, sutService, feedbackService, apiHistoryService, userService, authService, FileSaver, Blob, ctrlConstants) { + Promise.all([sutService.getAllSUTPromise(), userService.getAllUsersPromise()]).then(function (values) { + $scope.sutlist = values[0]; + $scope.userlist = values[1]; + if ($routeParams.user || $routeParams.sut) + performUpdateOnPathParams(); + else + $scope.filtersSelected(null, { name: authService.getUserInfo().username }); + }); - .catch(function (err) { - console.log(err); - }); + $scope.servicelist = []; + console.log($routeParams); - $http.get('/api/services/archive') - .then(function (response) { - console.log(response.data); - for (var i = 0; i < response.data.length; i++) { - var owner = response.data[i].user.uid; - var sut = response.data[i].sut.name; - - if (sutnames.includes(sut)){ - console.log("sut "+ sut + " exists"); - console.log(owner + " will be added to group: " + sut); - sutService.updateGroup(sut, owner); - } - else{ - console.log("sut " + sut + " does not exist"); - } - } - }) + $scope.buttonHit = false; - .catch(function (err) { - console.log(err); - }); - } - ///////////////////////////end script. to remove - - $scope.filtersSelected = function(sut, user) { - if (sut && !user) { - apiHistoryService.getServiceForArchiveSUT(sut.name) - - .then(function(response) { - var data = response.data; - console.log(data); - var arryListOfService=[]; - for (let i = 0; i < data.length; i++) { - if(data[i].service)arryListOfService.push(data[i].service); - if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - } - $scope.servicelist = arryListOfService; - }) - - .catch(function(err) { - console.log(err); - }); - } + $scope.$watchGroup(['selectedSut', 'selectedUser'], function (newVals) { + $scope.filtersSelected(newVals[0], newVals[1]); + $scope.buttonHit = true; //bool check so function isnt called twice + }); - else if (user && !sut) { - apiHistoryService.getServiceByArchiveUser(user.name) - .then(function(response) { - var data = response.data; - console.log(data); - var arryListOfService=[]; - for (let i = 0; i < data.length; i++) { - if(data[i].service)arryListOfService.push(data[i].service); - if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - } - $scope.servicelist = arryListOfService; - }) - - .catch(function(err) { - console.log(err); - }); - } - else if (user && sut) { - apiHistoryService.getServicesArchiveFiltered(sut.name, user.name) - - .then(function(response) { - var data = response.data; - console.log(data); - var arryListOfService=[]; - for (let i = 0; i < data.length; i++) { - if(data[i].service)arryListOfService.push(data[i].service); - if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - } - $scope.servicelist = arryListOfService; - }) - - .catch(function(err) { - console.log(err); - }); - } + $scope.filtersSelected = function (sut, user) { + $location.path("/fetchDeletedServices/" + (sut ? sut.name : '') + "/" + (user ? user.name : '')); - //returning a promise from factory didnt seem to work with .then() function here, alternative solution - $http.get('/api/systems') - .then(function (response) { - $scope.myUser = authService.getUserInfo().username; - $scope.myGroups = []; - response.data.forEach(function (sutData) { - var sut = { - name: sutData.name, - members: sutData.members - }; - sut.members.forEach(function (memberlist) { - if (memberlist.includes($scope.myUser)) { - $scope.myGroups.push(sut.name); - } - }); - }); - }) - - .catch(function (err) { - console.log(err); - }); + if (sut && !user) { + apiHistoryService.getServiceForArchiveSUT(sut.name) + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) - $http.get('/api/users/admin') - .then(function(response) { - $scope.adminUser = response.data; - }) - - .catch(function(err) { - console.log(err); - }); + .catch(function (err) { + console.log(err); + }); + } - }; - $scope.filtersSelected(null, { name: authService.getUserInfo().username }); + else if (user && !sut) { + apiHistoryService.getServiceByArchiveUser(user.name) + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) + + .catch(function (err) { + console.log(err); + }); + } + + else if (user && sut) { + apiHistoryService.getServicesArchiveFiltered(sut.name, user.name) + + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) + + .catch(function (err) { + console.log(err); + }); + } + $scope.orderByField = 'name'; + $scope.reverseSort = false; + }; + function performUpdateOnPathParams() { + $scope.filtersSelected($routeParams.sut ? { name: $routeParams.sut } : null, $routeParams.user ? { name: $routeParams.user } : null); + if ($routeParams.sut) { + for (let sut of $scope.sutlist) { + if (sut.name == $routeParams.sut) { + $scope.selectedSut = sut; + break; + } + } + } else { + $scope.selectedSut = null; + } + if ($routeParams.user) { + for (let user of $scope.userlist) { + if (user.name == $routeParams.user) { + $scope.selectedUser = user; + break; + } + } + } else { + $scope.selectedUser = null; + } + } + + $scope.$on('$routeUpdate', function () { + if (!$scope.buttonHit) + performUpdateOnPathParams(); + else + $scope.buttonHit = false; + }); + $scope.clearSelected = function () { + $scope.selectedSut = null; + $scope.selectedUser = null; + $scope.servicelist = []; + }; - $scope.clearSelected = function() { - $scope.selectedSut = null; - $scope.selectedUser = null; - $scope.servicelist = []; + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + $scope.myUser = authService.getUserInfo().username; + $scope.myGroups = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + $scope.myGroups.push(sut.name); + } + }); + }); + }) - $scope.deleteArchiveService = function (service) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_Permanent_CONFIRM_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - $('#modal-btn-yes').on("click", function () { - apiHistoryService.deleteServiceArchive(service) - .then(function (response) { - var data = response.data; - console.log(data); - $scope.servicelist.forEach(function (elem, i, arr) { - if (elem._id === data.id) - arr.splice(i, 1); - }); - }) - .catch(function (err) { - console.log(err); - }); + .catch(function (err) { + console.log(err); + }); + + + $http.get('/api/users/admin') + .then(function (response) { + $scope.adminUser = response.data; + }) + + .catch(function (err) { + console.log(err); + }); + + $scope.deleteArchiveService = function (service) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_Permanent_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.deleteServiceArchive(service) + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist.forEach(function (elem, i, arr) { + if (elem._id === data.id) + arr.splice(i, 1); + }); + }) + .catch(function (err) { + console.log(err); }); - }; + }); + }; + + $scope.restoreService = function (service) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.RESTORE_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.RESTORE_CONFIRM_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.restoreService(service) + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist.forEach(function (elem, i, arr) { + if (elem._id === data.id) + arr.splice(i, 1); + }); + }) + .catch(function (err) { + console.log(err); + }); + }); + }; + + $scope.exportService = function (serv) { + // clone the service + var service = JSON.parse(JSON.stringify(serv)); + + // clean up data before export + delete service._id; + delete service.sut._id; + delete service.user; + delete service.__v; + delete service.$$hashKey; + + if (service.basePath) { + service.basePath = service.basePath.replace('/' + service.sut.name, ''); + } + + service.rrpairs.forEach(function (rr) { + delete rr._id; + }); + + var data = new Blob([JSON.stringify(service, null, " ")], { type: 'application/json;charset=utf-8' }); + FileSaver.saveAs(data, service.name + '.json'); + }; + - $scope.restoreService = function (service) { - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.RESTORE_CONFIRM_TITLE); - $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.RESTORE_CONFIRM_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $scope.serviceInfo = function (serviceID) { + console.log('printing service id: ' + serviceID); + $http.get('/api/services/infoFrmArchive/' + serviceID) + .then(function (response) { + var data = response.data; + console.log(data); + if (data.service) feedbackService.displayServiceInfo(data.service); + if (data.mqservice) feedbackService.displayServiceInfo(data.mqservice); + $('#serviceInfo-modal').modal('toggle'); + }) + .catch(function (err) { + console.log(err); + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); - $('#modal-btn-yes').on("click", function () { - apiHistoryService.restoreService(service) - .then(function (response) { - var data = response.data; - console.log(data); - $scope.servicelist.forEach(function (elem, i, arr) { - if (elem._id === data.id) - arr.splice(i, 1); - }); - }) - .catch(function (err) { - console.log(err); - }); + }); + }; + }]) + + .controller("draftServiceController", ['$scope', '$location', '$routeParams', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', + function ($scope, $location, $routeParams, $http, $timeout, sutService, feedbackService, apiHistoryService, userService, authService, FileSaver, Blob, ctrlConstants) { + Promise.all([sutService.getAllSUTPromise(), userService.getAllUsersPromise()]).then(function (values) { + $scope.sutlist = values[0]; + $scope.userlist = values[1]; + if ($routeParams.user || $routeParams.sut) + performUpdateOnPathParams(); + else + $scope.filtersSelected(null, { name: authService.getUserInfo().username }); + }); + + $scope.servicelist = []; + console.log($routeParams); + + $scope.buttonHit = false; + + $scope.$watchGroup(['selectedSut', 'selectedUser'], function (newVals) { + $scope.filtersSelected(newVals[0], newVals[1]); + $scope.buttonHit = true; //bool check so function isnt called twice + }); + + + $scope.filtersSelected = function (sut, user) { + $location.path("/fetchDraftServices/" + (sut ? sut.name : '') + "/" + (user ? user.name : '')); + + if (sut && !user) { + apiHistoryService.getServiceForDraftSUT(sut.name) + + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) + + .catch(function (err) { + console.log(err); }); - }; + } + + else if (user && !sut) { + apiHistoryService.getServiceByDraftUser(user.name) + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) + + .catch(function (err) { + console.log(err); + }); + } + + else if (user && sut) { + apiHistoryService.getServicesDraftFiltered(sut.name, user.name) + + .then(function (response) { + var data = response.data; + console.log(data); + var arryListOfService = []; + for (let i = 0; i < data.length; i++) { + if (data[i].service) arryListOfService.push(data[i].service); + if (data[i].mqservice) arryListOfService.push(data[i].mqservice); + } + $scope.servicelist = arryListOfService; + }) - $scope.exportService = function(serv) { - // clone the service - var service = JSON.parse(JSON.stringify(serv)); + .catch(function (err) { + console.log(err); + }); + } + $scope.orderByField = 'name'; + $scope.reverseSort = false; + }; + function performUpdateOnPathParams() { + $scope.filtersSelected($routeParams.sut ? { name: $routeParams.sut } : null, $routeParams.user ? { name: $routeParams.user } : null); + if ($routeParams.sut) { + for (let sut of $scope.sutlist) { + if (sut.name == $routeParams.sut) { + $scope.selectedSut = sut; + break; + } + } + } else { + $scope.selectedSut = null; + } + if ($routeParams.user) { + for (let user of $scope.userlist) { + if (user.name == $routeParams.user) { + $scope.selectedUser = user; + break; + } + } + } else { + $scope.selectedUser = null; + } + } - // clean up data before export - delete service._id; - delete service.sut._id; - delete service.user; - delete service.__v; - delete service.$$hashKey; + $scope.$on('$routeUpdate', function () { + if (!$scope.buttonHit) + performUpdateOnPathParams(); + else + $scope.buttonHit = false; + }); + $scope.clearSelected = function () { + $scope.selectedSut = null; + $scope.selectedUser = null; + $scope.servicelist = []; + }; - if (service.basePath) { - service.basePath = service.basePath.replace('/' + service.sut.name, ''); + //returning a promise from factory didnt seem to work with .then() function here, alternative solution + $http.get('/api/systems') + .then(function (response) { + $scope.myUser = authService.getUserInfo().username; + $scope.myGroups = []; + response.data.forEach(function (sutData) { + var sut = { + name: sutData.name, + members: sutData.members + }; + sut.members.forEach(function (memberlist) { + if (memberlist.includes($scope.myUser)) { + $scope.myGroups.push(sut.name); } - - service.rrpairs.forEach(function(rr) { - delete rr._id; - }); + }); + }); + }).catch(function (err) { + console.log(err); + }); - var data = new Blob([JSON.stringify(service, null, " ")], { type: 'application/json;charset=utf-8' }); - FileSaver.saveAs(data, service.name + '.json'); - }; - $scope.serviceInfo = function(serviceID) { - console.log('printing service id: ' + serviceID); - $http.get('/api/services/infoFrmArchive/' + serviceID) - .then(function(response) { - var data = response.data; - console.log(data); - if(data.service)feedbackService.displayServiceInfo(data.service); - if(data.mqservice)feedbackService.displayServiceInfo(data.mqservice); - $('#serviceInfo-modal').modal('toggle'); - }) - .catch(function(err) { - console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(ctrlConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - }); - }; - }]); - - // .controller("draftServiceController", ['$scope', '$http', '$timeout', 'sutService', 'feedbackService', 'apiHistoryService', 'userService', 'authService', 'FileSaver', 'Blob', 'ctrlConstants', - // function($scope,$http,$timeout,sutService,feedbackService,apiHistoryService,userService,authService,FileSaver,Blob,ctrlConstants){ - // $scope.sutlist = sutService.getAllSUT(); - // $scope.userlist = userService.getAllUsers(); - // $scope.servicelist = []; - - // //script to retroactively assign group member. not needed for the future. - // $scope.script=function(){ - // console.log("starting script"); - // var sutnames = []; - // $http.get('/api/systems') - // .then(function (response) { - // response.data.forEach(function (sutData) { - // var sut = { - // name: sutData.name, - // members: sutData.members - // }; - // sutnames.push(sut.name); - // }); - // }) - - // .catch(function (err) { - // console.log(err); - // }); - - // $http.get('/api/services/draft') - // .then(function (response) { - // console.log(response.data); - // for (var i = 0; i < response.data.length; i++) { - // var owner = response.data[i].user.uid; - // var sut = response.data[i].sut.name; - - // if (sutnames.includes(sut)){ - // console.log("sut "+ sut + " exists"); - // console.log(owner + " will be added to group: " + sut); - // sutService.updateGroup(sut, owner); - // } - // else{ - // console.log("sut " + sut + " does not exist"); - // } - // } - // }) - - // .catch(function (err) { - // console.log(err); - // }); - // } - // ///////////////////////////end script. to remove - - // $scope.filtersSelected = function(sut, user) { - // if (sut && !user) { - // apiHistoryService.getServiceForDraftSUT(sut.name) - - // .then(function(response) { - // var data = response.data; - // console.log(data); - // var arryListOfService=[]; - // for (let i = 0; i < data.length; i++) { - // if(data[i].service)arryListOfService.push(data[i].service); - // if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - // } - // $scope.servicelist = arryListOfService; - // }) - - // .catch(function(err) { - // console.log(err); - // }); - // } - - // else if (user && !sut) { - // apiHistoryService.getServiceByDraftUser(user.name) - // .then(function(response) { - // var data = response.data; - // console.log(data); - // var arryListOfService=[]; - // for (let i = 0; i < data.length; i++) { - // if(data[i].service)arryListOfService.push(data[i].service); - // if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - // } - // $scope.servicelist = arryListOfService; - // }) - - // .catch(function(err) { - // console.log(err); - // }); - // } - - // else if (user && sut) { - // apiHistoryService.getServicesDraftFiltered(sut.name, user.name) - - // .then(function(response) { - // var data = response.data; - // console.log(data); - // var arryListOfService=[]; - // for (let i = 0; i < data.length; i++) { - // if(data[i].service)arryListOfService.push(data[i].service); - // if(data[i].mqservice)arryListOfService.push(data[i].mqservice); - // } - // $scope.servicelist = arryListOfService; - // }) - - // .catch(function(err) { - // console.log(err); - // }); - // } - - // //returning a promise from factory didnt seem to work with .then() function here, alternative solution - // $http.get('/api/systems') - // .then(function (response) { - // $scope.myUser = authService.getUserInfo().username; - // $scope.myGroups = []; - // response.data.forEach(function (sutData) { - // var sut = { - // name: sutData.name, - // members: sutData.members - // }; - // sut.members.forEach(function (memberlist) { - // if (memberlist.includes($scope.myUser)) { - // $scope.myGroups.push(sut.name); - // } - // }); - // }); - // }) - - // .catch(function (err) { - // console.log(err); - // }); - - - // $http.get('/api/users/admin') - // .then(function(response) { - // $scope.adminUser = response.data; - // }) - - // .catch(function(err) { - // console.log(err); - // }); - - // }; - // $scope.filtersSelected(null, { name: authService.getUserInfo().username }); - - // $scope.clearSelected = function() { - // $scope.selectedSut = null; - // $scope.selectedUser = null; - // $scope.servicelist = []; - // }; - - // $scope.deleteDraftService = function (service) { - // $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); - // $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_DRAFTSERVICE_BODY); - // $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); - // $('#genricMsg-dialog').modal('toggle'); - // $('#modal-btn-yes').on("click", function () { - // apiHistoryService.deleteDraftService(service) - // .then(function (response) { - // var data = response.data; - // console.log(data); - // $scope.servicelist.forEach(function (elem, i, arr) { - // if (elem._id === data.id) - // arr.splice(i, 1); - // }); - // }) - // .catch(function (err) { - // console.log(err); - // }); - // }); - // }; - - // }]); + $http.get('/api/users/admin') + .then(function (response) { + $scope.adminUser = response.data; + }).catch(function (err) { + console.log(err); + }); + + + $scope.deleteDraftService = function (service) { + $('#genricMsg-dialog').find('.modal-title').text(ctrlConstants.DEL_CONFIRM_TITLE); + $('#genricMsg-dialog').find('.modal-body').html(ctrlConstants.DEL_DRAFTSERVICE_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(ctrlConstants.DEL_CONFIRM_FOOTER); + $('#genricMsg-dialog').modal('toggle'); + $('#modal-btn-yes').on("click", function () { + apiHistoryService.deleteDraftService(service) + .then(function (response) { + var data = response.data; + console.log(data); + $scope.servicelist.forEach(function (elem, i, arr) { + if (elem._id === data.id) + arr.splice(i, 1); + }); + }) + .catch(function (err) { + console.log(err); + }); + }); + }; + }]) + //Put all the hard coding or constants here for controller. ctrl.constant("ctrlConstants", { - "DUP_REQ_ERR_TITLE" : "Duplicate Request Error", - "DUP_REQ_ERR_BODY" : "Two Requests are same. Either change request data or relative path of duplicate requests.", - "PUB_FAIL_ERR_TITLE" : "Publish Failure Error", - "PUB_FAIL_ERR_BODY" : "Please ensure your request / response pairs are well formed.", - "DUP_RECORDER_PATH_TITLE" : "Publish Failure: Duplicate Path", - "DUP_RECORDER_PATH_BODY" : "This recorder's group and path overlap with an active recorder.", - "REG_SUCCESS_TITLE" : "REGISTRATION SUCCESS", - "REG_SUCCESS_BODY" : "



Registration completed successfully

Thank you. You can log in for service virtualization now

", - "CLOSE_PRMRY_BTN_FOOTER" : '', - "DATAGEN_ALERT_MSG_1000ROWS" : "You may generate up to 1,000 rows of data at a time. Utilize the row id index for more.", - "DEL_CONFIRM_TITLE" : "Delete Confirmation", - "RESTORE_CONFIRM_TITLE" : "Restore Confirmation", - "DEL_CONFIRM_BODY" : "This service will be deleted and moved to Archive. Do you want to continue ?", - "DEL_REC_CONFIRM_BODY" : "Do you really want to delete this recording?", - "DEL_CONFIRM_FOOTER" : '', + "DUP_REQ_ERR_TITLE": "Duplicate Request Error", + "DUP_REQ_ERR_BODY": "Two Requests are same. Either change request data or relative path of duplicate requests.", + "PUB_FAIL_ERR_TITLE": "Publish Failure Error", + "PUB_FAIL_ERR_BODY": "Please ensure your request / response pairs are well formed.", + "DUP_RECORDER_PATH_TITLE": "Publish Failure: Duplicate Path", + "DUP_RECORDER_PATH_BODY": "This recorder's group and path overlap with an active recorder.", + "REG_SUCCESS_TITLE": "REGISTRATION SUCCESS", + "REG_SUCCESS_BODY": "



Registration completed successfully

Thank you. You can log in for service virtualization now

", + "CLOSE_PRMRY_BTN_FOOTER": '', + "DATAGEN_ALERT_MSG_1000ROWS": "You may generate up to 1,000 rows of data at a time. Utilize the row id index for more.", + "DEL_CONFIRM_TITLE": "Delete Confirmation", + "RESTORE_CONFIRM_TITLE": "Restore Confirmation", + "DEL_CONFIRM_BODY": "This service will be deleted and moved to Archive. Do you want to continue ?", + "DEL_REC_CONFIRM_BODY": "Do you really want to delete this recording?", + "DEL_CONFIRM_FOOTER": '', "DEL_CONFIRM_USER_BODY": 'Do you really want to remove this user from the group?', - "DEL_CONFIRM_RRPAIR_BODY" : 'Do you really want to delete this RRPair ?', - "BULK_UPLOAD_SUCCESS_MSG" : "Bulk Upload Success! File Uploaded - ", - "BULK_UPLOAD_FAILURE_MSG" : "Unexpected Error. Bulk Upload Fail. File Uploaded - ", - "BULK_UPLOAD_FILE_TYPE_FAILURE_MSG" : "Uploaded file type is not zip. File Uploaded - ", - "SPEC_UPLOAD_SUCCESS_MSG" : "Spec Upload Success! File Uploaded - ", - "SPEC_UPLOAD_FAILURE_MSG" : "Unexpected Error. Spec Upload Fail. File Uploaded - ", - "SPEC_FILE_TYPE_URL_PUBLISH_ERROR" : "Your uploaded file type Or URL don't match with Spec type.", - "SPEC_FILE_TYPE_UPLOAD_ERROR" : "Upload Fail - Your uploaded file type don't match with Spec type. Uploaded File - ", - "DUPLICATE_CONFIRM_FOOTER" : '', - "IMPORT_ERR_MSG" : "You should upload only correct json file.", - "SUCCESS" : "success", - "GRP_ALREADY_EXIST_MSG" : "Group Name Already exist.", - "DEL_Permanent_CONFIRM_BODY" : "This service will be deleted permanently. Do you want to continue ?", - "RESTORE_CONFIRM_BODY" : "This service will be restored. You can find this service in browse tab. Continue ?", + "DEL_CONFIRM_RRPAIR_BODY": 'Do you really want to delete this RRPair ?', + "BULK_UPLOAD_SUCCESS_MSG": "Bulk Upload Success! File Uploaded - ", + "BULK_UPLOAD_FAILURE_MSG": "Unexpected Error. Bulk Upload Fail. File Uploaded - ", + "BULK_UPLOAD_FILE_TYPE_FAILURE_MSG": "Uploaded file type is not zip. File Uploaded - ", + "SPEC_UPLOAD_SUCCESS_MSG": "Spec Upload Success! File Uploaded - ", + "SPEC_UPLOAD_FAILURE_MSG": "Unexpected Error. Spec Upload Fail. File Uploaded - ", + "SPEC_FILE_TYPE_URL_PUBLISH_ERROR": "Your uploaded file type Or URL don't match with Spec type.", + "SPEC_FILE_TYPE_UPLOAD_ERROR": "Upload Fail - Your uploaded file type don't match with Spec type. Uploaded File - ", + "DUPLICATE_CONFIRM_FOOTER": '', + "IMPORT_ERR_MSG": "You should upload only correct json file.", + "SUCCESS": "success", + "GRP_ALREADY_EXIST_MSG": "Group Name Already exist.", + "DEL_Permanent_CONFIRM_BODY": "This service will be deleted permanently. Do you want to continue ?", + "RESTORE_CONFIRM_BODY": "This service will be restored. You can find this service in browse tab. Continue ?", "GRP_CREATED_SUCCESS_MSG": "Group Created Successfully", - "GRP_DELETION_SUCCESS_MSG" : "Group Deleted Successfully", - "DEL_DRAFTSERVICE_BODY" : "This service Info will be deleted. Do you want to continue ?", - "PUB_FAIL_SERV_SAVE_BODY" : " Please ensure your request / response pairs are well formed. ", /*+ - "Do you want to save the Service Info as draft",*/ - //"PUB_FAIL_SERV_SAVE_FOOTER" : '', - "PUB_FAIL_SERV_SAVE_FOOTER" : '', - "SERV_INFO_NOT_FOUND" : "Service Info not found", - "SERV_SAVE_FAIL_ERR_TITLE" : "Service Info Failure", + "GRP_DELETION_SUCCESS_MSG": "Group Deleted Successfully", + "DEL_DRAFTSERVICE_BODY": "This service Info will be deleted. Do you want to continue ?", + "PUB_FAIL_SERV_SAVE_BODY": " Please ensure your request / response pairs are well formed. " + + "Do you want to save the Service Info as draft", + "PUB_FAIL_SERV_SAVE_FOOTER": '', + //"PUB_FAIL_SERV_SAVE_FOOTER" : '', + "SERV_INFO_NOT_FOUND": "Service Info not found", + "SERV_SAVE_FAIL_ERR_TITLE": "Service Info Failure", + "BACK_DANGER_BTN_FOOTER": '', + "MRG_CONFIRM_TITLE": "Merge Confirmation", + "MRG_CONFIRM_BODY": "Do you want to merge this RRPair into the service?", + "MRG_CONFIRM_FOOTER": '' }); diff --git a/public/js/app/factories.js b/public/js/app/factories.js index df3b76dd..21ffcd26 100644 --- a/public/js/app/factories.js +++ b/public/js/app/factories.js @@ -66,8 +66,15 @@ fact.factory('sutFactory', ['$http', '$q', function($http, $q) { $http.get('/api/services/sut/' + sut.name+'/archive') .then(function (response) { if(response.data.length==0){ + $http.get('/api/services/sut/' + sut.name+'/draft') + .then(function (response) { + if(response.data.length==0){ + $http.get('/api/recording/sut/' + sut.name) + .then(function (response) { + if(response.data.length==0){ + // console.log("Wee found",response.data); deleteSutList.push(sut); - } + } })}})} }) }}) diff --git a/public/js/app/services.js b/public/js/app/services.js index 1e919bcd..2895e743 100644 --- a/public/js/app/services.js +++ b/public/js/app/services.js @@ -1,5 +1,19 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) + .service('modalService',['$http','$rootScope','servConstants', + function($http,$rootScope,servConstants){ + function setRemoteModal(title,remoteBodyLocation,footer){ + $http.get(remoteBodyLocation).then(function(rsp){ + $('#genricMsg-dialog').find('.modal-title').text(title); + $('#genricMsg-dialog').find('.modal-body').html(rsp.data); + $('#genricMsg-dialog').find('.modal-footer').html(""); + $('#genricMsg-dialog').modal('toggle'); + }); + } + this.showTemplateHelp = function(){ + setRemoteModal(servConstants.MCH_HELP_TITLE,"/partials/modals/templateHelpModal.html",""); + } + }]) .service('authService', ['$http', '$window', '$location', '$rootScope', 'servConstants', function($http, $window, $location, $rootScope, servConstants) { var userInfo; @@ -52,6 +66,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.LOGIN_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.LOGIN_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); }; @@ -104,10 +119,11 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) op.path = op.path.slice(0,-1); var qs = '?'; - var qArr = Object.entries(rr.queries); - + var qArr = Object.entries(rr.queries); qArr.forEach(function(q) { - qs = qs + q[0] + '=' + q[1] + '&'; + if( q[0] != '' && q[1] != ''){ + qs = qs + q[0] + '=' + q[1] + '&'; + } }); // trim last & @@ -133,11 +149,34 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) .service('apiHistoryService', ['$http', '$location', 'authService', 'feedbackService', 'xmlService', 'servConstants','$routeParams', function($http, $location, authService, feedbackService, xmlService, servConstants,$routeParams) { + this.deleteRecordedLiveRRPair = function(serviceId,rrPairId){ + var token = authService.getUserInfo().token; + return $http.delete('/api/services/' + serviceId + '/recorded/' + rrPairId + "?token=" + token); + } + + this.addRRPairToService = function(serviceId,rr){ + var token = authService.getUserInfo().token; + return $http.patch('/api/services/' + serviceId + '/rrpairs?token=' + token, rr); + } + + this.getRecordedLiveRRPairs = function(serviceId){ + return $http.get('/api/services/' + serviceId + '/recorded'); + } + //gets all recordings, unfiltered this.getRecordings = function(){ return $http.get('/api/recording'); } + this.startRecorder = function(recorder){ + return $http.patch('/api/recording/' + recorder._id + "/start"); + + } + + this.stopRecorder = function(recorder){ + return $http.patch('/api/recording/' + recorder._id + "/stop"); + } + this.getRecordingById = function(id){ return $http.get('/api/recording/' + id); } @@ -375,6 +414,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) failStatusCodes : failCodesArray, failStrings : failStringsArray, ssl : servicevo.invokeSSL, + record : servicevo.liveRecordCheck, liveFirst : servicevo.liveInvokePrePost == 'PRE' }; @@ -389,12 +429,6 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) .then(function(response) { var data = response.data; console.log(data); - if(data.error == 'twoSeviceDiffNameSameBasePath'){ - $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.TWOSRVICE_DIFFNAME_SAMEBP_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - } - else{ if(isRecording){ $http.delete('/api/recording/' + $routeParams.id).then(function(){ $location.path('/update/' + data._id + '/frmServCreate'); @@ -402,13 +436,13 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) }else{ $location.path('/update/' + data._id + '/frmServCreate'); } - } }) .catch(function(err) { console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-body').text(err.data.error); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); } @@ -418,14 +452,20 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) .then(function(response) { var data = response.data; console.log(data); + + if($routeParams.frmWher == 'frmDraft'){ + $location.path('/selectService/'+ data._id); + }else{ feedbackService.displayServiceInfo(data); $('#success-modal').modal('toggle'); + } }) .catch(function(err) { console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(servConstants.err.data.error); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); } @@ -613,13 +653,15 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) if (!isUpdate) { $http.post('/api/services/draftservice?token=' + token, servData) .then(function(response) { - var data = response.data; - console.log(data); - if(data.error == 'twoSeviceDiffNameSameBasePath'){ - $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.TWOSRVICE_DIFFNAME_SAMEBP_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); - } + var data; + if(response.data.mqservice) + data = response.data.mqservice; + else + data = response.data.service; + console.log(data); + + $location.path('/showDraftService/' + data._id + '/frmCreateDraft'); + $('#service-save-success-modal').modal('toggle'); }) @@ -627,6 +669,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.SERVICE_SAVE_FAIL_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.SERVICE_SAVE_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); } @@ -641,7 +684,6 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) data = response.data.service; console.log(data); - feedbackService.displayServiceInfo(data); $('#service-save-success-modal').modal('toggle'); }) @@ -649,6 +691,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.SERVICE_SAVE_FAIL_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.SERVICE_SAVE_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); } @@ -703,7 +746,14 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) remotePort:servicevo.remotePort, basePath:servicevo.basePath, headerMask:[], - ssl:servicevo.ssl + ssl:servicevo.ssl, + creator:servicevo.currentUser, + filters:{ + enabled:servicevo.filterEnable, + bodyStrings:[], + headers:[], + statuses:[] + } } @@ -715,6 +765,25 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) if(head.k) recorder.headerMask.push(head.k.originalObject); } + + //Extract filters + servicevo.filterStatusCodes.forEach(function(code){ + if(code.v){ + recorder.filters.statuses.push(parseInt(code.v)); + } + }); + servicevo.filterStrings.forEach(function(string){ + if(string.v){ + recorder.filters.bodyStrings.push(string.v); + } + }); + servicevo.filterHeaders.forEach(function(header){ + if(header.k){ + recorder.filters.headers.push({key:header.k,value:header.v}); + } + }); + + console.log(servicevo); @@ -731,14 +800,10 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) .catch(function(err) { console.log(err); - if(err.data.error == "OverlappingRecorderPathError"){ - $('#genricMsg-dialog').find('.modal-title').text(servConstants.DUP_RECORDER_PATH_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.DUP_RECORDER_PATH_BODY); - }else{ $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_FAIL_ERR_TITLE); - } - $('#genricMsg-dialog').modal('toggle'); + $('#genricMsg-dialog').find('.modal-body').text(err.data.error); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); }); }; @@ -752,6 +817,22 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) return sutlist; }; + this.getAllSUTPromise = function(){ + return new Promise(function(resolve,reject){ + $http.get('/api/systems').then(function(response){ + var sutlist = []; + response.data.forEach(function(sutData) { + var sut = { + name: sutData.name + }; + + sutlist.push(sut); + }); + resolve(sutlist); + }); + }); + }; + this.getGroupsToBeDeleted = function(user){ var deleteSutList = sutFactory.getGroupsToBeDeleted(user); return deleteSutList; @@ -799,6 +880,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.ADD_SUT_FAIL_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.ADD_SUT_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); });} @@ -855,15 +937,8 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) }) .then(function (response) { var data = response.data; - if(data.error == 'twoSeviceDiffNameSameBasePath'){ - $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.TWOSRVICE_DIFFNAME_SAMEBP_ERR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(servConstants.CLOSE_PRMRY_BTN_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } - else{ $location.path('/update/' + data._id + '/frmServCreate'); - }}) + }) .catch(function (err) { console.log(err.data.error); return message(err.data.error); @@ -920,21 +995,14 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) }) .then(function (response) { var data = response.data; - if(data.error == 'twoSeviceDiffNameSameBasePath'){ - $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.TWOSRVICE_DIFFNAME_SAMEBP_ERR_BODY); - $('#genricMsg-dialog').find('.modal-footer').html(servConstants.CLOSE_PRMRY_BTN_FOOTER); - $('#genricMsg-dialog').modal('toggle'); - } - else{ $location.path('/update/' + data._id + '/frmServCreate'); - } return message(response.data.error); }) .catch(function (err) { console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_SPEC_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-body').text(err.data.error); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); }; @@ -944,63 +1012,64 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) function() { this.getDataType = function(dataType){ - var dataOut; - switch(dataType){ - case "First Name": - dataOut = chance.first(); - break; - case "Last Name": - dataOut = chance.last(); - break; - case "Boolean": - dataOut = chance.bool(); - break; - case "Country": - dataOut = chance.country({full: true}); - break; - case "Birthday": - dataOut = chance.birthday({string: true}); - break; - case "Email Address": - dataOut = chance.email({domain: 'example.com'}); - break; - case "IP Address": - dataOut = chance.ip(); - break; - case "Street Address": - dataOut = chance.address(); - break; - case "Date": - dataOut = chance.date({string: true}); - break; - case "Day of Week": - dataOut = chance.weekday(); - break; - case "Year": - dataOut = chance.year({min: 1900, max: 2100}); - break; - case "Integer": - dataOut = chance.integer({min: 1, max: 10}); - break; - - case "String": - dataOut = chance.string({ length: 10 }); - break; - - case "Numeric String": - dataOut = chance.string({ length: 10, pool: '0123456789'}); - break; - - case "String w/o Special Chars": - dataOut = chance.string({ length: 10, pool: '0123456789qwertyuiopasdfghjklzxcvbnm' }); - break; - - default: - //handles all chancejs functions that are spelled exactly the same in interface. ie: Zip to zip() - dataOut = eval("chance." + dataType.toLowerCase() + "()"); - } - - return dataOut; + if(dataType != null){ + var dataOut; + switch(dataType){ + case "First Name": + dataOut = chance.first(); + break; + case "Last Name": + dataOut = chance.last(); + break; + case "Boolean": + dataOut = chance.bool(); + break; + case "Country": + dataOut = chance.country({full: true}); + break; + case "Birthday": + dataOut = chance.birthday({string: true}); + break; + case "Email Address": + dataOut = chance.email({domain: 'example.com'}); + break; + case "IP Address": + dataOut = chance.ip(); + break; + case "Street Address": + dataOut = chance.address(); + break; + case "Date": + dataOut = chance.date({string: true}); + break; + case "Day of Week": + dataOut = chance.weekday(); + break; + case "Year": + dataOut = chance.year({min: 1900, max: 2100}); + break; + case "Integer": + dataOut = chance.integer({min: 1, max: 10}); + break; + + case "String": + dataOut = chance.string({ length: 10 }); + break; + + case "Numeric String": + dataOut = chance.string({ length: 10, pool: '0123456789'}); + break; + + case "String w/o Special Chars": + dataOut = chance.string({ length: 10, pool: '0123456789qwertyuiopasdfghjklzxcvbnm' }); + break; + + default: + //handles all chancejs functions that are spelled exactly the same in interface. ie: Zip to zip() + dataOut = eval("chance." + dataType.toLowerCase() + "()"); + } + } + return dataOut; }; this.json2xml = function(data){ @@ -1057,6 +1126,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(e); $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_FAIL_ERR_BODY_IMPORT_TEMPLATE); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); return; } @@ -1072,6 +1142,7 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) console.log(err); $('#genricMsg-dialog').find('.modal-title').text(servConstants.ADD_SUT_FAIL_ERR_TITLE); $('#genricMsg-dialog').find('.modal-body').text(servConstants.ADD_SUT_FAIL_ERR_BODY); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); $('#genricMsg-dialog').modal('toggle'); }); @@ -1083,19 +1154,31 @@ var serv = angular.module('mockapp.services',['mockapp.factories']) }) .catch(function(err) { console.log(err); - $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); - $('#genricMsg-dialog').find('.modal-body').text(servConstants.PUB_FAIL_ERR_BODY); - $('#genricMsg-dialog').modal('toggle'); + $('#genricMsg-dialog').find('.modal-title').text(servConstants.PUB_FAIL_ERR_TITLE); + $('#genricMsg-dialog').find('.modal-body').text(err.data.error); + $('#genricMsg-dialog').find('.modal-footer').html(servConstants.BACK_DANGER_BTN_FOOTER); + $('#genricMsg-dialog').modal('toggle'); }); }; }]) - .service('userService', ['userFactory', - function(userFactory) { + .service('userService', ['userFactory','$http', + function(userFactory,$http) { this.getAllUsers = function() { return userFactory.getAllUsers(); }; + this.getAllUsersPromise = function() { + return new Promise(function(resolve,reject){ + $http.get('/api/users').then(function(response){ + var userlist = []; + response.data.forEach(function(userData){ + userlist.push({name:userData.uid}); + }); + resolve(userlist); + }); + }); + }; }]) .service('suggestionsService', ['statusCodesFactory', 'headersFactory', @@ -1145,18 +1228,15 @@ serv.constant("servConstants", { "LOGIN_ERR_TITLE" : "Login Error", "LOGIN_ERR_BODY" : "Invalid credentials. Please try again.", "PUB_FAIL_ERR_TITLE" : "Publish Failure Error", - "PUB_FAIL_ERR_BODY" : "Please ensure your request / response pairs are well formed.", "PUB_FAIL_ERR_BODY_IMPORT_TEMPLATE" : "Please ensure you have uploaded a file in JSON format.", - "TWOSRVICE_DIFFNAME_SAMEBP_ERR_BODY" : "There is another service already exist in our system with same basepath.", "UPLOAD_FAIL_ERR_TITLE" : "Upload Failure Error", "UPLOAD_FAIL_ERR_BODY" : "Error occured in bulk upload.", "ADD_SUT_FAIL_ERR_TITLE" : "SUT Add Error", "ADD_SUT_FAIL_ERR_BODY" : "Error occured in creating new SUT.", - "PUB_SPEC_FAIL_ERR_BODY": "Spec publish failed. Please verify again the URL you have entered or spec file you have uploaded.", "SOME_ERR_IN_UPLOADING_ZIP" : "There is some problem in uploading this zip file." , - "CLOSE_PRMRY_BTN_FOOTER" : '', "DUP_RECORDER_PATH_TITLE" : "Publish Failure: Duplicate Path", - "DUP_RECORDER_PATH_BODY" : "This recorder's group and path overlap with an active recorder.", "SERVICE_SAVE_FAIL_ERR_TITLE" : "Service Info Failure", - "SERVICE_SAVE_FAIL_ERR_BODY": "Service Info save as draft failed" + "SERVICE_SAVE_FAIL_ERR_BODY": "Service Info save as draft failed", + "BACK_DANGER_BTN_FOOTER" : '', + "MCH_HELP_TITLE" : "Match Templates Help" }); \ No newline at end of file diff --git a/public/partials/addapiform.html b/public/partials/addapiform.html index 0865878c..359e55c0 100644 --- a/public/partials/addapiform.html +++ b/public/partials/addapiform.html @@ -68,10 +68,16 @@

Mock a REST, SOAP or MQ Service

-
+

- + +
+ +
+
- +
- +
+ + + +
+ +
+ +
@@ -251,6 +265,7 @@

Request / Response Pair

+
@@ -260,8 +275,8 @@

Request / Response Pair

-
-
@@ -301,6 +316,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
@@ -367,6 +383,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
@@ -407,7 +424,7 @@

Request / Response Pair

- +
diff --git a/public/partials/admin.html b/public/partials/admin.html index 69516ad3..29901a3b 100644 --- a/public/partials/admin.html +++ b/public/partials/admin.html @@ -4,42 +4,38 @@

Admin and Security for
- + +
+
+
{{createGroupMessage}}
-
- +
+
-
-
{{createGroupMessage}}
+ +
+ +
{{deleteGroupMessage}}
+
+ + +
+ +
+

+

- -
- -
-
-
- -
-
- -
-
-
{{deleteGroupMessage}}
-
- -
-
-

@@ -47,9 +43,9 @@

Admin and Security for

-
+
- +

pause="100" selected-object="header.k" local-data="possibleHeaders" - override-suggestions="true" - search-fields="name" - title-field="name" + minlength="3" input-class="form-control" match-class="highlight">
-
-
@@ -111,6 +110,101 @@

Create Recording Instance

+
+ + + +
+ +
+
+ +
+ +
+
+ + +
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+ +
+ + +
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+ +
+ + +
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+
diff --git a/public/partials/deletedServices.html b/public/partials/deletedServices.html index 69c0d1dc..c5f8ca3e 100644 --- a/public/partials/deletedServices.html +++ b/public/partials/deletedServices.html @@ -8,8 +8,8 @@

Deleted Services

  -   - + +
@@ -21,21 +21,29 @@

Deleted Services

- - - - - - - - - - - - - - - + + + + + + + + + + + + + +
NameOwnerGroupTypeBase URLAction
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }} +
+ Name + Owner + Group + + Type + + Base URL + Action
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}     diff --git a/public/partials/draftServices.html b/public/partials/draftServices.html index 16c9a9c3..1d1ba8d5 100644 --- a/public/partials/draftServices.html +++ b/public/partials/draftServices.html @@ -8,8 +8,8 @@

Draft Services

  -   - + + @@ -22,21 +22,29 @@

Draft Services

- - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/public/partials/modals/templateHelpModal.html b/public/partials/modals/templateHelpModal.html new file mode 100644 index 00000000..e5b5c2e9 --- /dev/null +++ b/public/partials/modals/templateHelpModal.html @@ -0,0 +1,202 @@ +

+ Matching templates allow the user to select which fields Mockiato should attempt to match on, and/or provide specific conditions + for if a field is considered to have matched. +

+

Template structure

+

+ A matching template should mirror the incoming request in structure, but only include fields that you wish Mockiato to attempt + to match on. E.g. if your incoming request looks like: +

+        
+            {
+                "abc":"def",
+                "foo":"bar"
+            }
+        
+    
But you only want to match on the "abc" field, ignoring "foo", you could construct a matching template as such: +
+        
+            {
+                "abc":""
+            }
+        
+    
Then, Mockiato will ONLY attempt to match on "abc", so any of these requests would work: +
+        
+            {
+                "abc":"def"
+            }
+        
+    
+
+        
+            {
+                "abc":"def",
+                "foo":"bar"
+            }
+        
+    
+
+        
+            {
+                "abc":"def",
+                "foo":"123",
+                "nonsense","argument"
+            }
+        
+    
+

+

Conditions

+

NOTE: Conditions will only work with SOAP and REST services, NOT MQ.

+

Conditions are tests that Mockiato can apply to specific fields during matching- for instance, Mockiato can use the 'any' condition to test only that a field is present, but not test its value, or the 'lt' condition to test that a field's value is less than a given value. This is done by filling the value of a field with a 'condition string'. This string can contain one or more conditions, separated by a semicolon, ";". The argument passed to the condition is seperated by a colon, ":". A field is only considered matched if ALL conditions provided are matched.

+
+    
+        {
+            "abc":"lt:4"
+        }
+    
+
+

List of conditions

+
NameOwnerGroupTypeBase URLAction
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }} +
+ Name + Owner + Group + + Type + + Base URL + Action
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Condition + + Name + + Argument + + Description +
+ lt + + Less Than + + A number + + This condition evaluates true if and only if the request's value for this field is less than the argument provided. +
+ gt + + Greater Than + + A number + + This condition evaluates true if and only if the request's value for this field is greater than the argument provided. +
+ any + + Any + + none + + This condition evaluates true if and only if the field is present in the request. No further evaluation is made (any value may be passed) +
+ regex + + Regular Expression + + A javascript regular expression + + This condition evaluates true if and only if the request's value for this field CONTAINS an expression that matches this regular expression (This means if you want an exact, complete match, you will need to use ^ and $) +
+ map + + Map value + + A parameter name + + This condition always evaluates true. Additionally, it takes the incoming request value and maps it to a parameter name, which can then be used to reference this value to echo it in the response Mockiato gives to the user. NOTE: This ALWAYS resolves true. If you want to ensure this field is present, pair with the 'any' condition. +
+

Value Mapping

+

Using the 'Map' condition, Mockiato can map values from the request to the response dynamically. This is done by giving a parameter name to the map condition to save a value from the request to. Then, template tags are used in the configured response, as: {{parameterName}}

+

For instance, if your request looked like:

+
+        
+            {
+                "abc":"def",
+                "foo":"bar"
+            }
+        
+    
+ +

And your response like:

+ +
+    
+        {
+            "firstName":"Bob",
+            "lastName":"Johnson"
+        }
+    
+
+ +

And you wanted to map the value of 'abc' in the request to the value of 'firstName' in the response, you would set up a matching template like this:

+ +
+    
+        {
+            "abc":"map:fname",
+            "foo":""
+        }
+    
+
+ +

And a response like this:

+ +
+    
+        {
+            "firstName":"{{fname}}",
+            "lastName":"Johnson"
+        }
+    
+
+ +

Then, any value for 'abc' will be accepted, and mapped into the value of firstName in the response.

+ +

Multiple Conditions

+

Mockiato can evaluate multiple conditions on each field. To do this, just separate your conditions by a semicolon- ";". Each condition must evaluate true for this field to be considered a match. For example, if you wanted to use regular expressions to make sure a field was a valid Social Security Number, AND wanted to map its value to the response, you could do:

+
+    
+        {
+            "ssn":"regex:^[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$;map:ssn"
+        }
+    
+
+

Then, any field will be evaluated against the regular expression, AND be mapped to the parameter name 'ssn'.

\ No newline at end of file diff --git a/public/partials/recordedInvokePairs.html b/public/partials/recordedInvokePairs.html new file mode 100644 index 00000000..bdf58544 --- /dev/null +++ b/public/partials/recordedInvokePairs.html @@ -0,0 +1,460 @@ +

Merge Recorded Live Invocation Request/Responses

+

You are unable to edit this service because you aren't part of the group "{{servicevo.sut.name}}". You can request access + from the user: {{servicevo.lastUpdateUser}}.

+ +
+
+ +
+
+ + + +
+
+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
/virtual
+ +
+
+
+ +
+ +
+ +
+
to
+
+ +
+
+ +
+ +
+
+
+
+
+
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+ + + +
+ +
+
+ +
+ +
+
+ +
+
+ + +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+ +
+ + + +
+ +
+
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+ +
+
+
+
+

Request / Response Pair

+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + +
+
+
+ +
+ +
+
+
+
+
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+ + + + + + + + diff --git a/public/partials/recorderList.html b/public/partials/recorderList.html index 13646ec5..553b0d73 100644 --- a/public/partials/recorderList.html +++ b/public/partials/recorderList.html @@ -19,21 +19,31 @@

Browse Recorders

- - - - - - - - - - - - - - - + + + + + + + + + + + + +
NameGroupTypeActiveBase URLDelete
{{recorder.name}}{{recorder.sut.name}}{{recorder.protocol}}{{recorder.active}}{{ mockiatoHost + '/recording/live/' + recorder.sut.name + recorder.path }}
+ Name + + Group + + Type + + Base URL + Action
{{recorder.name}}{{recorder.sut.name}}{{recorder.protocol}}{{ mockiatoHost + '/recording/live/' + recorder.sut.name + recorder.path }} + + + +
diff --git a/public/partials/selectService.html b/public/partials/selectService.html index 1fe31500..4e09ac7e 100644 --- a/public/partials/selectService.html +++ b/public/partials/selectService.html @@ -32,20 +32,20 @@

Create New Service

Recently Modified Services

- - - - - - + + + + + + - - - - - - + + + + + +
NameOwnerGroupTypeBase URLLast Modified ByNameOwnerGroupTypeBase URLLast Modified By
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}{{service.lastUpdateUser.uid}}{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}{{service.lastUpdateUser.uid}}
\ No newline at end of file diff --git a/public/partials/servicehistory.html b/public/partials/servicehistory.html index 28b3cf00..5f8a1e85 100644 --- a/public/partials/servicehistory.html +++ b/public/partials/servicehistory.html @@ -8,8 +8,8 @@

Browse Mocked Services

  -   - + + @@ -22,22 +22,32 @@

Browse Mocked Services

- - - - - - - + + + + + + + - - - - - - - - + + + + + + +
NameOwnerGroupTypeBase URLTransactionsAction + Name + Owner + Group + + Type + + Base URL + + Transactions + Action
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}{{service.txnCount}} +
{{service.name}}{{service.user.uid}}{{service.sut.name}}{{service.type}}{{ service.basePath ? mockiatoHost + '/virtual' + service.basePath : '' }}{{service.txnCount}}     diff --git a/public/partials/updateForm.html b/public/partials/updateForm.html index 25125690..b1d650af 100644 --- a/public/partials/updateForm.html +++ b/public/partials/updateForm.html @@ -1,4 +1,5 @@

Update Mock Service

+

You are unable to edit this service because you aren't part of the group "{{servicevo.sut.name}}". You can request access from the user: {{servicevo.lastUpdateUser}}.

@@ -70,10 +71,15 @@

Update Mock Service

-
+

+
+ +
+ +
+ + +
+ +
+
+ +
+

@@ -269,18 +286,19 @@

Request / Response Pair

+
- +
-
-
@@ -318,6 +336,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
@@ -387,6 +406,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
diff --git a/public/partials/viewRecorder.html b/public/partials/viewRecorder.html index a0ed4534..92377473 100644 --- a/public/partials/viewRecorder.html +++ b/public/partials/viewRecorder.html @@ -1,4 +1,6 @@

Finalize Recording

+

You are unable to edit this service because you aren't part of the group "{{servicevo.sut.name}}".

+
@@ -155,6 +157,7 @@

Request / Response Pair

+
@@ -164,8 +167,8 @@

Request / Response Pair

-
-
@@ -204,6 +207,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
@@ -273,6 +277,7 @@

Request / Response Pair

+
Request / Response Pair
-
-
@@ -331,6 +336,7 @@

Request / Response Pair

+