openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
508 lines (491 loc) • 13.1 kB
JavaScript
var Channel, Client, authorisation, buildFindChannelByIdOrNameCriteria, buildFindClientByIdOrClientIDCriteria, filterRolesFromChannels, logger, utils;
Channel = require('../model/channels').Channel;
Client = require('../model/clients').Client;
logger = require('winston');
authorisation = require('./authorisation');
utils = require('../utils');
/*
* Roles is a virtual API; virtual in the sense that it is not linked
* to a concrete roles collection.
*
* Rather it an abstraction of the 'allow' field on Channels and 'roles' on Clients,
* providing a mechanism for setting up allowed permissions.
*/
filterRolesFromChannels = function(channels, clients) {
var ch, cl, i, isClient, j, k, l, len, len1, len2, len3, len4, m, permission, ref, ref1, role, rolesArray, rolesMap;
rolesMap = {};
for (i = 0, len = channels.length; i < len; i++) {
ch = channels[i];
ref = ch.allow;
for (j = 0, len1 = ref.length; j < len1; j++) {
permission = ref[j];
isClient = false;
for (k = 0, len2 = clients.length; k < len2; k++) {
cl = clients[k];
if (cl.clientID === permission) {
isClient = true;
}
}
if (!isClient) {
if (!rolesMap[permission]) {
rolesMap[permission] = {
channels: [],
clients: []
};
}
rolesMap[permission].channels.push({
_id: ch._id,
name: ch.name
});
}
}
}
for (l = 0, len3 = clients.length; l < len3; l++) {
cl = clients[l];
ref1 = cl.roles;
for (m = 0, len4 = ref1.length; m < len4; m++) {
permission = ref1[m];
if (!rolesMap[permission]) {
rolesMap[permission] = {
channels: [],
clients: []
};
}
rolesMap[permission].clients.push({
_id: cl._id,
clientID: cl.clientID
});
}
}
rolesArray = [];
for (role in rolesMap) {
rolesArray.push({
name: role,
channels: rolesMap[role].channels,
clients: rolesMap[role].clients
});
}
return rolesArray;
};
exports.getRoles = function*() {
var channels, clients, e, error;
if (!authorisation.inGroup('admin', this.authenticated)) {
return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to getRoles denied.", 'info');
}
try {
channels = (yield Channel.find({}, {
name: 1,
allow: 1
}).exec());
clients = (yield Client.find({}, {
clientID: 1,
roles: 1
}).exec());
return this.body = filterRolesFromChannels(channels, clients);
} catch (error) {
e = error;
logger.error("Could not fetch roles via the API: " + e.message);
this.message = e.message;
return this.status = 500;
}
};
exports.getRole = function*(name) {
var channels, clients, e, error;
if (!authorisation.inGroup('admin', this.authenticated)) {
return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to getRole denied.", 'info');
}
try {
channels = (yield Channel.find({
allow: {
$in: [name]
}
}, {
name: 1
}).exec());
clients = (yield Client.find({
roles: {
$in: [name]
}
}, {
clientID: 1
}).exec());
if ((channels === null || channels.length === 0) && (clients === null || clients.length === 0)) {
return utils.logAndSetResponse(this, 404, "Role with name '" + name + "' could not be found.", 'info');
} else {
return this.body = {
name: name,
channels: channels.map(function(r) {
return {
_id: r._id,
name: r.name
};
}),
clients: clients.map(function(c) {
return {
_id: c._id,
clientID: c.clientID
};
})
};
}
} catch (error) {
e = error;
logger.error("Could not find role with name '" + name + "' via the API: " + e.message);
this.body = e.message;
return this.status = 500;
}
};
buildFindChannelByIdOrNameCriteria = function(ctx, role) {
var ch, criteria, i, ids, len, names, ref;
criteria = {};
ids = [];
names = [];
ref = role.channels;
for (i = 0, len = ref.length; i < len; i++) {
ch = ref[i];
if (ch._id) {
ids.push(ch._id);
} else if (ch.name) {
names.push(ch.name);
} else {
utils.logAndSetResponse(ctx, 400, "_id and/or name must be specified for a channel", 'info');
return null;
}
}
if (ids.length > 0 && names.length > 0) {
criteria = {
$or: [
{
_id: {
$in: ids
}
}, {
name: {
$in: names
}
}
]
};
} else {
if (ids.length > 0) {
criteria._id = {
$in: ids
};
}
if (names.length > 0) {
criteria.name = {
$in: names
};
}
}
return criteria;
};
buildFindClientByIdOrClientIDCriteria = function(ctx, role) {
var ch, clientIDs, criteria, i, ids, len, ref;
criteria = {};
ids = [];
clientIDs = [];
ref = role.clients;
for (i = 0, len = ref.length; i < len; i++) {
ch = ref[i];
if (ch._id) {
ids.push(ch._id);
} else if (ch.clientID) {
clientIDs.push(ch.clientID);
} else {
utils.logAndSetResponse(ctx, 400, "_id and/or clientID must be specified for a client", 'info');
return null;
}
}
if (ids.length > 0 && clientIDs.length > 0) {
criteria = {
$or: [
{
_id: {
$in: ids
}
}, {
clientID: {
$in: clientIDs
}
}
]
};
} else {
if (ids.length > 0) {
criteria._id = {
$in: ids
};
}
if (clientIDs.length > 0) {
criteria.clientID = {
$in: clientIDs
};
}
}
return criteria;
};
exports.addRole = function*() {
var chCriteria, chResult, clCriteria, clResult, e, error, ref, ref1, role;
if (!authorisation.inGroup('admin', this.authenticated)) {
return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to addRole denied.", 'info');
}
role = this.request.body;
if (!role.name) {
return utils.logAndSetResponse(this, 400, 'Must specify a role name', 'info');
}
if (((ref = role.channels) != null ? ref.length : void 0) === 0 && ((ref1 = role.clients) != null ? ref1.length : void 0) === 0) {
return utils.logAndSetResponse(this, 400, 'Must specify at least one channel or client to link the role to', 'info');
}
try {
chResult = (yield Channel.find({
allow: {
$in: [role.name]
}
}, {
name: 1
}).exec());
clResult = (yield Client.find({
roles: {
$in: [role.name]
}
}, {
clientID: 1
}).exec());
if ((chResult != null ? chResult.length : void 0) > 0 || (typeof clResults !== "undefined" && clResults !== null ? clResults.length : void 0) > 0) {
return utils.logAndSetResponse(this, 400, "Role with name '" + role.name + "' already exists.", 'info');
}
if (role.channels) {
chCriteria = buildFindChannelByIdOrNameCriteria(this, role);
if (!chCriteria) {
return;
}
}
if (role.clients) {
clCriteria = buildFindClientByIdOrClientIDCriteria(this, role);
if (!clCriteria) {
return;
}
}
if (role.channels) {
(yield Channel.update(chCriteria, {
$push: {
allow: role.name
}
}, {
multi: true
}).exec());
}
if (role.clients) {
(yield Client.update(clCriteria, {
$push: {
roles: role.name
}
}, {
multi: true
}).exec());
}
logger.info("User " + this.authenticated.email + " setup role '" + role.name + "'");
this.body = 'Role successfully created';
return this.status = 201;
} catch (error) {
e = error;
logger.error("Could not add a role via the API: " + e.message);
this.body = e.message;
return this.status = 400;
}
};
exports.updateRole = function*(name) {
var chCriteria, chResult, channels, clCriteria, clResult, clients, e, error, ref, role;
if (!authorisation.inGroup('admin', this.authenticated)) {
return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to updateRole denied.", 'info');
}
role = this.request.body;
try {
chResult = (yield Channel.find({
allow: {
$in: [name]
}
}, {
name: 1
}).exec());
clResult = (yield Client.find({
roles: {
$in: [name]
}
}, {
clientID: 1
}).exec());
if ((chResult === null || chResult.length === 0) && (clResult === null || clResult.length === 0)) {
return utils.logAndSetResponse(this, 404, "Role with name '" + name + "' could not be found.", 'info');
}
if (role.name) {
channels = (yield Channel.find({
allow: {
$in: [role.name]
}
}, {
name: 1
}).exec());
clients = (yield Client.find({
roles: {
$in: [role.name]
}
}, {
name: 1
}).exec());
if ((channels != null ? channels.length : void 0) > 0 || (clients != null ? clients.length : void 0) > 0) {
return utils.logAndSetResponse(this, 400, "Role with name '" + role.name + "' already exists.", 'info');
}
}
if (role.channels) {
chCriteria = buildFindChannelByIdOrNameCriteria(this, role);
if (!chCriteria) {
return;
}
}
if (role.clients) {
clCriteria = buildFindClientByIdOrClientIDCriteria(this, role);
if (!clCriteria) {
return;
}
}
if (role.channels) {
(yield Channel.update({}, {
$pull: {
allow: name
}
}, {
multi: true
}).exec());
if (role.channels.length > 0) {
(yield Channel.update(chCriteria, {
$push: {
allow: name
}
}, {
multi: true
}).exec());
}
}
if (role.clients) {
(yield Client.update({}, {
$pull: {
roles: name
}
}, {
multi: true
}).exec());
if (((ref = role.clients) != null ? ref.length : void 0) > 0) {
(yield Client.update(clCriteria, {
$push: {
roles: name
}
}, {
multi: true
}).exec());
}
}
if (role.name) {
(yield Channel.update({
allow: {
$in: [name]
}
}, {
$push: {
allow: role.name
}
}, {
multi: true
}).exec());
(yield Channel.update({
allow: {
$in: [name]
}
}, {
$pull: {
allow: name
}
}, {
multi: true
}).exec());
(yield Client.update({
roles: {
$in: [name]
}
}, {
$push: {
roles: role.name
}
}, {
multi: true
}).exec());
(yield Client.update({
roles: {
$in: [name]
}
}, {
$pull: {
roles: name
}
}, {
multi: true
}).exec());
}
logger.info("User " + this.authenticated.email + " updated role with name '" + name + "'");
this.body = 'Successfully updated role';
return this.status = 200;
} catch (error) {
e = error;
logger.error("Could not update role with name '" + name + "' via the API: " + e.message);
this.body = e.message;
return this.status = 500;
}
};
exports.deleteRole = function*(name) {
var channels, clients, e, error;
if (!authorisation.inGroup('admin', this.authenticated)) {
return utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to updateRole denied.", 'info');
}
try {
channels = (yield Channel.find({
allow: {
$in: [name]
}
}, {
name: 1
}).exec());
clients = (yield Client.find({
roles: {
$in: [name]
}
}, {
clientID: 1
}).exec());
if ((channels === null || channels.length === 0) && (clients === null || clients.length === 0)) {
return utils.logAndSetResponse(this, 404, "Role with name '" + name + "' could not be found.", 'info');
}
(yield Channel.update({}, {
$pull: {
allow: name
}
}, {
multi: true
}).exec());
(yield Client.update({}, {
$pull: {
roles: name
}
}, {
multi: true
}).exec());
logger.info("User " + this.authenticated.email + " deleted role with name '" + name + "'");
return this.body = 'Successfully deleted role';
} catch (error) {
e = error;
logger.error("Could not update role with name '" + name + "' via the API: " + e.message);
this.body = e.message;
return this.status = 500;
}
};
//# sourceMappingURL=roles.js.map