UNPKG

@mntu/nestjs-ldap

Version:

NestJS library to access LDAP

165 lines (139 loc) 4.48 kB
import { Ber, BerWriter, BerReader } from 'asn1'; import { Protocol } from './protocol'; export class Attribute { public _vals?: Record<string, any>; public type: string; /** * Get vals * * @returns {string | Buffer} */ get vals(): string | Buffer { return this._vals?.map((v: any) => v.toString(this.bufferEncoding(this.type)), ); } /** * Set vals * * @param {string | Buffer} vals */ set vals(vals: string | Buffer) { this._vals = []; if (Array.isArray(vals)) { vals.forEach((v) => { this.addValue(v); }); } else { this.addValue(vals); } } /** * Get buffers * * @returns {Record<any, any>} buffers */ get buffers(): Record<any, any> { return this._vals || {}; } /** * Get json * * @returns {Record<string, any>} { type, vals } */ get json(): Record<string, any> { return { type: this.type, vals: this.vals, }; } constructor(options: Record<string, any> = { type: '' }) { if (options.type && typeof options.type !== 'string') { throw new TypeError('options.type must be a string'); } this.type = options.type || ''; if (options.vals !== undefined && options.vals !== null) { this.vals = options.vals; } } bufferEncoding = (type: string): 'base64' | 'utf8' => /;binary$/.test(type) ? 'base64' : 'utf8'; addValue = (val: Buffer | string): void => { if (Buffer.isBuffer(val)) { this._vals?.push(val); } else { this._vals?.push(Buffer.from(val, this.bufferEncoding(this.type))); } }; static isAttribute = ( attr: Attribute | Record<string, unknown>, ): attr is Attribute => { if (attr instanceof Attribute) { return true; } if ( typeof attr.toBer === 'function' && typeof attr.type === 'string' && Array.isArray(attr.vals) && attr.vals.filter( (item) => typeof item === 'string' || Buffer.isBuffer(item), ).length === attr.vals.length ) { return true; } return false; }; static compare = ( a: Attribute | Record<string, any>, b: Attribute | Record<string, any>, ): number => { if (!Attribute.isAttribute(a) || !Attribute.isAttribute(b)) { throw new TypeError('can only compare Attributes'); } if (a.type < b.type) return -1; if (a.type > b.type) return 1; if (a.vals.length < b.vals.length) return -1; if (a.vals.length > b.vals.length) return 1; for (let i = 0; i < a.vals.length; i += 1) { if (a.vals[i] < b.vals[i]) return -1; if (a.vals[i] > b.vals[i]) return 1; } return 0; }; parse = (ber?: BerReader): boolean => { if (!ber) { throw new TypeError('ldapjs Attribute parse: ber is undefined'); } ber.readSequence(); this.type = ber.readString(); if (ber.peek() === Protocol.LBER_SET) { if (ber.readSequence(Protocol.LBER_SET)) { const end = ber.offset + ber.length; while (ber.offset < end) this._vals?.push(ber.readString(Ber.OctetString, true)); } } return true; }; toString = (): string => JSON.stringify(this.json); toBer = (ber?: BerWriter): BerWriter => { if (!ber) { throw new TypeError('ldapjs Attribute toBer: ber is undefined'); } ber.startSequence(); ber.writeString(this.type); ber.startSequence(Protocol.LBER_SET); if (this._vals?.length) { this._vals.forEach((b: any) => { ber.writeByte(Ber.OctetString); ber.writeLength(b.length); for (let i = 0; i < b.length; i += 1) ber.writeByte(b[i]); }); } else { ber.writeStringArray([]); } ber.endSequence(); ber.endSequence(); return ber; }; }