GH-49 Allow options.attributes = "dn" in client.search

This commit is contained in:
Mark Cavage 2012-01-19 15:39:16 -08:00
parent 87d7ef977e
commit 44a9d87863
2 changed files with 78 additions and 41 deletions

View File

@ -621,6 +621,15 @@ Client.prototype.search = function(base, options, controls, callback) {
if (typeof(callback) !== 'function') if (typeof(callback) !== 'function')
throw new TypeError('callback (function) required'); throw new TypeError('callback (function) required');
if (options.attributes) {
if (Array.isArray(options.attributes)) {
// noop
} else if (typeof(options.attributes) === 'string') {
options.attributes = [options.attributes];
} else {
throw new TypeError('options.attributes must be an Array of Strings');
}
}
var req = new SearchRequest({ var req = new SearchRequest({
baseObject: typeof(base) === 'string' ? dn.parse(base) : base, baseObject: typeof(base) === 'string' ? dn.parse(base) : base,
scope: options.scope || 'base', scope: options.scope || 'base',
@ -633,6 +642,8 @@ Client.prototype.search = function(base, options, controls, callback) {
controls: controls controls: controls
}); });
if (!this.connection) if (!this.connection)
return callback(new ConnectionError('no connection')); return callback(new ConnectionError('no connection'));
@ -698,18 +709,24 @@ Client.prototype._send = function(message, expect, callback, connection) {
var self = this; var self = this;
function closedConn() { function closeConn(err) {
if (conn) var err = err || new ConnectionError('no connection');
conn.destroy();
// This is lame, but we want to send the original error back, whereas
// this will trigger a connection event
process.nextTick(function() {
if (conn)
conn.destroy();
});
if (typeof(callback) === 'function') if (typeof(callback) === 'function')
return callback(new ConnectionError('no connection')); return callback(err);
return callback.emit('error', new ConnectionError('no connection')); return callback.emit('error', err);
} }
if (!conn) if (!conn)
return closedConn(); return closeConn();
// Now set up the callback in the messages table // Now set up the callback in the messages table
message.messageID = conn.ldap.nextMessageID; message.messageID = conn.ldap.nextMessageID;
@ -784,8 +801,7 @@ Client.prototype._send = function(message, expect, callback, connection) {
try { try {
return conn.write(message.toBer(), _writeCb); return conn.write(message.toBer(), _writeCb);
} catch (e) { } catch (e) {
conn.end(); return closeConn(e);
return closedConn();
} }
}; };

View File

@ -9,11 +9,36 @@ var ldap = require('../lib/index');
///--- Globals ///--- Globals
var SOCKET = '/tmp/.' + uuid(); var SOCKET = '/tmp/.' + uuid();
var SUFFIX = 'dc=' + uuid();
var client; var client;
var server; var server;
///--- Helper
function search(t, options, callback) {
client.search(SUFFIX, options, function(err, res) {
t.ifError(err);
t.ok(res);
var found = false;
res.on('searchEntry', function(entry) {
t.ok(entry);
found = true;
});
res.on('end', function() {
t.ok(found);
if (callback)
return callback();
t.end();
});
});
}
///--- Tests ///--- Tests
test('setup', function(t) { test('setup', function(t) {
@ -24,32 +49,30 @@ test('setup', function(t) {
socketPath: SOCKET socketPath: SOCKET
}); });
t.ok(client); t.ok(client);
// client.log4js.setLevel('Debug');
t.end(); t.end();
}); });
server.search(SUFFIX, function(req, res, next) {
var entry = {
dn: 'cn=foo, ' + SUFFIX,
attributes: {
objectclass: ['person', 'top'],
cn: 'Pogo Stick',
sn: 'Stick',
givenname: 'ogo',
mail: uuid() + '@pogostick.org'
}
};
if (req.filter.matches(entry.attributes))
res.send(entry);
res.end();
});
}); });
test('Evolution search filter (GH-3)', function(t) { test('Evolution search filter (GH-3)', function(t) {
var suffix = 'dc=' + uuid();
var entry = {
dn: 'cn=foo, ' + suffix,
attributes: {
objectclass: ['person', 'top'],
cn: 'Pogo Stick',
sn: 'Stick',
givenname: 'ogo',
mail: uuid() + '@pogostick.org'
}
};
server.search(suffix, function(req, res, next) {
console.log(req.filter.filters[0].type);
if (req.filter.matches(entry.attributes))
res.send(entry);
res.end();
});
// This is what Evolution sends, when searching for a contact 'ogo'. Wow. // This is what Evolution sends, when searching for a contact 'ogo'. Wow.
var filter = var filter =
'(|(cn=ogo*)(givenname=ogo*)(sn=ogo*)(mail=ogo*)(member=ogo*)' + '(|(cn=ogo*)(givenname=ogo*)(sn=ogo*)(mail=ogo*)(member=ogo*)' +
@ -69,19 +92,17 @@ test('Evolution search filter (GH-3)', function(t) {
'(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' + '(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' +
'(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))'; '(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))';
client.search(suffix, filter, function(err, res) { return search(t, filter);
t.ifError(err); });
t.ok(res);
var found = false;
res.on('searchEntry', function(entry) { test('GH-49 Client errors on bad attributes', function(t) {
t.ok(entry); var searchOpts = {
found = true; filter: 'cn=*ogo*',
}); scope: 'one',
res.on('end', function() { attributes: 'dn'
t.ok(found); };
t.end(); return search(t, searchOpts);
});
});
}); });