Created
October 26, 2017 18:56
-
-
Save winniecluk/f131dae18c4db39cbeada0e63d2e3009 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const functions = require('firebase-functions'); | |
| const admin = require('firebase-admin'); | |
| admin.initializeApp(functions.config().firebase); | |
| const ROOT_URL = 'https://kipuapi.kipuworks.com'; | |
| const ACCEPT_HEADER_VALUE = 'application/vnd.kipusystems+json; version=1'; | |
| const request = require('request'); | |
| const crypto = require('crypto'); | |
| const querystring = require('querystring'); | |
| const BOUNDARY = '741e90d31eff'; | |
| const APP_IDENTIFIER = 'Salesforce.com'; | |
| // var Readable = require('stream'); | |
| var streamifier = require('streamifier'); | |
| var FormData = require('form-data'); | |
| var http = require('http'); | |
| let resourceMap = { | |
| "patients": { | |
| method: "POST", | |
| params: [], | |
| route: "/api/patients", | |
| idRequired: false | |
| }, | |
| "occupancy": { | |
| method: "GET", | |
| params: ["phi_level"], | |
| route: "/api/patients/occupancy?app_id=", | |
| idRequired: false | |
| }, | |
| "census": { | |
| method: "GET", | |
| params: ["phi_level"], | |
| route: "/api/patients/census?app_id=", | |
| idRequired: false | |
| }, | |
| "admissions": { | |
| method: "GET", | |
| params: ["phi_level"], | |
| route: "/api/patients/census?app_id=", | |
| idRequired: false | |
| }, | |
| "patient": { | |
| method: "GET", | |
| params: ["phi_level", "patient_master_id"], | |
| route: "/api/patients/:ID?app_id=" , | |
| idRequired: true | |
| }, | |
| "utilization": { | |
| method: "GET", | |
| params: ["phi_level", "patient_master_id"], | |
| route: "/api/patients/:ID/ur?app_id=" , | |
| idRequired: true | |
| } | |
| } | |
| function createReq(configObj){ | |
| let md5Digest = crypto.createHash('md5').update(JSON.stringify(configObj.body)).digest('binary'); | |
| let contentStr = Buffer.from(md5Digest, 'binary').toString('base64', 0, 24); | |
| let dateStr = new Date().toUTCString(); | |
| var canonicalStr = ''; | |
| if (configObj.method != 'GET') canonicalStr += 'application/json'; | |
| canonicalStr += ','+contentStr+','+configObj.uri+','+dateStr; | |
| let signature = crypto.createHmac('sha1', configObj.credentials.secretKey).update(canonicalStr).digest('base64'); | |
| let reqObj = { | |
| url: ROOT_URL + configObj.uri, | |
| headers: { | |
| 'Accept': ACCEPT_HEADER_VALUE, | |
| 'Authorization': 'APIAuth '+configObj.credentials.accessId+':'+signature, | |
| 'Content-MD5': contentStr, | |
| 'Date': dateStr | |
| } | |
| } | |
| if (configObj.method === 'POST'){ | |
| reqObj.body = JSON.stringify(configObj.body); | |
| reqObj.method = 'POST'; | |
| reqObj.headers['Content-type'] = 'application/json'; | |
| } else { | |
| reqObj.method = 'GET'; | |
| } | |
| return reqObj; | |
| } | |
| function createMultiPost(configObj){ | |
| // should have already validated earlier | |
| let dataObj = configObj.body.document.data; | |
| let attachmentsArr = configObj.body.document['attachment_attributes']; | |
| var postBody = ''; | |
| console.log('this is dataObj '); | |
| console.log(dataObj); | |
| console.log('these are the attachments'); | |
| console.log(attachmentsArr); | |
| for (var field in dataObj){ | |
| if (Array.isArray(dataObj[field])){ | |
| for (let i = 0; i < dataObj[field].length; i++){ | |
| for (var attribute in dataObj[field][i]){ | |
| postBody += '--'+BOUNDARY+'\r\n'; | |
| postBody += 'Content-Disposition: form-data; '; | |
| postBody += 'name="document[data][' + field +'][' + i + ']['+attribute+']\r\n'; | |
| postBody += '\r\n'; | |
| postBody += dataObj[field][i][attribute]; | |
| postBody += '\r\n'; | |
| } | |
| } | |
| } else { | |
| postBody += '--'+BOUNDARY+'\r\n'; | |
| postBody += 'Content-Disposition: form-data; '; | |
| postBody += 'name="document[data][' + field +']"'+'\r\n'; | |
| postBody += '\r\n'; | |
| postBody += dataObj[field]; | |
| postBody += '\r\n'; | |
| } | |
| } | |
| postBody += '--'+BOUNDARY+'\r\n'; | |
| postBody += 'Content-Disposition: form-data; '; | |
| postBody += 'name="document[recipient_id]"'+'\r\n'; | |
| postBody += '\r\n'; | |
| if (configObj.credentials.recipientId){ | |
| postBody += configObj.credentials.recipientId; | |
| } else { | |
| postBody += configObj.credentials.accessId; | |
| } | |
| postBody += '\r\n'; | |
| postBody += '--'+BOUNDARY+'\r\n'; | |
| postBody += 'Content-Disposition: form-data; '; | |
| postBody += 'name="document[sending_app_name]"'+'\r\n'; | |
| postBody += '\r\n'; | |
| postBody += APP_IDENTIFIER; | |
| postBody += '\r\n'; | |
| for (let i = 0; i < attachmentsArr.length; i++){ | |
| postBody += '--'+BOUNDARY+'\r\n'; | |
| postBody += 'Content-Disposition: form-data; '; | |
| postBody += 'name="document[attachments_attributes]['+ i +'][attachment]'+'"; '; | |
| postBody += 'filename="'+ attachmentsArr[i]['filename'] + '"\r\n'; | |
| // postBody += 'Content-type: ' + 'text/html' +' \r\n'; | |
| postBody += 'Content-type: ' + 'application/pdf' +' \r\n'; | |
| postBody += '\r\n'; | |
| var b = Buffer.from(attachmentsArr[i].attachment, 'base64'); | |
| // var bArr = [b]; | |
| // var buf = Buffer.concat(bArr); | |
| // postBody += escape(b.toString()); | |
| postBody += b; | |
| // if (i === attachmentsArr.length - 1){ | |
| // postBody += '\r\n--'+BOUNDARY+'--\r\n'; | |
| // } else { | |
| postBody += '\r\n'; | |
| // } | |
| } // closes attachmentArr loop | |
| postBody += '--'+BOUNDARY+'--\r\n'; | |
| let md5Digest = crypto.createHash('md5').update(postBody).digest('binary'); | |
| let contentStr = Buffer.from(md5Digest, 'binary').toString('base64', 0, 24); | |
| let dateStr = new Date().toUTCString(); | |
| // boundary | |
| var canonicalStr = 'multipart/form-data, boundary='+BOUNDARY+','; | |
| canonicalStr += contentStr+','+configObj.uri+','+dateStr; | |
| let signature = crypto.createHmac('sha1', configObj.credentials.secretKey).update(canonicalStr).digest('base64'); | |
| console.log('THIS IS POSTBODY IN CREATE MULTIPART'); | |
| console.log(postBody); | |
| // url: ROOT_URL + configObj.uri, | |
| let reqObj = { | |
| url: ROOT_URL + configObj.uri, | |
| method: 'POST', | |
| headers: { | |
| 'Content-type': 'multipart/form-data, boundary='+BOUNDARY, | |
| 'Accept': ACCEPT_HEADER_VALUE, | |
| 'Authorization': 'APIAuth '+configObj.credentials.accessId+':'+signature, | |
| 'Date': new Date().toUTCString(), | |
| 'Content-MD5': contentStr | |
| }, | |
| body: postBody | |
| }; | |
| // let options = { | |
| // host: 'cc570bfc.ngrok.io', | |
| // port: 3000, | |
| // path: '/firebase', | |
| // method: 'POST', | |
| // headers: { | |
| // 'Content-type': 'multipart/form-data, boundary='+BOUNDARY, | |
| // 'Accept': ACCEPT_HEADER_VALUE, | |
| // 'Authorization': 'APIAuth '+configObj.credentials.accessId+':'+signature, | |
| // 'Date': new Date().toUTCString(), | |
| // 'Content-MD5': contentStr | |
| // }, | |
| // body: postBody | |
| // }; | |
| // console.log('THIS IS REQOBJ INSIDE CREATE MULTIPART'); | |
| // console.log(reqObj); | |
| // form.submit(reqObj, function(err, response){ | |
| // if (err){ | |
| // console.log('we have an error'); | |
| // console.log(err); | |
| // } else { | |
| // console.log('this is the response'); | |
| // console.log(response); | |
| // } | |
| // }) | |
| return reqObj; | |
| } | |
| function validate(req, res){ | |
| var scope = {}; | |
| if (req.query.hasOwnProperty('sfid') | |
| && req.query.hasOwnProperty('method') | |
| && req.query.hasOwnProperty('resource') | |
| && resourceMap[req.query.resource] | |
| && req.query.method.toUpperCase() === resourceMap[req.query.resource].method | |
| ){ | |
| scope.sfId = req.query.sfid; | |
| scope.method = req.query.method.toUpperCase(); | |
| scope.resource = req.query.resource; | |
| } else { | |
| res.send('Missing required parameters or invalid arguments.'); | |
| } | |
| if (resourceMap[scope.resource].idRequired){ | |
| if (req.query.patientId){ | |
| scope.patientId = req.query.patientid; | |
| } else { | |
| res.send('Missing patient ID.'); | |
| } | |
| } | |
| if (scope.method === 'POST'){ | |
| if (req.query.hasOwnProperty('multipart') | |
| && (req.query.multipart.toLowerCase() === 'true' | |
| || req.query.multipart.toLowerCase() === 'false') | |
| ){ | |
| scope.multipart = req.query.multipart; | |
| } else { | |
| res.send('Missing required parameters or invalid arguments.'); | |
| } | |
| if (req.body | |
| && req.body.document.data | |
| && req.body.document['attachment_attributes'] | |
| ){ | |
| scope.body = req.body; | |
| } else { | |
| res.send('Missing body of request.'); | |
| } | |
| } | |
| let queryParams = resourceMap[scope.resource].params; | |
| for (let i = 0; i < queryParams.length; i++){ | |
| if (!req.query[queryParams[i]]){ | |
| res.send('Missing required parameters for this request.'); | |
| } | |
| } | |
| return scope; | |
| } | |
| function createURI(scope, req, res){ | |
| var uri = resourceMap[scope.resource].route; | |
| if (scope.method != 'POST'){ | |
| if (scope.credentials.appId){ | |
| uri += scope.credentials.appId; | |
| } else if (scope.credentials.accessId){ | |
| uri += scope.credentials.accessId; | |
| } else { | |
| res.send('Credentials missing in database.'); | |
| } | |
| // if idRequired == true | |
| if (resourceMap[scope.resource].idRequired){ | |
| uri = uri.replace(/:ID/, patientId) | |
| } | |
| let queryParams = resourceMap[scope.resource].params; | |
| for (let i = 0; i < queryParams.length; i++){ | |
| uri += '&' + queryParams[i] +'=' + req.query[queryParams[i]] | |
| } | |
| } | |
| console.log('this is the URI: ' + uri); | |
| return uri; | |
| } | |
| exports.handleRequests = functions.https.onRequest((req, res) => { | |
| var scope = validate(req, res); | |
| console.log('this is the scope'); | |
| console.log(scope); | |
| admin.database().ref('orgIds/' + scope.sfId).once('value').then(snapshot => { | |
| let data = snapshot.val(); | |
| if (data) { | |
| return { | |
| accessId: data.accessId, | |
| appId: data.appId, | |
| recipientId: data.recipientId, | |
| secretKey: data.secretKey | |
| } | |
| } else { | |
| res.send('Salesforce ID not found in database.'); | |
| } | |
| }).then(credentials => { | |
| scope.credentials = credentials; | |
| var uri = createURI(scope, req, res); | |
| return uri; | |
| }).then(uri => { | |
| scope.uri = uri; | |
| var reqObj; | |
| if (scope.method === 'GET'){ | |
| scope.body = ''; | |
| reqObj = createReq(scope); | |
| } else if (scope.method === 'POST'){ | |
| reqObj = scope.multipart ? createMultiPost(scope) : createReq(scope); | |
| // if (scope.multipart){ | |
| // reqObj = createMultiPost(scope); | |
| // } else { | |
| // reqObj = createReq(scope); | |
| // } | |
| }; | |
| return reqObj; | |
| }).then(reqObj => { | |
| // const req = http.request(reqObj, (resp) =>{ | |
| // console.log(`STATUS: ${res.statusCode}`); | |
| // console.log(`HEADERS: ${JSON.stringify(res.headers)}`); | |
| // res.setEncoding('utf8'); | |
| // res.on('data', (chunk) => { | |
| // console.log(`BODY: ${chunk}`); | |
| // }); | |
| // res.on('end', () => { | |
| // console.log('No more data in response.'); | |
| // }); | |
| // }); | |
| // | |
| // req.on('error', (e) => { | |
| // console.error(`problem with request: ${e.message}`); | |
| // }); | |
| // | |
| // req.write(postBody); | |
| // req.end(); | |
| console.log('this is reqObj being sent'); | |
| console.log(reqObj); | |
| request(reqObj, function(error, response, body){ | |
| if (error){ | |
| console.log(error); | |
| res.send(error); | |
| } else if (!error && response.statusCode === 200){ | |
| console.log('THINGS ARE 200'); | |
| console.log(body); | |
| res.send(body); | |
| } else if (!error && response.statusCode === 201){ | |
| console.log('THINGS ARE 201'); | |
| console.log(body); | |
| res.send(body); | |
| } else { | |
| console.log('THIS IS THE RESPONSE FROM KIPU'); | |
| console.log(response); | |
| console.log(body); | |
| res.send(response); | |
| } | |
| }); | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment