Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from ldapjs/next
Browse files Browse the repository at this point in the history
Changes and fixes for `ldapjs@3`
  • Loading branch information
jsumners authored Feb 22, 2023
2 parents b5a65cb + 298e9e3 commit 9718b85
Show file tree
Hide file tree
Showing 18 changed files with 275 additions and 242 deletions.
7 changes: 0 additions & 7 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ This package provides implementations of [LDAP controls][controls]. The
primary purpose of this library is to facilitate client and server
implementations in the [`ldapjs`](https://npm.im/ldapjs) package.

## Note About API Stability

As of June 2022, this module provides an API that was directly copied from
the original code in the `ldapjs` module. This API is marked as v1.0.0. The
API is subject to drastic change in future semver major releases. The v1 release
was published as foundational work in the overall `ldapjs` project.

## Docs

At this time, one must reference the code to learn about the available
Expand Down
17 changes: 8 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
'use strict'

const { Ber } = require('@ldapjs/asn1')

const Control = require('./lib/control')
const {
EntryChangeNotificationControl,
PagedResultsControl,
PersistentSearchControl,
ServerSideSortingRequestControl,
ServerSideSortingResponseControl,
VirtualListViewRequestControl,
VirtualListViewResponseControl
} = require('./lib/controls')
const EntryChangeNotificationControl = require('./lib/controls/entry-change-notification-control')
const PagedResultsControl = require('./lib/controls/paged-results-control')
const PersistentSearchControl = require('./lib/controls/persistent-search-control')
const ServerSideSortingRequestControl = require('./lib/controls/server-side-sorting-request-control')
const ServerSideSortingResponseControl = require('./lib/controls/server-side-sorting-response-control')
const VirtualListViewRequestControl = require('./lib/controls/virtual-list-view-request-control')
const VirtualListViewResponseControl = require('./lib/controls/virtual-list-view-response-control')

module.exports = {

Expand Down
43 changes: 26 additions & 17 deletions lib/control.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,51 @@ const { BerWriter } = require('@ldapjs/asn1')
*/
class Control {
/**
* Create a new baseline LDAP control.
*
* @param {object} [options]
* @param {string} [options.type=''] The dotted decimal control type value.
* @param {boolean} [options.criticality=false] Criticality value for the control.
* @param {string|Buffer} [options.value] The value for the control. If this is
* @typedef {object} ControlParams
* @property {string} [type=''] The dotted decimal control type value.
* @property {boolean} [criticality=false] Criticality value for the control.
* @property {string|Buffer} [value] The value for the control. If this is
* a `string` then it will be written as-is. If it is an instance of `Buffer`
* then it will be written by `value.toString()` when generating a BER
* instance.
*/

/**
* Create a new baseline LDAP control.
*
* @param {ControlParams} [options]
*/
constructor (options = {}) {
const opts = Object.assign({ type: '', criticality: false, value: null }, options)
this.type = opts.type
this.criticality = opts.criticality
this.value = opts.value
}

get [Symbol.toStringTag] () {
return 'LdapControl'
}

/**
* Serializes the control instance into an LDAP style control object, e.g.
* `type` => `controlType`. If an instance has a `_updatePlainObject(obj)`
* Serializes the control into a plain JavaScript object that can be passed
* to the constructor as an options object. If an instance has a `_pojo(obj)`
* method then the built object will be sent to that method and the resulting
* mutated object returned.
*
* @returns {object} A plain JavaScript object that represents an LDAP control.
*/
get plainObject () {
get pojo () {
const obj = {
controlType: this.type,
criticality: this.criticality,
controlValue: this.value
type: this.type,
value: this.value,
criticality: this.criticality
}
return (
typeof (this._updatePlainObject) === 'function'
? this._updatePlainObject(obj)
: obj
)

if (typeof this._pojo === 'function') {
this._pojo(obj)
}

return obj
}

/**
Expand Down
58 changes: 31 additions & 27 deletions lib/control.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ const tap = require('tap')
const { BerWriter } = require('@ldapjs/asn1')
const Control = require('./control')

tap.test('contructor', t => {
tap.test('constructor', t => {
t.test('new no args', function (t) {
t.ok(new Control())
t.equal(Object.prototype.toString.call(new Control()), '[object LdapControl]')
t.end()
})

Expand All @@ -24,7 +25,35 @@ tap.test('contructor', t => {
t.end()
})

tap.test('#toBer', t => {
tap.test('pojo', t => {
t.test('passes through _pojo', async t => {
class Foo extends Control {
_pojo (obj) {
obj.foo = 'foo'
}
}
const control = new Foo()
t.strictSame(control.pojo, {
type: '',
value: null,
criticality: false,
foo: 'foo'
})
})

t.test('returns basic object', async t => {
const control = new Control({ type: '1.2.3', criticality: false, value: 'foo' })
t.strictSame(control.pojo, {
type: '1.2.3',
value: 'foo',
criticality: false
})
})

t.end()
})

tap.test('toBer', t => {
t.test('converts empty instance to BER', async t => {
const target = new BerWriter()
target.startSequence()
Expand Down Expand Up @@ -128,28 +157,3 @@ tap.test('#toBer', t => {

t.end()
})

tap.test('#plainObject', t => {
t.test('passes through _updatePlainObject', async t => {
t.plan(2)
const control = new Control()
control._updatePlainObject = () => {
t.pass()
return 'foo'
}
const str = control.plainObject
t.equal(str, 'foo')
})

t.test('returns basic object', async t => {
const control = new Control({ type: '1.2.3', criticality: false, value: 'foo' })
const str = control.plainObject
t.same(str, {
controlType: '1.2.3',
criticality: false,
controlValue: 'foo'
})
})

t.end()
})
8 changes: 6 additions & 2 deletions lib/controls/entry-change-notification-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ const Control = require('../control')
class EntryChangeNotificationControl extends Control {
static OID = '2.16.840.1.113730.3.4.7'

/**
* @typedef {ControlParams} EntryChangeNotificationParams
* @property {EntryChangeNotificationControlValue | Buffer} [value]
*/

/**
* Creates a new persistent search control.
*
* @param {object} [options]
* @param {EntryChangeNotificationControlValue | Buffer} [options.value]
* @param {EntryChangeNotificationParams} [options]
*/
constructor (options = {}) {
options.type = EntryChangeNotificationControl.OID
Expand Down
49 changes: 24 additions & 25 deletions lib/controls/entry-change-notification-control.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,30 @@ tap.test('contructor', t => {
t.end()
})

tap.test('#toBer', t => {
tap.test('pojo', t => {
t.test('adds control value', async t => {
const control = new ECNC({
value: {
changeType: 8,
previousDN: 'dn=foo',
changeNumber: 42
}
})
t.strictSame(control.pojo, {
type: ECNC.OID,
criticality: false,
value: {
changeType: 8,
previousDN: 'dn=foo',
changeNumber: 42
}
})
})

t.end()
})

tap.test('toBer', t => {
t.test('converts empty instance to BER', async t => {
const target = new BerWriter()
target.startSequence()
Expand Down Expand Up @@ -108,27 +131,3 @@ tap.test('#toBer', t => {

t.end()
})

tap.test('#plainObject', t => {
t.test('adds control value', async t => {
const control = new ECNC({
value: {
changeType: 8,
previousDN: 'dn=foo',
changeNumber: 42
}
})
const value = control.plainObject
t.same(value, {
controlType: ECNC.OID,
criticality: false,
controlValue: {
changeType: 8,
previousDN: 'dn=foo',
changeNumber: 42
}
})
})

t.end()
})
16 changes: 0 additions & 16 deletions lib/controls/index.js

This file was deleted.

8 changes: 6 additions & 2 deletions lib/controls/paged-results-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ const Control = require('../control')
class PagedResultsControl extends Control {
static OID = '1.2.840.113556.1.4.319'

/**
* @typedef {ControlParams} PagedResultsParams
* @property {PagedResultsControlValue | Buffer} [value]
*/

/**
* Creates a new paged results control.
*
* @param {object} [options]
* @param {PagedResultsControlValue | Buffer} [options.value]
* @param {PagedResultsParams} [options]
*/
constructor (options = {}) {
options.type = PagedResultsControl.OID
Expand Down
45 changes: 22 additions & 23 deletions lib/controls/paged-results-control.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,28 @@ tap.test('contructor', t => {
t.end()
})

tap.test('#toBer', t => {
tap.test('pojo', t => {
t.test('adds control value', async t => {
const control = new PSC({
value: {
size: 1,
cookie: 'foo'
}
})
t.same(control.pojo, {
type: PSC.OID,
criticality: false,
value: {
size: 1,
cookie: Buffer.from('foo')
}
})
})

t.end()
})

tap.test('toBer', t => {
t.test('converts empty instance to BER', async t => {
const target = new BerWriter()
target.startSequence()
Expand Down Expand Up @@ -116,25 +137,3 @@ tap.test('#toBer', t => {

t.end()
})

tap.test('#plainObject', t => {
t.test('adds control value', async t => {
const control = new PSC({
value: {
size: 1,
cookie: 'foo'
}
})
const value = control.plainObject
t.same(value, {
controlType: PSC.OID,
criticality: false,
controlValue: {
size: 1,
cookie: Buffer.from('foo')
}
})
})

t.end()
})
8 changes: 6 additions & 2 deletions lib/controls/persistent-search-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ const Control = require('../control')
class PersistentSearchControl extends Control {
static OID = '2.16.840.1.113730.3.4.3'

/**
* @typedef {ControlParams} PersistentSearchParams
* @property {PersistentSearchControlValue | Buffer} [value]
*/

/**
* Creates a new persistent search control.
*
* @param {object} [options]
* @param {PersistentSearchControlValue | Buffer} [options.value]
* @param {PersistentSearchParams} [options]
*/
constructor (options = {}) {
options.type = PersistentSearchControl.OID
Expand Down
Loading

0 comments on commit 9718b85

Please sign in to comment.