diff --git a/lib/index.js b/lib/index.js index 630e179..08f11db 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,6 +3,7 @@ var Client = require('./client'); var Attribute = require('./attribute'); var Change = require('./change'); +var PersistentSearch = require('./persistent_search'); var Protocol = require('./protocol'); var Server = require('./server'); @@ -72,7 +73,9 @@ module.exports = { loadSchema: schema.load, createSchemaAddHandler: schema.createAddHandler, createSchemaModifyHandler: schema.createModifyHandler, - createSchemaSearchHandler: schema.createSearchHandler + createSchemaSearchHandler: schema.createSearchHandler, + + PersistentSearch: PersistentSearch }; diff --git a/lib/persistent_search.js b/lib/persistent_search.js new file mode 100644 index 0000000..8b9b979 --- /dev/null +++ b/lib/persistent_search.js @@ -0,0 +1,118 @@ +///--- Globals + +var parseDN = require('./dn').parse; + +var EntryChangeNotificationControl = + require('./controls').EntryChangeNotificationControl; + +///--- API + + +// Cache used to store connected persistent search clients +function PersistentSearch() { + this.clientList = []; +} +module.exports = PersistentSearch; + +PersistentSearch.prototype.addClient = function(req, res, callback) { + if (typeof(req) !== 'object') + throw new TypeError('req must be an object'); + if (typeof(res) !== 'object') + throw new TypeError('res must be an object'); + if (callback && typeof(callback) !== 'function') + throw new TypeError('callback must be a function'); + + var log = req.log; + + var client = {}; + client.req = req; + client.res = res; + + log.debug('%s storing client', req.logId); + + this.clientList.push(client); + + log.debug('%s stored client', req.logId); + log.debug('%s total number of clients %s', + req.logId, this.clientList.length); + if (callback) + callback(client); +}; + + +PersistentSearch.prototype.removeClient = function(req, res, callback) { + if (typeof(req) !== 'object') + throw new TypeError('req must be an object'); + if (typeof(res) !== 'object') + throw new TypeError('res must be an object'); + if (callback && typeof(callback) !== 'function') + throw new TypeError('callback must be a function'); + + var log = req.log; + log.debug('%s removing client', req.logId); + var client = {}; + client.req = req; + client.res = res; + + // remove the client if it exists + this.clientList.forEach(function(element, index, array) { + if (element.req === client.req) { + log.debug('%s removing client from list', req.logId); + array.splice(index, 1); + } + }); + + log.debug('%s number of persistent search clients %s', + req.logId, this.clientList.length); + if (callback) + callback(client); +}; + + +getOperationType = function(requestType) { + switch (requestType) { + case 'AddRequest': + case 'add': + return 1; + case 'DeleteRequest': + case 'delete': + return 2; + case 'ModifyRequest': + case 'modify': + return 4; + case 'ModifyDNRequest': + case 'modrdn': + return 8; + default: + throw new TypeError('requestType %s, is an invalid request type', + request); + } +}; + + +PersistentSearch.getEntryChangeNotificationControl = + function(req, obj, callback) { + + console.log('getEntryChangeNotificationControl', obj); + // if we want to return a ECNC + if (req.persistentSearch.value.returnECs) { + var attrs = obj.attributes; + var value = {}; + value.changeType = getOperationType(attrs.changetype); + // if it's a modDN request, fill in the previous DN + if (value.changeType === 8 && attrs.previousDN) { + value.previousDN = attrs.previousDN; + } + + value.changeNumber = attrs.changenumber; + return new EntryChangeNotificationControl({ value: value }); + } else { + return false; + } +}; + + +PersistentSearch.checkChangeType = function(req, requestType) { + return (req.persistentSearch.value.changeTypes & + getOperationType(requestType)); +}; diff --git a/lib/url.js b/lib/url.js index 6e391f1..0f02a95 100644 --- a/lib/url.js +++ b/lib/url.js @@ -5,7 +5,7 @@ var url = require('url'); var util = require('util'); var dn = require('./dn'); - +var filter = require('./filters/index'); module.exports = { @@ -55,7 +55,9 @@ module.exports = { if (!u.scope) u.scope = 'base'; if (!u.filter) - u.filter = '(objectclass=*)'; + u.filter = filter.parseString('(objectclass=*)'); + else + u.filter = filter.parseString(u.filter); } return u; diff --git a/tst/url.test.js b/tst/url.test.js index 0a992b4..5e1d05b 100644 --- a/tst/url.test.js +++ b/tst/url.test.js @@ -67,7 +67,7 @@ test('parse full', function(t) { t.equal(u.attributes[0], 'cn'); t.equal(u.attributes[1], 'sn'); t.equal(u.scope, 'sub'); - t.equal(u.filter, '(cn=Babs Jensen)'); + t.equal(u.filter.toString(), '(cn=Babs Jensen)'); t.end(); });