From c23cadf8f6e85e96201511f0dca947aec30e1e8e Mon Sep 17 00:00:00 2001 From: anishapant21 Date: Wed, 30 Jul 2025 19:21:22 -0400 Subject: [PATCH 1/5] Map to webchart schema --- src/db/drivers/mysql.js | 136 +++++++++++++++++++++++----------------- src/utils/ldapUtils.js | 24 ++++--- 2 files changed, 92 insertions(+), 68 deletions(-) diff --git a/src/db/drivers/mysql.js b/src/db/drivers/mysql.js index b663129..842462e 100644 --- a/src/db/drivers/mysql.js +++ b/src/db/drivers/mysql.js @@ -1,4 +1,4 @@ -const mysql = require("mysql2/promise"); +const mysql = require('mysql2/promise'); // Create a connection pool at startup let pool; @@ -7,6 +7,7 @@ function createPool(config) { if (!pool) { pool = mysql.createPool({ host: config.host, + port: config.port, user: config.user, password: config.password, database: config.database, @@ -33,83 +34,102 @@ async function close() { } } -async function findUserByUsername(username) { - const connection = await pool.getConnection(); +async function executeQuery(sql, params = []) { + if (!pool) throw new Error('Pool not initialized. Call connect() first.'); + const conn = await pool.getConnection(); try { - const [rows] = await connection.execute( - "SELECT * FROM users WHERE username = ?", - [username] - ); - return rows[0] || null; + const [rows] = await conn.execute(sql, params); + console.log(`SQL: ${sql}\nParams: ${JSON.stringify(params)}\nReturned rows: ${rows.length}`); + return rows; } finally { - connection.release(); // Release connection back to pool + conn.release(); } } +async function findUserByUsername(username) { + const sql = ` + SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm + FROM users u + LEFT JOIN realms r ON r.realm = u.realm + WHERE u.username = ? + LIMIT 1 + `; + const rows = await executeQuery(sql, [username]); + console.log('findUserByUsername result:', rows); + return rows[0] || null; +} + async function findGroupsByMemberUid(username) { - const connection = await pool.getConnection(); - try { - const [rows] = await connection.execute( - "SELECT g.name, g.gid, g.member_uids " + - "FROM `groups` g " + - "WHERE JSON_CONTAINS(g.member_uids, JSON_QUOTE(?))", - [username] - ); - return rows.map(row => { - if (row.member_uids && typeof row.member_uids === 'string') { - try { - row.member_uids = JSON.parse(row.member_uids); - } catch (e) { - // error - } - } - return row; + const sql = ` + SELECT r.realm AS name, r.id AS gid + FROM user_realms ur + JOIN users u ON u.user_id = ur.user_id + JOIN realms r ON r.realm = ur.realm + WHERE u.username = ? + GROUP BY r.id, r.realm + ORDER BY r.realm + `; + const groups = await executeQuery(sql, [username]); + console.log('findGroupsByMemberUid groups:', groups); + + const out = []; + for (const g of groups) { + const membersSql = ` + SELECT u.username AS memberUid + FROM user_realms ur + JOIN users u ON u.user_id = ur.user_id + WHERE ur.realm = ? + ORDER BY u.username + `; + const members = await executeQuery(membersSql, [g.name]); + console.log(`Members for group ${g.name}:`, members); + out.push({ + name: g.name, + gid: g.gid, + member_uids: members.map(m => m.memberUid) }); - } finally { - connection.release(); } + return out; } async function getAllUsers() { - const [rows] = await this.pool.query('SELECT * FROM users'); - return rows; + const sql = ` + SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm + FROM users u + LEFT JOIN realms r ON r.realm = u.realm + ORDER BY u.username + `; + const rows = await executeQuery(sql); + return rows; } async function getAllGroups() { - try { - const query = ` - SELECT - g.id, - g.name, - g.gid, - GROUP_CONCAT(u.username) as member_uids - FROM groups g - LEFT JOIN user_groups ug ON g.id = ug.group_id - LEFT JOIN users u ON ug.user_id = u.id - GROUP BY g.id, g.name, g.gid - ORDER BY g.name - `; + const sql = ` + SELECT r.id, r.realm AS name, + COALESCE(GROUP_CONCAT(u.username ORDER BY u.username SEPARATOR ','), '') AS member_uids + FROM realms r + LEFT JOIN user_realms ur ON ur.realm = r.realm + LEFT JOIN users u ON u.user_id = ur.user_id + GROUP BY r.id, r.realm + ORDER BY r.realm + `; + const rows = await executeQuery(sql); + console.log('getAllGroups result count:', rows.length); - const groups = await this.executeQuery(query); - - return groups.map(group => ({ - id: group.id, - name: group.name, - gid: group.gid, - member_uids: group.member_uids ? group.member_uids.split(',') : [] - })); - } catch (error) { - logger.error('Error getting all groups from MySQL:', error); - throw error; - } + return rows.map(g => ({ + id: g.id, + name: g.name, + gid: g.id, + member_uids: g.member_uids ? g.member_uids.split(',').filter(Boolean) : [] + })); } - module.exports = { connect, close, findUserByUsername, findGroupsByMemberUid, getAllUsers, - getAllGroups -}; \ No newline at end of file + getAllGroups, + executeQuery +}; diff --git a/src/utils/ldapUtils.js b/src/utils/ldapUtils.js index 43e7415..9f8c93f 100644 --- a/src/utils/ldapUtils.js +++ b/src/utils/ldapUtils.js @@ -2,9 +2,14 @@ const logger = require("./logger"); function createLdapEntry(user) { - // Temp-Fix: Webchart schema doesn't have these right now - const uidNumber = user.uid_number !== undefined && user.uid_number !== null ? user.uid_number.toString() : "0"; - const gidNumber = user.gid_number !== undefined && user.gid_number !== null ? user.gid_number.toString() : "0"; + // // Temp-Fix: Webchart schema doesn't have these right now + const uidNumber = user.user_id !== undefined && user.user_id !== null + ? (parseInt(user.user_id) + 10000).toString() + : "10000"; + const gidNumber = user.gidNumber !== undefined && user.gidNumber !== null + ? (parseInt(user.gidNumber) + 10000).toString() + : "10000"; + const entry = { dn: `uid=${user.username},${process.env.LDAP_BASE_DN}`, @@ -13,14 +18,13 @@ function createLdapEntry(user) { uid: user.username, uidNumber, gidNumber, - cn: user.full_name || user.username, - gecos: user.full_name || user.username, - sn: user.surname || "Unknown", - mail: user.mail || `${user.username}@mieweb.com`, // Mandatory - homeDirectory: user.home_directory, + cn: user.first_name, + gecos: `${user.first_name || ''} ${user.last_name || ''}`.trim(), + sn: user.last_name || "Unknown", + mail: user.email || `${user.username}@mieweb.com`, + homeDirectory: `/home/${user.username}`, loginShell: "/bin/bash", - shadowLastChange: "0", - userpassword: user?.password, + shadowLastChange: "1", }, }; From ad63ec160783f2a0340696af7454935a0a091761 Mon Sep 17 00:00:00 2001 From: anishapant21 Date: Thu, 7 Aug 2025 13:41:37 -0400 Subject: [PATCH 2/5] Resolve PR comments and add proper loggers --- src/auth/providers/auth/ldapBackend.js | 40 +++++++++++----------- src/db/drivers/mysql.js | 46 ++++++++++++++++---------- src/server.js | 15 +++------ 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/auth/providers/auth/ldapBackend.js b/src/auth/providers/auth/ldapBackend.js index e66de31..41954fc 100644 --- a/src/auth/providers/auth/ldapBackend.js +++ b/src/auth/providers/auth/ldapBackend.js @@ -12,28 +12,23 @@ class LDAPBackend extends AuthProvider { setInterval(() => { this.failedServers.clear(); logger.debug("Resetting failed LDAP servers for retry."); - }, 5 * 60 * 1000); // every 5 minutes + }, 5 * 60 * 1000); } async authenticate(username, password, req) { for (const server of this.serverPool) { - if (this.failedServers.get(server.hostname)) { - continue; - } + if (this.failedServers.get(server.hostname)) continue; const url = `${server.scheme}//${server.hostname}:${server.port}`; - logger.debug(`Trying LDAP server: ${url} for user: ${username}`); + logger.debug("Attempting LDAP authentication via server", { host: server.hostname }); const success = await this.tryBind(url, username, password, server); - if (success) { - return true; - } else { - this.failedServers.set(server.hostname, Date.now()); - } + if (success) return true; + + this.failedServers.set(server.hostname, Date.now()); } - // if all tried and failed, clear the failed list for next time this.failedServers.clear(); return false; } @@ -45,11 +40,12 @@ class LDAPBackend extends AuthProvider { this.searchUserDN(client, username) .then((foundDN) => { if (!foundDN) { - logger.error("No DN found for user", { username }); + logger.warn("No DN found for user"); client.unbind(); return resolve(false); } - logger.debug(`Found user DN: ${foundDN}, attempting bind with user password...`); + + logger.debug("User DN found, attempting user bind..."); return this.attemptBind(client, foundDN, password); }) .then((success) => { @@ -57,13 +53,13 @@ class LDAPBackend extends AuthProvider { resolve(success); }) .catch((err) => { - logger.error("LDAP bind or search error", { url, username, err }); + logger.error("LDAP bind or search error", { error: err.message }); client.unbind(); resolve(false); }); client.on("error", (err) => { - logger.error("LDAP client connection error", { url, err }); + logger.error("LDAP client connection error", { error: err.message }); resolve(false); }); }); @@ -79,19 +75,20 @@ class LDAPBackend extends AuthProvider { client.bind(process.env.LDAP_BIND_DN, process.env.LDAP_BIND_PASSWORD, (err) => { if (err) { - logger.error("Service bind failed", err); - return reject(new Error("Service bind failed: " + err)); + logger.error("LDAP service bind failed", { error: err.message }); + return reject(new Error("Service bind failed")); } - logger.debug("Service bind successful, searching for user..."); + + logger.debug("LDAP service bind successful"); let foundDN = null; client.search('dc=mieweb,dc=com', opts, (err, res) => { if (err) return reject(err); res.on('searchEntry', (entry) => { - console.log("Found entry DN:", entry.objectName); foundDN = entry.dn.toString(); }); + res.on('error', (err) => reject(err)); res.on('end', () => resolve(foundDN)); }); @@ -103,10 +100,11 @@ class LDAPBackend extends AuthProvider { return new Promise((resolve) => { client.bind(dn, password, (err) => { if (err) { - logger.error("LDAP user bind failed", { dn, err }); + logger.warn("LDAP user bind failed"); return resolve(false); } - logger.info("LDAP user bind success", { dn }); + + logger.info("LDAP user bind succeeded"); return resolve(true); }); }); diff --git a/src/db/drivers/mysql.js b/src/db/drivers/mysql.js index 842462e..5afb64f 100644 --- a/src/db/drivers/mysql.js +++ b/src/db/drivers/mysql.js @@ -1,6 +1,6 @@ const mysql = require('mysql2/promise'); +const logger = require('../../utils/logger'); -// Create a connection pool at startup let pool; function createPool(config) { @@ -12,25 +12,32 @@ function createPool(config) { password: config.password, database: config.database, waitForConnections: true, - connectionLimit: 10, // Maximum number of connections in the pool - queueLimit: 0 // No limit on the number of waiting requests + connectionLimit: 10, + queueLimit: 0 }); - console.log("MySQL Connection Pool Created"); + logger.info("MySQL connection pool created"); } return pool; } -// Initialize the connection pool async function connect(config) { - return createPool(config); + try { + return createPool(config); + } catch (err) { + logger.error("Error creating MySQL pool", { error: err.message }); + throw err; + } } -// Close the pool (when shutting down the app) async function close() { if (pool) { - await pool.end(); - pool = null; - console.log("MySQL Connection Pool Closed"); + try { + await pool.end(); + logger.info("MySQL connection pool closed"); + pool = null; + } catch (err) { + logger.error("Error closing MySQL pool", { error: err.message }); + } } } @@ -39,14 +46,20 @@ async function executeQuery(sql, params = []) { const conn = await pool.getConnection(); try { const [rows] = await conn.execute(sql, params); - console.log(`SQL: ${sql}\nParams: ${JSON.stringify(params)}\nReturned rows: ${rows.length}`); return rows; + } catch (err) { + logger.error("Database query failed", { + error: err.message, + queryContext: sql.slice(0, 50) + '...', // don't log full user-generated queries + }); + throw err; } finally { conn.release(); } } async function findUserByUsername(username) { + logger.debug(`Looking up user: ${username}`); const sql = ` SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm FROM users u @@ -55,11 +68,11 @@ async function findUserByUsername(username) { LIMIT 1 `; const rows = await executeQuery(sql, [username]); - console.log('findUserByUsername result:', rows); return rows[0] || null; } async function findGroupsByMemberUid(username) { + logger.debug(`Fetching groups for user: ${username}`); const sql = ` SELECT r.realm AS name, r.id AS gid FROM user_realms ur @@ -70,7 +83,6 @@ async function findGroupsByMemberUid(username) { ORDER BY r.realm `; const groups = await executeQuery(sql, [username]); - console.log('findGroupsByMemberUid groups:', groups); const out = []; for (const g of groups) { @@ -82,7 +94,6 @@ async function findGroupsByMemberUid(username) { ORDER BY u.username `; const members = await executeQuery(membersSql, [g.name]); - console.log(`Members for group ${g.name}:`, members); out.push({ name: g.name, gid: g.gid, @@ -93,17 +104,18 @@ async function findGroupsByMemberUid(username) { } async function getAllUsers() { + logger.debug("Fetching all users"); const sql = ` SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm FROM users u LEFT JOIN realms r ON r.realm = u.realm ORDER BY u.username `; - const rows = await executeQuery(sql); - return rows; + return await executeQuery(sql); } async function getAllGroups() { + logger.debug("Fetching all groups"); const sql = ` SELECT r.id, r.realm AS name, COALESCE(GROUP_CONCAT(u.username ORDER BY u.username SEPARATOR ','), '') AS member_uids @@ -114,8 +126,6 @@ async function getAllGroups() { ORDER BY r.realm `; const rows = await executeQuery(sql); - console.log('getAllGroups result count:', rows.length); - return rows.map(g => ({ id: g.id, name: g.name, diff --git a/src/server.js b/src/server.js index 7bd087e..b9a6eb9 100644 --- a/src/server.js +++ b/src/server.js @@ -83,7 +83,7 @@ async function startServer() { res.end(); } } catch (error) { - logger.error("Bind error", { error }); + logger.error("Bind error", { message: error?.message }); return next(new ldap.OperationsError('Authentication error')); } }); @@ -92,7 +92,7 @@ async function startServer() { server.search(process.env.LDAP_BASE_DN, async (req, res, next) => { const filterStr = req.filter.toString(); - logger.debug(`LDAP Search - Filter: ${filterStr}, Attributes: ${req.attributes}`); + logger.debug("LDAP Search received", { attributes: req.attributes.length }); const username = getUsernameFromFilter(filterStr); @@ -110,14 +110,9 @@ async function startServer() { for (const user of users) { const entry = createLdapEntry(user); - logger.debug("Sending user entry:", { - dn: entry.dn, - uid: entry.attributes.uid, - objectClass: entry.attributes.objectClass, - cn: entry.attributes.cn, - uidNumber: entry.attributes.uidNumber, - gidNumber: entry.attributes.gidNumber - }); + + logger.debug("Sending user entry", { uid: entry.attributes?.uid }); + res.send(entry); } From ea48feaf969e3b426e777839aa96054028681f0f Mon Sep 17 00:00:00 2001 From: anishapant21 Date: Wed, 20 Aug 2025 18:42:13 -0400 Subject: [PATCH 3/5] Webchart obs code mapping to uid number --- src/config/dbConfig.js | 1 + src/db/drivers/mysql.js | 107 ++++++++++++++++++++++++++++++++++++++-- src/utils/ldapUtils.js | 47 ++++++++++++++---- 3 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/config/dbConfig.js b/src/config/dbConfig.js index 6d49a00..1cdb12b 100644 --- a/src/config/dbConfig.js +++ b/src/config/dbConfig.js @@ -6,6 +6,7 @@ const dbConfigs = { mysql: { type: 'mysql', host: process.env.MYSQL_HOST || "mysql", + port: process.env.MYSQL_PORT || "33306", user: process.env.MYSQL_USER || "root", password: process.env.MYSQL_PASSWORD || "rootpassword", database: process.env.MYSQL_DATABASE || "ldap_user_db", diff --git a/src/db/drivers/mysql.js b/src/db/drivers/mysql.js index 5afb64f..657ae3c 100644 --- a/src/db/drivers/mysql.js +++ b/src/db/drivers/mysql.js @@ -3,6 +3,39 @@ const logger = require('../../utils/logger'); let pool; +// cache for the obs_code lookup +let cachedObsCode = null; +let cachedObsName = null; + +async function getLdapUidObsCode() { + const obsName = process.env.LDAP_UID_OBS_NAME || 'LDAP UID Number'; + if (cachedObsCode !== null && cachedObsName === obsName) return cachedObsCode; + + const sql = ` + SELECT obs_code + FROM observation_codes + WHERE obs_name = ? + LIMIT 1 + `; + try { + const rows = await executeQuery(sql, [obsName]); + if (!rows[0]) { + logger.warn(`Observation code not found for name "${obsName}". ldap_uid_number will be NULL.`); + cachedObsCode = null; + } else { + cachedObsCode = rows[0].obs_code; + logger.info(`Using obs_code=${cachedObsCode} for "${obsName}"`); + } + cachedObsName = obsName; + return cachedObsCode; + } catch (err) { + logger.error("Failed to resolve LDAP UID observation code", { error: err.message }); + cachedObsCode = null; + cachedObsName = obsName; + return null; + } +} + function createPool(config) { if (!pool) { pool = mysql.createPool({ @@ -50,7 +83,7 @@ async function executeQuery(sql, params = []) { } catch (err) { logger.error("Database query failed", { error: err.message, - queryContext: sql.slice(0, 50) + '...', // don't log full user-generated queries + queryContext: sql.slice(0, 50) + '...', }); throw err; } finally { @@ -58,16 +91,63 @@ async function executeQuery(sql, params = []) { } } +function latestUidSubquery(obsCode) { + if (obsCode === null) return ''; // no-op + // Pick the latest by create_datetime; if tied, pick largest obs_id + return ` + LEFT JOIN ( + SELECT o1.user_id, o1.obs_result AS ldap_uid_number + FROM observations o1 + JOIN ( + SELECT user_id, + MAX(create_datetime) AS max_dt + FROM observations + WHERE obs_code = ? + GROUP BY user_id + ) mx + ON mx.user_id = o1.user_id + AND mx.max_dt = o1.create_datetime + WHERE o1.obs_code = ? + -- tie-breaker if multiple rows share the same timestamp + AND o1.obs_id = ( + SELECT MAX(o2.obs_id) + FROM observations o2 + WHERE o2.user_id = o1.user_id + AND o2.obs_code = o1.obs_code + AND o2.create_datetime = o1.create_datetime + ) + ) uid ON uid.user_id = u.user_id + `; +} + async function findUserByUsername(username) { logger.debug(`Looking up user: ${username}`); + const obsCode = await getLdapUidObsCode(); + const sql = ` - SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm + SELECT + u.user_id, + u.username, + u.first_name, + u.last_name, + u.email, + r.id AS gidNumber, + u.realm, + ${obsCode !== null ? 'uid.ldap_uid_number' : 'NULL AS ldap_uid_number'} FROM users u LEFT JOIN realms r ON r.realm = u.realm + ${obsCode !== null ? latestUidSubquery(obsCode) : ''} WHERE u.username = ? LIMIT 1 `; - const rows = await executeQuery(sql, [username]); + + const params = []; + if (obsCode !== null) { + params.push(obsCode, obsCode); // for the subquery + } + params.push(username); + + const rows = await executeQuery(sql, params); return rows[0] || null; } @@ -105,13 +185,30 @@ async function findGroupsByMemberUid(username) { async function getAllUsers() { logger.debug("Fetching all users"); + const obsCode = await getLdapUidObsCode(); + const sql = ` - SELECT u.user_id, u.username, u.first_name, u.last_name, u.email, r.id AS gidNumber, u.realm + SELECT + u.user_id, + u.username, + u.first_name, + u.last_name, + u.email, + r.id AS gidNumber, + u.realm, + ${obsCode !== null ? 'uid.ldap_uid_number' : 'NULL AS ldap_uid_number'} FROM users u LEFT JOIN realms r ON r.realm = u.realm + ${obsCode !== null ? latestUidSubquery(obsCode) : ''} ORDER BY u.username `; - return await executeQuery(sql); + + const params = []; + if (obsCode !== null) { + params.push(obsCode, obsCode); + } + + return await executeQuery(sql, params); } async function getAllGroups() { diff --git a/src/utils/ldapUtils.js b/src/utils/ldapUtils.js index 9f8c93f..db5c5a9 100644 --- a/src/utils/ldapUtils.js +++ b/src/utils/ldapUtils.js @@ -1,15 +1,35 @@ const logger = require("./logger"); +// Ensure we return a numeric string or undefined +function pickObsUid(user) { + const v = user?.ldap_uid_number; // set by the DB layer you just updated + if (v === undefined || v === null) return undefined; + const s = String(v).trim(); + if (s === "") return undefined; + + // uidNumber in LDAP must be an integer + const n = Number(s); + if (!Number.isFinite(n) || !Number.isInteger(n)) { + logger.warn("Invalid ldap_uid_number (not an integer). Falling back.", { value: s, user: user?.username }); + return undefined; + } + return String(n); +} function createLdapEntry(user) { - // // Temp-Fix: Webchart schema doesn't have these right now - const uidNumber = user.user_id !== undefined && user.user_id !== null - ? (parseInt(user.user_id) + 10000).toString() - : "10000"; - const gidNumber = user.gidNumber !== undefined && user.gidNumber !== null - ? (parseInt(user.gidNumber) + 10000).toString() - : "10000"; + // 1) Prefer observation-mapped UID (ldap_uid_number) + // 2) Fallback: old behavior (user_id + 10000) + const obsUid = pickObsUid(user); + const uidNumber = + obsUid ?? + (user.user_id !== undefined && user.user_id !== null + ? String(parseInt(user.user_id, 10) + 10000) + : "10000"); + const gidNumber = + (user.gidNumber !== undefined && user.gidNumber !== null + ? String(parseInt(user.gidNumber, 10) + 10000) + : "10000"); const entry = { dn: `uid=${user.username},${process.env.LDAP_BASE_DN}`, @@ -28,6 +48,16 @@ function createLdapEntry(user) { }, }; + logger.debug("Created LDAP user entry", { + dn: entry.dn, + uid: entry.attributes.uid, + uidNumber: entry.attributes.uidNumber, + gidNumber: entry.attributes.gidNumber, + uidSource: obsUid ? "observation" : "fallback", + }); + + console.log("entry", entry) + return entry; } @@ -51,7 +81,7 @@ function createLdapGroupEntry(group) { entry.attributes.member = group.members; } - logger.debug("Created LDAP group entry:", { + logger.debug("Created LDAP group entry", { dn: entry.dn, cn: entry.attributes.cn, gidNumber: entry.attributes.gidNumber, @@ -62,4 +92,3 @@ function createLdapGroupEntry(group) { } module.exports = { createLdapEntry, createLdapGroupEntry }; - From 352a330be1ea500fb5e0d73a8ffe653fc7180705 Mon Sep 17 00:00:00 2001 From: anishapant21 Date: Thu, 21 Aug 2025 12:17:33 -0400 Subject: [PATCH 4/5] Update env example --- src/.env.example | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/.env.example b/src/.env.example index a6cc33d..46787f4 100644 --- a/src/.env.example +++ b/src/.env.example @@ -14,6 +14,12 @@ DB_TYPE= # Authentication backend: 'db' or 'ldap' (Required) AUTH_BACKEND= +# Directory backend: 'db' or 'proxmox' (Required) +DIRECTORY_BACKEND= + +# WEBCHART OBSERVATION CODE (Optional : Required if WC) +LDAP_UID_OBS_NAME= + #LDAP configuration (Required) LDAP_BASE_DN= LDAP_PORT= @@ -27,4 +33,8 @@ LDAP_CERT_CONTENT= LDAP_KEY_CONTENT= # OpenLDAP Configuration (Required if AUTH_BACKEND is 'ldap') -LDAP_URL= \ No newline at end of file +LDAP_URL= + +# Bind Credentials (Optional: Required if WC) +LDAP_BIND_DN=CN= +LDAP_BIND_PASSWORD= \ No newline at end of file From 7c76f3ba6a9ee2efdd902798bd1115fd96f4a2a0 Mon Sep 17 00:00:00 2001 From: anishapant21 Date: Thu, 21 Aug 2025 12:35:05 -0400 Subject: [PATCH 5/5] Remove comments --- src/db/drivers/mysql.js | 2 +- src/utils/ldapUtils.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/drivers/mysql.js b/src/db/drivers/mysql.js index 657ae3c..76a2af6 100644 --- a/src/db/drivers/mysql.js +++ b/src/db/drivers/mysql.js @@ -92,7 +92,7 @@ async function executeQuery(sql, params = []) { } function latestUidSubquery(obsCode) { - if (obsCode === null) return ''; // no-op + if (obsCode === null) return ''; // Pick the latest by create_datetime; if tied, pick largest obs_id return ` LEFT JOIN ( diff --git a/src/utils/ldapUtils.js b/src/utils/ldapUtils.js index db5c5a9..3e88d03 100644 --- a/src/utils/ldapUtils.js +++ b/src/utils/ldapUtils.js @@ -2,7 +2,7 @@ const logger = require("./logger"); // Ensure we return a numeric string or undefined function pickObsUid(user) { - const v = user?.ldap_uid_number; // set by the DB layer you just updated + const v = user?.ldap_uid_number; if (v === undefined || v === null) return undefined; const s = String(v).trim(); if (s === "") return undefined;