fix: corretto veramente ldap e d altro

This commit is contained in:
2026-07-08 02:27:38 +02:00
parent 882a1949a1
commit e6c3a6a43f
2 changed files with 211 additions and 50 deletions
+110 -43
View File
@@ -1,9 +1,23 @@
const express = require('express');
const router = express.Router();
const pool = require('../db');
const { db } = require('../activityDb');
// In-memory cache for customer users fetched from LDAP
let ldapCustomerUsersCache = [];
// Ensure SQLite tables for customer user cache exist in internal.db
db.exec(`
CREATE TABLE IF NOT EXISTS customer_user_cache (
login TEXT PRIMARY KEY,
email TEXT,
first_name TEXT,
last_name TEXT,
customer_id TEXT,
phone TEXT
);
CREATE TABLE IF NOT EXISTS sync_status (
key TEXT PRIMARY KEY,
val TEXT
);
`);
// Helper for OTRS CE GenericInterface REST API calls
async function otrsRequest(method, path, bodyData = {}) {
@@ -37,7 +51,11 @@ async function otrsRequest(method, path, bodyData = {}) {
const errorText = await response.text();
throw new Error(`OTRS REST API error (${response.status}): ${errorText}`);
}
return await response.json();
const result = await response.json();
if (result && result.Error) {
throw new Error(`OTRS API Error: ${result.Error.ErrorMessage} (${result.Error.ErrorCode})`);
}
return result;
} catch (err) {
clearTimeout(timeoutId);
if (err.name === 'AbortError') {
@@ -208,34 +226,41 @@ router.get('/customer-users/search', async (req, res) => {
// 1. Try to search via OTRS GenericInterface REST API if configured
if (process.env.OTRS_API_URL && process.env.OTRS_API_USER) {
// Search the in-memory cache first if it contains data
if (ldapCustomerUsersCache.length > 0) {
const searchTerms = q.toLowerCase().split(/\s+/).filter(Boolean);
let matchedUsers = ldapCustomerUsersCache;
if (searchTerms.length > 0) {
matchedUsers = matchedUsers.filter(u => {
const login = (u.login || '').toLowerCase();
const email = (u.email || '').toLowerCase();
const first = (u.first_name || '').toLowerCase();
const last = (u.last_name || '').toLowerCase();
const company = (u.customer_id || '').toLowerCase();
return searchTerms.every(term =>
login.includes(term) ||
email.includes(term) ||
first.includes(term) ||
last.includes(term) ||
company.includes(term)
);
});
}
try {
// Query the local SQLite cache table first
const searchTerm = q ? `%${q}%` : '%';
let rows;
if (customer_company_id) {
matchedUsers = matchedUsers.filter(u => u.customer_id === customer_company_id);
rows = db.prepare(`
SELECT login, email, first_name, last_name, customer_id
FROM customer_user_cache
WHERE customer_id = ? AND (
login LIKE ? OR
email LIKE ? OR
first_name LIKE ? OR
last_name LIKE ?
)
ORDER BY last_name, first_name
LIMIT 20
`).all(customer_company_id, searchTerm, searchTerm, searchTerm, searchTerm);
} else {
rows = db.prepare(`
SELECT login, email, first_name, last_name, customer_id
FROM customer_user_cache
WHERE login LIKE ? OR
email LIKE ? OR
first_name LIKE ? OR
last_name LIKE ?
ORDER BY last_name, first_name
LIMIT 20
`).all(searchTerm, searchTerm, searchTerm, searchTerm);
}
return res.json(matchedUsers.slice(0, 20));
if (rows.length > 0) {
return res.json(rows);
}
} catch (dbErr) {
console.warn('[LDAP Cache Search] SQLite query failed, falling back to live API:', dbErr.message);
}
// Fallback to live API search if cache is not yet populated
@@ -396,7 +421,7 @@ router.get('/states/search', async (req, res) => {
}
});
// Helper function to sync customer users from LDAP (OTRS API) into in-memory cache
// Helper function to sync customer users from LDAP (OTRS API) into SQLite cache
async function syncCustomerUsers() {
if (!process.env.OTRS_API_URL || !process.env.OTRS_API_USER) {
console.log('[LDAP Sync] OTRS API not configured, skipping customer user sync.');
@@ -420,7 +445,20 @@ async function syncCustomerUsers() {
console.log(`[LDAP Sync] Found ${logins.length} customer users. Fetching details...`);
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const newCache = [];
// Prepare SQLite insert statement with upsert logic
const upsertStmt = db.prepare(`
INSERT INTO customer_user_cache (login, email, first_name, last_name, customer_id, phone)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(login) DO UPDATE SET
email=excluded.email,
first_name=excluded.first_name,
last_name=excluded.last_name,
customer_id=excluded.customer_id,
phone=excluded.phone
`);
let syncCount = 0;
// Fetch details in batches of 3 to avoid overloading the OTRS CGI server
const batchSize = 3;
for (let i = 0; i < logins.length; i += batchSize) {
@@ -433,13 +471,17 @@ async function syncCustomerUsers() {
const getData = (getResult && getResult.Data) || getResult;
if (getData && getData.CustomerUser) {
const u = getData.CustomerUser;
newCache.push({
login: u.UserLogin,
email: u.UserEmail || '',
first_name: u.UserFirstname || '',
last_name: u.UserLastname || '',
customer_id: u.UserCustomerID || ''
});
// Run insertion in SQLite cache table
upsertStmt.run(
u.UserLogin,
u.UserEmail || '',
u.UserFirstname || '',
u.UserLastname || '',
u.UserCustomerID || '',
u.UserPhone || ''
);
syncCount++;
}
break; // Success, break retry loop
} catch (getErr) {
@@ -456,9 +498,15 @@ async function syncCustomerUsers() {
await delay(50);
}
ldapCustomerUsersCache = newCache;
console.log(`[LDAP Sync] Completed. Synced ${ldapCustomerUsersCache.length} users to in-memory cache.`);
return ldapCustomerUsersCache.length;
// Update last sync timestamp in SQLite sync_status table
db.prepare(`
INSERT INTO sync_status (key, val)
VALUES ('last_ldap_sync_time', ?)
ON CONFLICT(key) DO UPDATE SET val=excluded.val
`).run(new Date().toISOString());
console.log(`[LDAP Sync] Completed. Synced ${syncCount} users to SQLite customer_user_cache.`);
return syncCount;
} catch (err) {
console.error('[LDAP Sync] Error during customer user sync:', err);
throw err;
@@ -471,13 +519,32 @@ router.post('/customer-users/sync', async (req, res) => {
const count = await syncCustomerUsers();
res.json({ message: `Sincronizzazione completata! ${count} utenti sincronizzati.`, count });
} catch (err) {
res.status(500).json({ error: 'Errore durante la sincronizzazione', message: err.message });
console.warn('[LDAP Sync] Sincronizzazione non riuscita:', err.message);
res.json({ message: `Sincronizzazione LDAP ignorata o non disponibile: ${err.message}`, count: 0 });
}
});
// Run LDAP synchronization in the background on startup (after 5 seconds)
// Run LDAP synchronization on startup if last sync was > LDAP_SYNC_INTERVAL_HOURS ago
setTimeout(() => {
syncCustomerUsers().catch(err => console.error('Startup LDAP sync failed:', err));
try {
const row = db.prepare("SELECT val FROM sync_status WHERE key = 'last_ldap_sync_time'").get();
let shouldSync = true;
if (row && row.val) {
const lastSync = new Date(row.val);
const intervalHours = parseFloat(process.env.LDAP_SYNC_INTERVAL_HOURS) || 24;
const thresholdTime = new Date(Date.now() - intervalHours * 60 * 60 * 1000);
if (lastSync > thresholdTime) {
shouldSync = false;
console.log(`[LDAP Sync] Last sync was on ${lastSync.toLocaleString()} (Threshold: ${intervalHours}h). Skipping auto-sync at startup.`);
}
}
if (shouldSync) {
syncCustomerUsers().catch(err => console.error('Startup LDAP sync failed:', err));
}
} catch (err) {
console.error('[LDAP Sync] Failed to check LDAP sync status:', err.message);
}
}, 5000);
module.exports = router;