activedirectory = function (url, baseDN, username, password, defaults) { if (this instanceof ActiveDirectory) { this.opts = {}; if (typeof(url) === 'string') { this.opts.url = url; this.baseDN = baseDN; this.opts.bindDN = username; this.opts.bindCredentials = password; if (typeof((defaults || {}).entryParser) === 'function') { this.opts.entryParser = defaults.entryParser; } } else { this.opts = _.defaults({}, url); this.baseDN = this.opts.baseDN; if (! this.opts.bindDN) this.opts.bindDN = this.opts.username; if (! this.opts.bindCredentials) this.opts.bindCredentials = this.opts.password; if (this.opts.logging) { log = bunyan.createLogger(_.defaults({}, this.opts.logging)); delete(this.opts.logging); } } defaultAttributes = _.extend({}, originalDefaultAttributes, (this.opts || {}).attributes || {}, (defaults || {}).attributes || {}); defaultReferrals = _.extend({}, originalDefaultReferrals, (this.opts || {}).referrals || {}, (defaults || {}).referrals || {}); log.info('Using username/password (%s/%s) to bind to ActiveDirectory (%s).', this.opts.bindDN, isPasswordLoggingEnabled ? this.opts.bindCredentials : '********', this.opts.url); log.info('Referrals are %s', defaultReferrals.enabled ? 'enabled. Exclusions: '+JSON.stringify(defaultReferrals.exclude): 'disabled '); log.info('Default user attributes: %j', defaultAttributes.user || []); log.info('Default group attributes: %j', defaultAttributes.group || []); // Enable connection pooling // TODO: To be disabled / removed in future release of ldapjs > 0.7.1 if (typeof(this.opts.maxConnections) === 'undefined') { this.opts.maxConnections = 20; } events.EventEmitter.call(this); } else { return(new ActiveDirectory(url, baseDN, username, password, defaults)); } }
n/a
function AndFilter(options) { parents.AndFilter.call(this, options); }
n/a
function ApproximateFilter(options) { parents.ApproximateFilter.call(this, options); }
n/a
function EqualityFilter(options) { parents.EqualityFilter.call(this, options); }
n/a
function ExtensibleFilter(options) { parents.ExtensibleFilter.call(this, options); }
n/a
function GreaterThanEqualsFilter(options) { parents.GreaterThanEqualsFilter.call(this, options); }
n/a
function LessThanEqualsFilter(options) { parents.LessThanEqualsFilter.call(this, options); }
n/a
function NotFilter(options) { parents.NotFilter.call(this, options); }
n/a
function OrFilter(options) { parents.OrFilter.call(this, options); }
n/a
function PresenceFilter(options) { parents.PresenceFilter.call(this, options); }
n/a
function SubstringFilter(options) { parents.SubstringFilter.call(this, options); }
n/a
rangeretrievalspecifierattribute = function (attribute) { if (this instanceof RangeRetrievalSpecifierAttribute) { if (! attribute) throw new Error('No attribute provided to create a range retrieval specifier.'); if (typeof(attribute) === 'string') { attribute = parseRangeRetrievalSpecifierAttribute(attribute); } for(var property in attribute) { if (Array.prototype.hasOwnProperty.call(attribute, property)) { this[property] = attribute[property]; } } } else { return(new RangeRetrievalSpecifierAttribute(attribute)); } }
n/a
function EventEmitter() { EventEmitter.init.call(this); }
n/a
user = function (properties) { if (this instanceof User) { for (var property in (properties || {})) { if (Array.prototype.hasOwnProperty.call(properties, property)) { this[property] = properties[property]; } } } else { return(new User(properties)); } }
n/a
activedirectory = function (url, baseDN, username, password, defaults) { if (this instanceof ActiveDirectory) { this.opts = {}; if (typeof(url) === 'string') { this.opts.url = url; this.baseDN = baseDN; this.opts.bindDN = username; this.opts.bindCredentials = password; if (typeof((defaults || {}).entryParser) === 'function') { this.opts.entryParser = defaults.entryParser; } } else { this.opts = _.defaults({}, url); this.baseDN = this.opts.baseDN; if (! this.opts.bindDN) this.opts.bindDN = this.opts.username; if (! this.opts.bindCredentials) this.opts.bindCredentials = this.opts.password; if (this.opts.logging) { log = bunyan.createLogger(_.defaults({}, this.opts.logging)); delete(this.opts.logging); } } defaultAttributes = _.extend({}, originalDefaultAttributes, (this.opts || {}).attributes || {}, (defaults || {}).attributes || {}); defaultReferrals = _.extend({}, originalDefaultReferrals, (this.opts || {}).referrals || {}, (defaults || {}).referrals || {}); log.info('Using username/password (%s/%s) to bind to ActiveDirectory (%s).', this.opts.bindDN, isPasswordLoggingEnabled ? this.opts.bindCredentials : '********', this.opts.url); log.info('Referrals are %s', defaultReferrals.enabled ? 'enabled. Exclusions: '+JSON.stringify(defaultReferrals.exclude): 'disabled '); log.info('Default user attributes: %j', defaultAttributes.user || []); log.info('Default group attributes: %j', defaultAttributes.group || []); // Enable connection pooling // TODO: To be disabled / removed in future release of ldapjs > 0.7.1 if (typeof(this.opts.maxConnections) === 'undefined') { this.opts.maxConnections = 20; } events.EventEmitter.call(this); } else { return(new ActiveDirectory(url, baseDN, username, password, defaults)); } }
n/a
function EventEmitter() { EventEmitter.init.call(this); }
n/a
function _getDefaultAttributes() { return(_.defaults({}, defaultAttributes)); }
...
});
it('should replace default user attributes if specified', function(done) {
var ad = new ActiveDirectory(_.extend({}, config, {
attributes: {
user: [ 'mycustomuserattribute' ]
}
}));
var defaultAttributes = ad._getDefaultAttributes() || {};
assert.equal(1, (defaultAttributes.user || []).length);
assert((defaultAttributes.group || []).length > 0);
done();
});
it('should replace default group attributes if specified', function(done) {
var ad = new ActiveDirectory(_.extend({}, config, {
attributes: {
...
function _getDefaultGroupAttributes() { return(_.defaults({}, (defaultAttributes || {}).group)); }
n/a
function _getDefaultUserAttributes() { return(_.defaults({}, (defaultAttributes || {}).user)); }
n/a
function authenticate(username, password, callback) { var self = this; log.trace('authenticate(%j,%s)', username, isPasswordLoggingEnabled ? password : '********'); // Skip authentication if an empty username or password is provided. if ((! username) || (! password)) { var err = { 'code': 0x31, 'errno': 'LDAP_INVALID_CREDENTIALS', 'description': 'The supplied credential is invalid' }; return(callback(err, false)); } var errorHandled = false; function handleError(err) { if (! errorHandled) { errorHandled = true; if (hasEvents.call(self, 'error')) self.emit('error', err); return(callback(err, false)); } } var client = createClient.call(self); client.on('error', handleError); client.bind(username, password, function(err) { client.unbind(); var message = util.format('Authentication %s for "%s" as "%s" (password: "%s")', err ? 'failed' : 'succeeded', self.opts.url, username, isPasswordLoggingEnabled ? password : '********'); if (err) { log.warn('%s. Error: %s', message, err); return(handleError(err)); } log.info(message); return(callback(err, true)); }); }
...
__Example__
```js
var ad = new ActiveDirectory(config);
var username = 'john.smith@domain.com';
var password = 'password';
ad.authenticate(username, password, function(err, auth) {
if (err) {
console.log('ERROR: '+JSON.stringify(err));
return;
}
if (auth) {
console.log('Authenticated!');
...
function find(opts, callback) { var self = this; if (typeof(opts) === 'function') { callback = opts; opts = undefined; } if (typeof(opts) === 'string') { opts = { filter: opts }; } log.trace('find(%j)', opts); var localOpts = _.defaults(_.omit(opts || {}, 'attributes'), { scope: 'sub', attributes: joinAttributes((opts || {}).attributes || [], defaultAttributes.group || [], defaultAttributes.user || [], getRequiredLdapAttributesForGroup(opts), getRequiredLdapAttributesForUser(opts), [ 'objectCategory' ]) }); search.call(self, localOpts, function onFind(err, results) { if (err) { if (callback) callback(err); return; } if ((! results) || (results.length === 0)) { log.warn('No results found for query "%s"', truncateLogOutput(localOpts.filter)); if (callback) callback(); self.emit('done'); return; } var result = { users: [], groups: [], other: [] }; // Parse the results in parallel. async.forEach(results, function(item, asyncCallback) { if (isGroupResult(item)) { var group = new Group(pickAttributes(item, (opts || {}).attributes || defaultAttributes.group)); result.groups.push(group); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'group')) { getGroupMembershipForDN.call(self, opts, group.dn, function(err, groups) { if (err) return(asyncCallback(err)); group.groups = groups; self.emit('group', group); asyncCallback(); }); } else { self.emit('group', group); asyncCallback(); } } else if (isUserResult(item)) { var user = new User(pickAttributes(item, (opts || {}).attributes || defaultAttributes.user)); result.users.push(user); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'user')) { getGroupMembershipForDN.call(self, opts, user.dn, function(err, groups) { if (err) return(asyncCallback(err)); user.groups = groups; self.emit('user', user); asyncCallback(); }); } else { self.emit('user', user); asyncCallback(); } } else { var other = pickAttributes(item, (opts || {}).attributes || _.union(defaultAttributes.user, defaultAttributes.group)); result.other.push(other); self.emit('other', other); asyncCallback(); } }, function(err) { if (err) { if (callback) callback(err); return; } log.info('%d group(s), %d user(s), %d other found for query "%s". Results: %j', result.groups.length, result.users.length, result.other.length, truncateLogOutput(opts.filter), result); self.emit('groups', result.groups); self.emit('users', result.users); if (callback) callback(null, result); }); }); }
...
var query = 'cn=*Exchange*';
var opts = {
includeMembership : [ 'group', 'user' ], // Optionally can use 'all'
includeDeleted : false
};
var ad = new ActiveDirectory(config);
ad.find(query, function(err, results) {
if ((err) || (! results)) {
console.log('ERROR: ' + JSON.stringify(err));
return;
}
console.log('Groups');
_.each(results.groups, function(group) {
...
function find(opts, callback) {
var self = this;
if (typeof(opts) === 'function') {
callback = opts;
opts = undefined;
}
if (typeof(opts) === 'string') {
opts = {
filter: opts
};
}
log.trace('findDeletedObjects(%j)', opts);
var defaultDeletedAttributes = [
'attributeID', 'attributeSyntax', 'dnReferenceUpdate' , 'dNSHostName' , 'flatName',
'governsID', 'groupType', 'instanceType', 'lDAPDisplayName', 'legacyExchangeDN',
'mS-DS-CreatorSID', 'mSMQOwnerID', 'nCName', 'objectClass', 'objectGUID', 'objectSid',
'oMSyntax', 'proxiedObjectName', 'replPropertyMetaData', 'sAMAccountName', 'securityIdentifier',
'sIDHistory', 'subClassOf', 'systemFlags', 'trustPartner', 'trustDirection', 'trustType',
'trustAttributes', 'userAccountControl', 'uSNChanged', 'uSNCreated', 'whenCreated',
'msDS-AdditionalSamÂAccountName', 'msDS-Auxiliary-Classes', 'msDS-Entry-Time-To-Die',
'msDS-IntId', 'msSFU30NisDomain', 'nTSecurityDescriptor', 'uid'
];
/**
* Performs the actul search of the specified baseDN for any deleted (tombstoned) objects.
* @param {String} baseDN The baseDN to search on.
* @param {Object} opts The ldapjs query options.
*/
function searchDeletedObjects(baseDN, opts) {
search.call(self, baseDN, _.defaults({}, opts, { includeDeleted: true }), function onFind(err, results) {
if (err) {
if (callback) callback(err);
return;
}
if ((! results) || (results.length === 0)) {
log.warn('No deleted objects found for query "%s"', truncateLogOutput(opts.filter));
if (callback) callback();
self.emit('done');
return;
}
var deletedItems = [];
// Parse the results in parallel.
_.forEach(deletedItemss, function(item) {
var deletedItem = pickAttributes(item, (opts | {}).attributes || []);
self.emit('entry:deleted', deletedItem);
deletedItems.push(deletedItem);
});
log.info('%d deleted objects found for query "%s". Results: %j',
deletedItems.length, truncateLogOutput(localOpts.filter), deletedItems);
self.emit('deleted', deletedItems);
if (callback) callback(null, deletedItems);
});
}
var localOpts = _.defaults(opts || {}, {
scope: 'one',
attributes: joinAttributes((opts || {}).attributes || [], defaultDeletedAttributes),
controls: [ ]
});
// Get the BaseDN for the tree
if (! localOpts.baseDN) {
log.debug('No baseDN specified for Deleted Object. Querying RootDSE at %s.', self.opts.url);
ActiveDirectory.prototype.getRootDSE(self.opts.url, [ 'defaultNamingContext' ], function(err, result) {
if (err) {
if (callback) callback(err);
return;
}
log.info('Retrieved defaultNamingContext (%s) from RootDSE at %s.', result.defaultNamingContext, self.opts.url);
searchDeletedObjects('CN=Deleted Objects,' + result.defaultNamingContext, localOpts);
});
}
else searchDeletedObjects(localOpts.baseDN, localOpts);
}
...
```js
var url = 'ldap://yourdomain.com';
var opts = {
baseDN: 'ou=Deleted Objects, dc=yourdomain, dc=com',
filter: 'cn=*Bob*'
};
ad.findDeletedObjects(opts, function(err, result) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
console.log('findDeletedObjects: '+JSON.stringify(result));
});
...
function findGroup(opts, groupName, callback) { var self = this; if (typeof(groupName) === 'function') { callback = groupName; groupName = opts; opts = undefined; } if (typeof(opts) === 'string') { groupName = opts; opts = undefined; } log.trace('findGroup(%j,%s)', opts, groupName); var localOpts = _.defaults(_.omit(opts || {}, 'attributes'), { filter: getGroupQueryFilter.call(self, groupName), scope: 'sub', attributes: joinAttributes((opts || {}).attributes || defaultAttributes.group, getRequiredLdapAttributesForGroup(opts)) }); search.call(self, localOpts, function onSearch(err, results) { if (err) { if (callback) callback(err); return; } if ((! results) || (results.length === 0)) { log.warn('Group "%s" not found for query "%s"', groupName, truncateLogOutput(localOpts.filter)); if (callback) callback(); return; } var group = new Group(pickAttributes(results[0], (opts || {}).attributes || defaultAttributes.group)); log.info('%d group(s) found for query "%s". Returning first group: %j', results.length, truncateLogOutput(localOpts.filter), group); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'group')) { getGroupMembershipForDN.call(self, opts, group.dn, function(err, groups) { if (err) { if (callback) callback(err); return; } group.groups = groups; self.emit('group', group); if (callback) callback(err, group); }); } else { self.emit('group', group); if (callback) callback(err, group); } }); }
...
```js
// Any of the following group names can be searched on
var groupName = 'Employees';
var dn = 'CN=Employees,OU=Groups,DC=domain,DC=com'
// Find group by common name
var ad = new ActiveDirectory(config);
ad.findGroup(groupName, function(err, group) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if (! user) console.log('Group: ' + groupName + ' not found.');
else {
...
function findGroup(opts, callback) { var self = this; var defaultGroupFilter = '(objectClass=group)(!(objectClass=computer))(!(objectClass=user))(!(objectClass=person))'; if (typeof(opts) === 'function') { callback = opts; opts = ''; } if ((typeof(opts) === 'string') && (opts)) { opts = { filter: '(&'+defaultGroupFilter+getCompoundFilter(opts)+')' }; } log.trace('findGroups(%j)', opts); var localOpts = _.defaults(_.omit(opts || {}, 'attributes'), { filter: '(&'+defaultGroupFilter+')', scope: 'sub', attributes: joinAttributes((opts || {}).attributes || defaultAttributes.group || [], getRequiredLdapAttributesForGroup(opts), [ 'groupType' ]) }); search.call(self, localOpts, function onSearch(err, results) { if (err) { if (callback) callback(err); return; } if ((! results) || (results.length === 0)) { log.warn('No groups found matching query "%s"', truncateLogOutput(localOpts.filter)); if (callback) callback(); return; } var groups = []; // Parse the results in parallel. async.forEach(results, function(result, asyncCallback) { if (isGroupResult(result)) { var group = new Group(pickAttributes(result, (opts || {}).attributes || defaultAttributes.user)); groups.push(group); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'group')) { getGroupMembershipForDN.call(self, opts, group.dn, function(err, groups) { if (err) return(asyncCallback(err)); group.groups = groups; self.emit('group', group); asyncCallback(); }); } else { self.emit('group', group); asyncCallback(); } } else asyncCallback(); }, function(err) { if (err) { if (callback) callback(err); return; } log.info('%d group(s) found for query "%s". Groups: %j', groups.length, truncateLogOutput(localOpts.filter), groups); self.emit('groups', groups); if (callback) callback(null, groups); }); }); }
...
__Example__
```js
var query = 'CN=*Admin*';
var ad = new ActiveDirectory(config);
ad.findGroups(query, function(err, groups) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if ((! groups) || (groups.length == 0)) console.log('No groups found.');
else {
...
function findUser(opts, username, includeMembership, callback) { var self = this; if (typeof(includeMembership) === 'function') { callback = includeMembership; includeMembership = undefined; } if (typeof(username) === 'function') { callback = username; username = opts; opts = undefined; } if (typeof(username) === 'boolean') { includeMembership = username; username = opts; } if (typeof(opts) === 'string') { username = opts; opts = undefined; } log.trace('findUser(%j,%s,%s)', opts, username, includeMembership); var localOpts = _.defaults(_.omit(opts || {}, 'attributes'), { filter: getUserQueryFilter.call(self, username), scope: 'sub', attributes: joinAttributes((opts || {}).attributes || defaultAttributes.user || [], getRequiredLdapAttributesForUser(opts)) }); search.call(self, localOpts, function onSearch(err, results) { if (err) { if (callback) callback(err); return; } if ((! results) || (results.length === 0)) { log.warn('User "%s" not found for query "%s"', username, truncateLogOutput(localOpts.filter)); if (callback) callback(); return; } var user = new User(pickAttributes(results[0], (opts || {}).attributes || defaultAttributes.user)); log.info('%d user(s) found for query "%s". Returning first user: %j', results.length, truncateLogOutput(localOpts.filter), user ); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'user') || includeMembership) { getGroupMembershipForDN.call(self, opts, user.dn, function(err, groups) { if (err) { if (callback) callback(err); return; } user.groups = groups; self.emit('user', user); if (callback) callback(err, user); }); } else { self.emit('user', user); if (callback) callback(err, user); } }); }
...
// Any of the following username types can be searched on
var sAMAccountName = 'username';
var userPrincipalName = 'username@domain.com';
var dn = 'CN=Smith\\, John,OU=Users,DC=domain,DC=com';
// Find user by a sAMAccountName
var ad = new ActiveDirectory(config);
ad.findUser(sAMAccountName, function(err, user) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if (! user) console.log('User: ' + sAMAccountName + ' not found.');
else console.log(JSON.stringify(user));
...
function findUsers(opts, includeMembership, callback) { var self = this; var defaultUserFilter = '(|(objectClass=user)(objectClass=person))(!(objectClass=computer))(!(objectClass=group))'; if (typeof(includeMembership) === 'function') { callback = includeMembership; includeMembership = false; } if (typeof(opts) === 'function') { callback = opts; opts = ''; } if ((typeof(opts) === 'string') && (opts)) { opts = { filter: '(&'+defaultUserFilter+getCompoundFilter(opts)+')' }; } log.trace('findUsers(%j,%s)', opts, includeMembership); var localOpts = _.defaults(_.omit(opts || {}, 'attributes'), { filter: '(&'+defaultUserFilter+')', scope: 'sub', attributes: joinAttributes((opts || {}).attributes || defaultAttributes.user || [], getRequiredLdapAttributesForUser(opts), [ 'objectCategory' ]) }); search.call(self, localOpts, function onSearch(err, results) { if (err) { if (callback) callback(err); return; } if ((! results) || (results.length === 0)) { log.warn('No users found matching query "%s"', truncateLogOutput(localOpts.filter)); if (callback) callback(); return; } var users = []; // Parse the results in parallel. async.forEach(results, function(result, asyncCallback) { if (isUserResult(result)) { var user = new User(pickAttributes(result, (opts || {}).attributes || defaultAttributes.user)); users.push(user); // Also retrieving user group memberships? if (includeGroupMembershipFor(opts, 'user') || includeMembership) { getGroupMembershipForDN.call(self, opts, user.dn, function(err, groups) { if (err) return(asyncCallback(err)); user.groups = groups; self.emit('user', user); asyncCallback(); }); } else { self.emit('user', user); asyncCallback(); } } else asyncCallback(); }, function(err) { if (err) { if (callback) callback(err); return; } log.info('%d user(s) found for query "%s". Users: %j', users.length, truncateLogOutput(opts.filter), users); self.emit('users', users); if (callback) callback(null, users); }); }); }
...
__Example__
```js
var query = 'cn=*George*';
var ad = new ActiveDirectory(config);
ad.findUsers(query, true, function(err, users) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if ((! users) || (users.length == 0)) console.log('No users found.');
else {
...
function getGroupMembershipForGroup(opts, groupName, callback) { var self = this; if (typeof(groupName) === 'function') { callback = groupName; groupName = opts; opts = undefined; } log.trace('getGroupMembershipForGroup(%j,%s)', opts, groupName); getGroupDistinguishedName.call(self, opts, groupName, function(err, dn) { if (err) { if (callback) callback(err); return; } if (! dn) { log.warn('Could not find a distinguishedName for the specified group name: "%s"', groupName); if (callback) callback(); return; } getGroupMembershipForDN.call(self, opts, dn, function(err, groups) { if (err) { if (callback) callback(err); return; } var results = []; _.each(groups, function(group) { var result = new Group(pickAttributes(group, (opts || {}).attributes || defaultAttributes.group)); self.emit(result); results.push(result); }); if (callback) callback(err, results); }); }); }
...
__Example__
```js
var groupName = 'Employees';
var ad = new ActiveDirectory(config);
ad.getGroupMembershipForGroup(groupName, function(err, groups) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if (! groups) console.log('Group: ' + groupName + ' not found.');
else console.log(JSON.stringify(groups));
...
function getGroupMembershipForUser(opts, username, callback) { var self = this; if (typeof(username) === 'function') { callback = username; username = opts; opts = undefined; } log.trace('getGroupMembershipForUser(%j,%s)', opts, username); getUserDistinguishedName.call(self, opts, username, function(err, dn) { if (err) { if (callback) callback(err); return; } if (! dn) { log.warn('Could not find a distinguishedName for the specified username: "%s"', username); if (callback) callback(); return; } getGroupMembershipForDN.call(self, opts, dn, function(err, groups) { if (err) { if (callback) callback(err); return; } var results = []; _.each(groups, function(group) { var result = new Group(pickAttributes(group, (opts || {}).attributes || defaultAttributes.group)); self.emit(result); results.push(result); }); if (callback) callback(err, results); }); }); }
...
__Example__
```js
var sAMAccountName = 'john.smith@domain.com';
var ad = new ActiveDirectory(config);
ad.getGroupMembershipForUser(sAMAccountName, function(err, groups) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if (! groups) console.log('User: ' + sAMAccountName + ' not found.');
else console.log(JSON.stringify(groups));
...
function getRootDSE(url, attributes, callback) {
var self = this;
if (typeof(attributes) === 'function') {
callback = attributes;
attributes = undefined;
}
if (typeof(url) === 'function') {
callback = url;
url = self.url || self.opts.url;
attributes = undefined;
}
if (! url) throw new Error('No url specified for the root DSE. Please specify an ldap url in the following format: "ldap://yourdomain
.com:389".');
log.trace('getRootDSE(%s,%j)', url, attributes || [ '*' ]);
/**
* Inline function handle connection and result errors.
*
* @private
**/
function onClientError(err) {
// Ignore ECONNRESET errors
if ((err || {}).errno !== 'ECONNRESET') {
log.error('An unhandled error occured when searching for the root DSE at "%s". Error: %j', url, err);
if (hasEvents.call(self, 'error')) self.emit('error', err)
}
}
var client = createClient.call(this, url);
client.on('error', onClientError);
// Anonymous bind
client.bind('', '', function(err) {
if (err) {
log.error('Anonymous bind to "%s" failed. Error: %s', url, err);
return(callback(err, false));
}
client.search('', { scope: 'base', attributes: attributes || [ '*' ], filter: '(objectClass=*)' }, function(err, result) {
if (err) {
log.error('Root DSE search failed for "%s". Error: %s', url, err);
return(callback(err));
}
result.on('error', onClientError);
result.on('end', function(result) {
client.unbind();
});
result.on('searchEntry', function(entry) {
callback(null, _.omit(entry.object, 'controls'));
});
});
});
}
...
* attributes - The optional list of attributes to retrieve. Returns all if not specified.
* callback - The callback to execute when completed. callback(err: {Object}, result: {Object})
__Example__
```js
var url = 'ldap://yourdomain.com';
ActiveDirectory.prototype.getRootDSE(url, [ 'defaultNamingContext' ], function
(err, result) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
console.log('getRootDSE: '+JSON.stringify(result));
});
...
function getUsersForGroup(opts, groupName, callback) {
var self = this;
if (typeof(groupName) === 'function') {
callback = groupName;
groupName = opts;
opts = undefined;
}
log.trace('getUsersForGroup(%j,%s)', opts, groupName);
var users = [];
var groups = [];
self.findGroup(_.defaults({}, _.omit(opts || {}, 'attributes'), {
attributes: joinAttributes((opts || {}).attributes || defaultAttributes.group, [ 'member' ])
}),
groupName, function(err, group) {
if (err) {
if (callback) callback(err);
return;
}
// Group not found
if (! group) {
if (callback) callback(null, group);
return;
}
// If only one result found, encapsulate result into array.
if (typeof(group.member) === 'string') {
group.member = [ group.member ];
}
/**
* Breaks the large array into chucks of the specified size.
* @param {Array} arr The array to break into chunks
* @param {Number} chunkSize The size of each chunk.
* @returns {Array} The resulting array containing each chunk
*/
function chunk(arr, chunkSize) {
var result = [];
for (var index = 0, length = arr.length; index < length; index += chunkSize) {
result.push(arr.slice(index,index + chunkSize));
}
return(result);
}
// We need to break this into the default size queries so
// we can have them running concurrently.
var chunks = chunk(group.member || [], defaultPageSize);
if (chunks.length > 1) {
log.debug('Splitting %d member(s) of "%s" into %d parallel chunks',
(group.member || []).length, groupName, chunks.length);
}
var chunksProcessed = 0;
async.each(chunks, function getUsersForGroup_ChunkItem(members, asyncChunkCallback) {
// We're going to build up a bulk LDAP query so we can reduce
// the number of round trips to the server. We need to get
// additional details about each 'member' to determine if
// it is a group or another user. If it's a group, we need
// to recursively retrieve the members of that group.
var filter = _.reduce(members || [], function(memo, member, index) {
return(memo+'(distinguishedName='+parseDistinguishedName(member)+')');
}, '');
filter = '(&(|(objectCategory=User)(objectCategory=Group))(|'+filter+'))';
var localOpts = {
filter: filter,
scope: 'sub',
attributes: joinAttributes((opts || {}).attributes || defaultAttributes.user || [],
getRequiredLdapAttributesForUser(opts), [ 'groupType' ])
};
search.call(self, localOpts, function onSearch(err, members) {
if (err) {
asyncChunkCallback(err);
return;
}
// Parse the results in parallel.
async.forEach(members, function(member, asyncCallback) {
// If a user, no groupType will be specified.
if (! member.groupType) {
var user = new User(pickAttributes(member, (opts || {}).attributes || defaultAttributes.user));
self.emit(user);
users.push(user);
asyncCallback();
}
else {
// We have a group, recursively get the users belonging to this group.
self.getUsersForGroup(opts, member.cn, function(err, nestedUsers) {
users.push.apply(users, nestedUsers);
asyncCallback();
});
}
}, function(err) {
if (chunks.length > 1) {
log.debug('Finished processing chunk %d/%d', ++chunksProcessed, chunks.length);
}
asyncChunkCallback(err);
});
});
}, function getUsersForGroup_ChunkComplete(err) {
// Remove duplicates
users = _.uniq(users, function(user) {
return(user.dn || user);
});
/*
// Remove the dn that was added for duplicate detection if not requested.
if (! _.any((opts || {}).attributes || defaultAttributes.user, function(attribute) { ...
...
__Example__
```js
var groupName = 'Employees';
var ad = new ActiveDirectory(config);
ad.getUsersForGroup(groupName, function(err, users) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
if (! users) console.log('Group: ' + groupName + ' not found.');
else {
...
function groupExists(opts, groupName, callback) { var self = this; if (typeof(groupName) === 'function') { callback = groupName; groupName = opts; opts = undefined; } log.trace('groupExists(%j,%s)', opts, groupName); self.findGroup(opts, groupName, function(err, result) { if (err) { callback(err); return; } log.info('"%s" %s exist.', groupName, (result != null) ? 'DOES' : 'DOES NOT'); callback(null, result != null); }); }
...
__Example__
```js
var groupName = 'Employees';
var ad = new ActiveDirectory(config);
ad.groupExists(groupName, function(err, exists) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
console.log(groupName + ' exists: ' + exists);
});
...
function isUserMemberOf(opts, username, groupName, callback) { var self = this; if (typeof(groupName) === 'function') { callback = groupName; groupName = username; username = opts; opts = undefined; } log.trace('isUserMemberOf(%j,%s,%s)', opts, username, groupName); opts = _.defaults(_.omit(opts || {}, 'attributes'), { attributes: [ 'cn', 'dn' ] }); self.getGroupMembershipForUser(opts, username, function(err, groups) { if (err) { callback(err); return; } if ((! groups) || (groups.length === 0)) { log.info('"%s" IS NOT a member of "%s". No groups found for user.', username, groupName); callback(null, false); return; } // Check to see if the group.distinguishedName or group.cn matches the list of // retrieved groups. var lowerCaseGroupName = (groupName || '').toLowerCase(); var result = _.any(groups, function(item) { return(((item.dn || '').toLowerCase() === lowerCaseGroupName) || ((item.cn || '').toLowerCase() === lowerCaseGroupName)); }); log.info('"%s" %s a member of "%s"', username, result ? 'IS' : 'IS NOT', groupName); callback(null, result); }); }
...
__Example__
```js
var username = 'user@domain.com';
var groupName = 'Employees';
var ad = new ActiveDirectory(config);
var ad.isUserMemberOf(username, groupName, function(err, isMember) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
console.log(username + ' isMemberOf ' + groupName + ': ' + isMember);
});
...
function userExists(opts, username, callback) { var self = this; if (typeof(username) === 'function') { callback = username; username = opts; opts = undefined; } log.trace('userExists(%j,%s)', opts, username); self.findUser(opts, username, function(err, user) { if (err) { callback(err); return; } log.info('"%s" %s exist.', username, (user != null) ? 'DOES' : 'DOES NOT'); callback(null, user != null); }); }
...
__Example__
```js
var username = 'john.smith@domain.com';
var ad = new ActiveDirectory(config);
ad.userExists(username, function(err, exists) {
if (err) {
console.log('ERROR: ' +JSON.stringify(err));
return;
}
console.log(username + ' exists: ' + exists);
});
...
function AndFilter(options) { parents.AndFilter.call(this, options); }
n/a
function ApproximateFilter(options) { parents.ApproximateFilter.call(this, options); }
n/a
function EqualityFilter(options) { parents.EqualityFilter.call(this, options); }
n/a
function ExtensibleFilter(options) { parents.ExtensibleFilter.call(this, options); }
n/a
function GreaterThanEqualsFilter(options) { parents.GreaterThanEqualsFilter.call(this, options); }
n/a
function LessThanEqualsFilter(options) { parents.LessThanEqualsFilter.call(this, options); }
n/a
function NotFilter(options) { parents.NotFilter.call(this, options); }
n/a
function OrFilter(options) { parents.OrFilter.call(this, options); }
n/a
function PresenceFilter(options) { parents.PresenceFilter.call(this, options); }
n/a
function SubstringFilter(options) { parents.SubstringFilter.call(this, options); }
n/a
function isFilter(filter) { if (!filter || typeof (filter) !== 'object') { return false; } // Do our best to duck-type it if (typeof (filter.toBer) === 'function' && typeof (filter.matches) === 'function' && TYPES[filter.type] !== undefined) { return true; } return false; }
n/a
parse = function (ber) { if (!ber || !(ber instanceof BerReader)) throw new TypeError('ber (BerReader) required'); return _parse(ber); }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function parseString(str) { var generic = parents.parse(str); // The filter object(s) return from ldap-filter.parse lack the toBer/parse // decoration that native ldapjs filter possess. cloneFilter adds that back. return cloneFilter(generic); }
n/a
function AndFilter(options) { parents.AndFilter.call(this, options); }
n/a
function AndFilter(options) { if (typeof (options) === 'object') { assert.arrayOfObject(options.filters, 'options.filters'); } else { options = {}; } this.__defineGetter__('type', function () { return 'and'; }); this.filters = options.filters ? options.filters.slice() : []; var self = this; this.__defineGetter__('json', function () { return { type: 'And', filters: self.filters }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); this.filters.forEach(function (f) { ber = f.toBer(ber); }); return ber; }
n/a
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
addFilter = function (filter) { assert.object(filter, 'filter'); this.filters.push(filter); }
n/a
matches = function (target, strictAttrCase) {
assert.object(target, 'target');
if (this.filters.length === 0) {
/* true per RFC4526 */
return true;
}
for (var i = 0; i < this.filters.length; i++) {
if (!this.filters[i].matches(target, strictAttrCase))
return false;
}
return true;
}
n/a
toString = function () { var str = '(&'; this.filters.forEach(function (f) { str += f.toString(); }); str += ')'; return str; }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function ApproximateFilter(options) { parents.ApproximateFilter.call(this, options); }
n/a
function ApproximateFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); assert.string(options.value, 'options.value'); this.attribute = options.attribute; this.value = options.value; } var self = this; this.__defineGetter__('type', function () { return 'approx'; }); this.__defineGetter__('json', function () { return { type: 'ApproximateMatch', attribute: self.attribute, value: self.value }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); ber.writeString(this.attribute); ber.writeString(this.value); return ber; }
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.readString().toLowerCase(); this.value = ber.readString(); return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function () { // Consumers must implement this themselves throw new Error('approx match implementation missing'); }
n/a
toString = function () { return ('(' + helpers.escape(this.attribute) + '~=' + helpers.escape(this.value) + ')'); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function EqualityFilter(options) { parents.EqualityFilter.call(this, options); }
n/a
function EqualityFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); this.attribute = options.attribute; // Prefer Buffers over strings to make filter cloning easier if (options.raw) { this.raw = options.raw; } else { this.raw = new Buffer(options.value); } } else { this.raw = new Buffer(0); } var self = this; this.__defineGetter__('type', function () { return 'equal'; }); this.__defineGetter__('value', function () { return (Buffer.isBuffer(self.raw)) ? self.raw.toString() : self.raw; }); this.__defineSetter__('value', function (data) { if (typeof (data) === 'string') { self.raw = new Buffer(data); } else if (Buffer.isBuffer(data)) { self.raw = new Buffer(data.length); data.copy(self.raw); } else { self.raw = data; } }); this.__defineGetter__('json', function () { return { type: 'EqualityMatch', attribute: self.attribute, value: self.value }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); ber.writeString(this.attribute); ber.writeBuffer(this.raw, ASN1.OctetString); return ber; }
n/a
matches = function (target, strictAttrCase) {
assert.object(target, 'target');
var tv = parents.getAttrValue(target, this.attribute, strictAttrCase);
var value = this.value;
if (this.attribute.toLowerCase() === 'objectclass') {
/*
* Perform case-insensitive match for objectClass since nearly every LDAP
* implementation behaves in this manner.
*/
value = value.toLowerCase();
return parents.testValues(function (v) {
return value === v.toLowerCase();
}, tv);
} else {
return parents.testValues(function (v) {
return value === v;
}, tv);
}
}
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.readString().toLowerCase(); this.value = ber.readString(ASN1.OctetString, true); if (this.attribute === 'objectclass') this.value = this.value.toLowerCase(); return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); var tv = helpers.getAttrValue(target, this.attribute, strictAttrCase); var value = this.value; return helpers.testValues(function (v) { return value === v; }, tv); }
n/a
toString = function () { return ('(' + helpers.escape(this.attribute) + '=' + helpers.escape(this.value) + ')'); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function ExtensibleFilter(options) { parents.ExtensibleFilter.call(this, options); }
n/a
function ExtensibleFilter(options) { if (typeof (options) === 'object') { assert.optionalString(options.rule, 'options.rule'); assert.optionalString(options.matchType, 'options.matchType'); assert.optionalString(options.attribute, 'options.attribute'); assert.optionalString(options.value, 'options.value'); } else { options = {}; } if (options.matchType !== undefined) { this.matchType = options.matchType; } else { this.matchType = options.attribute; } this.dnAttributes = options.dnAttributes || false; this.rule = options.rule; this.value = (options.value !== undefined) ? options.value : ''; var self = this; this.__defineGetter__('type', function () { return 'ext'; }); this.__defineGetter__('json', function () { return { type: 'ExtensibleMatch', matchRule: self.rule, matchType: self.matchType, matchValue: self.value, dnAttributes: self.dnAttributes }; }); this.__defineGetter__('matchingRule', function () { return self.rule; }); this.__defineGetter__('matchValue', function () { return self.value; }); this.__defineGetter__('attribute', function () { return this.matchType; }); this.__defineSetter__('attribute', function (value) { this.matchType = value; }); }
n/a
_toBer = function (ber) { assert.ok(ber); if (this.rule) ber.writeString(this.rule, 0x81); if (this.matchType) ber.writeString(this.matchType, 0x82); ber.writeString(this.value, 0x83); if (this.dnAttributes) ber.writeBoolean(this.dnAttributes, 0x84); return ber; }
n/a
parse = function (ber) { var end = ber.offset + ber.length; while (ber.offset < end) { var tag = ber.peek(); switch (tag) { case 0x81: this.rule = ber.readString(tag); break; case 0x82: this.matchType = ber.readString(tag); break; case 0x83: this.value = ber.readString(tag); break; case 0x84: this.dnAttributes = ber.readBoolean(tag); break; default: throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16)); } } return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function () { // Consumers must implement this themselves throw new Error('ext match implementation missing'); }
n/a
toString = function () { var str = '('; if (this.matchType) str += this.matchType; str += ':'; if (this.dnAttributes) str += 'dn:'; if (this.rule) str += this.rule + ':'; return (str + '=' + this.value + ')'); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function GreaterThanEqualsFilter(options) { parents.GreaterThanEqualsFilter.call(this, options); }
n/a
function GreaterThanEqualsFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); assert.string(options.value, 'options.value'); this.attribute = options.attribute; this.value = options.value; } var self = this; this.__defineGetter__('type', function () { return 'ge'; }); this.__defineGetter__('json', function () { return { type: 'GreaterThanEqualsMatch', attribute: self.attribute, value: self.value }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); ber.writeString(this.attribute); ber.writeString(this.value); return ber; }
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.readString().toLowerCase(); this.value = ber.readString(); return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); var tv = helpers.getAttrValue(target, this.attribute, strictAttrCase); var value = this.value; return helpers.testValues(function (v) { return value <= v; }, tv); }
n/a
toString = function () { return ('(' + helpers.escape(this.attribute) + '>=' + helpers.escape(this.value) + ')'); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function LessThanEqualsFilter(options) { parents.LessThanEqualsFilter.call(this, options); }
n/a
function LessThanEqualsFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); assert.string(options.value, 'options.attribute'); this.attribute = options.attribute; this.value = options.value; } var self = this; this.__defineGetter__('type', function () { return 'le'; }); this.__defineGetter__('json', function () { return { type: 'LessThanEqualsMatch', attribute: self.attribute, value: self.value }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); ber.writeString(this.attribute); ber.writeString(this.value); return ber; }
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.readString().toLowerCase(); this.value = ber.readString(); return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); var tv = helpers.getAttrValue(target, this.attribute, strictAttrCase); var value = this.value; return helpers.testValues(function (v) { return value >= v; }, tv); }
n/a
toString = function () { return ('(' + helpers.escape(this.attribute) + '<=' + helpers.escape(this.value) + ')'); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function NotFilter(options) { parents.NotFilter.call(this, options); }
n/a
function NotFilter(options) { if (typeof (options) === 'object') { assert.object(options.filter, 'options.filter'); } else { options = {}; } this.filter = options.filter || {}; var self = this; this.__defineGetter__('type', function () { return 'not'; }); this.__defineGetter__('json', function () { return { type: 'Not', filter: self.filter }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); return this.filter.toBer(ber); }
n/a
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
addFilter = function (filter) { assert.object(filter, 'filter'); this.filter = filter; }
n/a
matches = function (target, strictAttrCase) { return !this.filter.matches(target, strictAttrCase); }
n/a
toString = function () { return '(!' + this.filter.toString() + ')'; }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function OrFilter(options) { parents.OrFilter.call(this, options); }
n/a
function OrFilter(options) { if (typeof (options) === 'object') { assert.arrayOfObject(options.filters, 'options.filters'); } else { options = {}; } this.filters = options.filters ? options.filters.slice() : []; var self = this; this.__defineGetter__('type', function () { return 'or'; }); this.__defineGetter__('json', function () { return { type: 'Or', filters: self.filters }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); this.filters.forEach(function (f) { ber = f.toBer(ber); }); return ber; }
n/a
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
addFilter = function (filter) { assert.object(filter, 'filter'); this.filters.push(filter); }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); for (var i = 0; i < this.filters.length; i++) { if (this.filters[i].matches(target, strictAttrCase)) return true; } return false; }
n/a
toString = function () { var str = '(|'; this.filters.forEach(function (f) { str += f.toString(); }); str += ')'; return str; }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function PresenceFilter(options) { parents.PresenceFilter.call(this, options); }
n/a
function PresenceFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); this.attribute = options.attribute; } var self = this; this.__defineGetter__('type', function () { return 'present'; }); this.__defineGetter__('json', function () { return { type: 'PresenceMatch', attribute: self.attribute }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); for (var i = 0; i < this.attribute.length; i++) ber.writeByte(this.attribute.charCodeAt(i)); return ber; }
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase(); ber._offset += ber.length; return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); var value = helpers.getAttrValue(target, this.attribute, strictAttrCase); return (value !== undefined && value !== null); }
n/a
toString = function () { return '(' + helpers.escape(this.attribute) + '=*)'; }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
function SubstringFilter(options) { parents.SubstringFilter.call(this, options); }
n/a
function SubstringFilter(options) { if (typeof (options) === 'object') { assert.string(options.attribute, 'options.attribute'); this.attribute = options.attribute; this.initial = options.initial; this.any = options.any ? options.any.slice(0) : []; this.final = options.final; } else { this.any = []; } var self = this; this.__defineGetter__('type', function () { return 'substring'; }); this.__defineGetter__('json', function () { return { type: 'SubstringMatch', initial: self.initial, any: self.any, final: self.final }; }); }
n/a
_toBer = function (ber) { assert.ok(ber); ber.writeString(this.attribute); ber.startSequence(); if (this.initial) ber.writeString(this.initial, 0x80); if (this.any && this.any.length) this.any.forEach(function (s) { ber.writeString(s, 0x81); }); if (this.final) ber.writeString(this.final, 0x82); ber.endSequence(); return ber; }
n/a
parse = function (ber) { assert.ok(ber); this.attribute = ber.readString().toLowerCase(); ber.readSequence(); var end = ber.offset + ber.length; while (ber.offset < end) { var tag = ber.peek(); switch (tag) { case 0x80: // Initial this.initial = ber.readString(tag); if (this.attribute === 'objectclass') this.initial = this.initial.toLowerCase(); break; case 0x81: // Any var anyVal = ber.readString(tag); if (this.attribute === 'objectclass') anyVal = anyVal.toLowerCase(); this.any.push(anyVal); break; case 0x82: // Final this.final = ber.readString(tag); if (this.attribute === 'objectclass') this.final = this.final.toLowerCase(); break; default: throw new Error('Invalid substrings filter type: 0x' + tag.toString(16)); } } return true; }
...
// Loop over the referrals received.
while (referralUrl = (ref.uris || [])[index++]) {
if (isAllowedReferral(referralUrl)) {
log.debug('Following LDAP referral chase at %s', referralUrl);
var referralClient = createClient.call(self, referralUrl, opts);
pendingReferrals.push(referralClient);
var referral = Url.parse(referralUrl);
var referralBaseDn = (referral.pathname || '/').substring(1);
referralClient.search(referralBaseDn, getLdapOpts(opts), controls, function(err, res) {
/**
* Occurs when a error is encountered with the referral client.
* @param {Object} err The error object or string.
*/
function onReferralError(err) {
...
function toBer(ber) { if (!ber || !(ber instanceof BerWriter)) throw new TypeError('ber (BerWriter) required'); ber.startSequence(TYPES[this.type]); ber = this._toBer(ber); ber.endSequence(); return ber; }
n/a
matches = function (target, strictAttrCase) { assert.object(target, 'target'); var tv = helpers.getAttrValue(target, this.attribute, strictAttrCase); if (tv !== undefined && tv !== null) { var re = ''; if (this.initial) re += '^' + escapeRegExp(this.initial) + '.*'; this.any.forEach(function (s) { re += escapeRegExp(s) + '.*'; }); if (this.final) re += escapeRegExp(this.final) + '$'; var matcher = new RegExp(re); return helpers.testValues(function (v) { return matcher.test(v); }, tv); } return false; }
n/a
toString = function () { var str = '(' + helpers.escape(this.attribute) + '='; if (this.initial) str += helpers.escape(this.initial); str += '*'; this.any.forEach(function (s) { str += helpers.escape(s) + '*'; }); if (this.final) str += helpers.escape(this.final); str += ')'; return str; }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
rangeretrievalspecifierattribute = function (attribute) { if (this instanceof RangeRetrievalSpecifierAttribute) { if (! attribute) throw new Error('No attribute provided to create a range retrieval specifier.'); if (typeof(attribute) === 'string') { attribute = parseRangeRetrievalSpecifierAttribute(attribute); } for(var property in attribute) { if (Array.prototype.hasOwnProperty.call(attribute, property)) { this[property] = attribute[property]; } } } else { return(new RangeRetrievalSpecifierAttribute(attribute)); } }
n/a
function getRangeAttributes(item) { var attributes = []; for(var attribute in (item || {})) { if (RangeRetrievalSpecifierAttribute.prototype.isRangeAttribute(attribute)) { var range = new RangeRetrievalSpecifierAttribute(attribute); attributes.push(range); } } return(attributes.length > 0 ? attributes : null); }
...
if (! RangeRetrievalSpecifierAttribute.prototype.hasRangeAttributes(result)) {
callback(null, result);
return;
}
// Parse the range attributes that were provided. If the range attributes are null
// or indicate that the range is complete, return the result.
var rangeAttributes = RangeRetrievalSpecifierAttribute.prototype.getRangeAttributes(result
);
if ((! rangeAttributes) || (rangeAttributes.length <= 0)) {
callback(null, result);
return;
}
// Parse each of the range attributes. Merge the range attributes into
// the properly named property.
...
function hasRangeAttributes(item) { return(_.any(_.keys(item || {}), function(attribute) { return(RangeRetrievalSpecifierAttribute.prototype.isRangeAttribute(attribute)); })); }
...
*/
function parseRangeAttributes(result, opts, callback) {
log.trace('parseRangeAttributes(%j,%j)', result, opts);
var self = this;
// Check to see if any of the result attributes have range= attributes.
// If not, return immediately.
if (! RangeRetrievalSpecifierAttribute.prototype.hasRangeAttributes(result)) {
callback(null, result);
return;
}
// Parse the range attributes that were provided. If the range attributes are null
// or indicate that the range is complete, return the result.
var rangeAttributes = RangeRetrievalSpecifierAttribute.prototype.getRangeAttributes(result);
...
function isComplete() { var self = this; return((self.high == null) || (typeof(self.high) === 'undefined')); }
...
if (! result[rangeAttribute.attributeName]) result[rangeAttribute.attributeName] = [];
Array.prototype.push.apply(result[rangeAttribute.attributeName], result[rangeAttribute.toString()]);
delete(result[rangeAttribute.toString()]);
// Build our ldap query attributes with the proper attribute;range= tags to
// get the next sequence of data.
var queryAttribute = rangeAttribute.next();
if ((queryAttribute) && (! queryAttribute.isComplete())) {
queryAttributes.push(queryAttribute.toString());
}
});
// If we're at the end of the range (i.e. all items retrieved), return the result.
if (queryAttributes.length <= 0) {
log.debug('All attribute ranges %j retrieved for %s', rangeAttributes, result.dn);
...
function isRangeAttribute(attribute) { var re = new RegExp(pattern, 'i'); return(re.test(attribute)); }
...
* @static
* @param {Object} item The value to extract the range retrieval attributes from.
* @returns {Array[RangeRetrievalSpecifierAttribute]}
*/
RangeRetrievalSpecifierAttribute.prototype.getRangeAttributes = function getRangeAttributes(item) {
var attributes = [];
for(var attribute in (item || {})) {
if (RangeRetrievalSpecifierAttribute.prototype.isRangeAttribute(attribute)) {
var range = new RangeRetrievalSpecifierAttribute(attribute);
attributes.push(range);
}
}
return(attributes.length > 0 ? attributes : null);
};
...
function next() { var self = this; if ((self.high != null) && (self.high != self.low)) { var low = self.low; var high = self.high; self.low = high + 1; self.high = high + (high - low) + 1; return(this); } return(null); }
...
// Merge existing range into the properly named property.
if (! result[rangeAttribute.attributeName]) result[rangeAttribute.attributeName] = [];
Array.prototype.push.apply(result[rangeAttribute.attributeName], result[rangeAttribute.toString()]);
delete(result[rangeAttribute.toString()]);
// Build our ldap query attributes with the proper attribute;range= tags to
// get the next sequence of data.
var queryAttribute = rangeAttribute.next();
if ((queryAttribute) && (! queryAttribute.isComplete())) {
queryAttributes.push(queryAttribute.toString());
}
});
// If we're at the end of the range (i.e. all items retrieved), return the result.
if (queryAttributes.length <= 0) {
...
function toString() { var self = this; return(self.attributeName + ';range=' + self.low + '-' + (self.high ? self.high : '*')); }
...
* @param {String} output The output to truncate if too long
* @param {Number} [maxLength] The maximum length. If not specified, then the global value maxOutputLength is used.
*/
function truncateLogOutput(output, maxLength) {
if (typeof(maxLength) === 'undefined') maxLength = maxOutputLength;
if (! output) return(output);
if (typeof(output) !== 'string') output = output.toString();
var length = output.length;
if ((! length) || (length < (maxLength + 3))) return(output);
var prefix = Math.ceil((maxLength - 3)/2);
var suffix = Math.floor((maxLength - 3)/2);
return(output.slice(0, prefix)+ '...' +
output.slice(length-suffix));
...
user = function (properties) { if (this instanceof User) { for (var property in (properties || {})) { if (Array.prototype.hasOwnProperty.call(properties, property)) { this[property] = properties[property]; } } } else { return(new User(properties)); } }
n/a
function isMemberOf(group) { if (! group) return(false); group = (group || '').toLowerCase(); return(_.any(this.groups || [], function(item) { return (((item || {}).cn || '').toLowerCase() === group); })); }
n/a