openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
342 lines (303 loc) • 10.5 kB
JavaScript
var Channel, Channels, ObjectId, Q, Transaction, authorisation, config, isPathValid, logger, polling, processPostAddTriggers, processPostDeleteTriggers, processPostUpdateTriggers, request, routerMiddleware, server, tcpAdapter, utils;
Channels = require('../model/channels');
Channel = Channels.Channel;
Transaction = require('../model/transactions').Transaction;
ObjectId = require('mongoose').Types.ObjectId;
Q = require('q');
logger = require('winston');
authorisation = require('./authorisation');
tcpAdapter = require('../tcpAdapter');
server = require("../server");
polling = require("../polling");
routerMiddleware = require('../middleware/router');
utils = require("../utils");
config = require('../config/config');
config.polling = config.get('polling');
request = require('request');
isPathValid = function(channel) {
var i, len, ref, route;
if (channel.routes != null) {
ref = channel.routes;
for (i = 0, len = ref.length; i < len; i++) {
route = ref[i];
if ((route.path && route.pathTransform) || (route.pathTransform && !/s\/.*\/.*/.test(route.pathTransform))) {
return false;
}
}
}
return true;
};
/*
* Retrieves the list of active channels
*/
exports.getChannels = function*() {
var err, error;
try {
return this.body = (yield authorisation.getUserViewableChannels(this.authenticated));
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 500, "Could not fetch all channels via the API: " + err, 'error');
}
};
processPostAddTriggers = function(channel) {
if (channel.type && Channels.isChannelEnabled(channel)) {
if ((channel.type === 'tcp' || channel.type === 'tls') && server.isTcpHttpReceiverRunning()) {
return tcpAdapter.notifyMasterToStartTCPServer(channel._id, function(err) {
if (err) {
return logger.error(err);
}
});
} else if (channel.type === 'polling') {
return polling.registerPollingChannel(channel, function(err) {
if (err) {
return logger.error(err);
}
});
}
}
};
/*
* Creates a new channel
*/
exports.addChannel = function*() {
var channel, channelData, err, error, numPrimaries, result;
if (authorisation.inGroup('admin', this.authenticated) === false) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to addChannel denied.", 'info');
return;
}
channelData = this.request.body;
try {
channel = new Channel(channelData);
if (!isPathValid(channel)) {
this.body = 'Channel cannot have both path and pathTransform. pathTransform must be of the form s/from/to[/g]';
this.status = 400;
return;
}
if ((channel.priority != null) && channel.priority < 1) {
this.body = 'Channel priority cannot be below 1 (= Highest priority)';
this.status = 400;
return;
}
numPrimaries = routerMiddleware.numberOfPrimaryRoutes(channel.routes);
if (numPrimaries === 0) {
this.body = 'Channel must have a primary route';
this.status = 400;
return;
}
if (numPrimaries > 1) {
this.body = 'Channel cannot have a multiple primary routes';
this.status = 400;
return;
}
result = (yield Q.ninvoke(channel, 'save'));
this.body = 'Channel successfully created';
this.status = 201;
logger.info('User %s created channel with id %s', this.authenticated.email, channel.id);
channelData._id = channel._id;
return processPostAddTriggers(channelData);
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 400, "Could not add channel via the API: " + err, 'error');
}
};
/*
* Retrieves the details for a specific channel
*/
exports.getChannel = function*(channelId) {
var accessDenied, adminResult, err, error, id, result;
id = unescape(channelId);
try {
result = null;
accessDenied = false;
if (authorisation.inGroup('admin', this.authenticated) === false) {
result = (yield Channel.findOne({
_id: id,
txViewAcl: {
$in: this.authenticated.groups
}
}).exec());
adminResult = (yield Channel.findById(id).exec());
if (adminResult != null) {
accessDenied = true;
}
} else {
result = (yield Channel.findById(id).exec());
}
if (result === null) {
if (accessDenied) {
this.body = "Access denied to channel with Id: '" + id + "'.";
return this.status = 403;
} else {
this.body = "We could not find a channel with Id:'" + id + "'.";
return this.status = 404;
}
} else {
return this.body = result;
}
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 500, "Could not fetch channel by Id '" + id + "' via the API: " + err, 'error');
}
};
processPostUpdateTriggers = function(channel) {
if (channel.type) {
if ((channel.type === 'tcp' || channel.type === 'tls') && server.isTcpHttpReceiverRunning()) {
if (Channels.isChannelEnabled(channel)) {
return tcpAdapter.notifyMasterToStartTCPServer(channel._id, function(err) {
if (err) {
return logger.error(err);
}
});
} else {
return tcpAdapter.notifyMasterToStopTCPServer(channel._id, function(err) {
if (err) {
return logger.error(err);
}
});
}
} else if (channel.type === 'polling') {
if (Channels.isChannelEnabled(channel)) {
return polling.registerPollingChannel(channel, function(err) {
if (err) {
return logger.error(err);
}
});
} else {
return polling.removePollingChannel(channel, function(err) {
if (err) {
return logger.error(err);
}
});
}
}
}
};
/*
* Updates the details for a specific channel
*/
exports.updateChannel = function*(channelId) {
var channel, channelData, err, error, id, numPrimaries;
if (authorisation.inGroup('admin', this.authenticated) === false) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to updateChannel denied.", 'info');
return;
}
id = unescape(channelId);
channelData = this.request.body;
if (typeof channelData._id !== 'undefined') {
delete channelData._id;
}
if (!isPathValid(channelData)) {
utils.logAndSetResponse(this, 400, 'Channel cannot have both path and pathTransform. pathTransform must be of the form s/from/to[/g]', 'info');
return;
}
if ((channelData.priority != null) && channelData.priority < 1) {
this.body = 'Channel priority cannot be below 1 (= Highest priority)';
this.status = 400;
return;
}
if (channelData.routes != null) {
numPrimaries = routerMiddleware.numberOfPrimaryRoutes(channelData.routes);
if (numPrimaries === 0) {
this.body = 'Channel must have a primary route';
this.status = 400;
return;
}
if (numPrimaries > 1) {
this.body = 'Channel cannot have a multiple primary routes';
this.status = 400;
return;
}
}
try {
channel = (yield Channel.findByIdAndUpdate(id, channelData).exec());
this.body = 'The channel was successfully updated';
logger.info('User %s updated channel with id %s', this.authenticated.email, id);
channelData._id = ObjectId(id);
return processPostUpdateTriggers(channelData);
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 500, "Could not update channel by id: " + id + " via the API: " + e, 'error');
}
};
processPostDeleteTriggers = function(channel) {
if (channel.type) {
if ((channel.type === 'tcp' || channel.type === 'tls') && server.isTcpHttpReceiverRunning()) {
return tcpAdapter.notifyMasterToStopTCPServer(channel._id, function(err) {
if (err) {
return logger.error(err);
}
});
} else if (channel.type === 'polling') {
return polling.removePollingChannel(channel, function(err) {
if (err) {
return logger.error(err);
}
});
}
}
};
/*
* Deletes a specific channels details
*/
exports.removeChannel = function*(channelId) {
var channel, err, error, id, numExistingTransactions;
if (authorisation.inGroup('admin', this.authenticated) === false) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to removeChannel denied.", 'info');
return;
}
id = unescape(channelId);
try {
numExistingTransactions = (yield Transaction.count({
channelID: id
}).exec());
if (numExistingTransactions === 0) {
channel = (yield Channel.findByIdAndRemove(id).exec());
} else {
channel = (yield Channel.findByIdAndUpdate(id, {
status: 'deleted'
}).exec());
}
this.body = 'The channel was successfully deleted';
logger.info("User " + this.authenticated.email + " removed channel with id " + id);
return processPostDeleteTriggers(channel);
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 500, "Could not remove channel by id: " + id + " via the API: " + e, 'error');
}
};
/*
* Manually Triggers Polling Channel
*/
exports.triggerChannel = function*(channelId) {
var channel, err, error, id, options;
if (authorisation.inGroup('admin', this.authenticated) === false) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to removeChannel denied.", 'info');
return;
}
id = unescape(channelId);
this.status = 200;
try {
channel = (yield Channel.findById(id).exec());
if (channel === null) {
this.body = "We could not find a channel with Id:'" + id + "'.";
return this.status = 404;
} else {
logger.info("Manually Polling channel " + channel._id);
options = {
url: "http://" + config.polling.host + ":" + config.polling.pollingPort + "/trigger",
headers: {
'channel-id': channel._id,
'X-OpenHIM-LastRunAt': new Date
}
};
return request(options, function() {
logger.info("Channel Successfully polled " + channel._id);
return this.status = 200;
});
}
} catch (error) {
err = error;
return utils.logAndSetResponse(this, 500, "Could not fetch channel by Id '" + id + "' via the API: " + err, 'error');
}
};
//# sourceMappingURL=channels.js.map