UNPKG

umpack-express

Version:

user management pack for express framework app

599 lines (444 loc) 15.4 kB
var router = require('express').Router(); var cookie = require('cookie'); var jwt = require('jsonwebtoken'); var mongoose = require('mongoose'); var urlMatch = require('./urlMatch'); var Promise = require('bluebird'); var sendPromiseResult = require('./responseSender').sendPromiseResult; var Password = require('./domain/password'); var config = require('./config'); var API_ERRORS = require('./exceptions/apiErrorsEnum'); var requestLogger = require('./requestLogger'); var jwtVerifyAsync = Promise.promisify(jwt.verify, jwt); mongoose.Promise = require('bluebird'); var User = require('./models/user'); var Role = require('./models/role'); var UserDevice = require('./models/userDevice'); var credentialsInteractor = require('./interactors/credentialsInteractor'); var userInteractor = require('./interactors/userInteractor'); var roleInteractor = require('./interactors/roleInteractor'); var deviceInteractor = require('./interactors/deviceInteractor'); process.on("unhandledRejection", function(reason, promise) { config.logger.warn('unhandled rejection: ' + reason); }); router.post('/login', function(req, res, next) { var userData = req.body; var promise = credentialsInteractor.login(userData); sendPromiseResult(promise, req, res, next); }); router.post('/signup', function(req, res, next) { var userData = req.body; var promise = credentialsInteractor.signup(userData) .then(function() { return { success: true, message: 'Thanks for signUp' }; }); sendPromiseResult(promise, req, res, next); }); router.post('/resetpass', isAuthorized, function(req, res, next) { var userData = req.body; //userName //oldPassword //newPassword var promise = credentialsInteractor.changePassword(userData) .then(function(user) { return { success: true, message: 'Password Reset Done' }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/passwordResetRequest', function(req, res, next) { var promise = credentialsInteractor.passwordResetRequest(req.body.email, req.ip) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/passwordReset', function(req, res, next) { var promise = credentialsInteractor.passwordReset(req.body.resetKey, req.body.newPassword) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/:userName/passwordResetRequestByPhone', function(req, res, next) { var promise = credentialsInteractor.passwordResetRequestByPhone(req.params.userName) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/:userName/passwordResetByPhone', function(req, res, next) { var userName = req.params.userName; var resetKey = req.body.resetKey; var newPassword = req.body.newPassword; var promise = credentialsInteractor.passwordResetByPhone(userName, resetKey, newPassword) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.get('/users', isAuthorized, function(req, res, next) { var promise = userInteractor.getUsers(); sendPromiseResult(promise, req, res, next); }); router.post('/updateUserStatus', isAuthorized, function(req, res, next) { var promise = userInteractor.updateUserStatus(req.body.id, req.body.isActivated); sendPromiseResult(promise, req, res, next); }); router.get('/roles', isAuthorized, function(req, res, next) { var promise = roleInteractor.getRoles(); sendPromiseResult(promise, req, res, next); }); router.post('/updateUserRoles', isAuthorized, function(req, res, next) { var reqData = req.body; var promise = userInteractor.updateUserRoles(reqData.userId, reqData.roleName, reqData.enable); sendPromiseResult(promise, req, res, next); }); router.get('/users/:id', isAuthorized, function(req, res, next) { var promise = userInteractor.getUserById(req.params.id); sendPromiseResult(promise, req, res, next); }); router.get('/users/:userName/full', function(req, res, next) { var promise = userInteractor.getUserByUserName(req.params.userName); sendPromiseResult(promise, req, res, next); }); router.delete('/users/:id', isAuthorized, function(req, res, next) { var promise = userInteractor.deleteUserById(req.params.id) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.put('/users/:id/info', isAuthorized, function(req, res, next) { var promise = userInteractor.changeUserInfo(req.params.id, req.body) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.put('/users/:id/userName', isAuthorized, function(req, res, next) { var promise = userInteractor.changeUserName(req.params.id, req.body.userName) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.delete('/users/:id/password', isAuthorized, function(req, res, next) { var promise = userInteractor.resetUserPassword(req.params.id) .then(function(password) { return { success: true, password: password.original }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/:userName/devices/access', isAuthorized, function(req, res, next) { var promise = deviceInteractor.grantDeviceAccess(req.params.userName, req.body.deviceToken) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/users/:userName/devices/restriction', isAuthorized, function(req, res, next) { var promise = deviceInteractor.restrictDeviceAccess(req.params.userName, req.body.deviceToken) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.get('/users/:userName/devices', isAuthorized, function(req, res, next) { var promise = deviceInteractor.getAllRegisteredDevices(req.params.userName); sendPromiseResult(promise, req, res, next); }); router.get('/users/:userName/devices/permitted', isAuthorized, function(req, res, next) { var promise = deviceInteractor.getAllPermittedDevices(req.params.userName); sendPromiseResult(promise, req, res, next); }); router.put('/metadata', isAuthorized, function(req, res, next) { var promise = decodeRequestToken(req) .then(function(decoded) { return updateUserMetaData(decoded.user, req.body); }) .then(function() { return { success: true, message: 'metadata updated' }; }); sendPromiseResult(promise, req, res, next); }); router.put('/metadata/:key', isAuthorized, function(req, res, next) { var promise = decodeRequestToken(req) .then(function(decoded) { return getUserMetaDataByRequest(req) .then(function(metadata) { if (!metadata) { metadata = {}; } metadata[req.params.key] = req.body.value; return updateUserMetaData(decoded.user, metadata); }); }) .then(function() { return { success: true, message: 'metadata key: ' + req.params.key + ' updated' }; }); sendPromiseResult(promise, req, res, next); }); router.get('/metadata', isAuthorized, function(req, res, next) { var promise = getUserMetaDataByRequest(req); sendPromiseResult(promise, req, res, next); }); router.post('/roles', isAuthorized, function(req, res, next) { var promise = roleInteractor.createRole(req.body.name, req.body.description) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.get('/roles/:roleName', isAuthorized, function(req, res, next) { var promise = roleInteractor.getRoleByName(req.params.roleName); sendPromiseResult(promise, req, res, next); }); router.put('/roles/:roleName', isAuthorized, function(req, res, next) { var promise = roleInteractor.editRole(req.params.roleName, req.body) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.delete('/roles/:roleName', isAuthorized, function(req, res, next) { var promise = roleInteractor.deleteRole(req.params.roleName) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/roles/:roleName/actions', isAuthorized, function(req, res, next) { var roleName = req.params.roleName; var promise = roleInteractor.addActionToRole(roleName, req.body) .then(function(actionId) { return { success: true, actionId: actionId }; }); sendPromiseResult(promise, req, res, next); }); router.put('/roles/:roleName/actions/:actionId', isAuthorized, function(req, res, next) { var roleName = req.params.roleName; var actionId = req.params.actionId; var promise = roleInteractor.editAction(roleName, actionId, req.body) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.delete('/roles/:roleName/actions/:actionId', isAuthorized, function(req, res, next) { var roleName = req.params.roleName; var actionId = req.params.actionId; var promise = roleInteractor.deleteAction(roleName, actionId) .then(function() { return { success: true }; }); sendPromiseResult(promise, req, res, next); }); router.post('/initialization', function(req, res, next) { var promise = init(req.body.umBaseUrl, req.body.password, req.body.deviceToken) .then(function(passwordText) { var result = { success: true }; if (passwordText) result.password = passwordText; return result; }); sendPromiseResult(promise, req, res, next); }); router.head('/authorization', isAuthorized, function (req, res, next) { res.send(); }); function decodeRequestToken(req) { try { var cookies = cookie.parse(req.headers.cookie || ''); var jwtToken = req.headers.authorization || cookies[config.cookieAccessTokenName]; if (!jwtToken) { throw API_ERRORS.JWT_NOT_EXISTS; } return jwtVerifyAsync(jwtToken, config.accessTokenSecret) .catch(function(err) { if (err instanceof jwt.TokenExpiredError) { throw API_ERRORS.JWT_TOKEN_EXPIRED; } throw API_ERRORS.INVALID_JWT; }); } catch (err) { return Promise.reject(err); } } function isAuthorized(req, res, next) { decodeRequestToken(req) .then(function(decoded) { return { userName: decoded.user, roles: decoded.roles, deviceToken: decoded.device }; }) .then(function(userInfo) { var checkRolePromise = roleInteractor.checkRole(req.method, req.originalUrl, userInfo); if (!config.deviceControl) { return checkRolePromise; } var checkDevicePromise = deviceInteractor.checkDevice(userInfo.userName, userInfo.deviceToken); return Promise.all([ checkRolePromise, checkDevicePromise ]); }) .then(function() { requestLogger.logAuthorizationResult(req); next(); return null; }) .catch(function(err) { if (!err.internalStatus) { requestLogger.logAuthorizationInternalError(req, err); return res.status(500).send({ message: err.message }); } requestLogger.logAuthorizationFail(req, err); return res.status(err.responseStatus).send({ message: err.message, internalStatus: err.internalStatus }); }); } function handleOptions(options) { if (!options) return; if (options.mongodbConnectionString) mongoose.connect(options.mongodbConnectionString); config.handleOptions(options); } function updateUserMetaData(userName, metaDataObject) { return userInteractor.updateUserMetaData(userName, metaDataObject); } function getUserMetaDataByUserName(userName) { return userInteractor.getUserMetaDataByUserName(userName); } function getUserMetaDataByRequest(req) { return decodeRequestToken(req) .then(function(decoded) { return getUserMetaDataByUserName(decoded.user); }); } function filterUsersByMetaData(key, value) { return userInteractor.filterUsersMetaData(key, value); } function getFullUserObjectFromRequest(req) { return decodeRequestToken(req) .then(function(decoded) { return getFullUserObject(decoded.user); }); } function getFullUserObject(userName) { return userInteractor.getFullUserObject(userName); } function getUserRolesFromRequest(req) { return decodeRequestToken(req) .then(function(decoded) { return { userName: decoded.user, roles: decoded.roles }; }); } function getUserNameFromRequest(req) { return decodeRequestToken(req) .then(function(decoded) { return decoded.user; }); } function init(umBaseUrl, passwordText, deviceToken) { return Promise.join( User.initAndSaveDefaultUser(passwordText), Promise.all([ Role.initAndSaveDefaultRole(umBaseUrl), UserDevice.initUserDevice(deviceToken) ]), function(password) { if (!password) return password; return password.original; } ); } function initWithFullAccess(passwordText, deviceToken) { return Promise.join( User.initAndSaveDefaultUser(passwordText), Promise.all([ Role.initAndSaveDefaultRoleWithFullAccess(), UserDevice.initUserDevice(deviceToken) ]), function(password) { if (!password) return password; return password.original; } ); } module.exports = function(options) { handleOptions(options); return { router: router, isAuthorized: isAuthorized, updateUserMetaData: updateUserMetaData, getUserMetaDataByUserName: getUserMetaDataByUserName, getUserMetaDataByRequest: getUserMetaDataByRequest, filterUsersByMetaData: filterUsersByMetaData, getFullName: userInteractor.getFullName, getUserRolesByUserName: userInteractor.getUserRolesByUserName, getUserRolesFromRequest: getUserRolesFromRequest, getFullUserObject: getFullUserObject, getFullUserObjectFromRequest: getFullUserObjectFromRequest, filterUsersByRole: userInteractor.filterUsersByRole, init: init, initWithFullAccess: initWithFullAccess, getUserNameFromRequest: getUserNameFromRequest, signup: credentialsInteractor.signup }; };