ldapjs-client
Advanced tools
Comparing version 0.0.3 to 0.0.4
@@ -25,9 +25,5 @@ const Client = require('../src'); | ||
try { | ||
await client.destroy(); | ||
await client.destroy(); | ||
expect(true).toBeTruthy(); | ||
} catch (e) { | ||
expect(e).toBe(null); | ||
} | ||
expect(true).toBeTruthy(); | ||
}); | ||
@@ -40,9 +36,5 @@ | ||
try { | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
expect(true).toBeTruthy(); | ||
} catch (e) { | ||
expect(e).toBe(null); | ||
} | ||
expect(true).toBeTruthy(); | ||
@@ -114,14 +106,13 @@ await client.destroy(); | ||
it('search', async () => { | ||
expect.assertions(1); | ||
expect.assertions(4); | ||
const client = new Client({ url: 'ldap://www.zflexldap.com' }); | ||
try { | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
const response = await client.search('ou=guests,dc=zflexsoftware,dc=com', { scope: 'sub' }); | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
const response = await client.search('ou=guests,dc=zflexsoftware,dc=com', { scope: 'sub' }); | ||
expect(response.length).toBeGreaterThan(0); | ||
} catch (e) { | ||
expect(e).toBe(null); | ||
} | ||
expect(response.length).toBeGreaterThan(0); | ||
expect(response[0].dn).toBeDefined(); | ||
expect(response[0].ou).toBe('guests'); | ||
expect(response[0].objectclass.length).toBeGreaterThan(0); | ||
@@ -131,2 +122,16 @@ await client.destroy(); | ||
it('search not found', async () => { | ||
expect.assertions(2); | ||
const client = new Client({ url: 'ldap://www.zflexldap.com' }); | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
const response = await client.search('ou=guests,dc=zflexsoftware,dc=com', { filter: '(ou=sysadmins)', scope: 'sub' }); | ||
expect(Array.isArray(response)).toBeTruthy(); | ||
expect(response.length).toBe(0); | ||
await client.destroy(); | ||
}); | ||
it('unbind', async () => { | ||
@@ -137,13 +142,9 @@ expect.assertions(2); | ||
try { | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
await client.bind('cn=ro_admin,ou=sysadmins,dc=zflexsoftware,dc=com', 'zflexpass'); | ||
expect(true).toBeTruthy(); | ||
expect(true).toBeTruthy(); | ||
await client.unbind(); | ||
await client.unbind(); | ||
expect(true).toBeTruthy(); | ||
} catch (e) { | ||
expect(e).toBe(null); | ||
} | ||
expect(true).toBeTruthy(); | ||
@@ -150,0 +151,0 @@ await client.destroy(); |
@@ -13,3 +13,3 @@ { | ||
], | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"license": "MIT", | ||
@@ -16,0 +16,0 @@ "repository": { |
@@ -21,6 +21,2 @@ const assert = require('assert-plus'); | ||
get buffers() { | ||
return this._vals; | ||
} | ||
get json() { | ||
@@ -51,3 +47,3 @@ return { | ||
} else { | ||
this._vals.push(new Buffer(val + '', _bufferEncoding(this.type))); | ||
this._vals.push(new Buffer(String(val), _bufferEncoding(this.type))); | ||
} | ||
@@ -83,4 +79,3 @@ } | ||
ber.writeLength(b.length); | ||
for (let i = 0; i < b.length; ++i) | ||
ber.writeByte(b[i]); | ||
b.forEach(i => ber.writeByte(i)); | ||
}); | ||
@@ -130,4 +125,18 @@ } else { | ||
} | ||
static fromObject(attributes) { | ||
return Object.keys(attributes).map(k => { | ||
const attr = new Attribute({ type: k }); | ||
if (Array.isArray(attributes[k])) { | ||
attributes[k].forEach(v => attr.addValue(v.toString())); | ||
} else { | ||
attr.addValue(attributes[k].toString()); | ||
} | ||
return attr; | ||
}); | ||
} | ||
} | ||
module.exports = Attribute; |
@@ -86,49 +86,2 @@ const assert = require('assert-plus'); | ||
static apply(change, obj, scalar) { | ||
assert.string(change.operation); | ||
assert.string(change.modification.type); | ||
assert.ok(Array.isArray(change.modification.vals)); | ||
assert.object(obj); | ||
const type = change.modification.type; | ||
const vals = change.modification.vals; | ||
let data = obj[type]; | ||
if (data !== undefined) { | ||
if (!Array.isArray(data)) { | ||
data = [data]; | ||
} | ||
} else { | ||
data = []; | ||
} | ||
switch (change.operation) { | ||
case 'replace': | ||
if (vals.length === 0) { | ||
delete obj[type]; | ||
return obj; | ||
} else { | ||
data = vals; | ||
} | ||
break; | ||
case 'add': | ||
data.push(...vals.filter(entry => !data.inlcudes(entry))); | ||
break; | ||
case 'delete': | ||
data = data.filter(entry => !vals.includes(entry)); | ||
if (data.length === 0) { | ||
delete obj[type]; | ||
return obj; | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
if (scalar && data.length === 1) { | ||
// store single-value outputs as scalars, if requested | ||
obj[type] = data[0]; | ||
} else { | ||
obj[type] = data; | ||
} | ||
return obj; | ||
} | ||
static compare(a, b) { | ||
@@ -152,2 +105,21 @@ assert.ok(Change.isChange(a) && Change.isChange(b), 'can only compare Changes'); | ||
static fromObject(change) { | ||
assert.ok(change.operation || change.type, 'change.operation required'); | ||
assert.object(change.modification, 'change.modification'); | ||
if (Object.keys(change.modification).length == 2 && typeof change.modification.type === 'string' && Array.isArray(change.modification.vals)) { | ||
return [new Change({ | ||
operation: change.operation || change.type, | ||
modification: change.modification | ||
})]; | ||
} else { | ||
return Object.keys(change.modification).map(k => new Change({ | ||
operation: change.operation || change.type, | ||
modification: { | ||
[k]: change.modification[k] | ||
} | ||
})); | ||
} | ||
} | ||
parse(ber) { | ||
@@ -154,0 +126,0 @@ assert.ok(ber); |
166
src/dn.js
@@ -34,3 +34,3 @@ const assert = require('assert-plus'); | ||
if (quoted) | ||
out = '"' + out + '"'; | ||
out = `"${ out }"`; | ||
return out; | ||
@@ -50,3 +50,3 @@ }; | ||
set(name, value, opts) { | ||
set(name, value) { | ||
assert.string(name, 'name (string) required'); | ||
@@ -57,43 +57,12 @@ assert.string(value, 'value (string) required'); | ||
this.attrs[lname] = { name, value }; | ||
if (opts && typeof opts === 'object') { | ||
Object.keys(opts).forEach(k => { | ||
if (k !== 'value') | ||
this.attrs[lname][k] = opts[k]; | ||
}); | ||
} | ||
} | ||
equals(rdn) { | ||
if (typeof rdn !== 'object') { | ||
return false; | ||
} | ||
const _1 = Object.keys(this.attrs).sort(); | ||
const _2 = Object.keys(rdn.attrs).sort(); | ||
return _1.length === _2.length && _1.join() === _2.join() && _1.map(i => this.attrs[i].value).join() === _2.map(i => rdn.attrs[i].value).join(); | ||
} | ||
format(options = {}) { | ||
assert.optionalObject(options, 'options must be an object'); | ||
toString() { | ||
const keys = Object.keys(this.attrs); | ||
if (options.keepOrder) { | ||
keys.sort((a, b) => this.attrs[a].order - this.attrs[b].order); | ||
} else { | ||
keys.sort((a, b) => a.localeCompare(b) || this.attrs[a].value.localeCompare(this.attrs[b].value)); | ||
} | ||
keys.sort((a, b) => a.localeCompare(b) || this.attrs[a].value.localeCompare(this.attrs[b].value)); | ||
return keys | ||
.map(key => { | ||
const { name, value, quoted } = this.attrs[key]; | ||
return `${options.keepCase ? name : options.upperName ? key.toUpperCase() : key}=${escapeValue(value, options.keepQuote && quoted)}`; | ||
}) | ||
.map(key => `${key}=${escapeValue(this.attrs[key].value)}`) | ||
.join('+'); | ||
} | ||
toString() { | ||
return this.format(); | ||
} | ||
} | ||
@@ -249,12 +218,7 @@ | ||
constructor(rdns) { | ||
assert.optionalArrayOfObject(rdns, '[object] required'); | ||
assert.optionalArrayOfObject(rdns, 'rdns'); | ||
this.rdns = rdns ? rdns.slice() : []; | ||
this._format = {}; | ||
} | ||
get length() { | ||
return this.rdns.length; | ||
} | ||
static isDN(dn) { | ||
@@ -264,121 +228,5 @@ return dn instanceof DN || (dn && Array.isArray(dn.rdns)); | ||
format(options) { | ||
assert.optionalObject(options, 'options must be an object'); | ||
options = options || this._format; | ||
let str = ''; | ||
this.rdns.forEach(rdn => { | ||
const rdnString = rdn.format(options); | ||
if (str.length !== 0) { | ||
str += ','; | ||
} | ||
if (options.keepSpace) { | ||
str += ' '.repeat(rdn.spLead) + rdnString + ' '.repeat(rdn.spTrail); | ||
} else if (options.skipSpace === true || str.length === 0) { | ||
str += rdnString; | ||
} else { | ||
str += ' ' + rdnString; | ||
} | ||
}); | ||
return str; | ||
} | ||
setFormat(options) { | ||
assert.object(options, 'options must be an object'); | ||
this._format = options; | ||
} | ||
toString() { | ||
return this.format(); | ||
return this.rdns.map(String).join(', '); | ||
} | ||
parentOf(dn) { | ||
if (typeof (dn) !== 'object') { | ||
dn = parse(dn); | ||
} | ||
if (this.rdns.length >= dn.rdns.length) | ||
return false; | ||
const diff = dn.rdns.length - this.rdns.length; | ||
for (let i = this.rdns.length - 1; i >= 0; --i) { | ||
const myRDN = this.rdns[i]; | ||
const theirRDN = dn.rdns[i + diff]; | ||
if (!myRDN.equals(theirRDN)) | ||
return false; | ||
} | ||
return true; | ||
} | ||
childOf(dn) { | ||
if (typeof (dn) !== 'object') { | ||
dn = parse(dn); | ||
} | ||
return dn.parentOf(this); | ||
} | ||
isEmpty() { | ||
return (this.rdns.length === 0); | ||
} | ||
equals(dn) { | ||
if (typeof (dn) !== 'object') { | ||
dn = parse(dn); | ||
} | ||
if (this.rdns.length !== dn.rdns.length) | ||
return false; | ||
for (let i = 0; i < this.rdns.length; ++i) { | ||
if (!this.rdns[i].equals(dn.rdns[i])) | ||
return false; | ||
} | ||
return true; | ||
} | ||
parent() { | ||
if (this.rdns.length !== 0) { | ||
const save = this.rdns.shift(); | ||
const dn = new DN(this.rdns); | ||
this.rdns.unshift(save); | ||
return dn; | ||
} | ||
return null; | ||
} | ||
clone() { | ||
const dn = new DN(this.rdns); | ||
dn._format = this._format; | ||
return dn; | ||
} | ||
reverse() { | ||
this.rdns.reverse(); | ||
return this; | ||
} | ||
pop() { | ||
return this.rdns.pop(); | ||
} | ||
push(rdn) { | ||
assert.object(rdn, 'rdn (RDN) required'); | ||
return this.rdns.push(rdn); | ||
} | ||
shift() { | ||
return this.rdns.shift(); | ||
} | ||
unshift(rdn) { | ||
assert.object(rdn, 'rdn (RDN) required'); | ||
return this.rdns.unshift(rdn); | ||
} | ||
} | ||
@@ -385,0 +233,0 @@ |
@@ -1,14 +0,16 @@ | ||
const assert = require('assert'); | ||
const assert = require('assert-plus'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_AND } = require('../protocol'); | ||
class AndFilter extends parents.AndFilter { | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
return this.filters.reduce((ber, f) => f.toBer(ber), ber); | ||
} | ||
} | ||
module.exports = class AndFilter extends parents.AndFilter { | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
Filter.mixin(AndFilter); | ||
ber.startSequence(FILTER_AND); | ||
ber = this.filters.reduce((ber, f) => f.toBer(ber), ber); | ||
ber.endSequence(); | ||
module.exports = AndFilter; | ||
return ber; | ||
} | ||
}; |
@@ -1,6 +0,7 @@ | ||
const assert = require('assert'); | ||
const assert = require('assert-plus'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_APPROX } = require('../protocol'); | ||
class ApproximateFilter extends parents.ApproximateFilter { | ||
module.exports = class ApproximateFilter extends parents.ApproximateFilter { | ||
parse(ber) { | ||
@@ -15,14 +16,12 @@ assert.ok(ber); | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_APPROX); | ||
ber.writeString(this.attribute); | ||
ber.writeString(this.value); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(ApproximateFilter); | ||
module.exports = ApproximateFilter; | ||
}; |
const assert = require('assert-plus'); | ||
const { Ber: { OctetString } } = require('asn1'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { Ber: { OctetString }, BerWriter } = require('asn1'); | ||
const { FILTER_EQUALITY } = require('../protocol'); | ||
class EqualityFilter extends parents.EqualityFilter { | ||
module.exports = class EqualityFilter extends parents.EqualityFilter { | ||
matches(target, strictAttrCase) { | ||
@@ -33,14 +33,12 @@ assert.object(target, 'target'); | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_EQUALITY); | ||
ber.writeString(this.attribute); | ||
ber.writeBuffer(this.raw, OctetString); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(EqualityFilter); | ||
module.exports = EqualityFilter; | ||
}; |
@@ -1,6 +0,7 @@ | ||
const assert = require('assert'); | ||
const assert = require('assert-plus'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_EXT } = require('../protocol'); | ||
class ExtensibleFilter extends parents.ExtensibleFilter { | ||
module.exports = class ExtensibleFilter extends parents.ExtensibleFilter { | ||
parse(ber) { | ||
@@ -24,3 +25,3 @@ const end = ber.offset + ber.length; | ||
default: | ||
throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16)); | ||
throw new Error(`Invalid ext_match filter type: 0x${tag.toString(16)}`); | ||
} | ||
@@ -32,5 +33,7 @@ } | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_EXT); | ||
if (this.rule) { | ||
@@ -50,8 +53,6 @@ ber.writeString(this.rule, 0x81); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(ExtensibleFilter); | ||
module.exports = ExtensibleFilter; | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_GE } = require('../protocol'); | ||
class GreaterThanEqualsFilter extends parents.GreaterThanEqualsFilter { | ||
module.exports = class GreaterThanEqualsFilter extends parents.GreaterThanEqualsFilter { | ||
parse(ber) { | ||
@@ -15,14 +16,12 @@ assert.ok(ber); | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_GE); | ||
ber.writeString(this.attribute); | ||
ber.writeString(this.value); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(GreaterThanEqualsFilter); | ||
module.exports = GreaterThanEqualsFilter; | ||
}; |
const assert = require('assert-plus'); | ||
const { BerReader } = require('asn1'); | ||
const parents = require('ldap-filter'); | ||
const ldapFilter = require('ldap-filter'); | ||
const Protocol = require('../protocol'); | ||
const Filter = require('./filter'); | ||
const AndFilter = require('./and_filter'); | ||
@@ -17,12 +16,16 @@ const ApproximateFilter = require('./approx_filter'); | ||
const parseSet = ber => { | ||
const filters = []; | ||
const end = ber.offset + ber.length; | ||
while (ber.offset < end) { | ||
filters.push(_parse(ber)); | ||
} | ||
return filters; | ||
}; | ||
const _parse = ber => { | ||
assert.ok(ber); | ||
assert.ok(ber instanceof BerReader, 'ber (BerReader) required'); | ||
const parseSet = f => { | ||
const end = ber.offset + ber.length; | ||
while (ber.offset < end) { | ||
f.addFilter(_parse(ber)); | ||
} | ||
}; | ||
let f; | ||
@@ -33,4 +36,3 @@ | ||
case Protocol.FILTER_AND: | ||
f = new AndFilter(); | ||
parseSet(f); | ||
f = new AndFilter({ filters: parseSet(ber) }); | ||
break; | ||
@@ -46,3 +48,3 @@ | ||
f.parse(ber); | ||
return f; | ||
break; | ||
@@ -52,3 +54,3 @@ case Protocol.FILTER_EXT: | ||
f.parse(ber); | ||
return f; | ||
break; | ||
@@ -58,3 +60,3 @@ case Protocol.FILTER_GE: | ||
f.parse(ber); | ||
return f; | ||
break; | ||
@@ -64,13 +66,10 @@ case Protocol.FILTER_LE: | ||
f.parse(ber); | ||
return f; | ||
break; | ||
case Protocol.FILTER_NOT: | ||
f = new NotFilter({ | ||
filter: _parse(ber) | ||
}); | ||
f = new NotFilter({ filter: _parse(ber) }); | ||
break; | ||
case Protocol.FILTER_OR: | ||
f = new OrFilter(); | ||
parseSet(f); | ||
f = new OrFilter({ filters: parseSet(ber) }); | ||
break; | ||
@@ -89,7 +88,5 @@ | ||
default: | ||
throw new Error('Invalid search filter type: 0x' + type.toString(16)); | ||
throw new Error(`Invalid search filter type: 0x${type.toString(16)}`); | ||
} | ||
assert.ok(f); | ||
return f; | ||
@@ -99,15 +96,9 @@ }; | ||
const cloneFilter = input => { | ||
let child; | ||
if (input.type === 'and' || input.type === 'or') { | ||
child = input.filters.map(cloneFilter); | ||
} else if (input.type === 'not') { | ||
child = cloneFilter(input.filter); | ||
} | ||
switch (input.type) { | ||
case 'and': | ||
return new AndFilter({ filters: child }); | ||
return new AndFilter({ filters: input.filters.map(cloneFilter) }); | ||
case 'or': | ||
return new OrFilter({ filters: child }); | ||
return new OrFilter({ filters: input.filters.map(cloneFilter) }); | ||
case 'not': | ||
return new NotFilter({ filter: child }); | ||
return new NotFilter({ filter: cloneFilter(input.filter) }); | ||
case 'equal': | ||
@@ -128,3 +119,3 @@ return new EqualityFilter(input); | ||
default: | ||
throw new Error('invalid filter type:' + input.type); | ||
throw new Error(`invalid filter type: ${input.type}`); | ||
} | ||
@@ -134,13 +125,5 @@ }; | ||
module.exports = { | ||
parse(ber) { | ||
assert.ok(ber instanceof BerReader, 'ber (BerReader) required'); | ||
return _parse(ber); | ||
}, | ||
parseString(str) { | ||
return cloneFilter(parents.parse(str)); | ||
}, | ||
isFilter: Filter.isFilter, | ||
parse: ber => _parse(ber), | ||
parseString: str => cloneFilter(ldapFilter.parse(str)), | ||
PresenceFilter | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_LE } = require('../protocol'); | ||
class LessThanEqualsFilter extends parents.LessThanEqualsFilter { | ||
module.exports = class LessThanEqualsFilter extends parents.LessThanEqualsFilter { | ||
parse(ber) { | ||
@@ -15,14 +16,12 @@ assert.ok(ber); | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_LE); | ||
ber.writeString(this.attribute); | ||
ber.writeString(this.value); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(LessThanEqualsFilter); | ||
module.exports = LessThanEqualsFilter; | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_NOT } = require('../protocol'); | ||
class NotFilter extends parents.NotFilter { | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
return this.filter.toBer(ber); | ||
} | ||
} | ||
module.exports = class NotFilter extends parents.NotFilter { | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
Filter.mixin(NotFilter); | ||
ber.startSequence(FILTER_NOT); | ||
ber = this.filter.toBer(ber); | ||
ber.endSequence(); | ||
module.exports = NotFilter; | ||
return ber; | ||
} | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_OR } = require('../protocol'); | ||
class OrFilter extends parents.OrFilter { | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
return this.filters.reduce((ber, f) => f.toBer(ber), ber); | ||
} | ||
} | ||
module.exports = class OrFilter extends parents.OrFilter { | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
Filter.mixin(OrFilter); | ||
ber.startSequence(FILTER_OR); | ||
ber = this.filters.reduce((ber, f) => f.toBer(ber), ber); | ||
ber.endSequence(); | ||
module.exports = OrFilter; | ||
return ber; | ||
} | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_PRESENT } = require('../protocol'); | ||
class PresenceFilter extends parents.PresenceFilter { | ||
module.exports = class PresenceFilter extends parents.PresenceFilter { | ||
parse(ber) { | ||
@@ -10,3 +11,2 @@ assert.ok(ber); | ||
this.attribute = ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase(); | ||
ber._offset += ber.length; | ||
@@ -17,15 +17,11 @@ | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
for (let i = 0; i < this.attribute.length; ++i) { | ||
ber.writeByte(this.attribute.charCodeAt(i)); | ||
} | ||
ber.startSequence(FILTER_PRESENT); | ||
new Buffer(this.attribute).forEach(i => ber.writeByte(i)); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(PresenceFilter); | ||
module.exports = PresenceFilter; | ||
}; |
const assert = require('assert'); | ||
const parents = require('ldap-filter'); | ||
const Filter = require('./filter'); | ||
const { BerWriter } = require('asn1'); | ||
const { FILTER_SUBSTRINGS } = require('../protocol'); | ||
class SubstringFilter extends parents.SubstringFilter { | ||
module.exports = class SubstringFilter extends parents.SubstringFilter { | ||
parse(ber) { | ||
@@ -26,3 +27,3 @@ assert.ok(ber); | ||
default: | ||
throw new Error('Invalid substrings filter type: 0x' + tag.toString(16)); | ||
throw new Error(`Invalid substrings filter type: 0x${tag.toString(16)}`); | ||
} | ||
@@ -34,5 +35,6 @@ } | ||
_toBer(ber) { | ||
assert.ok(ber); | ||
toBer(ber) { | ||
assert.ok(ber instanceof BerWriter, 'ber (BerWriter) required'); | ||
ber.startSequence(FILTER_SUBSTRINGS); | ||
ber.writeString(this.attribute); | ||
@@ -45,4 +47,5 @@ ber.startSequence(); | ||
if (this.any && this.any.length) | ||
if (this.any && this.any.length) { | ||
this.any.forEach(s => ber.writeString(s, 0x81)); | ||
} | ||
@@ -54,9 +57,6 @@ if (this.final) { | ||
ber.endSequence(); | ||
ber.endSequence(); | ||
return ber; | ||
} | ||
} | ||
Filter.mixin(SubstringFilter); | ||
module.exports = SubstringFilter; | ||
}; |
@@ -14,21 +14,2 @@ const net = require('net'); | ||
const changeFromObject = change => { | ||
assert.ok(change.operation || change.type, 'change.operation required'); | ||
assert.object(change.modification, 'change.modification'); | ||
if (Object.keys(change.modification).length == 2 && typeof change.modification.type === 'string' && Array.isArray(change.modification.vals)) { | ||
return [new Change({ | ||
operation: change.operation || change.type, | ||
modification: change.modification | ||
})]; | ||
} else { | ||
return Object.keys(change.modification).map(k => new Change({ | ||
operation: change.operation || change.type, | ||
modification: { | ||
[k]: change.modification[k] | ||
} | ||
})); | ||
} | ||
}; | ||
class Client { | ||
@@ -55,3 +36,3 @@ constructor(options) { | ||
} else { | ||
const { resolve, reject, result } = this._queue.get(msg.id); | ||
const { resolve, reject, result, type } = this._queue.get(msg.id); | ||
@@ -63,3 +44,3 @@ if (msg instanceof LDAPResult) { | ||
resolve(result || msg.object); | ||
resolve(type === 'SearchRequest' ? result || [] : msg.object); | ||
} else if (msg instanceof Error) { | ||
@@ -80,15 +61,3 @@ reject(msg); | ||
attributes = Object.keys(attributes).map(k => { | ||
const attr = new Attribute({ type: k }); | ||
if (Array.isArray(attributes[k])) { | ||
attributes[k].forEach(v => attr.addValue(v.toString())); | ||
} else { | ||
attr.addValue(attributes[k].toString()); | ||
} | ||
return attr; | ||
}); | ||
return this._send(new AddRequest({ entry, attributes })); | ||
return this._send(new AddRequest({ entry, attributes: Attribute.fromObject(attributes) })); | ||
} | ||
@@ -105,2 +74,3 @@ | ||
assert.string(entry, 'entry'); | ||
return this._send(new DeleteRequest({ entry })); | ||
@@ -116,9 +86,3 @@ } | ||
const changes = []; | ||
change.forEach(c => { | ||
if (Change.isChange(c)) { | ||
changes.push(c); | ||
} else { | ||
changes.push(...changeFromObject(c)); | ||
} | ||
}); | ||
change.forEach(c => changes.push(...Change.fromObject(c))); | ||
@@ -135,3 +99,3 @@ return this._send(new ModifyRequest({ object, changes })); | ||
if (newDN.length !== 1) { | ||
if (newDN.rdns.length !== 1) { | ||
req.newRdn = dn.parse(newDN.rdns.shift().toString()); | ||
@@ -149,21 +113,9 @@ req.newSuperior = newDN; | ||
assert.object(options, 'options'); | ||
assert.optionalString(options.filter, 'options.filter'); | ||
assert.optionalArrayOfString(options.attributes, 'options.attributes'); | ||
options.filter = options.filter || '(objectclass=*)'; | ||
assert.string(options.filter, 'options.filter'); | ||
options.filter = parseString(options.filter); | ||
if (options.attributes) { | ||
if (typeof (options.attributes) === 'string') { | ||
options.attributes = [options.attributes]; | ||
} | ||
assert.arrayOfString(options.attributes, 'options.attributes'); | ||
} | ||
return this._send(new SearchRequest({ | ||
baseObject, | ||
scope: options.scope || 'base', | ||
filter: options.filter, | ||
filter: parseString(options.filter || '(objectclass=*)'), | ||
derefAliases: options.derefAliases || NEVER_DEREF_ALIASES, | ||
@@ -242,6 +194,7 @@ sizeLimit: options.sizeLimit || 0, | ||
try { | ||
this._queue.set(message.id, { resolve, reject }); | ||
this._queue.set(message.id, { resolve, reject, type: message.type }); | ||
this._socket.write(message.toBer()); | ||
if (message.type === 'UnbindRequest') { | ||
this._queue.delete(message.id); | ||
resolve(new UnbindResponse({ messageID: message.id })); | ||
@@ -248,0 +201,0 @@ } else if (this.timeout) { |
@@ -5,3 +5,3 @@ const assert = require('assert-plus'); | ||
const { LDAP_REQ_ADD } = require('../protocol'); | ||
const lassert = require('../assert'); | ||
const lassert = require('../utils/assert'); | ||
@@ -62,43 +62,2 @@ module.exports = class AddRequest extends LDAPMessage { | ||
} | ||
indexOf(attr) { | ||
assert.string(attr, 'attr'); | ||
return this.attributes.findIndex(i => i.type === attr); | ||
} | ||
attributeNames() { | ||
return this.attributes.map(i => i.type.toLowerCase()); | ||
} | ||
getAttribute(name) { | ||
assert.string(name, 'attribute name'); | ||
return this.attributes.find(i => i.type === name.toLowerCase()) || null; | ||
} | ||
addAttribute(attr) { | ||
assert.ok(attr instanceof Attribute, 'attribute (Attribute) required'); | ||
return this.attributes.push(attr); | ||
} | ||
toObject() { | ||
const obj = { | ||
dn: this.entry ? this.entry.toString() : '', | ||
attributes: {} | ||
}; | ||
if (!this.attributes || !this.attributes.length) | ||
return obj; | ||
this.attributes.forEach(a => { | ||
if (!obj.attributes[a.type]) | ||
obj.attributes[a.type] = []; | ||
a.vals.forEach(v => { | ||
if (obj.attributes[a.type].indexOf(v) === -1) | ||
obj.attributes[a.type].push(v); | ||
}); | ||
}); | ||
return obj; | ||
} | ||
}; |
const assert = require('assert-plus'); | ||
const LDAPMessage = require('./message'); | ||
const { LDAP_REQ_DELETE } = require('../protocol'); | ||
const lassert = require('../assert'); | ||
const lassert = require('../utils/assert'); | ||
@@ -38,5 +38,3 @@ module.exports = class DeleteRequest extends LDAPMessage { | ||
const buf = new Buffer(this.entry.toString()); | ||
for (let i = 0; i < buf.length; ++i) | ||
ber.writeByte(buf[i]); | ||
new Buffer(this.entry.toString()).forEach(i => ber.writeByte(i)); | ||
@@ -43,0 +41,0 @@ return ber; |
@@ -5,3 +5,3 @@ const assert = require('assert-plus'); | ||
const dn = require('../dn'); | ||
const lassert = require('../assert'); | ||
const lassert = require('../utils/assert'); | ||
@@ -8,0 +8,0 @@ module.exports = class ModifyDNRequest extends LDAPMessage { |
@@ -5,3 +5,3 @@ const assert = require('assert-plus'); | ||
const { LDAP_REQ_MODIFY } = require('../protocol'); | ||
const lassert = require('../assert'); | ||
const lassert = require('../utils/assert'); | ||
@@ -8,0 +8,0 @@ module.exports = class ModifyRequest extends LDAPMessage { |
@@ -5,3 +5,3 @@ const assert = require('assert-plus'); | ||
const { LDAP_REP_SEARCH_ENTRY } = require('../protocol'); | ||
const lassert = require('../assert'); | ||
const lassert = require('../utils/assert'); | ||
@@ -18,3 +18,3 @@ module.exports = class SearchEntry extends LDAPMessage { | ||
this.objectName = options.objectName || null; | ||
this.setAttributes(options.attributes || []); | ||
this._setAttributes(options.attributes || []); | ||
} | ||
@@ -44,38 +44,3 @@ | ||
get raw() { | ||
const obj = { | ||
dn: this.dn.toString() | ||
}; | ||
this.attributes.forEach(a => { | ||
if (a.buffers && a.buffers.length) { | ||
obj[a.type] = a.buffers.length > 1 ? a.buffers.slice() : a.buffers[0]; | ||
} else { | ||
obj[a.type] = []; | ||
} | ||
}); | ||
return obj; | ||
} | ||
addAttribute(attr) { | ||
assert.object(attr, 'attr'); | ||
this.attributes.push(attr); | ||
} | ||
toObject() { | ||
return this.object; | ||
} | ||
fromObject(obj) { | ||
assert.object(obj); | ||
obj = obj.attributes || obj; | ||
this.attributes = Object.keys(obj).map(type => new Attribute({ type, vals: obj[type] })); | ||
return true; | ||
} | ||
setAttributes(obj) { | ||
assert.object(obj); | ||
_setAttributes(obj) { | ||
if (Array.isArray(obj)) { | ||
@@ -82,0 +47,0 @@ if (obj.some(a => !Attribute.isAttribute(a))) { |
@@ -19,3 +19,3 @@ const assert = require('assert-plus'); | ||
get _dn() { | ||
return new DN(''); | ||
return new DN(); | ||
} | ||
@@ -40,14 +40,2 @@ | ||
toObject() { | ||
return this.object; | ||
} | ||
fromObject(obj) { | ||
assert.object(obj); | ||
this.uris = obj.uris ? obj.uris.slice() : []; | ||
return true; | ||
} | ||
_parse(ber, length) { | ||
@@ -54,0 +42,0 @@ assert.ok(ber); |
@@ -5,3 +5,3 @@ const assert = require('assert-plus'); | ||
const dn = require('../dn'); | ||
const filters = require('../filters'); | ||
const { parse, PresenceFilter } = require('../filters'); | ||
const { LDAP_REQ_SEARCH, NEVER_DEREF_ALIASES, SCOPE_BASE_OBJECT, SCOPE_ONE_LEVEL, SCOPE_SUBTREE } = require('../protocol'); | ||
@@ -37,3 +37,3 @@ | ||
default: | ||
throw new Error(this._scope + ' is an invalid search scope'); | ||
throw new Error(`${this._scope} is an invalid search scope`); | ||
} | ||
@@ -55,3 +55,3 @@ } | ||
default: | ||
throw new Error(val + ' is an invalid search scope'); | ||
throw new Error(`${val} is an invalid search scope`); | ||
} | ||
@@ -73,3 +73,3 @@ } else { | ||
this.filter = filters.parse(ber); | ||
this.filter = parse(ber); | ||
@@ -96,3 +96,3 @@ if (ber.peek() === 0x30) { | ||
const f = this.filter || new filters.PresenceFilter({ attribute: 'objectclass' }); | ||
const f = this.filter || new PresenceFilter({ attribute: 'objectclass' }); | ||
ber = f.toBer(ber); | ||
@@ -99,0 +99,0 @@ |
@@ -1,7 +0,2 @@ | ||
const assert = require('assert-plus'); | ||
const LDAPResult = require('./result'); | ||
const SearchEntry = require('./search_entry'); | ||
const SearchReference = require('./search_reference'); | ||
const parseDN = require('../dn').parse; | ||
const parseURL = require('../utils/parse-url'); | ||
const { LDAP_REP_SEARCH } = require('../protocol'); | ||
@@ -11,85 +6,4 @@ | ||
constructor(options) { | ||
super(Object.assign({}, options, { protocolOp: LDAP_REP_SEARCH })); | ||
this.attributes = options.attributes ? options.attributes.slice() : []; | ||
this.notAttributes = []; | ||
this.sentEntries = 0; | ||
super(Object.assign({ attributes : [] }, options, { protocolOp: LDAP_REP_SEARCH })); | ||
} | ||
send(entry, nofiltering = false) { | ||
assert.object(entry, 'entry'); | ||
assert.bool(nofiltering, 'nofiltering'); | ||
const savedAttrs = {}; | ||
const save = entry; | ||
if (entry instanceof SearchEntry || entry instanceof SearchReference) { | ||
if (!entry.messageID) | ||
entry.messageID = this.messageID; | ||
assert.ok(entry.messageID === this.messageID, 'SearchEntry messageID mismatch'); | ||
} else { | ||
assert.ok(entry.attributes, 'entry.attributes required'); | ||
const all = (this.attributes.indexOf('*') !== -1); | ||
Object.keys(entry.attributes).forEach(a => { | ||
const _a = a.toLowerCase(); | ||
if (!nofiltering && _a.length && _a[0] === '_') { | ||
savedAttrs[a] = entry.attributes[a]; | ||
delete entry.attributes[a]; | ||
} else if (!nofiltering && this.notAttributes.indexOf(_a) !== -1) { | ||
savedAttrs[a] = entry.attributes[a]; | ||
delete entry.attributes[a]; | ||
} else if (all) { | ||
return; | ||
} else if (this.attributes.length && this.attributes.indexOf(_a) === -1) { | ||
savedAttrs[a] = entry.attributes[a]; | ||
delete entry.attributes[a]; | ||
} | ||
}); | ||
entry = new SearchEntry({ | ||
objectName: typeof (save.dn) === 'string' ? parseDN(save.dn) : save.dn, | ||
messageID: this.messageID | ||
}); | ||
entry.fromObject(save); | ||
} | ||
try { | ||
this.connection.write(entry.toBer()); | ||
this.sentEntries++; | ||
// Restore attributes | ||
Object.keys(savedAttrs || {}).forEach(k => { | ||
save.attributes[k] = savedAttrs[k]; | ||
}); | ||
} catch (e) { | ||
console.warn(e, '%s failure to write message %j', this.connection.ldap.id, this.type); | ||
} | ||
} | ||
createSearchEntry(object) { | ||
assert.object(object); | ||
const entry = new SearchEntry({ | ||
messageID: this.messageID, | ||
objectName: object.objectName || object.dn | ||
}); | ||
entry.fromObject((object.attributes || object)); | ||
return entry; | ||
} | ||
createSearchReference(uris) { | ||
assert.ok(uris, 'uris ([string]) required'); | ||
if (!Array.isArray(uris)) | ||
uris = [uris]; | ||
for (let i = 0; i < uris.length; ++i) { | ||
if (typeof (uris[i]) == 'string') | ||
uris[i] = parseURL(uris[i]); | ||
} | ||
return new SearchReference({ messageID: this.messageID, uris }); | ||
} | ||
}; |
@@ -7,6 +7,2 @@ const LDAPResult = require('./result'); | ||
} | ||
get type() { | ||
return 'UnbindResponse'; | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
65366
46
1930