openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
376 lines (330 loc) • 13.2 kB
JavaScript
var Q, User, atna, auditing, authorisation, config, contact, himSourceID, htmlMessageTemplate, logger, moment, os, passwordResetHtmlMessageTemplate, passwordResetPlainMessageTemplate, plainMessageTemplate, randtoken, utils;
User = require('../model/users').User;
Q = require('q');
logger = require('winston');
authorisation = require('./authorisation');
moment = require('moment');
randtoken = require('rand-token');
contact = require('../contact');
config = require("../config/config");
config.newUserExpiry = config.get('newUserExpiry');
config.userPasswordResetExpiry = config.get('userPasswordResetExpiry');
config.alerts = config.get('alerts');
utils = require("../utils");
atna = require('atna-audit');
os = require('os');
auditing = require('../auditing');
himSourceID = config.get('auditing').auditEvents.auditSourceID;
/*
* Get authentication details
*/
exports.authenticate = function*(email) {
var audit, e, error, user;
email = unescape(email);
try {
user = (yield User.findOne({
email: email
}).exec());
if (!user) {
utils.logAndSetResponse(this, 404, "Could not find user by email " + email, 'info');
audit = atna.userLoginAudit(atna.OUTCOME_SERIOUS_FAILURE, himSourceID, os.hostname(), email);
audit = atna.wrapInSyslog(audit);
return auditing.sendAuditEvent(audit, function() {
return logger.debug('Processed internal audit');
});
} else {
return this.body = {
salt: user.passwordSalt,
ts: new Date()
};
}
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Error during authentication " + e, 'error');
}
};
/* Reset password Functions */
passwordResetPlainMessageTemplate = function(firstname, setPasswordLink) {
return "<---------- Existing User - Reset Password ---------->\nHi " + firstname + ",\n\nA request has been made to reset your password on the OpenHIM instance running on " + config.alerts.himInstance + "\nFollow the below link to reset your password and log into OpenHIM Console\n" + setPasswordLink + "\n<---------- Existing User - Reset Password ---------->";
};
passwordResetHtmlMessageTemplate = function(firstname, setPasswordLink) {
return "<h1>Reset OpenHIM Password</h1>\n<p>Hi " + firstname + ",<br/><br/>A request has been made to reset your password on the OpenHIM instance running on " + config.alerts.himInstance + "</p>\n<p>Follow the below link to set your password and log into OpenHIM Console</p>\n<p>" + setPasswordLink + "</p>";
};
exports.generateRandomToken = function() {
return randtoken.generate(32);
};
/*
* update user token/expiry and send new password email
*/
exports.userPasswordResetRequest = function*(email) {
var consoleURL, duration, durationType, e, error, expiry, htmlMessage, plainMessage, sendEmail, sendEmailError, setPasswordLink, token, updateUserTokenExpiry, user;
email = unescape(email);
if (email === 'root@openhim.org') {
this.body = "Cannot request password reset for 'root@openhim.org'";
this.status = 403;
return;
}
token = exports.generateRandomToken();
duration = config.userPasswordResetExpiry.duration;
durationType = config.userPasswordResetExpiry.durationType;
expiry = moment().add(duration, durationType).utc().format();
updateUserTokenExpiry = {
token: token,
tokenType: 'existingUser',
expiry: expiry
};
try {
user = (yield User.findOneAndUpdate({
email: email
}, updateUserTokenExpiry).exec());
if (!user) {
this.body = "Tried to request password reset for invalid email address: " + email;
this.status = 404;
logger.info("Tried to request password reset for invalid email address: " + email);
return;
}
consoleURL = config.alerts.consoleURL;
setPasswordLink = consoleURL + "/#/set-password/" + token;
plainMessage = passwordResetPlainMessageTemplate(user.firstname, setPasswordLink);
htmlMessage = passwordResetHtmlMessageTemplate(user.firstname, setPasswordLink);
sendEmail = Q.denodeify(contact.contactUser);
sendEmailError = (yield sendEmail('email', email, 'OpenHIM Console Password Reset', plainMessage, htmlMessage));
if (sendEmailError) {
utils.logAndSetResponse(this, 500, "Could not send email to user via the API " + e, 'error');
}
logger.info('The email has been sent to the user');
this.body = "Successfully set user token/expiry for password reset.";
this.status = 201;
return logger.info("User updated token/expiry for password reset " + email);
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not update user with email " + email + " via the API " + e, 'error');
}
};
/* New User Set Password Functions */
exports.getUserByToken = function*(token) {
var e, error, projectionRestriction, result;
token = unescape(token);
try {
projectionRestriction = {
"email": 1,
"firstname": 1,
"surname": 1,
"msisdn": 1,
"token": 1,
"tokenType": 1,
"locked": 1,
"expiry": 1,
"_id": 0
};
result = (yield User.findOne({
token: token
}, projectionRestriction).exec());
if (!result) {
this.body = "User with token " + token + " could not be found.";
return this.status = 404;
} else {
if (moment(result.expiry).isBefore(moment())) {
this.body = "Token " + token + " has expired";
return this.status = 410;
} else {
return this.body = result;
}
}
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not find user with token " + token + " via the API " + e, 'error');
}
};
exports.updateUserByToken = function*(token) {
var e, error, error1, msisdn, userData, userDataExpiry, userUpdateObj;
token = unescape(token);
userData = this.request.body;
try {
userDataExpiry = (yield User.findOne({
token: token
}).exec());
if (!userDataExpiry) {
this.body = "User with token " + token + " could not be found.";
this.status = 404;
return;
} else {
if (moment(userDataExpiry.expiry).isBefore(moment())) {
this.body = "User with token " + token + " has expired to set their password.";
this.status = 410;
return;
}
}
} catch (error) {
e = error;
utils.logAndSetResponse(this, 500, "Could not find user with token " + token + " via the API " + e, 'error');
return;
}
if (userData.msisdn) {
msisdn = userData.msisdn;
} else {
msisdn = null;
}
userUpdateObj = {
token: null,
tokenType: null,
expiry: null,
passwordAlgorithm: userData.passwordAlgorithm,
passwordSalt: userData.passwordSalt,
passwordHash: userData.passwordHash
};
if (userDataExpiry.tokenType === 'newUser') {
userUpdateObj.firstname = userData.firstname;
userUpdateObj.surname = userData.surname;
userUpdateObj.locked = false;
userUpdateObj.msisdn = msisdn;
}
try {
(yield User.findOneAndUpdate({
token: token
}, userUpdateObj).exec());
this.body = "Successfully set new user password.";
return logger.info("User updated by token " + token);
} catch (error1) {
e = error1;
return utils.logAndSetResponse(this, 500, "Could not update user with token " + token + " via the API " + e, 'error');
}
};
/* New User Set Password Functions */
plainMessageTemplate = function(firstname, setPasswordLink) {
return "<---------- New User - Set Password ---------->\nHi " + firstname + ",\n\nA profile has been created for you on the OpenHIM instance running on " + config.alerts.himInstance + "\nFollow the below link to set your password and log into OpenHIM Console\n" + setPasswordLink + "\n<---------- New User - Set Password ---------->";
};
htmlMessageTemplate = function(firstname, setPasswordLink) {
return "<h1>New OpenHIM Profile</h1>\n<p>Hi " + firstname + ",<br/><br/>A profile has been created for you on the OpenHIM instance running on " + config.alerts.himInstance + "</p>\n<p>Follow the below link to set your password and log into OpenHIM Console</p>\n<p>" + setPasswordLink + "</p>";
};
/*
* Adds a user
*/
exports.addUser = function*() {
var consoleURL, duration, durationType, e, error, htmlMessage, plainMessage, result, setPasswordLink, token, user, userData;
if (!authorisation.inGroup('admin', this.authenticated)) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to addUser denied.", 'info');
return;
}
userData = this.request.body;
token = randtoken.generate(32);
userData.token = token;
userData.tokenType = 'newUser';
userData.locked = true;
duration = config.newUserExpiry.duration;
durationType = config.newUserExpiry.durationType;
userData.expiry = moment().add(duration, durationType).utc().format();
consoleURL = config.alerts.consoleURL;
setPasswordLink = consoleURL + "/#/set-password/" + token;
try {
user = new User(userData);
result = (yield Q.ninvoke(user, 'save'));
plainMessage = plainMessageTemplate(userData.firstname, setPasswordLink);
htmlMessage = htmlMessageTemplate(userData.firstname, setPasswordLink);
contact.contactUser('email', userData.email, 'OpenHIM Console Profile', plainMessage, htmlMessage, function(err) {
if (err) {
return logger.error("The email could not be sent to the user via the API " + err);
} else {
return logger.info('The email has been sent to the new user');
}
});
this.body = 'User successfully created';
this.status = 201;
return logger.info("User " + this.authenticated.email + " created user " + userData.email);
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not add user via the API " + e, 'error');
}
};
/*
* Retrieves the details of a specific user
*/
exports.getUser = function*(email) {
var e, error, result;
email = unescape(email);
if (!authorisation.inGroup('admin', this.authenticated) && this.authenticated.email !== email) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to getUser denied.", 'info');
return;
}
try {
result = (yield User.findOne({
email: email
}).exec());
if (!result) {
this.body = "User with email " + email + " could not be found.";
return this.status = 404;
} else {
return this.body = result;
}
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not get user via the API " + e, 'error');
}
};
exports.updateUser = function*(email) {
var e, error, userData;
email = unescape(email);
if (!authorisation.inGroup('admin', this.authenticated) && this.authenticated.email !== email) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to updateUser denied.", 'info');
return;
}
userData = this.request.body;
if (userData.passwordAlgorithm && userData.passwordHash && userData.passwordSalt) {
userData.token = null;
userData.tokenType = null;
userData.locked = false;
userData.expiry = null;
}
if (this.authenticated.email === email && !authorisation.inGroup('admin', this.authenticated)) {
delete userData.groups;
}
if (userData._id) {
delete userData._id;
}
try {
(yield User.findOneAndUpdate({
email: email
}, userData).exec());
this.body = "Successfully updated user.";
return logger.info("User " + this.authenticated.email + " updated user " + userData.email);
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not update user " + email + " via the API " + e, 'error');
}
};
exports.removeUser = function*(email) {
var e, error;
if (!authorisation.inGroup('admin', this.authenticated)) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to removeUser denied.", 'info');
return;
}
email = unescape(email);
if (email === 'root@openhim.org') {
utils.logAndSetResponse(this, 403, "User root@openhim.org is OpenHIM root, User cannot be deleted through the API", 'info');
return;
}
try {
(yield User.findOneAndRemove({
email: email
}).exec());
this.body = "Successfully removed user with email " + email;
return logger.info("User " + this.authenticated.email + " removed user " + email);
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not remove user " + email + " via the API " + e, 'error');
}
};
exports.getUsers = function*() {
var e, error;
if (!authorisation.inGroup('admin', this.authenticated)) {
utils.logAndSetResponse(this, 403, "User " + this.authenticated.email + " is not an admin, API access to getUsers denied.", 'info');
return;
}
try {
return this.body = (yield User.find().exec());
} catch (error) {
e = error;
return utils.logAndSetResponse(this, 500, "Could not fetch all users via the API " + e, 'error');
}
};
//# sourceMappingURL=users.js.map