UNPKG

openhim-core

Version:

The OpenHIM core application that provides logging and routing of http requests

174 lines (148 loc) 5.55 kB
var Q, SDC, Transaction, application, config, dom, domain, extractContentType, getJSONValByString, isChannelEnabled, logger, matchContent, matchJsonPath, matchRegex, matchXpath, os, sdc, statsdServer, utils, xpath; Transaction = require("../model/transactions").Transaction; Q = require("q"); xpath = require("xpath"); dom = require("xmldom").DOMParser; logger = require("winston"); config = require('../config/config'); config.authentication = config.get('authentication'); utils = require('../utils'); statsdServer = config.get('statsd'); application = config.get('application'); SDC = require('statsd-client'); os = require('os'); domain = (os.hostname()) + "." + application.name + ".appMetrics"; sdc = new SDC(statsdServer); matchContent = function(channel, body) { if (channel.matchContentRegex) { return matchRegex(channel.matchContentRegex, body); } else if (channel.matchContentXpath && channel.matchContentValue) { return matchXpath(channel.matchContentXpath, channel.matchContentValue, body); } else if (channel.matchContentJson && channel.matchContentValue) { return matchJsonPath(channel.matchContentJson, channel.matchContentValue, body); } else if (channel.matchContentXpath || channel.matchContentJson) { logger.error('Channel with name "' + channel.name + '" is invalid as it has a content match expression but no value to match'); return false; } else { return true; } }; matchRegex = function(regexPat, body) { var regex; regex = new RegExp(regexPat); return regex.test(body.toString()); }; matchXpath = function(xpathStr, val, xml) { var doc, xpathVal; doc = new dom().parseFromString(xml.toString()); xpathVal = xpath.select(xpathStr, doc).toString(); return val === xpathVal; }; matchJsonPath = function(jsonPath, val, json) { var jsonObj, jsonVal; jsonObj = JSON.parse(json.toString()); jsonVal = getJSONValByString(jsonObj, jsonPath); return val === jsonVal.toString(); }; getJSONValByString = function(jsonObj, jsonPath) { var part, parts; jsonPath = jsonPath.replace(/\[(\w+)\]/g, '.$1'); jsonPath = jsonPath.replace(/^\./, ''); parts = jsonPath.split('.'); while (parts.length) { part = parts.shift(); if (part in jsonObj) { jsonObj = jsonObj[part]; } else { return; } } return jsonObj; }; extractContentType = function(ctHeader) { var index; index = ctHeader.indexOf(';'); if (index !== -1) { return ctHeader.substring(0, index).trim(); } else { return ctHeader.trim(); } }; if (process.env.NODE_ENV === "test") { exports.matchContent = matchContent; exports.matchRegex = matchRegex; exports.matchXpath = matchXpath; exports.matchJsonPath = matchJsonPath; exports.extractContentType = extractContentType; } exports.isChannelEnabled = isChannelEnabled = function(channel) { return !channel.status || channel.status === 'enabled'; }; exports.authorise = function(ctx, done) { return utils.getAllChannels(function(err, channels) { var allowedClient, channel, ct, i, isWhiteListed, len, matchedRoles, pat, requireWhitelistCheck; for (i = 0, len = channels.length; i < len; i++) { channel = channels[i]; pat = new RegExp(channel.urlPattern); if (pat.test(ctx.request.path)) { matchedRoles = {}; allowedClient = false; if (ctx.authenticated != null) { ctx.authenticated.ip = ctx.ip; if (ctx.authenticated.roles != null) { matchedRoles = channel.allow.filter(function(element) { return (ctx.authenticated.roles.indexOf(element)) !== -1; }); } if ((channel.allow.indexOf(ctx.authenticated.clientID)) !== -1) { allowedClient = true; } } else { ctx.authenticated = { ip: ctx.ip }; } requireWhitelistCheck = channel.whitelist.length > 0; isWhiteListed = !requireWhitelistCheck || ((channel.whitelist.indexOf(ctx.ip)) !== -1); if (isWhiteListed && ((matchedRoles.length > 0) || allowedClient || ((channel.authType === 'public') === true))) { if (channel.matchContentTypes && channel.matchContentTypes.length > 0) { if (ctx.request.header && ctx.request.header['content-type']) { ct = extractContentType(ctx.request.header['content-type']); if ((channel.matchContentTypes.indexOf(ct)) === -1) { continue; } } else { continue; } } if (isChannelEnabled(channel) && matchContent(channel, ctx.body)) { ctx.authorisedChannel = channel; logger.info("The request, '" + ctx.request.path + "' is authorised to access " + ctx.authorisedChannel.name); return done(); } } } } ctx.response.status = 401; if (config.authentication.enableBasicAuthentication) { ctx.set("WWW-Authenticate", "Basic"); } logger.info("The request, '" + ctx.request.path + "', is not authorised to access any channels."); return done(); }); }; exports.koaMiddleware = function*(next) { var authorise, startTime; if (statsdServer.enabled) { startTime = new Date(); } authorise = Q.denodeify(exports.authorise); (yield authorise(this)); if (this.authorisedChannel != null) { if (statsdServer.enabled) { sdc.timing(domain + ".authorisationMiddleware", startTime); } return (yield next); } }; //# sourceMappingURL=authorisation.js.map