|
|
@@ -0,0 +1,155 @@
|
|
|
+const ldapjs = require("ldapjs");
|
|
|
+import ConfigManager, { LDAPCategory } from "./ConfigLoader";
|
|
|
+import LDAPEntry from "./LDAPEntry";
|
|
|
+
|
|
|
+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<Array<LDAPEntry>>;
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public Search(base: string, scope: string, filter: string|undefined, attributes: Array<string>): Promise<Map<string, Map<string, any>>> {
|
|
|
+ return new Promise((ok, ko) => {
|
|
|
+ this.cli.search(base, { scope: scope, filter: filter, attributes: attributes, 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, any>();
|
|
|
+ for (let attr in i.object) {
|
|
|
+ let value = i.object[attr];
|
|
|
+ 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 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 ListEntries(category: LDAPCategory): Promise<Array<LDAPEntry>> {
|
|
|
+ return new Promise((ok, ko) => {
|
|
|
+ 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();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+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 };
|