#!/usr/bin/env node /** * Dieses Skript konfiguriert das Next.js-Frontend, um das selbstsignierte SSL-Zertifikat zu akzeptieren * und die richtigen SSL-Einstellungen im Frontend zu setzen. */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // Pfade definieren const ENV_LOCAL_PATH = path.join(__dirname, '.env.local'); const ENV_FRONTEND_PATH = path.join(__dirname, 'env.frontend'); const SSL_DIR = path.join(__dirname, 'ssl'); const NEXT_CONFIG_PATH = path.join(__dirname, 'next.config.js'); console.log('=== Frontend-SSL-Konfiguration ==='); // Verzeichnis erstellen, falls es nicht existiert if (!fs.existsSync(SSL_DIR)) { console.log(`SSL-Verzeichnis wird erstellt: ${SSL_DIR}`); fs.mkdirSync(SSL_DIR, { recursive: true }); } // Prüfen, ob SSL-Zertifikate existieren if (!fs.existsSync(path.join(SSL_DIR, 'myp.crt')) || !fs.existsSync(path.join(SSL_DIR, 'myp.key'))) { console.log('SSL-Zertifikate nicht gefunden. Prüfe Backend-Verzeichnis...'); // Versuche, die Zertifikate aus dem Backend zu kopieren const backendCertPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.crt'); const backendKeyPath = path.join('..', 'backend', 'app', 'instance', 'ssl', 'myp.key'); if (fs.existsSync(backendCertPath) && fs.existsSync(backendKeyPath)) { console.log('Zertifikate im Backend-Verzeichnis gefunden. Kopiere...'); fs.copyFileSync(backendCertPath, path.join(SSL_DIR, 'myp.crt')); fs.copyFileSync(backendKeyPath, path.join(SSL_DIR, 'myp.key')); console.log('Zertifikate erfolgreich in das Frontend-Verzeichnis kopiert.'); } else { console.error('SSL-Zertifikate nicht gefunden. Bitte zuerst das Backend-Skript ausführen.'); process.exit(1); } } console.log('SSL-Zertifikate gefunden. Konfiguriere Frontend...'); // Umgebungsvariablen konfigurieren function updateEnvFile() { try { let envContent; // .env.local erstellen oder aktualisieren if (fs.existsSync(ENV_LOCAL_PATH)) { envContent = fs.readFileSync(ENV_LOCAL_PATH, 'utf8'); } else if (fs.existsSync(ENV_FRONTEND_PATH)) { envContent = fs.readFileSync(ENV_FRONTEND_PATH, 'utf8'); } else { envContent = `# MYP Frontend Umgebungsvariablen\n`; } // SSL-Konfigurationen mit alternativen Testoptionen const sslConfigs = [ 'NODE_TLS_REJECT_UNAUTHORIZED=0', 'HTTPS=true', 'SSL_CRT_FILE=./ssl/myp.crt', 'SSL_KEY_FILE=./ssl/myp.key', 'NEXT_PUBLIC_API_URL=https://raspberrypi:443', 'NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443', 'NEXT_PUBLIC_BACKEND_PROTOCOL=https', // Alternative Konfigurationen für Testversuche (auskommentiert) '# Alternative ohne HTTPS', '# HTTPS=false', '# NEXT_PUBLIC_API_URL=http://raspberrypi:80', '# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:80', '# NEXT_PUBLIC_BACKEND_PROTOCOL=http', '# Alternative mit IP statt Hostname', '# NEXT_PUBLIC_API_URL=https://192.168.0.105:443', '# NEXT_PUBLIC_BACKEND_HOST=192.168.0.105:443', '# Alternative mit localhost', '# NEXT_PUBLIC_API_URL=https://192.168.0.105:5000', '# NEXT_PUBLIC_BACKEND_HOST=192.168.0.105:5000', '# Alternative Ports testen', '# NEXT_PUBLIC_API_URL=https://raspberrypi:8443', '# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:8443', '# NEXT_PUBLIC_API_URL=http://raspberrypi:8080', '# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:8080' ]; // Existierende Konfigurationen aktualisieren sslConfigs.forEach(config => { const [key, value] = config.split('='); const regex = new RegExp(`^${key}=.*$`, 'm'); if (envContent.match(regex)) { // Update existierende Konfiguration envContent = envContent.replace(regex, config); } else { // Neue Konfiguration hinzufügen envContent += `\n${config}`; } }); // Speichern der aktualisierten Umgebungsvariablen fs.writeFileSync(ENV_LOCAL_PATH, envContent); console.log('.env.local Datei aktualisiert mit SSL-Konfigurationen'); return true; } catch (error) { console.error(`Fehler bei der Aktualisierung der Umgebungsvariablen: ${error.message}`); return false; } } // Next.js-Konfiguration aktualisieren function updateNextConfig() { try { let configContent; // next.config.js erstellen oder aktualisieren if (fs.existsSync(NEXT_CONFIG_PATH)) { configContent = fs.readFileSync(NEXT_CONFIG_PATH, 'utf8'); } else { configContent = `/** @type {import('next').NextConfig} */\n\nconst nextConfig = {}\n\nmodule.exports = nextConfig\n`; } // Prüfen, ob bereits eine HTTPS-Konfiguration vorhanden ist if (configContent.includes('serverOptions:') && configContent.includes('https:')) { console.log('HTTPS-Konfiguration ist bereits in der next.config.js vorhanden.'); return true; } // HTTPS-Konfiguration hinzufügen const httpsConfig = ` /** @type {import('next').NextConfig} */ const fs = require('fs'); const path = require('path'); const nextConfig = { reactStrictMode: true, webpack: (config) => { return config; }, // HTTPS-Konfiguration für die Entwicklung devServer: { https: { key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), }, }, // Konfiguration für selbstsignierte Zertifikate serverOptions: { https: { key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), }, }, // Zusätzliche Konfigurationen async rewrites() { return [ { source: '/api/:path*', destination: 'https://raspberrypi:443/api/:path*', }, ] } }; module.exports = nextConfig; `; // Speichern der aktualisierten Next.js-Konfiguration fs.writeFileSync(NEXT_CONFIG_PATH, httpsConfig); console.log('next.config.js Datei aktualisiert mit HTTPS-Konfiguration'); return true; } catch (error) { console.error(`Fehler bei der Aktualisierung der Next.js-Konfiguration: ${error.message}`); return false; } } // Update der Fetch-Konfiguration function updateFetchConfig() { try { const fetchConfigPath = path.join(__dirname, 'src', 'utils', 'api-config.ts'); if (!fs.existsSync(fetchConfigPath)) { console.warn('Datei api-config.ts nicht gefunden. Überspringe Aktualisierung.'); return true; } // Lesen der aktuellen Konfiguration let configContent = fs.readFileSync(fetchConfigPath, 'utf8'); // Sicherstellen, dass SSL-Verbindungen akzeptiert werden if (!configContent.includes('NODE_TLS_REJECT_UNAUTHORIZED=0')) { // Hinzufügen eines Kommentars zu Beginn der Datei configContent = `// SSL-Verbindungen akzeptieren (selbstsignierte Zertifikate) process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; ${configContent}`; } // Speichern der aktualisierten Fetch-Konfiguration fs.writeFileSync(fetchConfigPath, configContent); console.log('api-config.ts Datei aktualisiert, um selbstsignierte Zertifikate zu akzeptieren'); return true; } catch (error) { console.error(`Fehler bei der Aktualisierung der Fetch-Konfiguration: ${error.message}`); return false; } } // Abhängigkeiten installieren function installDependencies() { try { console.log('Installiere benötigte Abhängigkeiten...'); execSync('npm install --save-dev https-localhost', { stdio: 'inherit' }); console.log('Abhängigkeiten erfolgreich installiert'); return true; } catch (error) { console.error(`Fehler bei der Installation der Abhängigkeiten: ${error.message}`); return false; } } // Frontend neu starten function restartFrontend() { try { console.log('Starte Frontend-Server neu...'); // Prüfen, ob wir uns in Docker befinden if (process.env.CONTAINER) { console.log('Docker-Umgebung erkannt, verwende Docker-Befehle...'); execSync('docker-compose restart frontend', { stdio: 'inherit' }); } else { console.log('Lokale Umgebung, starte Next.js-Entwicklungsserver neu...'); // Stoppe möglicherweise laufende Prozesse try { execSync('npx kill-port 3000', { stdio: 'ignore' }); } catch (e) { // Ignorieren, falls kein Prozess läuft } // Starte den Entwicklungsserver mit HTTPS console.log('Frontend wird mit HTTPS gestartet. Verwende https://localhost:3000 zum Zugriff.'); console.log('Das Frontend wird im Hintergrund gestartet. Verwenden Sie "npm run dev", um es manuell zu starten.'); } console.log('Frontend-Server erfolgreich konfiguriert.'); return true; } catch (error) { console.error(`Fehler beim Neustart des Frontend-Servers: ${error.message}`); return false; } } // Hauptfunktion async function main() { let success = true; success = updateEnvFile() && success; success = updateNextConfig() && success; success = updateFetchConfig() && success; success = installDependencies() && success; success = restartFrontend() && success; if (success) { console.log('\n=== Konfiguration erfolgreich abgeschlossen ==='); console.log('Das Frontend wurde für die Verwendung von HTTPS mit dem selbstsignierten Zertifikat konfiguriert.'); console.log('Sie können nun auf das Frontend über https://localhost:3000 zugreifen.'); console.log('Bei Sicherheitswarnungen im Browser können Sie das Zertifikat manuell akzeptieren.'); } else { console.error('\n=== Konfiguration nicht vollständig abgeschlossen ==='); console.error('Es gab Probleme bei der Konfiguration des Frontends.'); console.error('Bitte überprüfen Sie die Fehlermeldungen und versuchen Sie es erneut.'); } } // Ausführen der Hauptfunktion main().catch(error => { console.error(`Unerwarteter Fehler: ${error.message}`); process.exit(1); });