| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- const ldapjs = require("ldapjs");
- import ConfigManager, { LDAPAttribute, LDAPCategory } from "./ConfigLoader";
- import { LDAPSchemaAttribute, LDAPSchemaObjectClass } from './LDAPSchema';
- import LDAPEntry from "./LDAPEntry";
- import LDAPTree from "./LDAPTree";
- interface ILDAPManager {
- Release(): Promise<void>;
- /**
- * Try to login as user to check password
- * @param dn
- * @param password
- */
- TryBind(dn: string, password: string): Promise<boolean>;
- CheckLoginExists(user: string): Promise<string>;
- ListEntries(category: LDAPCategory): Promise<LDAPEntry[]>;
- /** @return all dn */
- GetTree(): Promise<LDAPTree>;
- GetEntry(dn: string): Promise<Map<string, string[]>>;
- Remove(dn: string): Promise<void>;
- GetSchema(): Promise<Map<string, LDAPSchemaObjectClass>>;
- }
- class LDAPManager implements ILDAPManager {
- protected cli: any;
- public constructor(cli: any) {
- this.cli = cli;
- }
- public static Create(): Promise<LDAPManager> {
- return new Promise((ok, ko) => {
- let config = ConfigManager.GetInstance();
- let cli = ldapjs.createClient({
- url: config.GetLDAPUrls()
- });
- cli.on('error', (err: any) => {
- console.error("LDAP general error: ", err);
- ko(err);
- });
- cli.bind(config.GetBindDn(), config.GetBindPassword(), (err: any) => {
- if (err) {
- console.error("LDAP bind error: ", err);
- ko(err);
- } else {
- ok(new LDAPManager(cli));
- }
- });
- });
- }
- public TryBind(userDn: string, password: string): Promise<boolean> {
- return new Promise((ok, ko) => {
- let cli = ldapjs.createClient({
- url: ConfigManager.GetInstance().GetLDAPUrls()
- });
- cli.on('error', (err: any) => {
- console.error("LDAP general error: ", err);
- ko(err);
- });
- cli.bind(userDn, password, (err: any) => {
- if (err) {
- ok(false);
- } else {
- ok(true);
- }
- });
- });
- }
- private Search(base: string, scope: string, filter: string|undefined =undefined, attributes: string[]|undefined =undefined): Promise<Map<string, Map<string, string[]>>> {
- return new Promise((ok, ko) => {
- this.cli.search(base, { scope: scope, filter: filter, attributes: attributes || ['*', 'memberof'], paged: false }, (err: any, res: any) => {
- if (err) {
- console.error("Search error: ", { base: base, scope: scope, filter: filter, attributes: attributes });
- ko(err);
- return;
- }
- let result = new Map<string, any>();
- let error = false;
- res.on('searchEntry', (i: any) => {
- if (error) return;
- let LDAPEntry = new Map<string, string[]>();
- for (let attr in i.object) {
- let value = i.object[attr];
- if (Array.isArray(value)) {
- let arr = new Array();
- for (let j of value)
- arr.push(j);
- value = arr;
- } else {
- let arr = new Array();
- arr.push(value);
- value = arr;
- }
- LDAPEntry.set(attr, value);
- }
- result.set(i.dn, LDAPEntry);
- });
- res.on('error', (err: any) => {
- error = true;
- console.error("Search error: ", { base: base, scope: scope, filter: filter, attributes: attributes });
- ko(err);
- });
- res.on('end', () => {
- if (error) return;
- ok(result);
- });
- });
- });
- }
- public GetEntry(dn: string): Promise<Map<string, string[]>> {
- return new Promise((ok, ko) => {
- this.Search(dn, "sub").then(result => {
- for (let [_, val] of result) {
- ok(val);
- return;
- }
- }).catch(err => {
- ko(err);
- });
- });
- }
- public CheckLoginExists(user: string): Promise<string> {
- return new Promise((ok, ko) => {
- let config = ConfigManager.GetInstance();
- return this.Search(config.GetLoginBase(), config.GetLoginScope(), config.GetLoginFilter(user), []).then(result => {
- if (!result || result.size !== 1)
- ko();
- for (let [addr, _] of result) {
- ok(addr);
- }
- });
- });
- }
- public GetTree(): Promise<LDAPTree> {
- return new Promise(ok => {
- const rootDn: string = ConfigManager.GetInstance().GetLDAPRoot();
- this.Search(rootDn, "sub", undefined, ["dn", "ObjectClass"]).then(searchDns => {
- let result = LDAPTree.CreateRoot();
- searchDns.forEach((val, dn) => {
- let classes = val.get("objectClass");
- classes && result.push(dn, classes);
- });
- ok(result.Compress());
- });
- });
- }
- public ListEntries(category: LDAPCategory): Promise<LDAPEntry[]> {
- return new Promise((ok, _) => {
- this.Search(category.GetBaseDn(), category.GetScope(), category.GetFilter() || undefined, category.GetAttributes().map(i => i.mapped)).then(result => {
- let userArray = new Array();
- for (let [addr, val] of result)
- userArray.push(new LDAPEntry(category.GetAttributes(), addr, val));
- ok(userArray);
- });
- });
- }
- public Release():Promise<void> {
- return new Promise(ok => {
- this.cli.unbind((err: any) => {
- if (err)
- console.error("LDAP unbind error: ", err);
- ok();
- });
- });
- }
- public Remove(dn: string): Promise<void> {
- return new Promise((ok, ko) => {
- this.cli.del(dn, (err: any) => {
- if (err)
- ko(err["message"]);
- else
- ok();
- });
- });
- }
- public GetSchema(): Promise<Map<string, LDAPSchemaObjectClass>> {
- return new Promise((ok, ko) => {
- const rootDn = ConfigManager.GetInstance().GetLDAPRoot();
- let subschema: string;
- this.Search(rootDn, "base", undefined, ["subschemaSubentry"]).then(result => {
- const baseItem = result?.get(rootDn)?.get("subschemaSubentry");
- const _subschema = baseItem && baseItem.length ? baseItem[0] : null;
- if (!_subschema) {
- console.error("Cannot find schema for base " + rootDn);
- ko("Schema not found");
- return;
- }
- subschema = _subschema;
- return this.Search(subschema, "base", undefined, ["attributeTypes", "objectClasses"]);
- }).then(result => {
- const attributesArr = result?.get(subschema)?.get("attributeTypes");
- const classesArr = result?.get(subschema)?.get("objectClasses");
- if (!attributesArr || !classesArr) {
- console.error("Cannot find schema definition for " + rootDn);
- ko("Schema definition not found");
- return;
- }
- let attributes: Map<string, LDAPSchemaAttribute> = new Map();
- let schemas: Map<string, LDAPSchemaObjectClass> = new Map();
- for (let i of attributesArr) {
- let attr = new LDAPSchemaAttribute(i);
- attributes.set(attr.GetName(), attr);
- }
- for (let i of classesArr) {
- let schema = new LDAPSchemaObjectClass(i, attributes);
- schemas.set(schema.GetName(), schema);
- }
- for (let [_, schema] of schemas)
- schema.Consolidate(schemas, attributes);
- ok(schemas);
- }).catch(err => {
- console.error("Failed to retreive schema: ", err);
- ko(err);
- });
- });
- }
- }
- export default class LDAPFactory {
- private _instance: ILDAPManager|null = null;
- public GetInstance(): Promise<ILDAPManager> {
- if (!this._instance) {
- return new Promise((ok, ko) => {
- LDAPManager.Create().then(inst => {
- this._instance = inst;
- ok(this._instance);
- });
- });
- }
- return Promise.resolve(this._instance);
- }
- public Release(): Promise<null> {
- if (this._instance)
- return this._instance.Release().then(() => this._instance = null);
- return Promise.resolve(null);
- }
- }
- export { ILDAPManager };
|