openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
174 lines (148 loc) • 5.55 kB
JavaScript
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