@aarconada/urserver
Version:
Basic Server definitions to develope REST API with a node + express Server
436 lines (426 loc) • 21.7 kB
JavaScript
/**
* Created by ubuntu on 12/11/18.
*/
;
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);
}
});
});
});
});
};
}