First commit
This commit is contained in:
244
node_modules/@ldapjs/messages/lib/ldap-result.js
generated
vendored
Normal file
244
node_modules/@ldapjs/messages/lib/ldap-result.js
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
'use strict'
|
||||
|
||||
const LdapMessage = require('./ldap-message')
|
||||
const { resultCodes, operations } = require('@ldapjs/protocol')
|
||||
const warning = require('./deprecations')
|
||||
|
||||
/**
|
||||
* Implements the base LDAP response message as defined in
|
||||
* https://www.rfc-editor.org/rfc/rfc4511.html#section-4.1.9.
|
||||
*/
|
||||
class LdapResult extends LdapMessage {
|
||||
#connection = null
|
||||
#diagnosticMessage
|
||||
#matchedDN
|
||||
#referrals = []
|
||||
#status
|
||||
|
||||
/**
|
||||
* @typedef {LdapMessageOptions} LdapResultOptions
|
||||
* @property {number} [status=0] An LDAP status code.
|
||||
* @param {string} [matchedDN=''] The DN that matched the request.
|
||||
* @param {string[]} [referrals=[]] A set of servers to query for references.
|
||||
* @param {string} [diagnosticMessage] A message indicating why a request
|
||||
* failed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {LdapResultOptions} options
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
super(options)
|
||||
|
||||
this.#status = options.status ?? resultCodes.SUCCESS
|
||||
this.#matchedDN = options.matchedDN || ''
|
||||
this.#referrals = options.referrals || []
|
||||
this.#diagnosticMessage = options.diagnosticMessage || options.errorMessage || ''
|
||||
if (options.errorMessage) {
|
||||
warning.emit('LDAP_MESSAGE_DEP_004')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The failure message as returned by the server if one is present.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
get diagnosticMessage () {
|
||||
return this.#diagnosticMessage
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a diagnostic message to the instance.
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
set diagnosticMessage (message) {
|
||||
this.#diagnosticMessage = message
|
||||
}
|
||||
|
||||
/**
|
||||
* The DN that a request matched.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
get matchedDN () {
|
||||
return this.#matchedDN
|
||||
}
|
||||
|
||||
/**
|
||||
* Define which DN a request matched.
|
||||
*
|
||||
* @param {string} dn
|
||||
*/
|
||||
set matchedDN (dn) {
|
||||
this.#matchedDN = dn
|
||||
}
|
||||
|
||||
/**
|
||||
* A serialized representation of the message as a plain JavaScript object.
|
||||
* Specific message types must implement the `_pojo(obj)` method. The passed
|
||||
* in `obj` must be extended with the specific message's unique properties
|
||||
* and returned as the result.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
get pojo () {
|
||||
let result = {
|
||||
status: this.status,
|
||||
matchedDN: this.matchedDN,
|
||||
diagnosticMessage: this.diagnosticMessage,
|
||||
referrals: this.referrals
|
||||
}
|
||||
|
||||
if (typeof this._pojo === 'function') {
|
||||
result = this._pojo(result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of servers that should be consulted to get an answer
|
||||
* to the query.
|
||||
*
|
||||
* @returns {string[]}
|
||||
*/
|
||||
get referrals () {
|
||||
return this.#referrals.slice(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* The LDAP response code for the request.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
get status () {
|
||||
return this.#status
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the response code for the request.
|
||||
*
|
||||
* @param {number} s
|
||||
*/
|
||||
set status (s) {
|
||||
this.#status = s
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the request type.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
get type () {
|
||||
return 'LdapResult'
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new server to the list of servers that should be
|
||||
* consulted for an answer to the query.
|
||||
*
|
||||
* @param {string} referral
|
||||
*/
|
||||
addReferral (referral) {
|
||||
this.#referrals.push(referral)
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only. Subclasses may implement a `_writeResponse`
|
||||
* method to add to the sequence after any referrals.
|
||||
*
|
||||
* @param {import('@ldapjs/asn1').BerWriter} ber
|
||||
*
|
||||
* @returns {import('@ldapjs/asn1').BerWriter}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_toBer (ber) {
|
||||
ber.startSequence(this.protocolOp)
|
||||
ber.writeEnumeration(this.status)
|
||||
ber.writeString(this.matchedDN)
|
||||
ber.writeString(this.diagnosticMessage)
|
||||
|
||||
if (this.referrals.length > 0) {
|
||||
ber.startSequence(operations.LDAP_RES_REFERRAL)
|
||||
ber.writeStringArray(this.referrals)
|
||||
ber.endSequence()
|
||||
}
|
||||
|
||||
if (typeof this._writeResponse === 'function') {
|
||||
this._writeResponse(ber)
|
||||
}
|
||||
|
||||
ber.endSequence()
|
||||
}
|
||||
|
||||
/**
|
||||
* When invoked on specific message types, e.g. {@link AddResponse}, this
|
||||
* method will parse a BER into a plain JavaScript object that is usable as
|
||||
* an options object for constructing that specific message object.
|
||||
*
|
||||
* @param {import('@ldapjs/asn1').BerReader} ber A BER to parse. The reader
|
||||
* offset must point to the start of a valid sequence, i.e. the "tag" byte
|
||||
* in the TLV tuple, that represents the message to be parsed. For example,
|
||||
* in a {@link AddResponse} the starting sequence and message identifier must
|
||||
* already be read such that the offset is at the protocol operation sequence
|
||||
* byte.
|
||||
*/
|
||||
static parseToPojo (ber) {
|
||||
throw Error('Use LdapMessage.parse, or a specific message type\'s parseToPojo, instead.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*
|
||||
* Response messages are a little more generic to parse than request messages.
|
||||
* However, they still need to recognize the correct protocol operation. So
|
||||
* the public {@link parseToPojo} for each response object should invoke this
|
||||
* private static method to parse the BER and indicate the correct protocol
|
||||
* operation to recognize.
|
||||
*
|
||||
* @param {object} input
|
||||
* @param {number} input.opCode The expected protocol operation to look for.
|
||||
* @param {import('@ldapjs/asn1').BerReader} berReader The BER to process. It
|
||||
* must start at an offset representing a protocol operation tag.
|
||||
* @param {object} [input.pojo] A plain JavaScript object to populate with
|
||||
* the parsed keys and values.
|
||||
*
|
||||
* @returns {object}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
static _parseToPojo ({ opCode, berReader, pojo = {} }) {
|
||||
const protocolOp = berReader.readSequence()
|
||||
if (protocolOp !== opCode) {
|
||||
const op = protocolOp.toString(16).padStart(2, '0')
|
||||
throw Error(`found wrong protocol operation: 0x${op}`)
|
||||
}
|
||||
|
||||
const status = berReader.readEnumeration()
|
||||
const matchedDN = berReader.readString()
|
||||
const diagnosticMessage = berReader.readString()
|
||||
const referrals = []
|
||||
|
||||
if (berReader.peek() === operations.LDAP_RES_REFERRAL) {
|
||||
// Advance the offset to the start of the value and
|
||||
// put the sequence length into the `reader.length` field.
|
||||
berReader.readSequence(operations.LDAP_RES_REFERRAL)
|
||||
const end = berReader.length
|
||||
while (berReader.offset < end) {
|
||||
referrals.push(berReader.readString())
|
||||
}
|
||||
}
|
||||
|
||||
pojo.status = status
|
||||
pojo.matchedDN = matchedDN
|
||||
pojo.diagnosticMessage = diagnosticMessage
|
||||
pojo.referrals = referrals
|
||||
|
||||
return pojo
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LdapResult
|
||||
Reference in New Issue
Block a user