UNPKG

@aarconada/urserver

Version:

Basic Server definitions to develope REST API with a node + express Server

436 lines (426 loc) 21.7 kB
/** * Created by ubuntu on 12/11/18. */ 'use strict'; const server = require('../server')(); const promise = require('bluebird'); const _ = require('lodash'); const ldap = require('ldapjs'); module.exports.enabled = server.configuration.authentication.ldap.enabled; if(server.configuration.authentication.ldap.enabled) { var ldapUserSchema = { uid : {type: server.sequelize.api.STRING , allowNull: false}, type : {type: server.sequelize.api.INTEGER , allowNull: true}, lastlogin : {type: server.sequelize.api.DATE , allowNull: null} }; const ldapUserModel = server.sequelize.define( { modelname: 'ldapUser', schema: ldapUserSchema, configuration: { defaultScope: { attributes: { exclude: [] } } }, POST: { single: { enabled: false }, all: { enabled: false } }, PUT: { single: { enabled: false } , all: { enabled: false } }, DELETE: { single: { enabled: false } , all: { enabled: false } }, GET: { single: { enabled: false } , all: { enabled: false } } } ); module.exports.signup = function (transaction, type, uid) { return checkExistsUserInLDAP(uid, server.configuration.authentication.ldap.customFilter) .then(ldapObject => { return ldapUserModel.findOne( { where: {uid: uid}, transaction: transaction }) .then(existingUser => { server.debug('User exists yet?', existingUser !== null); if (!_.isUndefined(existingUser) && !_.isNull(existingUser)) server.utils.throwError(server.defaultResponses.authentication_user_exists_yet); return ldapUserModel.create( { uid: uid, type: type }, { transaction: transaction }) .then(newLDAPUser => { server.debug('New ldap user created?', newLDAPUser !== null); newLDAPUser.ldapAttributes = ldapObject.object; return newLDAPUser; }) .catch(err => { server.debug('Error during ldap user creation', err); server.utils.throwError(server.defaultResponses.authentication_unable_signup, err); }); }); }) .catch(err => { server.utils.throwError(server.defaultResponses.ldap_user_does_not_exists, err); }); }; module.exports.login = function (transaction, uid, password) { return checkUserInLDAP(uid, password, server.configuration.authentication.ldap.customFilter) .then(ldapObject => { if(_.isNull(ldapObject)) { server.debug('LDAP OBJECT IS NULL!!!'); server.utils.throwError(server.defaultResponses.authentication_user_not_found); } server.debug('Finding user in custom database...'); server.debug(ldapObject.object); return ldapUserModel.findOne( { subQuery: false, where: {uid: uid}, include: {all: true}, transaction: transaction }) .then(foundedUser => { server.debug('User founded?', foundedUser !== null); if (_.isUndefined(foundedUser) || _.isNull(foundedUser)) server.utils.throwError(server.defaultResponses.authentication_user_not_found); const currentDate = new Date(); return foundedUser.update( { lastlogin: currentDate }, {transaction: transaction}) .then(loggedUser => { foundedUser.ldapAttributes = {}; Object.keys(ldapObject.object).forEach(currentAttribute => { if(currentAttribute.toUpperCase() !== 'CONTROLS' && currentAttribute.toUpperCase() !== 'OBJECTCLASS' && currentAttribute.toUpperCase() !== 'USERPASSWORD') { foundedUser.ldapAttributes[currentAttribute] = ldapObject.object[currentAttribute]; } }); return foundedUser; }) .catch(err => { server.debug('Error on user updating', err); server.utils.throwError(server.defaultResponses.entity_unable_update_element, err); }); }) .catch(err => { server.debug('Error on LDAP user login', err); server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }) .catch(err => { server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }; module.exports.loginWithSignup = function (transaction, uid, password, type) { return checkUserInLDAP(uid, password, server.configuration.authentication.ldap.customFilter) .then(ldapObject => { if(_.isNull(ldapObject)) { server.debug('LDAP OBJECT IS NULL!!!'); server.utils.throwError(server.defaultResponses.authentication_user_not_found); } server.debug('Finding user in custom database...'); server.debug(ldapObject.object); return ldapUserModel.findOrCreate( { subQuery: false, where: {uid: uid}, defaults: {type: type}, include: {all: true}, transaction: transaction }) .then(([foundedUser, created]) => { server.debug('User founded?', foundedUser !== null); if (_.isUndefined(foundedUser) || _.isNull(foundedUser)) server.utils.throwError(server.defaultResponses.authentication_user_not_found); const currentDate = new Date(); return foundedUser.update( { lastlogin: currentDate }, {transaction: transaction}) .then(loggedUser => { foundedUser.ldapAttributes = {}; Object.keys(ldapObject.object).forEach(currentAttribute => { if(currentAttribute.toUpperCase() !== 'CONTROLS' && currentAttribute.toUpperCase() !== 'OBJECTCLASS' && currentAttribute.toUpperCase() !== 'USERPASSWORD') { foundedUser.ldapAttributes[currentAttribute] = ldapObject.object[currentAttribute]; } }); return foundedUser; }) .catch(err => { server.debug('Error on user updating', err); server.utils.throwError(server.defaultResponses.entity_unable_update_element, err); }); }) .catch(err => { server.debug('Error on LDAP user login', err); server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }) .catch(err => { server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }; module.exports.silentLogin = function (transaction, uid) { return checkExistsUserInLDAP(uid, server.configuration.authentication.ldap.customFilter) .then(ldapObject => { if(_.isNull(ldapObject)) { server.debug('LDAP OBJECT IS NULL!!!'); server.utils.throwError(server.defaultResponses.authentication_user_not_found); } server.debug('Finding user in custom database...'); server.debug(ldapObject.object); return ldapUserModel.findOne( { subQuery: false, where: {uid: uid}, include: {all: true}, transaction: transaction }) .then(foundedUser => { server.debug('User founded?', foundedUser !== null); if (_.isUndefined(foundedUser) || _.isNull(foundedUser)) server.utils.throwError(server.defaultResponses.authentication_user_not_found); const currentDate = new Date(); return foundedUser.update( { lastlogin: currentDate }, {transaction: transaction}) .then(loggedUser => { foundedUser.ldapAttributes = {}; Object.keys(ldapObject.object).forEach(currentAttribute => { if(currentAttribute.toUpperCase() !== 'CONTROLS' && currentAttribute.toUpperCase() !== 'OBJECTCLASS' && currentAttribute.toUpperCase() !== 'USERPASSWORD') { foundedUser.ldapAttributes[currentAttribute] = ldapObject.object[currentAttribute]; } }); return foundedUser; }) .catch(err => { server.debug('Error on user updating', err); server.utils.throwError(server.defaultResponses.entity_unable_update_element, err); }); }) .catch(err => { server.debug('Error on LDAP user login', err); server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }) .catch(err => { server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }; module.exports.silentLoginWithSignup = function (transaction, uid, type) { return checkExistsUserInLDAP(uid, server.configuration.authentication.ldap.customFilter) .then(ldapObject => { if(_.isNull(ldapObject)) { server.debug('LDAP OBJECT IS NULL!!!'); server.utils.throwError(server.defaultResponses.authentication_user_not_found); } server.debug('Finding user in custom database...'); server.debug(ldapObject.object); return ldapUserModel.findOrCreate( { subQuery: false, where: {uid: uid}, defaults: {type: type}, include: {all: true}, transaction: transaction }) .then(([foundedUser, created]) => { server.debug('User founded?', foundedUser !== null); if (_.isUndefined(foundedUser) || _.isNull(foundedUser)) server.utils.throwError(server.defaultResponses.authentication_user_not_found); const currentDate = new Date(); return foundedUser.update( { lastlogin: currentDate }, {transaction: transaction}) .then(loggedUser => { foundedUser.ldapAttributes = {}; Object.keys(ldapObject.object).forEach(currentAttribute => { if(currentAttribute.toUpperCase() !== 'CONTROLS' && currentAttribute.toUpperCase() !== 'OBJECTCLASS' && currentAttribute.toUpperCase() !== 'USERPASSWORD') { foundedUser.ldapAttributes[currentAttribute] = ldapObject.object[currentAttribute]; } }); return foundedUser; }) .catch(err => { server.debug('Error on user updating', err); server.utils.throwError(server.defaultResponses.entity_unable_update_element, err); }); }) .catch(err => { server.debug('Error on LDAP user login', err); server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }) .catch(err => { server.utils.throwError(server.defaultResponses.authentication_login_error, err); }); }; var checkUserInLDAP = function(uid, password, customFilter) { return new promise((resolve, reject) => { var client = ldap.createClient({ url: server.configuration.authentication.ldap.serverUrl }); server.debug('Tryin to bind LDAP Server...'); client.bind(server.configuration.authentication.ldap.readerDN, server.configuration.authentication.ldap.readerPass, function (err) { if(err) { server.debug('Bind error', err); reject(server.defaultResponses.ldap_unable_bind_to_server); } server.debug('Binded!!!'); var filter = `(|(sAMAccountName=${uid})(uid=${uid}))`; if(!_.isUndefined(customFilter) && !_.isNull(customFilter) && !_.isEmpty(customFilter)) { filter = `(&${filter}(${customFilter}))` } server.debug('Filter', filter); var opts = { filter: filter, //(|(sAMAccountName=${uid})(uid=${uid})))`, scope: 'sub' }; server.debug('Searching user in LDAP server...'); client.search(server.configuration.authentication.ldap.searchSuffix, opts, function (err, res) { if (err) { server.debug('Reader bind failed ' + err); reject(server.defaultResponses.ldap_unable_bind_to_server); return; } server.debug('Succesfully searched', res); var searchList = []; res.on('searchEntry', function (entry) { server.debug('entry: ' + JSON.stringify(entry.object)); searchList.push(entry); }); res.on('searchReference', function (referral) { server.debug('referral: ' + referral.uris.join()); }); res.on('error', function (err) { server.debug('Search failed with ' + err); reject(server.defaultResponses.ldap_search_failed); return; }); res.on('end', function (result) { if (searchList.length === 1) { client.bind(searchList[0].objectName, password, function (err) { if (err) { server.debug('Bind with real credential error: ' + err); reject(server.defaultResponses.authentication_invalid_credentials); } else { server.debug('Bind with real credential is a success'); resolve(searchList[0]); } }); } else if (searchList.length === 0) { server.debug(searchList); server.debug('User not found'); reject(server.defaultResponses.authentication_invalid_credentials); } else { server.debug(searchList); server.debug('No unique user to bind'); reject(server.defaultResponses.ldap_multiple_occurrences_founded); } }); }); }); }); }; var checkExistsUserInLDAP = function(uid, customFilter) { return new promise((resolve, reject) => { var client = ldap.createClient({ url: server.configuration.authentication.ldap.serverUrl }); server.debug('Trying to bind LDAP Server...'); client.bind(server.configuration.authentication.ldap.readerDN, server.configuration.authentication.ldap.readerPass, function (err) { if(err) { server.debug('Bind error', err); reject(server.defaultResponses.ldap_unable_bind_to_server); } server.debug('Binded!!!'); var filter = `(|(sAMAccountName=${uid})(uid=${uid}))`; if(!_.isUndefined(customFilter) && !_.isNull(customFilter) && !_.isEmpty(customFilter)) { filter = `(&${filter}(${customFilter}))` } server.debug('Filter', filter); var opts = { filter: filter, scope: 'sub' }; server.debug('Searching user in LDAP server...'); client.search(server.configuration.authentication.ldap.searchSuffix, opts, function (err, res) { if (err) { server.debug('Reader bind failed ' + err); reject(server.defaultResponses.ldap_unable_bind_to_server); return; } server.debug('Succesfully searched', res); var searchList = []; res.on('searchEntry', function (entry) { server.debug('entry: ' + JSON.stringify(entry.object)); searchList.push(entry); }); res.on('searchReference', function (referral) { server.debug('referral: ' + referral.uris.join()); }); res.on('error', function (err) { server.debug('Search failed with ' + err); reject(server.defaultResponses.ldap_search_failed); return; }); res.on('end', function (result) { if (searchList.length === 1) { resolve(searchList[0]); } else if (searchList.length === 0) { server.debug(searchList); server.debug('User not found'); reject(server.defaultResponses.authentication_invalid_credentials); } else { server.debug(searchList); server.debug('No unique user to bind'); reject(server.defaultResponses.ldap_multiple_occurrences_founded); } }); }); }); }); }; }