fix: verificare, ma dovrebbe essere corretta la lattura da ldap
This commit is contained in:
+175
-5
@@ -2,6 +2,9 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const pool = require('../db');
|
||||
|
||||
// In-memory cache for customer users fetched from LDAP
|
||||
let ldapCustomerUsersCache = [];
|
||||
|
||||
// Helper for OTRS CE GenericInterface REST API calls
|
||||
async function otrsRequest(method, path, bodyData = {}) {
|
||||
const OTRS_API_USER = process.env.OTRS_API_USER;
|
||||
@@ -19,7 +22,7 @@ async function otrsRequest(method, path, bodyData = {}) {
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 6000);
|
||||
const timeoutId = setTimeout(() => controller.abort(), 15000);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
@@ -38,7 +41,7 @@ async function otrsRequest(method, path, bodyData = {}) {
|
||||
} catch (err) {
|
||||
clearTimeout(timeoutId);
|
||||
if (err.name === 'AbortError') {
|
||||
throw new Error('OTRS REST API request timed out (6s limit exceeded)');
|
||||
throw new Error('OTRS REST API request timed out (15s limit exceeded)');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
@@ -199,11 +202,94 @@ router.get('/customer-companies/search', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/customer-users/search — Search customer users (always from local DB)
|
||||
// GET /api/customer-users/search — Search customer users (supports LDAP via REST, fallbacks to DB)
|
||||
router.get('/customer-users/search', async (req, res) => {
|
||||
try {
|
||||
const { q = '', customer_company_id } = req.query;
|
||||
const { q = '', customer_company_id } = req.query;
|
||||
|
||||
// 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)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (customer_company_id) {
|
||||
matchedUsers = matchedUsers.filter(u => u.customer_id === customer_company_id);
|
||||
}
|
||||
|
||||
return res.json(matchedUsers.slice(0, 20));
|
||||
}
|
||||
|
||||
// Fallback to live API search if cache is not yet populated
|
||||
try {
|
||||
const searchPattern = q ? `*${q}*` : '*';
|
||||
const searchPayload = {
|
||||
Search: searchPattern,
|
||||
Valid: 1
|
||||
};
|
||||
if (customer_company_id) {
|
||||
searchPayload.CustomerID = customer_company_id;
|
||||
}
|
||||
|
||||
const searchResult = await otrsRequest('POST', '/CustomerUserSearch', searchPayload);
|
||||
|
||||
const searchData = (searchResult && searchResult.Data) || searchResult;
|
||||
if (searchData && searchData.CustomerUserID) {
|
||||
let logins = searchData.CustomerUserID;
|
||||
if (!Array.isArray(logins)) {
|
||||
logins = [logins];
|
||||
}
|
||||
logins = logins.slice(0, 20); // limit to 20 results
|
||||
|
||||
// Fetch details for each login in parallel
|
||||
const detailsPromises = logins.map(async (login) => {
|
||||
try {
|
||||
const getResult = await otrsRequest('POST', '/CustomerUserGet', { UserLogin: login });
|
||||
const getData = (getResult && getResult.Data) || getResult;
|
||||
if (getData && getData.CustomerUser) {
|
||||
const u = getData.CustomerUser;
|
||||
return {
|
||||
login: u.UserLogin,
|
||||
email: u.UserEmail || '',
|
||||
first_name: u.UserFirstname || '',
|
||||
last_name: u.UserLastname || '',
|
||||
customer_id: u.UserCustomerID || ''
|
||||
};
|
||||
}
|
||||
} catch (getErr) {
|
||||
console.warn(`Failed to fetch details for customer user ${login}:`, getErr.message);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const users = (await Promise.all(detailsPromises)).filter(u => u !== null);
|
||||
return res.json(users);
|
||||
}
|
||||
} catch (restErr) {
|
||||
console.warn('Failed to search customer users via REST API, falling back to database query:', restErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fallback to local DB query
|
||||
try {
|
||||
let queryText;
|
||||
let queryParams;
|
||||
if (q) {
|
||||
@@ -310,4 +396,88 @@ router.get('/states/search', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to sync customer users from LDAP (OTRS API) into in-memory 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.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
console.log('[LDAP Sync] Starting customer user synchronization...');
|
||||
try {
|
||||
const searchResult = await otrsRequest('POST', '/CustomerUserSearch', { Search: '*', Valid: 1 });
|
||||
const searchData = (searchResult && searchResult.Data) || searchResult;
|
||||
if (!searchData || !searchData.CustomerUserID) {
|
||||
console.log('[LDAP Sync] No customer users found to sync.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
let logins = searchData.CustomerUserID;
|
||||
if (!Array.isArray(logins)) {
|
||||
logins = [logins];
|
||||
}
|
||||
|
||||
console.log(`[LDAP Sync] Found ${logins.length} customer users. Fetching details...`);
|
||||
|
||||
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
const newCache = [];
|
||||
// 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) {
|
||||
const batchLogins = logins.slice(i, i + batchSize);
|
||||
await Promise.all(batchLogins.map(async (login) => {
|
||||
let retries = 2;
|
||||
while (retries >= 0) {
|
||||
try {
|
||||
const getResult = await otrsRequest('POST', '/CustomerUserGet', { UserLogin: login });
|
||||
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 || ''
|
||||
});
|
||||
}
|
||||
break; // Success, break retry loop
|
||||
} catch (getErr) {
|
||||
if (retries === 0) {
|
||||
console.warn(`[LDAP Sync] Failed to sync customer user ${login} after retries:`, getErr.message);
|
||||
} else {
|
||||
await delay(200); // Wait 200ms before retrying
|
||||
}
|
||||
retries--;
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Add a small delay between batches
|
||||
await delay(50);
|
||||
}
|
||||
|
||||
ldapCustomerUsersCache = newCache;
|
||||
console.log(`[LDAP Sync] Completed. Synced ${ldapCustomerUsersCache.length} users to in-memory cache.`);
|
||||
return ldapCustomerUsersCache.length;
|
||||
} catch (err) {
|
||||
console.error('[LDAP Sync] Error during customer user sync:', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/customer-users/sync — Sync customer users from LDAP
|
||||
router.post('/customer-users/sync', async (req, res) => {
|
||||
try {
|
||||
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 });
|
||||
}
|
||||
});
|
||||
|
||||
// Run LDAP synchronization in the background on startup (after 5 seconds)
|
||||
setTimeout(() => {
|
||||
syncCustomerUsers().catch(err => console.error('Startup LDAP sync failed:', err));
|
||||
}, 5000);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
+13
-1
@@ -459,6 +459,18 @@ router.post('/', async (req, res) => {
|
||||
const c = custRes.rows[0];
|
||||
customerFrom = `${c.first_name} ${c.last_name} <${c.email}>`;
|
||||
senderTypeName = 'customer';
|
||||
} else if (process.env.OTRS_API_URL && process.env.OTRS_API_USER) {
|
||||
try {
|
||||
const getResult = await otrsRequest('POST', '/CustomerUserGet', { UserLogin: customer_user_id });
|
||||
const getData = (getResult && getResult.Data) || getResult;
|
||||
if (getData && getData.CustomerUser) {
|
||||
const u = getData.CustomerUser;
|
||||
customerFrom = `${u.UserFirstname || ''} ${u.UserLastname || ''} <${u.UserEmail || ''}>`.trim();
|
||||
senderTypeName = 'customer';
|
||||
}
|
||||
} catch (apiErr) {
|
||||
console.warn(`Failed to fetch LDAP customer details for ${customer_user_id}:`, apiErr.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1351,7 +1363,7 @@ router.get('/attachments/:id', async (req, res) => {
|
||||
} else if (typeof attachment.content === 'string') {
|
||||
contentStr = attachment.content;
|
||||
}
|
||||
|
||||
|
||||
const cleaned = contentStr.replace(/\s+/g, '');
|
||||
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
||||
if (cleaned.length % 4 === 0 && base64Regex.test(cleaned)) {
|
||||
|
||||
Reference in New Issue
Block a user