From 00c81827ef14d91996800f4ec91fdbbc1f394691 Mon Sep 17 00:00:00 2001 From: Khaled FERJANI Date: Thu, 2 Oct 2025 18:14:37 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20LDAP=20mobile=20searc?= =?UTF-8?q?h=20helper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/cli/cmds/migration_cmds/utils/ldap.ts | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 tdrive/backend/node/src/cli/cmds/migration_cmds/utils/ldap.ts diff --git a/tdrive/backend/node/src/cli/cmds/migration_cmds/utils/ldap.ts b/tdrive/backend/node/src/cli/cmds/migration_cmds/utils/ldap.ts new file mode 100644 index 00000000..bac77ad8 --- /dev/null +++ b/tdrive/backend/node/src/cli/cmds/migration_cmds/utils/ldap.ts @@ -0,0 +1,106 @@ +import ldap, { type SearchEntry, type Client } from "ldapjs"; +import dotenv from "dotenv"; + +dotenv.config(); + +interface LdapConfig { + url: string; + bindDN: string; + bindCredentials: string; + searchBase: string; +} + +/** + * Retrieves the LDAP configuration from environment variables. + * + * @returns {LdapConfig} The LDAP configuration object. + */ +function getLdapConfig(): LdapConfig { + return { + url: process.env.LDAP_URL || "localhost", + bindDN: process.env.LDAP_BIND_DN || "", + bindCredentials: process.env.LDAP_BIND_CREDENTIALS || "", + searchBase: process.env.LDAP_SEARCH_BASE || "dc=example,dc=com", + }; +} + +/** + * creates a ldap client and binds to the ldap server + * + * @param {LdapConfig} config - the LDAP connection config + * @returns {Promise} A promise that resolves to the LDAP client instance. + */ +function createLdapClient(config: LdapConfig): Promise { + return new Promise((resolve, reject) => { + const client = ldap.createClient({ url: config.url }); + client.bind(config.bindDN, config.bindCredentials, err => { + if (err) { + client.unbind(); + reject(err); + } else { + resolve(client); + } + }); + }); +} + +/** + * Searches for a user in LDAP by username and returns their mobile number. + * + * @param {Client} client The LDAP client instance. + * @param {LdapConfig} config The LDAP configuration. + * @param {string} username The username to search for. + * @returns A promise that resolves to the user's mobile number, or null if not found. + */ +function searchForUserMobile( + client: Client, + config: LdapConfig, + username: string, +): Promise { + return new Promise((resolve, reject) => { + client.search( + config.searchBase, + { + filter: `(&(objectClass=inetorgperson)(uid=${username}))`, + attributes: ["mobile"], + scope: "sub", + }, + (searchErr, searchResult) => { + if (searchErr) return reject(searchErr); + + let found = false; + + searchResult.on("searchEntry", (entry: SearchEntry) => { + const mobile = entry.attributes.find(a => a.type === "mobile")?.vals[0]; + + found = true; + resolve(mobile || null); + }); + + searchResult.on("error", reject); + searchResult.on("end", () => !found && resolve(null)); + }, + ); + }); +} + +/** + * Fetches the mobile number for a given username from LDAP. + * + * @param {string} username The username to search for in LDAP. + * @returns A promise that resolves to the user's mobile number, or null if not found. + */ +export async function getLDAPUserMobile(username: string): Promise { + const config = getLdapConfig(); + const client = await createLdapClient(config); + + try { + return await searchForUserMobile(client, config, username); + } catch (error) { + console.log("LDAP search error", error); + + return null; + } finally { + client.unbind(); + } +}