diff --git a/src/lib.js b/src/lib.js index faabd0ce..becd1543 100644 --- a/src/lib.js +++ b/src/lib.js @@ -251,9 +251,8 @@ function adjustResponseUrls(bodyText, fhirUrl, requestUrl, fhirBaseUrl, requestB return bodyText; } -function adjustUrl(url, isGet, sandboxes = []) { - - url = url.replace(RE_RESOURCE_SLASH_ID, ( +function adjustUrl(url) { + return url.replace(RE_RESOURCE_SLASH_ID, ( resourceAndId, resource, slashAndId, @@ -262,38 +261,39 @@ function adjustUrl(url, isGet, sandboxes = []) { slashAndQuery, query ) => resource + "?" + (query ? query + "&" : "") + "_id=" + id); - - // Also add tags if needed - if (sandboxes.length) { - // For GET requests add all the tags to act as filters. - // Otherwise only keep the first (the custom) tag - let sandboxTags = isGet ? sandboxes.join(",") : sandboxes[0]; - url += (url.indexOf("?") == -1 ? "?" : "&") + "_tag=" + sandboxTags; - } - - return url; } -function adjustRequestBody(json, system, sandboxes) { +function adjustRequestBody(json) { (json.entry || [{resource: json}]).forEach( entry => { if (entry.request) { - entry.request.url = - adjustUrl(entry.request.url, entry.request.method.toUpperCase() == "GET", sandboxes); - } - - let resource = entry.resource; - if (!resource.meta) { - resource.meta = {tag: [{system: system, code: sandboxes[0]}]}; - } else if (!resource.meta.tag) { - resource.meta.tag = [{system: system, code: sandboxes[0]}]; - } else { - resource.meta.tag = resource.meta.tag.filter( t => t.system != system ); - resource.meta.tag.push({system: system, code: sandboxes[0]}); + entry.request.url = adjustUrl(entry.request.url); } }); return json; } +/** + * Checks if the currentValue is within the white-listed values. If so, returns + * it. Otherwise returns the defaultValue if one is set, or throws an exception + * if no defaultValue is provided. + * @param {any[]} allowedValues + * @param {*} currentValue + * @param {*} defaultValue + */ +function whitelist(allowedValues, currentValue, defaultValue) { + if (allowedValues.indexOf(currentValue) == -1) { + if (arguments.length < 3) { + throw new Error( + `The value "${currentValue}" is not allowed. Must be one of ${ + allowedValues.join(", ") + }.` + ) + } + return defaultValue + } + return currentValue +} + module.exports = { getPath, generateRefreshToken, @@ -315,5 +315,6 @@ module.exports = { adjustUrl, adjustRequestBody, getRequestBaseURL, + whitelist, die -}; \ No newline at end of file +}; diff --git a/src/reverse-proxy.js b/src/reverse-proxy.js index 18a0fdda..fd435018 100644 --- a/src/reverse-proxy.js +++ b/src/reverse-proxy.js @@ -36,14 +36,6 @@ module.exports = function (req, res) { error: `FHIR server ${req.params.fhir_release} not found` }); } - - // only allow gets to blacklisted sandboxes (like the SMART default patients) - if (req.method != "GET" && !req.url.endsWith("/_search") && ( - !sandboxes || - config.protectedSandboxWords.find( w => sandboxes[0].toLowerCase().indexOf(w) != -1 ) - )) { - return res.status(401).send( fhirError("You do not have permission to modify this sandbox") ); - } // require a valid auth token if there is an auth token if (req.headers.authorization) { @@ -75,21 +67,17 @@ module.exports = function (req, res) { // fhirRequest.body = String(fhirRequest.body) + "&_tag=" + sandboxes.join("&"); } else if (Object.keys(req.body).length) { - fhirRequest.body = Lib.adjustRequestBody(req.body, config.sandboxTagSystem, sandboxes); + fhirRequest.body = Lib.adjustRequestBody(req.body); fhirRequest.body = Buffer.from(JSON.stringify(fhirRequest.body), 'utf8'); fhirRequest.headers['content-length'] = Buffer.byteLength(fhirRequest.body) } // make urls conditional and if exists, change /id to ?_id= if (isSearchPost) { - fhirRequest.url = Lib.buildUrlPath( - fhirServer, req.url - ); + fhirRequest.url = Lib.buildUrlPath(fhirServer, req.url); } else { - fhirRequest.url = Lib.buildUrlPath( - fhirServer, Lib.adjustUrl(req.url, req.method == "GET", sandboxes) - ); + fhirRequest.url = Lib.buildUrlPath(fhirServer, Lib.adjustUrl(req.url)); } // if applicable, apply patient scope to GET requests, largely for