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

Changes and fixes for ldapjs@3 #2

Merged
merged 5 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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