const CanonicalUnit = require('libflitter/canon/CanonicalUnit') class LDAPRoutingUnit extends CanonicalUnit { static get name() { return 'ldap_routers' } static get services() { return [...super.services, 'output', 'canon', 'ldap_server'] } constructor(base_directory = './app/ldap/routes') { super(base_directory) this.canonical_item = 'ldap_router' this.suffix = '.routes.js' } async init_canonical_file({app, name, instance}) { const router_middleware = [] if ( !instance ) { this.output.warn(`Skipping LDAP routing file ${name}. No members were exported.`) } this.output.info(`Building LDAP routes for router ${name}.`) // Load the router-level middleware functions if ( Array.isArray(instance.middleware) ) { for ( const mw of instance.middleware ) { const mw_instance = this.canon.get(`ldap_middleware::${mw}`) if ( !mw_instance ) { const msg = `Unable to create LDAP routes. Invalid or unknown LDAP middleware: ldap_middleware::${mw} in router ${name}.` this.output.error(msg) throw new Error(msg) } router_middleware.push(mw_instance) } } this.output.debug(`Found ${router_middleware.length} router-level middlewares.`) // Determine the prefix (suffix) and total suffix from config let suffix = [] if ( instance.prefix && typeof instance.prefix === 'string' ) { suffix.push(instance.prefix) } else if ( instance.prefix !== false ) { this.output.warn(`No prefix specified for LDAP routing file ${name}.`) } // If the server has a base DC=...,DC=... &c. suffix, include that if ( this.ldap_server.config.schema.base_dc ) { suffix.push(this.ldap_server.config.schema.base_dc) } suffix = suffix.join(',') // Load the individual routes const supported_ldap_types = [ 'search', 'bind', 'add', 'del', 'modify', 'compare', 'modifyDN', 'exop', 'unbind', ] // Iterate over the various query types that might be in the definition for ( const type of supported_ldap_types ) { if ( typeof instance[type] === 'object' ) { // Iterate over each of the route definitions in the type definition for ( const route_prefix in instance[type] ) { if ( !instance[type].hasOwnProperty(route_prefix) ) continue let route_handlers = instance[type][route_prefix] if ( typeof route_handlers === 'string' ) route_handlers = [route_handlers] if ( !Array.isArray(route_handlers) ) { const msg = `Invalid route handlers for route ${route_prefix} (${type}) in router ${name}.` this.output.error(msg) throw new Error(msg) } let route_functions = [...router_middleware] // For each of the route handler definitions, resolve the canonical for ( const route_handler_name of route_handlers ) { const route_handler = this.canon.get(route_handler_name) if ( !route_handler || typeof route_handler !== 'function' ) { const msg = `Unable to resolve route handler for route ${route_prefix} (${type}) in router ${name}. Handler name: ${route_handler_name}` this.output.error(msg) throw new Error(msg) } route_functions.push(route_handler) } this.output.debug(`Registering route ${type} :: ${[route_prefix, suffix].join(',')} with ${route_functions.length} handlers.`) this.ldap_server.server[type]([route_prefix, suffix].join(','), ...route_functions) } } else { // Unbind has a default handler, so don't warn about that. if ( type !== 'unbind' ) this.output.warn(`Missing or invalid LDAP protocol definition ${type} in router ${name}. The protocol will be skipped.`) } } } } module.exports = exports = LDAPRoutingUnit