UNPKG

survey-mcp-server

Version:
400 lines (399 loc) 15.2 kB
/** * Company Name Filtering Utilities * Helper functions for filtering data based on company IMO numbers * * ============================================================================ * OLD IMPLEMENTATION (COMMENTED OUT - REPLACED BY OPTIMIZED VERSION) * ============================================================================ * The old implementation has been replaced with an optimized version that includes: * - In-memory caching with TTL (5 minutes) * - MongoDB connection pooling * - Set-based IMO lookups (O(1) instead of O(n)) * - Cached environment variables * ============================================================================ */ import { MongoClient } from "mongodb"; /** * Check if IMO filtering should be bypassed for admin companies */ function shouldBypassImoFiltering(companyName) { const adminCompanies = ['admin', 'administrator', 'superadmin', 'syia']; return adminCompanies.some(admin => companyName.toLowerCase().includes(admin.toLowerCase())); } /** * Optimized Company Filter Manager with caching and connection pooling */ class CompanyFilterManager { // Cache structure: Map<"companyName:dbName", { imos: Set<string>, timestamp: number }> imoCache = new Map(); // Connection pool: Map<"mongoUri", MongoClient> mongoClients = new Map(); // Cache TTL: 5 minutes CACHE_TTL = 5 * 60 * 1000; // Cached environment variables cachedCompanyName = null; cachedDbConfig = null; /** * Get company name (cached) */ getCompanyName() { if (this.cachedCompanyName === null) { this.cachedCompanyName = process.env.COMPANY_NAME || ''; } return this.cachedCompanyName; } /** * Get database configuration (cached) */ getDbConfig() { if (this.cachedDbConfig === null) { this.cachedDbConfig = { dbName: process.env.GROUP_DETAILS_DB_NAME || process.env.FLEET_DISTRIBUTION_DB_NAME || '', mongoUri: process.env.GROUP_DETAILS_MONGO_URI || process.env.FLEET_DISTRIBUTION_MONGO_URI || '' }; } return this.cachedDbConfig; } /** * Get or create MongoDB client (connection pooling) */ async getMongoClient(mongoUri) { if (!this.mongoClients.has(mongoUri)) { const client = new MongoClient(mongoUri, { maxPoolSize: 10, minPoolSize: 2, maxIdleTimeMS: 30000 }); await client.connect(); this.mongoClients.set(mongoUri, client); } return this.mongoClients.get(mongoUri); } /** * Get company IMO set with caching (returns Set for O(1) lookups) */ async getCompanyImoSet(companyName, dbName, mongoUri, collectionName = 'common_group_details') { const cacheKey = `${companyName}:${dbName}`; const cached = this.imoCache.get(cacheKey); // Return from cache if valid if (cached && (Date.now() - cached.timestamp) < this.CACHE_TTL) { return cached.imos; } // Fetch from MongoDB if (!dbName || !mongoUri || !companyName) { return new Set(); } try { const client = await this.getMongoClient(mongoUri); const db = client.db(dbName); const collection = db.collection(collectionName); // Try both companyName and groupName fields for compatibility const result = await collection.findOne({ $or: [{ companyName: companyName }, { groupName: companyName }] }, { projection: { imoList: 1, _id: 0 } }); const imoSet = new Set(result?.imoList?.map((imo) => String(imo)) || []); // Update cache this.imoCache.set(cacheKey, { imos: imoSet, timestamp: Date.now() }); return imoSet; } catch (error) { console.error(`Error fetching IMO numbers for company ${companyName}:`, error); return new Set(); } } /** * Validate if an IMO belongs to the company (optimized) */ async isValidImoForCompany(imo, companyName, dbName, mongoUri) { const finalCompanyName = companyName || this.getCompanyName(); if (!finalCompanyName) { return true; // If no company name, allow all } // Bypass validation for "Synergy" company if (finalCompanyName === "Synergy") { return true; } // Bypass validation for admin companies if (shouldBypassImoFiltering(finalCompanyName)) { return true; } // Use provided dbName/mongoUri or fallback to cached environment variables const config = this.getDbConfig(); const finalDbName = dbName || config.dbName; const finalMongoUri = mongoUri || config.mongoUri; if (!finalDbName || !finalMongoUri) { return true; // Allow if config is missing } try { const imoSet = await this.getCompanyImoSet(finalCompanyName, finalDbName, finalMongoUri); // O(1) lookup using Set return imoSet.has(String(imo)); } catch (error) { console.error(`Error validating IMO for company: ${error}`); return true; // Allow on error to prevent blocking } } /** * Update Typesense filter with company IMO numbers (optimized) */ async updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri) { const companyName = this.getCompanyName(); if (!companyName) { return filter; } // Bypass filtering for "Synergy" company if (companyName === "Synergy") { return filter; } // Bypass filtering for admin companies if (shouldBypassImoFiltering(companyName)) { return filter; } // Use provided dbName/mongoUri or fallback to cached environment variables const config = this.getDbConfig(); const finalDbName = dbName || config.dbName; const finalMongoUri = mongoUri || config.mongoUri; if (!finalDbName || !finalMongoUri) { return filter; } try { const imoSet = await this.getCompanyImoSet(companyName, finalDbName, finalMongoUri); if (imoSet.size === 0) { // If no company IMO numbers found, return a filter that matches nothing for security // This prevents access to all data when company configuration is missing return filter ? `${filter} && imo:0` : 'imo:0'; } const imoFilter = `imo:[${Array.from(imoSet).join(",")}]`; if (filter && filter.trim()) { return `${filter} && ${imoFilter}`; } else { return imoFilter; } } catch (error) { console.error(`Error updating Typesense filter with company IMOs: ${error}`); return filter; // Return original filter on error } } /** * Get authorized IMO numbers for a company (for fleet filtering) */ async getAuthorizedImoNumbers(companyName, dbName, mongoUri) { const finalCompanyName = companyName || this.getCompanyName(); if (!finalCompanyName) { return []; } // Bypass for "Synergy" company - return empty to allow all if (finalCompanyName === "Synergy") { return []; } // Bypass for admin companies - return empty to allow all if (shouldBypassImoFiltering(finalCompanyName)) { return []; } // Use provided dbName/mongoUri or fallback to cached environment variables const config = this.getDbConfig(); const finalDbName = dbName || config.dbName; const finalMongoUri = mongoUri || config.mongoUri; if (!finalDbName || !finalMongoUri) { return []; } try { const imoSet = await this.getCompanyImoSet(finalCompanyName, finalDbName, finalMongoUri); return Array.from(imoSet); } catch (error) { console.error(`Error fetching authorized IMO numbers: ${error}`); return []; } } /** * Clear cache (useful for testing or forced refresh) */ clearCache() { this.imoCache.clear(); this.cachedCompanyName = null; this.cachedDbConfig = null; } /** * Close all MongoDB connections (cleanup) */ async closeConnections() { const closePromises = Array.from(this.mongoClients.values()).map(client => client.close()); await Promise.all(closePromises); this.mongoClients.clear(); } } // Singleton instance export const companyFilter = new CompanyFilterManager(); // Export functions for backward compatibility export async function isValidImoForCompany(imo, companyName, dbName, mongoUri) { return companyFilter.isValidImoForCompany(imo, companyName, dbName, mongoUri); } export async function updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri) { return companyFilter.updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri); } export async function getAuthorizedImoNumbers(companyName, dbName, mongoUri) { return companyFilter.getAuthorizedImoNumbers(companyName, dbName, mongoUri); } // Export shouldBypassImoFiltering for use in handlers export { shouldBypassImoFiltering }; /** * ============================================================================ * OLD IMPLEMENTATION (COMMENTED OUT) * ============================================================================ */ // /** // * Fetch IMO numbers for a specific company from MongoDB // */ // async function fetchCompanyImoNumbers(companyName: string, dbName: string, mongoUri: string, collectionName: string = 'common_group_details'): Promise<string[]> { // if (!dbName || !mongoUri || !companyName) { // return []; // } // // const mongoClient = new MongoClient(mongoUri); // await mongoClient.connect(); // // try { // const db = mongoClient.db(dbName); // const collection = db.collection(collectionName); // // const companyDoc = await collection.findOne({ companyName: companyName }); // // if (companyDoc && companyDoc.imoList && Array.isArray(companyDoc.imoList)) { // return companyDoc.imoList.map((imo: any) => String(imo)); // } // // return []; // } catch (error) { // console.error(`Error fetching company IMO numbers: ${error}`); // return []; // } finally { // await mongoClient.close(); // } // } // /** // * Check if IMO filtering should be bypassed for admin companies // */ // function shouldBypassImoFiltering(companyName: string): boolean { // const adminCompanies = ['admin', 'Admin', 'ADMIN', 'SYIA', 'Syia']; // return adminCompanies.includes(companyName); // } // /** // * Validate if an IMO belongs to the company // */ // export async function isValidImoForCompany(imo: string | number, companyName?: string, dbName?: string, mongoUri?: string): Promise<boolean> { // const finalCompanyName = companyName || process.env.COMPANY_NAME || ''; // // if (!finalCompanyName) { // return true; // If no company name, allow all // } // // // Bypass validation for "Synergy" company // if (finalCompanyName === "Synergy") { // return true; // } // // // Bypass validation for admin companies // if (shouldBypassImoFiltering(finalCompanyName)) { // return true; // } // // // Use provided dbName/mongoUri or fallback to environment variables // const finalDbName = dbName || process.env.GROUP_DETAILS_DB_NAME || process.env.FLEET_DISTRIBUTION_DB_NAME || ''; // const finalMongoUri = mongoUri || process.env.GROUP_DETAILS_MONGO_URI || process.env.FLEET_DISTRIBUTION_MONGO_URI || ''; // // if (!finalDbName || !finalMongoUri) { // return true; // Allow if config is missing // } // // try { // const imoNumbers = await fetchCompanyImoNumbers(finalCompanyName, finalDbName, finalMongoUri); // return imoNumbers.includes(String(imo)); // } catch (error) { // console.error(`Error validating IMO for company: ${error}`); // return true; // Allow on error to prevent blocking // } // } // /** // * Update Typesense filter with company IMO numbers for filtering // */ // export async function updateTypesenseFilterWithCompanyImos(filter: string, dbName?: string, mongoUri?: string): Promise<string> { // const companyName = process.env.COMPANY_NAME || ''; // // if (!companyName) { // return filter; // } // // // Bypass filtering for "Synergy" company // if (companyName === "Synergy") { // return filter; // } // // // Bypass filtering for admin companies // if (shouldBypassImoFiltering(companyName)) { // return filter; // } // // // Use provided dbName/mongoUri or fallback to environment variables // const finalDbName = dbName || process.env.GROUP_DETAILS_DB_NAME || process.env.FLEET_DISTRIBUTION_DB_NAME || ''; // const finalMongoUri = mongoUri || process.env.GROUP_DETAILS_MONGO_URI || process.env.FLEET_DISTRIBUTION_MONGO_URI || ''; // // if (!finalDbName || !finalMongoUri) { // return filter; // } // // const companyImos = await fetchCompanyImoNumbers(companyName, finalDbName, finalMongoUri); // // if (companyImos.length === 0) { // // If no company IMO numbers found, return a filter that matches nothing for security // // This prevents access to all data when company configuration is missing // return filter ? `${filter} && imo:0` : 'imo:0'; // } // // const imoFilter = `imo:[${companyImos.join(",")}]`; // // if (filter && filter.trim()) { // return `${filter} && ${imoFilter}`; // } else { // return imoFilter; // } // } // /** // * Get authorized IMO numbers for a company // */ // export async function getAuthorizedImoNumbers(companyName?: string, dbName?: string, mongoUri?: string): Promise<string[]> { // const finalCompanyName = companyName || process.env.COMPANY_NAME || ''; // // if (!finalCompanyName) { // return []; // If no company name, return empty // } // // // Bypass for "Synergy" company - return empty to allow all // if (finalCompanyName === "Synergy") { // return []; // } // // // Bypass for admin companies - return empty to allow all // if (shouldBypassImoFiltering(finalCompanyName)) { // return []; // } // // // Use provided dbName/mongoUri or fallback to environment variables // const finalDbName = dbName || process.env.GROUP_DETAILS_DB_NAME || process.env.FLEET_DISTRIBUTION_DB_NAME || ''; // const finalMongoUri = mongoUri || process.env.GROUP_DETAILS_MONGO_URI || process.env.FLEET_DISTRIBUTION_MONGO_URI || ''; // // if (!finalDbName || !finalMongoUri) { // return []; // } // // try { // return await fetchCompanyImoNumbers(finalCompanyName, finalDbName, finalMongoUri); // } catch (error) { // console.error(`Error fetching authorized IMO numbers: ${error}`); // return []; // } // }