From 5dd1b7b78b4232f089c64a8341a784e9dedbf00d Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Mon, 19 May 2025 07:30:16 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20=C3=84nderungen=20commited?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../debug-server/package.json | 22 +- .../debug-server/public/css/style.css | 1 + .../debug-server/public/views/index.ejs | 186 +++++++ .../debug-server/src/index.js | 471 ++++++++++++++++++ 4 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 packages/reservation-platform/debug-server/public/css/style.css create mode 100644 packages/reservation-platform/debug-server/public/views/index.ejs create mode 100644 packages/reservation-platform/debug-server/src/index.js diff --git a/packages/reservation-platform/debug-server/package.json b/packages/reservation-platform/debug-server/package.json index 0519ecba..648a9f83 100644 --- a/packages/reservation-platform/debug-server/package.json +++ b/packages/reservation-platform/debug-server/package.json @@ -1 +1,21 @@ - \ No newline at end of file +{ + "name": "myp-frontend-debug-server", + "version": "1.0.0", + "description": "Debug-Server für das MYP Frontend", + "main": "src/index.js", + "scripts": { + "start": "node src/index.js", + "dev": "nodemon src/index.js" + }, + "dependencies": { + "express": "^4.18.2", + "systeminformation": "^5.18.15", + "ejs": "^3.1.9", + "os-utils": "^0.0.14", + "node-fetch": "^2.6.7", + "socket.io": "^4.7.2" + }, + "devDependencies": { + "nodemon": "^3.0.2" + } +} \ No newline at end of file diff --git a/packages/reservation-platform/debug-server/public/css/style.css b/packages/reservation-platform/debug-server/public/css/style.css new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/packages/reservation-platform/debug-server/public/css/style.css @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/reservation-platform/debug-server/public/views/index.ejs b/packages/reservation-platform/debug-server/public/views/index.ejs new file mode 100644 index 00000000..a9a1da96 --- /dev/null +++ b/packages/reservation-platform/debug-server/public/views/index.ejs @@ -0,0 +1,186 @@ + + + + + + MYP Frontend Debug-Server + + + + + +
+
+

MYP Frontend Debug-Server

+
+ Hostname: <%= hostname %> + <% for(const [interface, ip] of Object.entries(ipAddresses)) { %> + <%= interface %>: <%= ip %> + <% } %> + Zeitstempel: <%= timestamp %> +
+
+
+ + + +
+ +
+

Systeminformationen

+
Lade Daten...
+ +
+ + +
+

Netzwerkinformationen

+
Lade Daten...
+ +
+ + +
+

Dienststatus

+
Lade Daten...
+ +
+ + +
+

Netzwerk-Diagnosetools

+
+
+

Ping

+
+ + +
+
Geben Sie einen Hostnamen oder eine IP-Adresse ein...
+
+ +
+

Traceroute

+
+ + +
+
Geben Sie einen Hostnamen oder eine IP-Adresse ein...
+
+ +
+

DNS-Lookup

+
+ + +
+
Geben Sie einen Hostnamen oder eine IP-Adresse ein...
+
+
+
+ + +
+

Echtzeit-Monitoring

+
+
+

CPU-Auslastung

+
+
+
+
+
+
+
0%
+
+
+
+
+ +
+

Arbeitsspeicher

+
+
+
+
+
+
+
0%
+
+
+
+
+ +
+

Netzwerkdurchsatz

