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')
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({
baseObject: typeof(base) === 'string' ? dn.parse(base) : base,
scope: options.scope || 'base',
@ -633,6 +642,8 @@ Client.prototype.search = function(base, options, controls, callback) {
controls: controls
});
if (!this.connection)
return callback(new ConnectionError('no connection'));
@ -698,18 +709,24 @@ Client.prototype._send = function(message, expect, callback, connection) {
var self = this;
function closedConn() {
function closeConn(err) {
var err = err || new ConnectionError('no connection');
// 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')
return callback(new ConnectionError('no connection'));
return callback(err);
return callback.emit('error', new ConnectionError('no connection'));
return callback.emit('error', err);
}
if (!conn)
return closedConn();
return closeConn();
// Now set up the callback in the messages table
message.messageID = conn.ldap.nextMessageID;
@ -784,8 +801,7 @@ Client.prototype._send = function(message, expect, callback, connection) {
try {
return conn.write(message.toBer(), _writeCb);
} catch (e) {
conn.end();
return closedConn();
return closeConn(e);
}
};

View File

@ -9,11 +9,36 @@ var ldap = require('../lib/index');
///--- Globals
var SOCKET = '/tmp/.' + uuid();
var SUFFIX = 'dc=' + uuid();
var client;
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
test('setup', function(t) {
@ -24,16 +49,12 @@ test('setup', function(t) {
socketPath: SOCKET
});
t.ok(client);
// client.log4js.setLevel('Debug');
t.end();
});
});
test('Evolution search filter (GH-3)', function(t) {
var suffix = 'dc=' + uuid();
server.search(SUFFIX, function(req, res, next) {
var entry = {
dn: 'cn=foo, ' + suffix,
dn: 'cn=foo, ' + SUFFIX,
attributes: {
objectclass: ['person', 'top'],
cn: 'Pogo Stick',
@ -43,13 +64,15 @@ test('Evolution search filter (GH-3)', function(t) {
}
};
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();
});
});
test('Evolution search filter (GH-3)', function(t) {
// This is what Evolution sends, when searching for a contact 'ogo'. Wow.
var filter =
'(|(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*)' +
'(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))';
client.search(suffix, filter, 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);
t.end();
});
return search(t, filter);
});
test('GH-49 Client errors on bad attributes', function(t) {
var searchOpts = {
filter: 'cn=*ogo*',
scope: 'one',
attributes: 'dn'
};
return search(t, searchOpts);
});