helper.js•9.03 kB
// 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
};