+
+ +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/packages/reservation-platform/debug-server/src/index.js b/packages/reservation-platform/debug-server/src/index.js new file mode 100644 index 00000000..f3bf3f20 --- /dev/null +++ b/packages/reservation-platform/debug-server/src/index.js @@ -0,0 +1,471 @@ +// Frontend Debug-Server für MYP +const express = require('express'); +const path = require('path'); +const http = require('http'); +const si = require('systeminformation'); +const os = require('os'); +const osUtils = require('os-utils'); +const { exec } = require('child_process'); +const fetch = require('node-fetch'); +const socketIo = require('socket.io'); + +// Konfiguration +const app = express(); +const server = http.createServer(app); +const io = socketIo(server); +const PORT = 6666; +const FRONTEND_PORT = 3000; +const FRONTEND_HOST = 'localhost'; +const BACKEND_HOST = 'localhost'; +const BACKEND_PORT = 5000; + +// View Engine einrichten +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, '../public/views')); +app.use(express.static(path.join(__dirname, '../public'))); +app.use(express.json()); + +// Hauptseite rendern +app.get('/', async (req, res) => { + const hostname = os.hostname(); + const networkInterfaces = os.networkInterfaces(); + const ipAddresses = {}; + + // IP-Adressen sammeln + Object.keys(networkInterfaces).forEach(interfaceName => { + const interfaceInfo = networkInterfaces[interfaceName]; + const ipv4Addresses = interfaceInfo.filter(info => info.family === 'IPv4'); + if (ipv4Addresses.length > 0) { + ipAddresses[interfaceName] = ipv4Addresses[0].address; + } + }); + + // Rendere die Hauptseite mit Basisdaten + res.render('index', { + hostname: hostname, + ipAddresses: ipAddresses, + timestamp: new Date().toLocaleString('de-DE'), + }); +}); + +// API-Endpunkte + +// Systeminformationen +app.get('/api/system', async (req, res) => { + try { + const [cpu, mem, osInfo, diskLayout, fsSize] = await Promise.all([ + si.cpu(), + si.mem(), + si.osInfo(), + si.diskLayout(), + si.fsSize() + ]); + + const data = { + cpu: { + manufacturer: cpu.manufacturer, + brand: cpu.brand, + speed: cpu.speed, + cores: cpu.cores, + physicalCores: cpu.physicalCores + }, + memory: { + total: formatBytes(mem.total), + free: formatBytes(mem.free), + used: formatBytes(mem.used), + usedPercent: Math.round(mem.used / mem.total * 100) + }, + os: { + platform: osInfo.platform, + distro: osInfo.distro, + release: osInfo.release, + arch: osInfo.arch, + uptime: formatUptime(os.uptime()) + }, + filesystem: fsSize.map(fs => ({ + fs: fs.fs, + type: fs.type, + size: formatBytes(fs.size), + used: formatBytes(fs.used), + available: formatBytes(fs.available), + mount: fs.mount, + usePercent: Math.round(fs.use) + })), + disks: diskLayout.map(disk => ({ + device: disk.device, + type: disk.type, + name: disk.name, + size: formatBytes(disk.size) + })) + }; + + res.json(data); + } catch (error) { + console.error('Fehler beim Abrufen der Systemdaten:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Systemdaten' }); + } +}); + +// Netzwerkinformationen +app.get('/api/network', async (req, res) => { + try { + const [netInterfaces, netStats] = await Promise.all([ + si.networkInterfaces(), + si.networkStats() + ]); + + const dns = await getDnsServers(); + const gateway = await getDefaultGateway(); + + const data = { + interfaces: netInterfaces.map(iface => ({ + iface: iface.iface, + ip4: iface.ip4, + ip6: iface.ip6, + mac: iface.mac, + internal: iface.internal, + operstate: iface.operstate, + type: iface.type, + speed: iface.speed, + dhcp: iface.dhcp + })), + stats: netStats.map(stat => ({ + iface: stat.iface, + rx_bytes: formatBytes(stat.rx_bytes), + tx_bytes: formatBytes(stat.tx_bytes), + rx_sec: formatBytes(stat.rx_sec), + tx_sec: formatBytes(stat.tx_sec) + })), + dns: dns, + gateway: gateway + }; + + res.json(data); + } catch (error) { + console.error('Fehler beim Abrufen der Netzwerkdaten:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Netzwerkdaten' }); + } +}); + +// Dienststatus +app.get('/api/services', async (req, res) => { + try { + // Prüfen ob Frontend (Next.js) läuft + const frontendStatus = await checkServiceStatus(FRONTEND_HOST, FRONTEND_PORT); + + // Prüfen ob Backend (Flask) läuft + const backendStatus = await checkServiceStatus(BACKEND_HOST, BACKEND_PORT); + + // Docker-Container Status abrufen + const containers = await getDockerContainers(); + + const data = { + frontend: { + name: 'Next.js Frontend', + status: frontendStatus ? 'online' : 'offline', + port: FRONTEND_PORT, + host: FRONTEND_HOST + }, + backend: { + name: 'Flask Backend', + status: backendStatus ? 'online' : 'offline', + port: BACKEND_PORT, + host: BACKEND_HOST + }, + docker: { + containers: containers + } + }; + + res.json(data); + } catch (error) { + console.error('Fehler beim Abrufen der Dienststatus:', error); + res.status(500).json({ error: 'Fehler beim Abrufen der Dienststatus' }); + } +}); + +// Ping-Endpunkt für Netzwerkdiagnose +app.get('/api/ping/:host', (req, res) => { + const host = req.params.host; + + // Sicherheitscheck für den Hostnamen + if (!isValidHostname(host)) { + return res.status(400).json({ error: 'Ungültiger Hostname oder IP-Adresse' }); + } + + // Ping-Befehl ausführen + exec(`ping -n 4 ${host}`, (error, stdout, stderr) => { + if (error) { + return res.json({ + success: false, + output: stderr || stdout, + error: error.message + }); + } + + res.json({ + success: true, + output: stdout + }); + }); +}); + +// Traceroute-Endpunkt für Netzwerkdiagnose +app.get('/api/traceroute/:host', (req, res) => { + const host = req.params.host; + + // Sicherheitscheck für den Hostnamen + if (!isValidHostname(host)) { + return res.status(400).json({ error: 'Ungültiger Hostname oder IP-Adresse' }); + } + + // Traceroute-Befehl ausführen (Windows: tracert, Unix: traceroute) + const command = process.platform === 'win32' ? 'tracert' : 'traceroute'; + exec(`${command} ${host}`, (error, stdout, stderr) => { + // Traceroute kann einen Nicht-Null-Exit-Code zurückgeben, selbst wenn es teilweise erfolgreich ist + res.json({ + success: true, + output: stdout, + error: stderr + }); + }); +}); + +// DNS-Lookup-Endpunkt für Netzwerkdiagnose +app.get('/api/nslookup/:host', (req, res) => { + const host = req.params.host; + + // Sicherheitscheck für den Hostnamen + if (!isValidHostname(host)) { + return res.status(400).json({ error: 'Ungültiger Hostname oder IP-Adresse' }); + } + + // NSLookup-Befehl ausführen + exec(`nslookup ${host}`, (error, stdout, stderr) => { + if (error) { + return res.json({ + success: false, + output: stderr || stdout, + error: error.message + }); + } + + res.json({ + success: true, + output: stdout + }); + }); +}); + +// Echtzeit-Updates über WebSockets +io.on('connection', (socket) => { + console.log('Neue WebSocket-Verbindung'); + + // CPU- und Arbeitsspeichernutzung im Intervall senden + const systemMonitorInterval = setInterval(async () => { + try { + const [cpu, mem] = await Promise.all([ + si.currentLoad(), + si.mem() + ]); + + socket.emit('system-stats', { + cpu: { + load: Math.round(cpu.currentLoad), + cores: cpu.cpus.map(core => Math.round(core.load)) + }, + memory: { + total: mem.total, + used: mem.used, + free: mem.free, + usedPercent: Math.round(mem.used / mem.total * 100) + } + }); + } catch (error) { + console.error('Fehler beim Senden der Systemstatistiken:', error); + } + }, 2000); + + // Netzwerkstatistiken im Intervall senden + const networkMonitorInterval = setInterval(async () => { + try { + const netStats = await si.networkStats(); + + socket.emit('network-stats', { + stats: netStats.map(stat => ({ + iface: stat.iface, + rx_bytes: stat.rx_bytes, + tx_bytes: stat.tx_bytes, + rx_sec: stat.rx_sec, + tx_sec: stat.tx_sec + })) + }); + } catch (error) { + console.error('Fehler beim Senden der Netzwerkstatistiken:', error); + } + }, 2000); + + // Aufräumen, wenn die Verbindung getrennt wird + socket.on('disconnect', () => { + console.log('WebSocket-Verbindung getrennt'); + clearInterval(systemMonitorInterval); + clearInterval(networkMonitorInterval); + }); +}); + +// Hilfsfunktionen + +// Bytes in lesbare Größen formatieren +function formatBytes(bytes, decimals = 2) { + if (bytes === 0) return '0 B'; + + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; + + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i]; +} + +// Uptime in lesbare Zeit formatieren +function formatUptime(seconds) { + const days = Math.floor(seconds / 86400); + const hours = Math.floor((seconds % 86400) / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const secs = Math.floor(seconds % 60); + + return `${days} Tage, ${hours} Stunden, ${minutes} Minuten, ${secs} Sekunden`; +} + +// Service-Status überprüfen +async function checkServiceStatus(host, port) { + return new Promise(resolve => { + const socket = new (require('net').Socket)(); + + socket.setTimeout(1000); + + socket.on('connect', () => { + socket.destroy(); + resolve(true); + }); + + socket.on('timeout', () => { + socket.destroy(); + resolve(false); + }); + + socket.on('error', () => { + socket.destroy(); + resolve(false); + }); + + socket.connect(port, host); + }); +} + +// Docker-Container abfragen +async function getDockerContainers() { + return new Promise((resolve) => { + exec('docker ps --format "{{.ID}},{{.Image}},{{.Status}},{{.Ports}},{{.Names}}"', (error, stdout) => { + if (error) { + resolve([]); + return; + } + + const containers = []; + const lines = stdout.trim().split('\n'); + + for (const line of lines) { + if (line) { + const [id, image, status, ports, name] = line.split(','); + containers.push({ id, image, status, ports, name }); + } + } + + resolve(containers); + }); + }); +} + +// DNS-Server abfragen +async function getDnsServers() { + return new Promise((resolve) => { + if (process.platform === 'win32') { + // Windows: DNS-Server über PowerShell abfragen + exec('powershell.exe -Command "Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses"', (error, stdout) => { + if (error) { + resolve(['DNS-Server konnten nicht ermittelt werden']); + return; + } + + const servers = stdout.trim().split('\r\n').filter(Boolean); + resolve(servers); + }); + } else { + // Unix: DNS-Server aus /etc/resolv.conf lesen + exec('cat /etc/resolv.conf | grep nameserver | cut -d " " -f 2', (error, stdout) => { + if (error) { + resolve(['DNS-Server konnten nicht ermittelt werden']); + return; + } + + const servers = stdout.trim().split('\n').filter(Boolean); + resolve(servers); + }); + } + }); +} + +// Standard-Gateway abfragen +async function getDefaultGateway() { + return new Promise((resolve) => { + if (process.platform === 'win32') { + // Windows: Gateway über PowerShell abfragen + exec('powershell.exe -Command "Get-NetRoute -DestinationPrefix 0.0.0.0/0 | Select-Object -ExpandProperty NextHop"', (error, stdout) => { + if (error) { + resolve('Gateway konnte nicht ermittelt werden'); + return; + } + + resolve(stdout.trim()); + }); + } else { + // Unix: Gateway aus den Routentabellen lesen + exec("ip route | grep default | awk '{print $3}'", (error, stdout) => { + if (error) { + resolve('Gateway konnte nicht ermittelt werden'); + return; + } + + resolve(stdout.trim()); + }); + } + }); +} + +// Validierung des Hostnamens für Sicherheit +function isValidHostname(hostname) { + // Längenprüfung + if (!hostname || hostname.length > 255) { + return false; + } + + // Erlaubte Hostnamen + if (hostname === 'localhost' || hostname === '127.0.0.1') { + return true; + } + + // IPv4-Prüfung + const ipv4Regex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + if (ipv4Regex.test(hostname)) { + return true; + } + + // Hostname-Prüfung + const hostnameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$/; + return hostnameRegex.test(hostname); +} + +// Server starten +server.listen(PORT, () => { + console.log(`MYP Frontend Debug-Server läuft auf http://localhost:${PORT}`); +}); \ No newline at end of file