123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- 'use strict'
- const tap = require('tap')
- const warning = require('./deprecations')
- const { resultCodes, operations } = require('@ldapjs/protocol')
- const { BerReader } = require('@ldapjs/asn1')
- const {
- addResponseBasicBytes,
- addResponseNoSuchObjectBytes,
- addResponseReferralsBytes,
- extensionDisconnectionNotificationResponseBytes
- } = require('./messages/_fixtures/message-byte-arrays')
- const RECOGNIZED_OIDS = require('./messages/extension-utils/recognized-oids')
- const LdapResult = require('./ldap-result')
- const ExtensionResponse = require('./messages/extension-response')
- // Silence the standard warning logs. We will test the messages explicitly.
- process.removeAllListeners('warning')
- tap.test('constructor', t => {
- t.test('no args', async t => {
- const res = new LdapResult()
- t.equal(res.status, 0)
- t.equal(res.matchedDN, '')
- t.strictSame(res.referrals, [])
- t.equal(res.diagnosticMessage, '')
- })
- t.test('emits warning for abandonID', t => {
- process.on('warning', handler)
- t.teardown(async () => {
- process.removeListener('warning', handler)
- warning.emitted.set('LDAP_MESSAGE_DEP_004', false)
- })
- const res = new LdapResult({
- errorMessage: 'foo'
- })
- t.ok(res)
- function handler (error) {
- t.equal(
- error.message,
- 'errorMessage is deprecated. Use diagnosticMessage instead.'
- )
- t.end()
- }
- })
- t.test('with options', async t => {
- const res = new LdapResult({
- status: 1,
- matchedDN: 'foo',
- referrals: ['foo.example.com'],
- diagnosticMessage: 'bar'
- })
- t.equal(res.status, 1)
- t.equal(res.matchedDN, 'foo')
- t.strictSame(res.referrals, ['foo.example.com'])
- t.equal(res.diagnosticMessage, 'bar')
- })
- t.end()
- })
- tap.test('.diagnosticMessage', t => {
- t.test('sets and gets', async t => {
- const res = new LdapResult()
- t.equal(res.diagnosticMessage, '')
- res.diagnosticMessage = 'foo'
- t.equal(res.diagnosticMessage, 'foo')
- })
- t.end()
- })
- tap.test('.matchedDN', t => {
- t.test('sets and gets', async t => {
- const res = new LdapResult()
- t.equal(res.matchedDN, '')
- res.matchedDN = 'foo'
- t.equal(res.matchedDN, 'foo')
- })
- t.end()
- })
- tap.test('.pojo', t => {
- t.test('returns a plain JavaScript object', async t => {
- const res = new LdapResult()
- t.strictSame(res.pojo, {
- status: 0,
- matchedDN: '',
- diagnosticMessage: '',
- referrals: []
- })
- })
- t.test('returns a plain JavaScript object from subclass', async t => {
- class Foo extends LdapResult {
- _pojo (obj) {
- obj.foo = 'foo'
- return obj
- }
- }
- const res = new Foo()
- t.strictSame(res.pojo, {
- status: 0,
- matchedDN: '',
- diagnosticMessage: '',
- referrals: [],
- foo: 'foo'
- })
- })
- t.end()
- })
- tap.test('.referrals', t => {
- t.test('gets', async t => {
- const res = new LdapResult({ referrals: ['foo'] })
- t.strictSame(res.referrals, ['foo'])
- })
- t.end()
- })
- tap.test('.status', t => {
- t.test('sets and gets', async t => {
- const res = new LdapResult()
- t.equal(res.status, 0)
- res.status = 1
- t.equal(res.status, 1)
- })
- t.end()
- })
- tap.test('.type', t => {
- t.test('gets', async t => {
- const res = new LdapResult()
- t.equal(res.type, 'LdapResult')
- })
- t.end()
- })
- tap.test('addReferral', t => {
- t.test('adds to existing list', async t => {
- const res = new LdapResult({ referrals: ['foo'] })
- t.strictSame(res.referrals, ['foo'])
- res.addReferral('bar')
- t.strictSame(res.referrals, ['foo', 'bar'])
- })
- t.end()
- })
- tap.test('_toBer', t => {
- t.test('returns basic bytes', async t => {
- const res = new LdapResult({
- protocolOp: operations.LDAP_RES_ADD,
- messageId: 2
- })
- const ber = res.toBer()
- const expected = Buffer.from(addResponseBasicBytes)
- t.equal(expected.compare(ber.buffer), 0)
- })
- t.test('returns bytes with referrals', async t => {
- const res = new LdapResult({
- protocolOp: operations.LDAP_RES_ADD,
- messageId: 3,
- status: resultCodes.REFERRAL,
- diagnosticMessage: 'This server is read-only. Try a different one.',
- referrals: [
- 'ldap://alternate1.example.com:389/uid=jdoe,ou=Remote,dc=example,dc=com',
- 'ldap://alternate2.example.com:389/uid=jdoe,ou=Remote,dc=example,dc=com'
- ]
- })
- const ber = res.toBer()
- const expected = Buffer.from(addResponseReferralsBytes)
- t.equal(expected.compare(ber.buffer), 0)
- })
- t.test('hands off to _writeResponse', async t => {
- const res = new ExtensionResponse({
- protocolOp: operations.LDAP_RES_EXTENSION,
- messageId: 0,
- status: resultCodes.UNAVAILABLE,
- diagnosticMessage: 'The Directory Server is shutting down',
- referrals: [],
- responseName: RECOGNIZED_OIDS.get('DISCONNECTION_NOTIFICATION')
- })
- const ber = res.toBer()
- const expected = Buffer.from(extensionDisconnectionNotificationResponseBytes)
- t.equal(expected.compare(ber.buffer), 0)
- })
- t.end()
- })
- tap.test('#parseToPojo', t => {
- t.test('throws because not implemented', async t => {
- const expected = Error('Use LdapMessage.parse, or a specific message type\'s parseToPojo, instead.')
- t.throws(
- () => LdapResult.parseToPojo(),
- expected
- )
- })
- t.end()
- })
- tap.test('#_parseToPojo', async t => {
- t.test('throws if protocol op is wrong', async t => {
- const bytes = addResponseBasicBytes.slice(5)
- bytes[0] = 0x68
- const berReader = new BerReader(Buffer.from(bytes))
- t.throws(
- () => LdapResult._parseToPojo({
- opCode: operations.LDAP_RES_ADD,
- berReader
- }),
- Error('found wrong protocol operation: 0x68')
- )
- })
- t.test('parses a basic object', async t => {
- const bytes = addResponseBasicBytes.slice(5)
- const berReader = new BerReader(Buffer.from(bytes))
- const pojo = { foo: 'foo' }
- LdapResult._parseToPojo({
- opCode: operations.LDAP_RES_ADD,
- berReader,
- pojo
- })
- t.strictSame(pojo, {
- status: 0,
- matchedDN: '',
- diagnosticMessage: '',
- referrals: [],
- foo: 'foo'
- })
- })
- t.test('parses object with matched dn and diagnostic message', async t => {
- const bytes = addResponseNoSuchObjectBytes.slice(6)
- const berReader = new BerReader(Buffer.from(bytes))
- const pojo = LdapResult._parseToPojo({
- opCode: operations.LDAP_RES_ADD,
- berReader
- })
- t.strictSame(pojo, {
- status: resultCodes.NO_SUCH_OBJECT,
- referrals: [],
- matchedDN: 'ou=People, dc=example, dc=com',
- diagnosticMessage: [
- 'Entry uid=missing1, ou=missing2, ou=People, dc=example, dc=com cannot',
- ' be created because its parent does not exist.'
- ].join('')
- })
- })
- t.test('parses object with referrals', async t => {
- const bytes = addResponseReferralsBytes.slice(6)
- const berReader = new BerReader(Buffer.from(bytes))
- const pojo = LdapResult._parseToPojo({
- opCode: operations.LDAP_RES_ADD,
- berReader
- })
- t.strictSame(pojo, {
- status: resultCodes.REFERRAL,
- referrals: [
- 'ldap://alternate1.example.com:389/uid=jdoe,ou=Remote,dc=example,dc=com',
- 'ldap://alternate2.example.com:389/uid=jdoe,ou=Remote,dc=example,dc=com'
- ],
- matchedDN: '',
- diagnosticMessage: 'This server is read-only. Try a different one.'
- })
- })
- })
|