diff --git a/src/externalldap.js b/src/externalldap.js index c4370cf6e..37cc3aaeb 100644 --- a/src/externalldap.js +++ b/src/externalldap.js @@ -82,6 +82,41 @@ function getClient(externalLdapConfig, callback) { }); } +function ldapGetByDN(externalLdapConfig, dn, callback) { + assert.strictEqual(typeof externalLdapConfig, 'object'); + assert.strictEqual(typeof dn, 'string'); + assert.strictEqual(typeof callback, 'function'); + + getClient(externalLdapConfig, function (error, client) { + if (error) return callback(error); + + let searchOptions = { + paged: true, + scope: 'sub' // We may have to make this configurable + }; + + debug(`Get object at ${dn}`); + + client.search(dn, searchOptions, function (error, result) { + if (error instanceof ldap.NoSuchObjectError) return callback(new BoxError(BoxError.NOT_FOUND)); + if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, error)); + + let ldapObjects = []; + + result.on('searchEntry', entry => ldapObjects.push(entry.object)); + result.on('error', error => callback(new BoxError(BoxError.EXTERNAL_ERROR, error))); + + result.on('end', function (result) { + client.unbind(); + + if (result.status !== 0) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Server returned status ' + result.status)); + if (ldapObjects.length === 0) return callback(new BoxError(BoxError.NOT_FOUND)); + + callback(null, ldapObjects[0]); + }); + }); + }); +} // TODO support search by email function ldapUserSearch(externalLdapConfig, options, callback) { @@ -140,10 +175,10 @@ function ldapGroupSearch(externalLdapConfig, options, callback) { if (externalLdapConfig.groupFilter) searchOptions.filter = ldap.parseFilter(externalLdapConfig.groupFilter); - // if (options.filter) { // https://github.com/ldapjs/node-ldapjs/blob/master/docs/filters.md - // let extraFilter = ldap.parseFilter(options.filter); - // searchOptions.filter = new ldap.AndFilter({ filters: [ extraFilter, searchOptions.filter ] }); - // } + if (options.filter) { // https://github.com/ldapjs/node-ldapjs/blob/master/docs/filters.md + let extraFilter = ldap.parseFilter(options.filter); + searchOptions.filter = new ldap.AndFilter({ filters: [ extraFilter, searchOptions.filter ] }); + } debug(`Listing groups at ${externalLdapConfig.groupBaseDn} with filter ${searchOptions.filter.toString()}`); @@ -420,13 +455,56 @@ function syncGroupUsers(externalLdapConfig, progressCallback, callback) { return callback(null, []); } - groups.getAllWithMembers(function (error, groups) { + groups.getAll(function (error, result) { if (error) return callback(error); - var ldapGroups = groups.filter(function (g) { return g.source === 'ldap'; }); + var ldapGroups = result.filter(function (g) { return g.source === 'ldap'; }); debug(`Found ${ldapGroups.length} groups to sync users`); - callback(); + async.eachSeries(ldapGroups, function (group, iteratorCallback) { + debug(`Synd users for group ${group.name}`); + + ldapGroupSearch(externalLdapConfig, { filter: `${externalLdapConfig.groupnameField}=${group.name}` }, function (error, result) { + if (error) return callback(error); + if (!result || result.length === 0) { + console.error(`Unable to find group ${group.name} ignoring for now.`); + return callback(); + } + + var ldapGroupMembers = result[0].member; + + debug(`Group ${group.name} has ${ldapGroupMembers.length} members.`); + + async.eachSeries(ldapGroupMembers, function (memberDn, iteratorCallback) { + ldapGetByDN(externalLdapConfig, memberDn, function (error, result) { + if (error) { + console.error(`Failed to get ${memberDn}:`, error); + return iteratorCallback(); + } + + debug(`Found member object at ${memberDn} adding to group ${group.name}`); + + const username = result[externalLdapConfig.usernameField]; + if (!username) return iteratorCallback(); + + users.getByUsername(username, function (error, result) { + if (error) { + console.error(`Failed to get user by username ${username}`, error); + return iteratorCallback(); + } + + groups.addMember(group.id, result.id, function (error) { + if (error && error.reason !== BoxError.ALREADY_EXISTS) console.error('Failed to add member', error); + iteratorCallback(); + }); + }); + }); + }, function (error) { + if (error) console.error(error); + iteratorCallback(); + }); + }); + }, callback); }); }