UNPKG

openhim-core

Version:

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

425 lines (382 loc) 16.6 kB
var Channel, Client, Q, application, authorisation, config, domain, getChannelIDsArray, getProjectionObject, logger, os, sdc, statsd_client, statsd_server, timer, transactions, utils, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; transactions = require('../model/transactions'); Channel = require('../model/channels').Channel; Client = require('../model/clients').Client; Q = require('q'); logger = require('winston'); authorisation = require('./authorisation'); utils = require("../utils"); config = require('../config/config'); statsd_client = require("statsd-client"); statsd_server = config.get('statsd'); sdc = new statsd_client(statsd_server); application = config.get('application'); os = require("os"); timer = new Date(); domain = os.hostname() + '.' + application.name; getChannelIDsArray = function(channels) { var channel, channelIDs, i, len; channelIDs = []; for (i = 0, len = channels.length; i < len; i++) { channel = channels[i]; channelIDs.push(channel._id.toString()); } return channelIDs; }; getProjectionObject = function(filterRepresentation) { switch (filterRepresentation) { case "simpledetails": return { "request.body": 0, "response.body": 0, "routes.request.body": 0, "routes.response.body": 0, "orchestrations.request.body": 0, "orchestrations.response.body": 0 }; case "full": return {}; case "bulkrerun": return { "_id": 1, "childIDs": 1, "canRerun": 1, "channelID": 1 }; default: return { "request.body": 0, "request.headers": 0, "response.body": 0, "response.headers": 0, orchestrations: 0, routes: 0 }; } }; /* * Retrieves the list of transactions */ exports.getTransactions = function*() { var channels, e, filterLimit, filterPage, filterRepresentation, filterSkip, filters, filtersObject, key, projectionFiltersObject, ref; try { filtersObject = this.request.query; filterLimit = filtersObject.filterLimit; filterPage = filtersObject.filterPage; filterRepresentation = filtersObject.filterRepresentation; delete filtersObject.filterLimit; delete filtersObject.filterPage; delete filtersObject.filterRepresentation; filterSkip = filterPage * filterLimit; filters = filtersObject.filters != null ? JSON.parse(filtersObject.filters) : {}; if (!authorisation.inGroup('admin', this.authenticated)) { channels = (yield authorisation.getUserViewableChannels(this.authenticated)); if (!filtersObject.channelID) { filters.channelID = { $in: getChannelIDsArray(channels) }; } else if (ref = filtersObject.channelID, indexOf.call(getChannelIDsArray(channels), ref) < 0) { return utils.logAndSetResponse(this, 403, "Forbidden: Unauthorized channel " + filtersObject.channelID, 'info'); } filterRepresentation = ''; } projectionFiltersObject = getProjectionObject(filterRepresentation); if (filtersObject.channelID) { filters.channelID = filtersObject.channelID; } if (filters['request.timestamp']) { filters['request.timestamp'] = JSON.parse(filters['request.timestamp']); } /* Transaction Filters */ if (filters['request.path']) { filters['request.path'] = new RegExp(filters['request.path'], "i"); } if (filters['request.querystring']) { filters['request.querystring'] = new RegExp(filters['request.querystring'], "i"); } if (filters['response.status'] && utils.statusCodePatternMatch(filters['response.status'])) { filters['response.status'] = { "$gte": filters['response.status'][0] * 100, "$lt": filters['response.status'][0] * 100 + 100 }; } if (filters['properties']) { key = Object.keys(filters['properties'])[0]; filters['properties.' + key] = filters['properties'][key]; if (filters['properties'][key] === null) { filters['properties.' + key] = { '$exists': true }; } delete filters['properties']; } if (filters['childIDs.0']) { filters['childIDs.0'] = JSON.parse(filters['childIDs.0']); } /* Route Filters */ if (filters['routes.request.path']) { filters['routes.request.path'] = new RegExp(filters['routes.request.path'], "i"); } if (filters['routes.request.querystring']) { filters['routes.request.querystring'] = new RegExp(filters['routes.request.querystring'], "i"); } if (filters['routes.response.status'] && utils.statusCodePatternMatch(filters['routes.response.status'])) { filters['routes.response.status'] = { "$gte": filters['routes.response.status'][0] * 100, "$lt": filters['routes.response.status'][0] * 100 + 100 }; } /* orchestration Filters */ if (filters['orchestrations.request.path']) { filters['orchestrations.request.path'] = new RegExp(filters['orchestrations.request.path'], "i"); } if (filters['orchestrations.request.querystring']) { filters['orchestrations.request.querystring'] = new RegExp(filters['orchestrations.request.querystring'], "i"); } if (filters['orchestrations.response.status'] && utils.statusCodePatternMatch(filters['orchestrations.response.status'])) { filters['orchestrations.response.status'] = { "$gte": filters['orchestrations.response.status'][0] * 100, "$lt": filters['orchestrations.response.status'][0] * 100 + 100 }; } return this.body = (yield transactions.Transaction.find(filters, projectionFiltersObject).skip(filterSkip).limit(filterLimit).sort({ 'request.timestamp': -1 }).exec()); } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not retrieve transactions via the API: " + e, 'error'); } }; /* * Adds an transaction */ exports.addTransaction = function*() { var e, transactionData, tx; if (!authorisation.inGroup('admin', this.authenticated)) { utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to addTransaction denied.", 'info'); return; } transactionData = this.request.body; tx = new transactions.Transaction(transactionData); try { (yield Q.ninvoke(tx, "save")); this.status = 201; return logger.info("User " + this.authenticated.email + " created transaction with id " + tx.id); } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not add a transaction via the API: " + e, 'error'); } }; /* * Retrieves the details for a specific transaction */ exports.getTransactionById = function*(transactionId) { var channel, channels, e, filterRepresentation, filtersObject, group, i, len, projectionFiltersObject, ref, result, txChannelID; transactionId = unescape(transactionId); try { filtersObject = this.request.query; filterRepresentation = filtersObject.filterRepresentation; delete filtersObject.filterRepresentation; if (!filterRepresentation) { filterRepresentation = 'full'; } if (!authorisation.inGroup('admin', this.authenticated)) { txChannelID = (yield transactions.Transaction.findById(transactionId, { channelID: 1, _id: 0 }).exec()); if ((txChannelID != null ? txChannelID.length : void 0) === 0) { this.body = "Could not find transaction with ID: " + transactionId; this.status = 404; return; } else { filterRepresentation = 'simpledetails'; channel = (yield Channel.findById(txChannelID.channelID, { txViewFullAcl: 1, _id: 0 }).exec()); ref = this.authenticated.groups; for (i = 0, len = ref.length; i < len; i++) { group = ref[i]; if (channel.txViewFullAcl.indexOf(group) >= 0) { filterRepresentation = 'full'; break; } } } } projectionFiltersObject = getProjectionObject(filterRepresentation); result = (yield transactions.Transaction.findById(transactionId, projectionFiltersObject).exec()); if (!result) { this.body = "Could not find transaction with ID: " + transactionId; return this.status = 404; } else if (!authorisation.inGroup('admin', this.authenticated)) { channels = (yield authorisation.getUserViewableChannels(this.authenticated)); if (getChannelIDsArray(channels).indexOf(result.channelID.toString()) >= 0) { return this.body = result; } else { return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not authenticated to retrieve transaction " + transactionId, 'info'); } } else { return this.body = result; } } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not get transaction by ID via the API: " + e, 'error'); } }; /* * Retrieves all transactions specified by clientId */ exports.findTransactionByClientId = function*(clientId) { var channels, e, filterRepresentation, filtersObject, projectionFiltersObject; clientId = unescape(clientId); try { filtersObject = this.request.query; filterRepresentation = filtersObject.filterRepresentation; projectionFiltersObject = getProjectionObject(filterRepresentation); filtersObject = {}; filtersObject.clientID = clientId; if (!authorisation.inGroup('admin', this.authenticated)) { channels = (yield authorisation.getUserViewableChannels(this.authenticated)); filtersObject.channelID = { $in: getChannelIDsArray(channels) }; filterRepresentation = ''; } return this.body = (yield transactions.Transaction.find(filtersObject, projectionFiltersObject).sort({ 'request.timestamp': -1 }).exec()); } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not get transaction by clientID via the API: " + e, 'error'); } }; /* * Updates a transaction record specified by transactionId */ exports.updateTransaction = function*(transactionId) { var e, that, updates; if (!authorisation.inGroup('admin', this.authenticated)) { utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to updateTransaction denied.", 'info'); return; } transactionId = unescape(transactionId); updates = this.request.body; that = this; try { (yield transactions.Transaction.findByIdAndUpdate(transactionId, updates).exec()); that.body = "Transaction with ID: " + transactionId + " successfully updated"; that.status = 200; logger.info("User " + that.authenticated.email + " updated transaction with id " + transactionId); /* * Update transaction metrics */ return transactions.Transaction.findById(transactionId, function(err, doc) { var k, ref, ref1, results, route; if (((ref = updates['$push']) != null ? ref.routes : void 0) != null) { ref1 = updates['$push']; results = []; for (k in ref1) { route = ref1[k]; results.push((function(route) { var i, j, len, len1, metric, orchestration, ref2, ref3, results1; if (route.metrics != null) { ref2 = route.metrics; for (i = 0, len = ref2.length; i < len; i++) { metric = ref2[i]; if (metric.type === 'counter') { logger.info("incrementing mediator counter " + metric.name); sdc.increment(domain + ".channels." + doc.channelID + "." + route.name + ".mediator_metrics." + metric.name); } if (metric.type === 'timer') { logger.info("incrementing mediator timer " + metric.name); sdc.timing(domain + ".channels." + doc.channelID + "." + route.name + ".mediator_metrics." + metric.name, metric.value); } if (metric.type === 'gauge') { logger.info("incrementing mediator gauge " + metric.name); sdc.gauge(domain + ".channels." + doc.channelID + "." + route.name + ".mediator_metrics." + metric.name, metric.value); } } } ref3 = route.orchestrations; results1 = []; for (j = 0, len1 = ref3.length; j < len1; j++) { orchestration = ref3[j]; results1.push((function(orchestration) { var l, len2, orchestrationDuration, orchestrationName, orchestrationStatus, ref4, results2; orchestrationDuration = orchestration.response.timestamp - orchestration.request.timestamp; orchestrationStatus = orchestration.response.status; orchestrationName = orchestration.name; if (orchestration.group) { orchestrationName = orchestration.group + "." + orchestration.name; } /* * Update timers */ logger.info('updating async route timers'); sdc.timing(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName, orchestrationDuration); sdc.timing(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName + ".statusCodes." + orchestrationStatus, orchestrationDuration); /* * Update counters */ logger.info('updating async route counters'); sdc.increment(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName); sdc.increment(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName + ".statusCodes." + orchestrationStatus); if (orchestration.metrics != null) { ref4 = orchestration.metrics; results2 = []; for (l = 0, len2 = ref4.length; l < len2; l++) { metric = ref4[l]; if (metric.type === 'counter') { logger.info("incrementing " + route.name + " orchestration counter " + metric.name); sdc.increment(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName + "." + metric.name, metric.value); } if (metric.type === 'timer') { logger.info("incrementing " + route.name + " orchestration timer " + metric.name); sdc.timing(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName + "." + metric.name, metric.value); } if (metric.type === 'gauge') { logger.info("incrementing " + route.name + " orchestration gauge " + metric.name); results2.push(sdc.gauge(domain + ".channels." + doc.channelID + "." + route.name + ".orchestrations." + orchestrationName + "." + metric.name, metric.value)); } else { results2.push(void 0); } } return results2; } })(orchestration)); } return results1; })(route)); } return results; } }); } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not update transaction via the API: " + e, 'error'); } }; /* #Removes a transaction */ exports.removeTransaction = function*(transactionId) { var e; if (!authorisation.inGroup('admin', this.authenticated)) { utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to removeTransaction denied.", 'info'); return; } transactionId = unescape(transactionId); try { (yield transactions.Transaction.findByIdAndRemove(transactionId).exec()); this.body = 'Transaction successfully deleted'; this.status = 200; return logger.info("User " + this.authenticated.email + " removed transaction with id " + transactionId); } catch (_error) { e = _error; return utils.logAndSetResponse(this, 500, "Could not remove transaction via the API: " + e, 'error'); } }; //# sourceMappingURL=transactions.js.map