privateGPT MCP Server

  • src
// helper.js import fs from 'fs'; import path from 'path'; import os from 'os'; import crypto from 'crypto'; import { fileURLToPath } from 'url'; import { logEvent } from './logger.js'; import { messages } from './pgpt-messages.js'; /** * Lädt die Umgebungsvariablen aus der JSON-Datei. * @param {string} envFilePath - Der Pfad zur JSON-Umgebungsdatei. * @returns {object} - Das geladene Konfigurationsobjekt. */ function loadEnvConfig(envFilePath) { try { const config = JSON.parse(fs.readFileSync(envFilePath, 'utf-8')); return config; } catch (error) { logEvent('system', 'N/A', 'Env Load Err', error.message, 'error'); process.exit(1); } } /** * Funktion zum Abrufen von Umgebungsvariablen mit optionalem verschachteltem Pfad und Fallback. * @param {object} envConfig - Das Konfigurationsobjekt. * @param {string} key - Der Schlüssel der Umgebungsvariable. * @param {Array<string>} [nestedPath=null] - Ein optionaler verschachtelter Pfad. * @param {any} [fallback=null] - Ein optionaler Fallback-Wert. * @param {string} lang - Die gewählte Sprache. * @returns {any} - Der Wert der Umgebungsvariable oder der Fallback-Wert. */ function getEnvVar(envConfig, key, nestedPath = null, fallback = null, lang = 'en') { const t = messages[lang]; // Prüfen, ob ein verschachtelter Pfad angegeben ist if (nestedPath) { const value = nestedPath.reduce((acc, part) => acc && acc[part], envConfig); if (value === undefined || value === null) { if (fallback !== null) return fallback; logEvent( 'system', 'N/A', 'Missing Config', t.missingConfigError.replace('${key}', key), 'error' ); process.exit(1); } return value; } // Direkter Zugriff if (envConfig[key] === undefined || envConfig[key] === null) { if (fallback !== null) return fallback; logEvent('system', 'N/A', 'Missing Config', `Missing .json configuration variable: ${key}`, 'error'); process.exit(1); } return envConfig[key]; } /** * Funktion zur Pfad-Expansion. * @param {string} filePath - Der zu erweiternde Pfad. * @returns {string} - Der erweiterte Pfad. */ function expandPath(filePath) { if (filePath.startsWith('~')) { return path.join(os.homedir(), filePath.slice(1)); } return filePath; } /** * Validiert eine URL und passt sie gegebenenfalls an. * @param {string} url - Die zu validierende URL. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @returns {string} - Die validierte und ggf. angepasste URL. */ function validateUrl(url, t) { if (!url.startsWith('https://')) { logEvent('system', 'N/A', 'URL Warning', t.apiUrlWarning, 'warn'); url = url.replace(/^http:\/\//, 'https://'); } url = url.replace(/([^:]\/)\/+/g, '$1'); // Doppelte Schrägstriche nach "://" entfernen if (!url.endsWith('/api/v1')) { logEvent('system', 'N/A', 'URL Warning V1', t.apiUrlWarningV1, 'warn'); url = `${url.replace(/\/$/, '')}/api/v1`; } try { new URL(url); } catch { logEvent('system', 'N/A', 'URL Invalid', `${t.apiUrlInvalid} ${url}`, 'error'); process.exit(1); } return url; } /** * Validiert einen Port. * @param {string} port - Der zu validierende Port. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @returns {number} - Der validierte Port. */ function validatePort(port, t) { const portNumber = parseInt(port, 10); if (isNaN(portNumber) || portNumber < 1 || portNumber > 65535) { logEvent('system', 'N/A', 'Port Invalid', t.portInvalid, 'error'); process.exit(1); } return portNumber; } /** * Validiert einen booleschen Wert. * @param {string} varName - Der Name der Variable. * @param {string} value - Der zu validierende Wert. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @param {boolean} [useProxy=false] - Ob eine Proxy-Verwendung erfolgt. * @returns {boolean} - Der validierte boolesche Wert. */ function validateBoolean(varName, value, t, useProxy = false) { if (useProxy && (varName === 'HEADER_ENCRYPTED')) { if (value !== 'true' && value !== 'false') { logEvent('system', 'N/A', 'Validation Err', t.validationError.replace('${var}', varName).replace('${value}', value), 'error'); process.exit(1); } return value === 'true'; } // Allgemeine Validierung if (value !== 'true' && value !== 'false') { logEvent('system', 'N/A', 'Validation Err', t.validationError.replace('${var}', varName).replace('${value}', value), 'error'); process.exit(1); } return value === 'true'; } /** * Entschlüsselt eine verschlüsselte Zeichenkette mit dem privaten Schlüssel. * @param {string} encryptedData - Die verschlüsselte Zeichenkette im Base64-Format. * @param {string} privateKey - Der private Schlüssel. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @returns {string} - Das entschlüsselte Passwort. */ function decryptPassword(encryptedData, privateKey, t) { try { const decryptedPassword = crypto.privateDecrypt( { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING, // Konsistentes Padding sicherstellen }, Buffer.from(encryptedData, 'base64') ).toString('utf8'); return decryptedPassword; } catch (error) { logEvent('system', 'N/A', 'Decryption Error', t.decryptionError, 'error'); throw new Error(t.decryptPwdError); } } /** * Verschlüsselt Daten mit dem öffentlichen Schlüssel. * @param {string} data - Die zu verschlüsselnden Daten. * @param {string} publicKey - Der öffentliche Schlüssel. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @returns {string} - Die verschlüsselten Daten als Base64-String. */ function encryptWithPublicKey(data, publicKey, t) { try { return crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING, // Padding explizit setzen }, Buffer.from(data) ).toString('base64'); } catch (err) { logEvent('system', 'N/A', 'Encryption Error', t.encryptionError, 'error'); throw new Error(t.encryptPwdError); } } /** * Verschlüsselt ein gegebenes Passwort und gibt den verschlüsselten Schlüssel zurück. * @param {string} password - Das zu verschlüsselnde Passwort. * @param {string} publicKey - Der öffentliche Schlüssel. * @param {object} t - Die Übersetzungen basierend auf der Sprache. * @returns {string} - Das verschlüsselte Passwort als Base64-String. */ function getEncryptedKey(password, publicKey, t) { try { return encryptWithPublicKey(password, publicKey, t); } catch (err) { // Fehlerbehandlung wurde bereits in encryptWithPublicKey durchgeführt throw err; } } /** * Prüft, ob ein bestimmtes Tool aktiviert ist. * @param {string} toolName - Der Name des Tools. * @param {object} envConfig - Die Umgebungs-Konfigurationsdaten. * @param {boolean} AllowKeygen - Ob Keygen erlaubt ist. * @param {string} lang - Die ausgewählte Sprache. * @returns {object|null} - Gibt einen Fehler zurück, wenn das Tool deaktiviert ist, sonst null. */ function checkToolEnabled(toolName, envConfig, AllowKeygen, lang) { const t = messages[lang]; if (toolName === "keygen" && AllowKeygen) { return null; } if (!isToolEnabled(toolName, envConfig, lang)) { logEvent( 'system', 'N/A', 'Tool Disabled', t.toolDisabledLog.replace('${toolName}', toolName), 'error' ); return { status: 'error', message: messages[lang].toolDisabledError.replace('${toolName}', toolName), }; } return null; // Tool ist aktiviert } /** * Prüft, ob ein bestimmtes Tool aktiviert ist. * @param {string} toolName - Der Name des Tools. * @param {object} envConfig - Die Umgebungs-Konfigurationsdaten. * @param {string} lang - Die ausgewählte Sprache. * @returns {boolean} - Gibt true zurück, wenn das Tool aktiviert ist, sonst false. */ function isToolEnabled(toolName, envConfig, lang) { const envKey = `ENABLE_${toolName.toUpperCase()}`; if (!(envKey in envConfig.Functions)) { logEvent( 'system', 'N/A', 'Tool Warn', messages[lang].toolNotDefinedInConfig.replace('${toolName}', toolName), 'warn' ); return false; } return envConfig.Functions[envKey] === true; } export { loadEnvConfig, getEnvVar, expandPath, validateUrl, validatePort, validateBoolean, decryptPassword, encryptWithPublicKey, getEncryptedKey, checkToolEnabled, isToolEnabled };