Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x |
const ldap = require('ldapjs');
const _ = require('underscore');
const createClient = require('./service.createClient');
const truncateLogOutput = require('./service.truncateLogOutput');
const getLdapOpts = require('./service.getLdapOpts');
const log = require('./service.log');
const limitpromises = require('limitpromises');
const maxPromiseConfig = require('../../configs/config.maxPromiseGroup');
const onClientError = require('./search/service.search.onClientError');
const onSearchEnd = require('./search/service.onSearchEnd');
const onSearchEntry = require('./search/service.search.onSearchEntry');
const onReferralChase = require('./search/service.search.onReferralChase');
const defaultPageSize = 1000; // The maximum number of results that AD will return in a single call. Default=1000
/**
* Performs a search on the LDAP tree.
*
* @private
* @param {String} [baseDN] The optional base directory where the LDAP query is to originate from. If not specified, then starts at the root.
* @param {Object} [opts] LDAP query string parameters to execute. { scope: '', filter: '', attributes: [ '', '', ... ], sizeLimit: 0, timelimit: 0 }
* @param {Function} callback The callback to execure when completed. callback(err: {Object}, results: {Array[Object]}})
*/
function search (baseDN, opts, callback) {
return new Promise((resolve, reject) => {
let searchStarted = new Date();
let self = this;
let results = [];
let isDone = false;
if (typeof (opts) === 'function') {
callback = opts;
opts = baseDN;
baseDN = undefined;
}
if (typeof (baseDN) === 'object') {
opts = baseDN;
baseDN = undefined;
}
opts || (opts = {});
baseDN || (baseDN = opts.baseDN) || (baseDN = self.baseDN);
log.trace('search(%s,%j)', baseDN, opts);
var controls = opts.controls || (opts.controls = []);
// Add paging results control by default if not already added.
if (!_.any(controls, function (control) { return (control instanceof ldap.PagedResultsControl); })) {
log.debug('Adding PagedResultControl to search (%s) with filter "%s" for %j',
baseDN, truncateLogOutput(opts.filter), _.any(opts.attributes) ? opts.attributes : '[*]');
controls.push(new ldap.PagedResultsControl({ value: { size: defaultPageSize } }));
}
if (opts.includeDeleted) {
if (!_.any(controls, function (control) { return (control.type === '1.2.840.113556.1.4.417'); })) {
log.debug('Adding ShowDeletedOidControl(1.2.840.113556.1.4.417) to search (%s) with filter "%s" for %j',
baseDN, truncateLogOutput(opts.filter), _.any(opts.attributes) ? opts.attributes : '[*]');
controls.push(new ldap.Control({ type: '1.2.840.113556.1.4.417', criticality: true }));
}
}
log.debug('Querying active directory (%s) with filter "%s" for %j',
baseDN,
truncateLogOutput(opts.filter),
_.any(opts.attributes) ? opts.attributes : '[*]'
);
// We want to limit the total of the searches, we will use [true] as InputValues as we don't use it anyways in the function
let s = limitpromises(Input => {
return new Promise((resolve, reject) => {
var client = createClient.call(self, null, opts);
client.on('error', err => {
onClientError(err, client, searchStarted, baseDN, opts, results, resolve, reject)
});
client.search(baseDN, getLdapOpts(opts), controls, function onSearch(err, res) {
if (err) {
reject(err);
}
res.on('searchEntry', entry => {
onSearchEntry(entry, client, baseDN, self, opts, isDone, results, resolve, reject);
});
res.on('searchReference', ref => {
onReferralChase(self, client, ref, opts, controls, results, resolve, reject);
});
res.on('error', function (err) {
onClientError(err, client, searchStarted, baseDN, opts, results, resolve, reject);
});
res.on('end', function (result) {
isDone = true; // Flag that the primary query is complete
onSearchEnd(client, baseDN, opts, results, resolve, reject);
});
});
});
}, [true], self.opts.maxSearchesAtOnce || maxPromiseConfig.maxSearchesAtOnce, "searches", maxPromiseConfig.searchTimeoutAndReject);
Promise.all(s.map(r => {return r.result})).then(results => {
if(callback){
callback(null, results[0]);
}
return resolve(results[0]);
}, err => {
if(callback){
callback(err);
}
return reject(err);
});
})
}
module.exports = search; |