GH-28 Support extensible filters (client only)
This commit is contained in:
parent
920b9e00f4
commit
aedd9f222c
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
var util = require('util');
|
||||
|
||||
var Filter = require('./filter');
|
||||
|
||||
var Protocol = require('../protocol');
|
||||
|
||||
|
||||
|
||||
///--- API
|
||||
|
||||
function ExtensibleFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (options.rule && typeof(options.rule) !== 'string')
|
||||
throw new TypeError('options.rule must be a string');
|
||||
if (options.matchType && typeof(options.matchType) !== 'string')
|
||||
throw new TypeError('options.type must be a string');
|
||||
if (options.value && typeof(options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
this.matchType = options.matchType || null;
|
||||
this.rule = options.rule || null;
|
||||
this.value = options.value || '';
|
||||
this.dnAttributes = options.dnAttributes || false;
|
||||
options.type = Protocol.FILTER_EXT;
|
||||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
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;
|
||||
});
|
||||
}
|
||||
util.inherits(ExtensibleFilter, Filter);
|
||||
module.exports = ExtensibleFilter;
|
||||
|
||||
|
||||
ExtensibleFilter.prototype.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 + ')');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* THIS IS A STUB!
|
||||
*
|
||||
* ldapjs does not support server side extensible matching. This class exists
|
||||
* only for the client to send them.
|
||||
*
|
||||
* @param {Object} target the target object.
|
||||
* @return {Boolean} false always.
|
||||
*/
|
||||
ExtensibleFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
ExtensibleFilter.prototype.parse = function(ber) {
|
||||
throw new Error('ExtensibleFilter not supported');
|
||||
};
|
||||
|
||||
|
||||
ExtensibleFilter.prototype._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;
|
||||
};
|
|
@ -10,6 +10,7 @@ var Filter = require('./filter');
|
|||
var AndFilter = require('./and_filter');
|
||||
var ApproximateFilter = require('./approx_filter');
|
||||
var EqualityFilter = require('./equality_filter');
|
||||
var ExtensibleFilter = require('./ext_filter');
|
||||
var GreaterThanEqualsFilter = require('./ge_filter');
|
||||
var LessThanEqualsFilter = require('./le_filter');
|
||||
var NotFilter = require('./not_filter');
|
||||
|
@ -123,7 +124,7 @@ function _parseString(str) {
|
|||
}));
|
||||
} else {
|
||||
switch (stack[i].op) {
|
||||
case '=': // could be presence, equality or substr
|
||||
case '=': // could be presence, equality, substr or ext
|
||||
if (stack[i].value === '*') {
|
||||
filters.push(new PresenceFilter(stack[i]));
|
||||
} else {
|
||||
|
@ -150,7 +151,32 @@ function _parseString(str) {
|
|||
}
|
||||
}
|
||||
if (vals.length === 1) {
|
||||
filters.push(new EqualityFilter(stack[i]));
|
||||
if (stack[i].attribute.indexOf(':') !== -1) {
|
||||
var extTmp = stack[i].attribute.split(':');
|
||||
var extOpts = {};
|
||||
extOpts.matchType = extTmp[0];
|
||||
switch (extTmp.length) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (extTmp[1].toLowerCase() === 'dn') {
|
||||
extOpts.dnAttributes = true;
|
||||
} else {
|
||||
extOpts.rule = extTmp[1];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
extOpts.dnAttributes = true;
|
||||
extOpts.rule = extTmp[2];
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid extensible filter');
|
||||
}
|
||||
extOpts.value = vals[0];
|
||||
filters.push(new ExtensibleFilter(extOpts));
|
||||
} else {
|
||||
filters.push(new EqualityFilter(stack[i]));
|
||||
}
|
||||
} else {
|
||||
filters.push(new SubstringFilter({
|
||||
attribute: stack[i].attribute,
|
||||
|
@ -245,6 +271,11 @@ function _parse(ber) {
|
|||
f.parse(ber);
|
||||
return f;
|
||||
|
||||
case Protocol.FILTER_EXT:
|
||||
f = new ExtensibleFilter();
|
||||
f.parse(ber);
|
||||
return f;
|
||||
|
||||
case Protocol.FILTER_GE:
|
||||
f = new GreaterThanEqualsFilter();
|
||||
f.parse(ber);
|
||||
|
@ -309,6 +340,7 @@ module.exports = {
|
|||
AndFilter: AndFilter,
|
||||
ApproximateFilter: ApproximateFilter,
|
||||
EqualityFilter: EqualityFilter,
|
||||
ExtensibleFilter: ExtensibleFilter,
|
||||
GreaterThanEqualsFilter: GreaterThanEqualsFilter,
|
||||
LessThanEqualsFilter: LessThanEqualsFilter,
|
||||
NotFilter: NotFilter,
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var test = require('tap').test;
|
||||
|
||||
var asn1 = require('asn1');
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
||||
var ExtensibleFilter;
|
||||
var BerReader = asn1.BerReader;
|
||||
var BerWriter = asn1.BerWriter;
|
||||
var filters;
|
||||
|
||||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
ExtensibleFilter = filters.ExtensibleFilter;
|
||||
t.ok(ExtensibleFilter);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
var f = new ExtensibleFilter();
|
||||
t.ok(f);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
var f = new ExtensibleFilter({
|
||||
matchType: 'foo',
|
||||
value: 'bar',
|
||||
});
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'foo');
|
||||
t.equal(f.value, 'bar');
|
||||
t.equal(f.toString(), '(foo:=bar)');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 1', function(t) {
|
||||
var f = filters.parseString('(cn:caseExactMatch:=Fred Flintstone)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'cn');
|
||||
t.equal(f.matchingRule, 'caseExactMatch');
|
||||
t.equal(f.matchValue, 'Fred Flintstone');
|
||||
t.notOk(f.dnAttributes);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 2', function(t) {
|
||||
var f = filters.parseString('(cn:=Betty Rubble)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'cn');
|
||||
t.equal(f.matchValue, 'Betty Rubble');
|
||||
t.notOk(f.dnAttributes);
|
||||
t.notOk(f.matchingRule);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 3', function(t) {
|
||||
var f = filters.parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'sn');
|
||||
t.equal(f.matchingRule, '2.4.6.8.10');
|
||||
t.equal(f.matchValue, 'Barney Rubble');
|
||||
t.ok(f.dnAttributes);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 3', function(t) {
|
||||
var f = filters.parseString('(o:dn:=Ace Industry)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'o');
|
||||
t.notOk(f.matchingRule);
|
||||
t.equal(f.matchValue, 'Ace Industry');
|
||||
t.ok(f.dnAttributes);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 4', function(t) {
|
||||
var f = filters.parseString('(:1.2.3:=Wilma Flintstone)');
|
||||
t.ok(f);
|
||||
t.notOk(f.matchType);
|
||||
t.equal(f.matchingRule, '1.2.3');
|
||||
t.equal(f.matchValue, 'Wilma Flintstone');
|
||||
t.notOk(f.dnAttributes);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse RFC example 5', function(t) {
|
||||
var f = filters.parseString('(:DN:2.4.6.8.10:=Dino)');
|
||||
t.ok(f);
|
||||
t.notOk(f.matchType);
|
||||
t.equal(f.matchingRule, '2.4.6.8.10');
|
||||
t.equal(f.matchValue, 'Dino');
|
||||
t.ok(f.dnAttributes);
|
||||
t.end();
|
||||
});
|
Loading…
Reference in New Issue