Virtual List View control support
This commit is contained in:
parent
d6f58e6487
commit
311c94ef15
|
@ -12,6 +12,10 @@ var ServerSideSortingRequestControl =
|
||||||
require('./server_side_sorting_request_control.js')
|
require('./server_side_sorting_request_control.js')
|
||||||
var ServerSideSortingResponseControl =
|
var ServerSideSortingResponseControl =
|
||||||
require('./server_side_sorting_response_control.js')
|
require('./server_side_sorting_response_control.js')
|
||||||
|
var VirtualListViewRequestControl =
|
||||||
|
require('./virtual_list_view_request_control.js')
|
||||||
|
var VirtualListViewResponseControl =
|
||||||
|
require('./virtual_list_view_response_control.js')
|
||||||
|
|
||||||
/// --- API
|
/// --- API
|
||||||
|
|
||||||
|
@ -56,6 +60,12 @@ module.exports = {
|
||||||
case ServerSideSortingResponseControl.OID:
|
case ServerSideSortingResponseControl.OID:
|
||||||
control = new ServerSideSortingResponseControl(opts)
|
control = new ServerSideSortingResponseControl(opts)
|
||||||
break
|
break
|
||||||
|
case VirtualListViewRequestControl.OID:
|
||||||
|
control = new VirtualListViewRequestControl(opts)
|
||||||
|
break
|
||||||
|
case VirtualListViewResponseControl.OID:
|
||||||
|
control = new VirtualListViewResponseControl(opts)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
opts.type = type
|
opts.type = type
|
||||||
control = new Control(opts)
|
control = new Control(opts)
|
||||||
|
@ -70,5 +80,7 @@ module.exports = {
|
||||||
PagedResultsControl: PagedResultsControl,
|
PagedResultsControl: PagedResultsControl,
|
||||||
PersistentSearchControl: PersistentSearchControl,
|
PersistentSearchControl: PersistentSearchControl,
|
||||||
ServerSideSortingRequestControl: ServerSideSortingRequestControl,
|
ServerSideSortingRequestControl: ServerSideSortingRequestControl,
|
||||||
ServerSideSortingResponseControl: ServerSideSortingResponseControl
|
ServerSideSortingResponseControl: ServerSideSortingResponseControl,
|
||||||
|
VirtualListViewRequestControl: VirtualListViewRequestControl,
|
||||||
|
VirtualListViewResponseControl: VirtualListViewResponseControl
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
var assert = require('assert-plus')
|
||||||
|
var util = require('util')
|
||||||
|
|
||||||
|
var asn1 = require('asn1')
|
||||||
|
|
||||||
|
var Control = require('./control')
|
||||||
|
|
||||||
|
/// --- Globals
|
||||||
|
|
||||||
|
var BerReader = asn1.BerReader
|
||||||
|
var BerWriter = asn1.BerWriter
|
||||||
|
|
||||||
|
/// --- API
|
||||||
|
|
||||||
|
function VirtualListViewControl (options) {
|
||||||
|
assert.optionalObject(options)
|
||||||
|
options = options || {}
|
||||||
|
options.type = VirtualListViewControl.OID
|
||||||
|
if (options.value) {
|
||||||
|
if (Buffer.isBuffer(options.value)) {
|
||||||
|
this.parse(options.value)
|
||||||
|
} else if (typeof (options.value) === 'object') {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(options.value, 'beforeCount') === false) {
|
||||||
|
throw new Error('Missing required key: beforeCount')
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(options.value, 'afterCount') === false) {
|
||||||
|
throw new Error('Missing required key: afterCount')
|
||||||
|
}
|
||||||
|
this._value = options.value
|
||||||
|
} else {
|
||||||
|
throw new TypeError('options.value must be a Buffer or Object')
|
||||||
|
}
|
||||||
|
options.value = null
|
||||||
|
}
|
||||||
|
Control.call(this, options)
|
||||||
|
}
|
||||||
|
util.inherits(VirtualListViewControl, Control)
|
||||||
|
Object.defineProperties(VirtualListViewControl.prototype, {
|
||||||
|
value: {
|
||||||
|
get: function () { return this._value || [] },
|
||||||
|
configurable: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
VirtualListViewControl.prototype.parse = function parse (buffer) {
|
||||||
|
assert.ok(buffer)
|
||||||
|
var ber = new BerReader(buffer)
|
||||||
|
if (ber.readSequence()) {
|
||||||
|
this._value = {}
|
||||||
|
this._value.beforeCount = ber.readInt()
|
||||||
|
this._value.afterCount = ber.readInt()
|
||||||
|
if (ber.peek() === 0xa0) {
|
||||||
|
if (ber.readSequence(0xa0)) {
|
||||||
|
this._value.targetOffset = ber.readInt()
|
||||||
|
this._value.contentCount = ber.readInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ber.peek() === 0x81) {
|
||||||
|
this._value.greaterThanOrEqual = ber.readString(0x81)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualListViewControl.prototype._toBer = function (ber) {
|
||||||
|
assert.ok(ber)
|
||||||
|
if (!this._value || this.value.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var writer = new BerWriter()
|
||||||
|
writer.startSequence(0x30)
|
||||||
|
writer.writeInt(this.value.beforeCount)
|
||||||
|
writer.writeInt(this.value.afterCount)
|
||||||
|
if (this.value.targetOffset !== undefined) {
|
||||||
|
writer.startSequence(0xa0)
|
||||||
|
writer.writeInt(this.value.targetOffset)
|
||||||
|
writer.writeInt(this.value.contentCount)
|
||||||
|
writer.endSequence()
|
||||||
|
} else if (this.value.greaterThanOrEqual !== undefined) {
|
||||||
|
writer.writeString(this.value.greaterThanOrEqual, 0x81)
|
||||||
|
}
|
||||||
|
writer.endSequence()
|
||||||
|
ber.writeBuffer(writer.buffer, 0x04)
|
||||||
|
}
|
||||||
|
VirtualListViewControl.prototype._json = function (obj) {
|
||||||
|
obj.controlValue = this.value
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
VirtualListViewControl.OID = '2.16.840.1.113730.3.4.9'
|
||||||
|
|
||||||
|
/// ---Exports
|
||||||
|
|
||||||
|
module.exports = VirtualListViewControl
|
|
@ -0,0 +1,112 @@
|
||||||
|
var assert = require('assert-plus')
|
||||||
|
var util = require('util')
|
||||||
|
|
||||||
|
var asn1 = require('asn1')
|
||||||
|
|
||||||
|
var Control = require('./control')
|
||||||
|
var CODES = require('../errors/codes')
|
||||||
|
|
||||||
|
/// --- Globals
|
||||||
|
|
||||||
|
var BerReader = asn1.BerReader
|
||||||
|
var BerWriter = asn1.BerWriter
|
||||||
|
|
||||||
|
var VALID_CODES = [
|
||||||
|
CODES.LDAP_SUCCESS,
|
||||||
|
CODES.LDAP_OPERATIONS_ERROR,
|
||||||
|
CODES.LDAP_UNWILLING_TO_PERFORM,
|
||||||
|
CODES.LDAP_INSUFFICIENT_ACCESS_RIGHTS,
|
||||||
|
CODES.LDAP_BUSY,
|
||||||
|
CODES.LDAP_TIME_LIMIT_EXCEEDED,
|
||||||
|
CODES.LDAP_ADMIN_LIMIT_EXCEEDED,
|
||||||
|
CODES.LDAP_SORT_CONTROL_MISSING,
|
||||||
|
CODES.LDAP_INDEX_RANGE_ERROR,
|
||||||
|
CODES.LDAP_CONTROL_ERROR,
|
||||||
|
CODES.LDAP_OTHER
|
||||||
|
]
|
||||||
|
|
||||||
|
function VirtualListViewResponseControl (options) {
|
||||||
|
assert.optionalObject(options)
|
||||||
|
options = options || {}
|
||||||
|
options.type = VirtualListViewResponseControl.OID
|
||||||
|
options.criticality = false
|
||||||
|
|
||||||
|
if (options.value) {
|
||||||
|
if (Buffer.isBuffer(options.value)) {
|
||||||
|
this.parse(options.value)
|
||||||
|
} else if (typeof (options.value) === 'object') {
|
||||||
|
if (VALID_CODES.indexOf(options.value.result) === -1) {
|
||||||
|
throw new Error('Invalid result code')
|
||||||
|
}
|
||||||
|
this._value = options.value
|
||||||
|
} else {
|
||||||
|
throw new TypeError('options.value must be a Buffer or Object')
|
||||||
|
}
|
||||||
|
options.value = null
|
||||||
|
}
|
||||||
|
Control.call(this, options)
|
||||||
|
}
|
||||||
|
util.inherits(VirtualListViewResponseControl, Control)
|
||||||
|
Object.defineProperties(VirtualListViewResponseControl.prototype, {
|
||||||
|
value: {
|
||||||
|
get: function () { return this._value || {} },
|
||||||
|
configurable: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
VirtualListViewResponseControl.prototype.parse = function parse (buffer) {
|
||||||
|
assert.ok(buffer)
|
||||||
|
var ber = new BerReader(buffer)
|
||||||
|
if (ber.readSequence()) {
|
||||||
|
this._value = {}
|
||||||
|
if (ber.peek(0x02)) {
|
||||||
|
this._value.targetPosition = ber.readInt()
|
||||||
|
}
|
||||||
|
if (ber.peek(0x02)) {
|
||||||
|
this._value.contentCount = ber.readInt()
|
||||||
|
}
|
||||||
|
this._value.result = ber.readEnumeration()
|
||||||
|
this._value.cookie = ber.readString(asn1.Ber.OctetString, true)
|
||||||
|
// readString returns '' instead of a zero-length buffer
|
||||||
|
if (!this._value.cookie) {
|
||||||
|
this._value.cookie = Buffer.alloc(0)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualListViewResponseControl.prototype._toBer = function (ber) {
|
||||||
|
assert.ok(ber)
|
||||||
|
|
||||||
|
if (!this._value || this.value.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = new BerWriter()
|
||||||
|
writer.startSequence()
|
||||||
|
if (this.value.targetPosition !== undefined) {
|
||||||
|
writer.writeInt(this.value.targetPosition)
|
||||||
|
}
|
||||||
|
if (this.value.contentCount !== undefined) {
|
||||||
|
writer.writeInt(this.value.contentCount)
|
||||||
|
}
|
||||||
|
writer.writeEnumeration(this.value.result)
|
||||||
|
if (this.value.cookie && this.value.cookie.length > 0) {
|
||||||
|
writer.writeBuffer(this.value.cookie, asn1.Ber.OctetString)
|
||||||
|
} else {
|
||||||
|
writer.writeString('') // writeBuffer rejects zero-length buffers
|
||||||
|
}
|
||||||
|
writer.endSequence()
|
||||||
|
ber.writeBuffer(writer.buffer, 0x04)
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualListViewResponseControl.prototype._json = function (obj) {
|
||||||
|
obj.controlValue = this.value
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualListViewResponseControl.OID = '2.16.840.1.113730.3.4.10'
|
||||||
|
|
||||||
|
/// --- Exports
|
||||||
|
module.exports = VirtualListViewResponseControl
|
|
@ -32,6 +32,8 @@ module.exports = {
|
||||||
LDAP_UNAVAILABLE: 52,
|
LDAP_UNAVAILABLE: 52,
|
||||||
LDAP_UNWILLING_TO_PERFORM: 53,
|
LDAP_UNWILLING_TO_PERFORM: 53,
|
||||||
LDAP_LOOP_DETECT: 54,
|
LDAP_LOOP_DETECT: 54,
|
||||||
|
LDAP_SORT_CONTROL_MISSING: 60,
|
||||||
|
LDAP_INDEX_RANGE_ERROR: 61,
|
||||||
LDAP_NAMING_VIOLATION: 64,
|
LDAP_NAMING_VIOLATION: 64,
|
||||||
LDAP_OBJECTCLASS_VIOLATION: 65,
|
LDAP_OBJECTCLASS_VIOLATION: 65,
|
||||||
LDAP_NOT_ALLOWED_ON_NON_LEAF: 66,
|
LDAP_NOT_ALLOWED_ON_NON_LEAF: 66,
|
||||||
|
@ -39,6 +41,7 @@ module.exports = {
|
||||||
LDAP_ENTRY_ALREADY_EXISTS: 68,
|
LDAP_ENTRY_ALREADY_EXISTS: 68,
|
||||||
LDAP_OBJECTCLASS_MODS_PROHIBITED: 69,
|
LDAP_OBJECTCLASS_MODS_PROHIBITED: 69,
|
||||||
LDAP_AFFECTS_MULTIPLE_DSAS: 71,
|
LDAP_AFFECTS_MULTIPLE_DSAS: 71,
|
||||||
|
LDAP_CONTROL_ERROR: 76,
|
||||||
LDAP_OTHER: 80,
|
LDAP_OTHER: 80,
|
||||||
LDAP_PROXIED_AUTHORIZATION_DENIED: 123
|
LDAP_PROXIED_AUTHORIZATION_DENIED: 123
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,62 @@ tap.beforeEach((done, t) => {
|
||||||
next(new ldap.UnwillingToPerformError())
|
next(new ldap.UnwillingToPerformError())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
server.search('cn=sssvlv', function (req, res, next) {
|
||||||
|
const min = 0
|
||||||
|
const max = 100
|
||||||
|
const results = []
|
||||||
|
let o = 'aa'
|
||||||
|
for (let i = min; i < max; i++) {
|
||||||
|
results.push({
|
||||||
|
dn: util.format('o=%s, cn=sssvlv', o),
|
||||||
|
attributes: {
|
||||||
|
o: [o],
|
||||||
|
objectclass: ['sssvlvResult']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
o = ((parseInt(o, 36) + 1).toString(36)).replace(/0/g, 'a')
|
||||||
|
}
|
||||||
|
function sendResults (start, end, sortBy, sortDesc) {
|
||||||
|
start = (start < min) ? min : start
|
||||||
|
end = (end > max || end < min) ? max : end
|
||||||
|
const sorted = results.sort((a, b) => {
|
||||||
|
if (a.attributes[sortBy][0] < b.attributes[sortBy][0]) {
|
||||||
|
return sortDesc ? 1 : -1
|
||||||
|
} else if (a.attributes[sortBy][0] > b.attributes[sortBy][0]) {
|
||||||
|
return sortDesc ? -1 : 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
for (let i = start; i < end; i++) {
|
||||||
|
res.send(sorted[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sortBy = null
|
||||||
|
let sortDesc = null
|
||||||
|
let afterCount = null
|
||||||
|
let targetOffset = null
|
||||||
|
req.controls.forEach(function (control) {
|
||||||
|
if (control.type === ldap.ServerSideSortingRequestControl.OID) {
|
||||||
|
sortBy = control.value[0].attributeType
|
||||||
|
sortDesc = control.value[0].reverseOrder
|
||||||
|
}
|
||||||
|
if (control.type === ldap.VirtualListViewRequestControl.OID) {
|
||||||
|
afterCount = control.value.afterCount
|
||||||
|
targetOffset = control.value.targetOffset
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (sortBy) {
|
||||||
|
if (afterCount && targetOffset) {
|
||||||
|
sendResults(targetOffset - 1, (targetOffset + afterCount), sortBy, sortDesc)
|
||||||
|
} else {
|
||||||
|
sendResults(min, max, sortBy, sortDesc)
|
||||||
|
}
|
||||||
|
res.end()
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
next(new ldap.UnwillingToPerformError())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
server.search('cn=pagederr', function (req, res, next) {
|
server.search('cn=pagederr', function (req, res, next) {
|
||||||
let cookie = null
|
let cookie = null
|
||||||
|
@ -738,6 +794,153 @@ tap.test('search paged', { timeout: 10000 }, function (t) {
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tap.test('search - sssvlv', { timeout: 10000 }, function (t) {
|
||||||
|
t.test('ssv - asc', function (t2) {
|
||||||
|
let preventry = null
|
||||||
|
const sssrcontrol = new ldap.ServerSideSortingRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
attributeType: 'o',
|
||||||
|
orderingRule: 'caseIgnoreOrderingMatch',
|
||||||
|
reverseOrder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
t.context.client.search('cn=sssvlv', {}, sssrcontrol, function (err, res) {
|
||||||
|
t2.error(err)
|
||||||
|
res.on('searchEntry', function (entry) {
|
||||||
|
t2.ok(entry)
|
||||||
|
t2.ok(entry instanceof ldap.SearchEntry)
|
||||||
|
t2.ok(entry.attributes)
|
||||||
|
t2.ok(entry.attributes.length)
|
||||||
|
if (preventry != null) {
|
||||||
|
t2.ok(entry.attributes[0]._vals[0] >= preventry.attributes[0]._vals[0])
|
||||||
|
}
|
||||||
|
preventry = entry
|
||||||
|
})
|
||||||
|
res.on('error', (err) => t2.error(err))
|
||||||
|
res.on('end', function () {
|
||||||
|
t2.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.test('ssv - desc', function (t2) {
|
||||||
|
let preventry = null
|
||||||
|
const sssrcontrol = new ldap.ServerSideSortingRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
attributeType: 'o',
|
||||||
|
orderingRule: 'caseIgnoreOrderingMatch',
|
||||||
|
reverseOrder: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
t.context.client.search('cn=sssvlv', {}, sssrcontrol, function (err, res) {
|
||||||
|
t2.error(err)
|
||||||
|
res.on('searchEntry', function (entry) {
|
||||||
|
t2.ok(entry)
|
||||||
|
t2.ok(entry instanceof ldap.SearchEntry)
|
||||||
|
t2.ok(entry.attributes)
|
||||||
|
t2.ok(entry.attributes.length)
|
||||||
|
if (preventry != null) {
|
||||||
|
t2.ok(entry.attributes[0]._vals[0] <= preventry.attributes[0]._vals[0])
|
||||||
|
}
|
||||||
|
preventry = entry
|
||||||
|
})
|
||||||
|
res.on('error', (err) => t2.error(err))
|
||||||
|
res.on('end', function () {
|
||||||
|
t2.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('vlv - first page', function (t2) {
|
||||||
|
const sssrcontrol = new ldap.ServerSideSortingRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
attributeType: 'o',
|
||||||
|
orderingRule: 'caseIgnoreOrderingMatch',
|
||||||
|
reverseOrder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const vlvrcontrol = new ldap.VirtualListViewRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
beforeCount: 0,
|
||||||
|
afterCount: 9,
|
||||||
|
targetOffset: 1,
|
||||||
|
contentCount: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let count = 0
|
||||||
|
let preventry = null
|
||||||
|
t.context.client.search('cn=sssvlv', {}, [sssrcontrol, vlvrcontrol], function (err, res) {
|
||||||
|
t2.error(err)
|
||||||
|
res.on('searchEntry', function (entry) {
|
||||||
|
t2.ok(entry)
|
||||||
|
t2.ok(entry instanceof ldap.SearchEntry)
|
||||||
|
t2.ok(entry.attributes)
|
||||||
|
t2.ok(entry.attributes.length)
|
||||||
|
if (preventry != null) {
|
||||||
|
t2.ok(entry.attributes[0]._vals[0] >= preventry.attributes[0]._vals[0])
|
||||||
|
}
|
||||||
|
preventry = entry
|
||||||
|
count++
|
||||||
|
})
|
||||||
|
res.on('error', (err) => t2.error(err))
|
||||||
|
res.on('end', function (result) {
|
||||||
|
t2.equals(count, 10)
|
||||||
|
t2.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.test('vlv - last page', function (t2) {
|
||||||
|
const sssrcontrol = new ldap.ServerSideSortingRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
attributeType: 'o',
|
||||||
|
orderingRule: 'caseIgnoreOrderingMatch',
|
||||||
|
reverseOrder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const vlvrcontrol = new ldap.VirtualListViewRequestControl(
|
||||||
|
{
|
||||||
|
value: {
|
||||||
|
beforeCount: 0,
|
||||||
|
afterCount: 9,
|
||||||
|
targetOffset: 91,
|
||||||
|
contentCount: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let count = 0
|
||||||
|
let preventry = null
|
||||||
|
t.context.client.search('cn=sssvlv', {}, [sssrcontrol, vlvrcontrol], function (err, res) {
|
||||||
|
t2.error(err)
|
||||||
|
res.on('searchEntry', function (entry) {
|
||||||
|
t2.ok(entry)
|
||||||
|
t2.ok(entry instanceof ldap.SearchEntry)
|
||||||
|
t2.ok(entry.attributes)
|
||||||
|
t2.ok(entry.attributes.length)
|
||||||
|
if (preventry != null) {
|
||||||
|
t2.ok(entry.attributes[0]._vals[0] >= preventry.attributes[0]._vals[0])
|
||||||
|
}
|
||||||
|
preventry = entry
|
||||||
|
count++
|
||||||
|
})
|
||||||
|
res.on('error', (err) => t2.error(err))
|
||||||
|
res.on('end', function (result) {
|
||||||
|
t2.equals(count, 10)
|
||||||
|
t2.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
tap.test('search referral', function (t) {
|
tap.test('search referral', function (t) {
|
||||||
t.context.client.search('cn=ref, ' + SUFFIX, '(objectclass=*)', function (err, res) {
|
t.context.client.search('cn=ref, ' + SUFFIX, '(objectclass=*)', function (err, res) {
|
||||||
t.error(err)
|
t.error(err)
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { test } = require('tap')
|
||||||
|
const { BerReader, BerWriter } = require('asn1')
|
||||||
|
const { getControl, VirtualListViewRequestControl: VLVRControl } = require('../../lib')
|
||||||
|
|
||||||
|
test('VLV request - new no args', function (t) {
|
||||||
|
t.ok(new VLVRControl())
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV request - new with args', function (t) {
|
||||||
|
const c = new VLVRControl({
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
beforeCount: 0,
|
||||||
|
afterCount: 3,
|
||||||
|
targetOffset: 1,
|
||||||
|
contentCount: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||||
|
t.ok(c.criticality)
|
||||||
|
t.equal(c.value.beforeCount, 0)
|
||||||
|
t.equal(c.value.afterCount, 3)
|
||||||
|
t.equal(c.value.targetOffset, 1)
|
||||||
|
t.equal(c.value.contentCount, 0)
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV request - toBer - with offset', function (t) {
|
||||||
|
const vlvc = new VLVRControl({
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
beforeCount: 0,
|
||||||
|
afterCount: 3,
|
||||||
|
targetOffset: 1,
|
||||||
|
contentCount: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const ber = new BerWriter()
|
||||||
|
vlvc.toBer(ber)
|
||||||
|
|
||||||
|
const c = getControl(new BerReader(ber.buffer))
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||||
|
t.ok(c.criticality)
|
||||||
|
t.equal(c.value.beforeCount, 0)
|
||||||
|
t.equal(c.value.afterCount, 3)
|
||||||
|
t.equal(c.value.targetOffset, 1)
|
||||||
|
t.equal(c.value.contentCount, 0)
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV request - toBer - with assertion', function (t) {
|
||||||
|
const vlvc = new VLVRControl({
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
beforeCount: 0,
|
||||||
|
afterCount: 3,
|
||||||
|
greaterThanOrEqual: '*foo*'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const ber = new BerWriter()
|
||||||
|
vlvc.toBer(ber)
|
||||||
|
|
||||||
|
const c = getControl(new BerReader(ber.buffer))
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||||
|
t.ok(c.criticality)
|
||||||
|
t.equal(c.value.beforeCount, 0)
|
||||||
|
t.equal(c.value.afterCount, 3)
|
||||||
|
t.equal(c.value.greaterThanOrEqual, '*foo*')
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV request - toBer - empty', function (t) {
|
||||||
|
const vlvc = new VLVRControl()
|
||||||
|
const ber = new BerWriter()
|
||||||
|
vlvc.toBer(ber)
|
||||||
|
|
||||||
|
const c = getControl(new BerReader(ber.buffer))
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||||
|
t.equal(c.criticality, false)
|
||||||
|
t.notOk(c.value.result)
|
||||||
|
t.end()
|
||||||
|
})
|
|
@ -0,0 +1,68 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { test } = require('tap')
|
||||||
|
const { BerReader, BerWriter } = require('asn1')
|
||||||
|
const ldap = require('../../lib')
|
||||||
|
const { getControl, VirtualListViewResponseControl: VLVResponseControl } = require('../../lib')
|
||||||
|
const OID = '2.16.840.1.113730.3.4.10'
|
||||||
|
|
||||||
|
test('VLV response - new no args', function (t) {
|
||||||
|
const c = new VLVResponseControl()
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, OID)
|
||||||
|
t.equal(c.criticality, false)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV response - new with args', function (t) {
|
||||||
|
const c = new VLVResponseControl({
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
result: ldap.LDAP_SUCCESS,
|
||||||
|
targetPosition: 0,
|
||||||
|
contentCount: 10
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, OID)
|
||||||
|
t.equal(c.criticality, false)
|
||||||
|
t.equal(c.value.result, ldap.LDAP_SUCCESS)
|
||||||
|
t.equal(c.value.targetPosition, 0)
|
||||||
|
t.equal(c.value.contentCount, 10)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV response - toBer', function (t) {
|
||||||
|
const vlpc = new VLVResponseControl({
|
||||||
|
value: {
|
||||||
|
targetPosition: 0,
|
||||||
|
contentCount: 10,
|
||||||
|
result: ldap.LDAP_SUCCESS
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const ber = new BerWriter()
|
||||||
|
vlpc.toBer(ber)
|
||||||
|
|
||||||
|
const c = getControl(new BerReader(ber.buffer))
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, OID)
|
||||||
|
t.equal(c.criticality, false)
|
||||||
|
t.equal(c.value.result, ldap.LDAP_SUCCESS)
|
||||||
|
t.equal(c.value.targetPosition, 0)
|
||||||
|
t.equal(c.value.contentCount, 10)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('VLV response - toBer - empty', function (t) {
|
||||||
|
const vlpc = new VLVResponseControl()
|
||||||
|
const ber = new BerWriter()
|
||||||
|
vlpc.toBer(ber)
|
||||||
|
|
||||||
|
const c = getControl(new BerReader(ber.buffer))
|
||||||
|
t.ok(c)
|
||||||
|
t.equal(c.type, OID)
|
||||||
|
t.equal(c.criticality, false)
|
||||||
|
t.notOk(c.value.result)
|
||||||
|
t.end()
|
||||||
|
})
|
Loading…
Reference in New Issue