26 lines
13 KiB
JSON
26 lines
13 KiB
JSON
{
|
|
"permissions": {
|
|
"allow": [
|
|
"Bash(ssh:*)",
|
|
"Bash(scp:*)",
|
|
"Bash(veth.*)",
|
|
"Bash(docker.*)",
|
|
"Bash(curl:*)",
|
|
"Bash(findstr:*)",
|
|
"Bash(cat:*)",
|
|
"Bash(powershell -Command @'\n$content = @\"\"\nimport { useState, useEffect } from 'react'\nimport { useNavigate } from 'react-router-dom'\nimport { getServers } from '../api'\nimport { useUser } from '../context/UserContext'\nimport ServerCard from '../components/ServerCard'\nimport SettingsModal from '../components/SettingsModal'\nimport UserManagement from '../components/UserManagement'\n\nexport default function Dashboard\\({ onLogout }\\) {\n const navigate = useNavigate\\(\\)\n const { user, token, loading: userLoading, isSuperadmin, role } = useUser\\(\\)\n const [servers, setServers] = useState\\([]\\)\n const [loading, setLoading] = useState\\(true\\)\n const [error, setError] = useState\\(''\\)\n const [showSettings, setShowSettings] = useState\\(false\\)\n const [showUserMgmt, setShowUserMgmt] = useState\\(false\\)\n\n const fetchServers = async \\(\\) => {\n try {\n const data = await getServers\\(token\\)\n setServers\\(data\\)\n setError\\(''\\)\n } catch \\(err\\) {\n setError\\('Failed to connect to server'\\)\n if \\(err.message.includes\\('401'\\) || err.message.includes\\('403'\\)\\) {\n onLogout\\(\\)\n }\n } finally {\n setLoading\\(false\\)\n }\n }\n\n useEffect\\(\\(\\) => {\n if \\(!userLoading\\) {\n fetchServers\\(\\)\n const interval = setInterval\\(fetchServers, 10000\\)\n return \\(\\) => clearInterval\\(interval\\)\n }\n }, [token, userLoading]\\)\n\n const roleLabels = {\n user: 'Viewer',\n moderator: 'Operator',\n superadmin: 'Admin'\n }\n\n if \\(userLoading\\) {\n return \\(\n <div className=\"\"min-h-screen flex items-center justify-center\"\">\n <div className=\"\"text-neutral-400\"\">Loading...</div>\n </div>\n \\)\n }\n\n const onlineCount = servers.filter\\(s => s.running\\).length\n const totalPlayers = servers.reduce\\(\\(sum, s\\) => sum + \\(s.players?.online || 0\\), 0\\)\n\n return \\(\n <div className=\"\"min-h-screen page-enter\"\">\n {/* Header */}\n <header className=\"\"border-b border-neutral-800 bg-neutral-900/50 backdrop-blur-sm sticky top-0 z-10\"\">\n <div className=\"\"container-main py-4\"\">\n <div className=\"\"flex items-center justify-between\"\">\n <div className=\"\"flex items-center gap-6\"\">\n <h1 className=\"\"text-xl font-semibold text-white\"\">\n Gameserver Monitor\n </h1>\n <div className=\"\"hidden md:flex items-center gap-4 text-sm text-neutral-400\"\">\n <span>\n <span className=\"\"text-white font-medium\"\">{onlineCount}</span>/{servers.length} online\n </span>\n <span className=\"\"text-neutral-600\"\">|</span>\n <span>\n <span className=\"\"text-white font-medium\"\">{totalPlayers}</span> players\n </span>\n </div>\n </div>\n\n <div className=\"\"flex items-center gap-3\"\">\n <div className=\"\"hidden sm:block text-right mr-2\"\">\n <div className=\"\"text-sm text-white\"\">{user?.username}</div>\n <div className=\"\"text-xs text-neutral-500\"\">{roleLabels[role]}</div>\n </div>\n\n {isSuperadmin && \\(\n <button\n onClick={\\(\\) => setShowUserMgmt\\(true\\)}\n className=\"\"btn btn-ghost\"\"\n >\n Users\n </button>\n \\)}\n\n <button\n onClick={\\(\\) => setShowSettings\\(true\\)}\n className=\"\"btn btn-ghost\"\"\n >\n Settings\n </button>\n\n <button\n onClick={onLogout}\n className=\"\"btn btn-outline\"\"\n >\n Sign out\n </button>\n </div>\n </div>\n </div>\n </header>\n\n {/* Main Content */}\n <main className=\"\"container-main py-8\"\">\n {error && \\(\n <div className=\"\"mb-6 alert alert-error fade-in\"\">\n {error}\n </div>\n \\)}\n\n {loading ? \\(\n <div className=\"\"text-center py-12\"\">\n <div className=\"\"text-neutral-400\"\">Loading servers...</div>\n </div>\n \\) : \\(\n <div className=\"\"grid grid-cols-1 md:grid-cols-2 gap-6\"\">\n {servers.map\\(\\(server, index\\) => \\(\n <div\n key={server.id}\n className=\"\"fade-in-up\"\"\n style={{ animationDelay: ``$``{index * 50}ms``, animationFillMode: 'both' }}\n >\n <ServerCard\n server={server}\n onClick={\\(\\) => navigate\\('/server/' + server.id\\)}\n />\n </div>\n \\)\\)}\n </div>\n \\)}\n </main>\n\n {/* Modals */}\n {showSettings && \\(\n <SettingsModal onClose={\\(\\) => setShowSettings\\(false\\)} />\n \\)}\n\n {showUserMgmt && \\(\n <UserManagement onClose={\\(\\) => setShowUserMgmt\\(false\\)} />\n \\)}\n </div>\n \\)\n}\n\"\"@\n$content | Out-File -FilePath \"\"Dashboard.jsx\"\" -Encoding UTF8\n'@)",
|
|
"Bash(git add:*)",
|
|
"Bash(dir:*)",
|
|
"Bash(ssh-keygen:*)",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''cat /etc/nginx/nginx.conf''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''curl -s --max-time 5 http://localhost:3000/api/health''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''sleep 3 && curl -s --max-time 10 http://localhost:3000/api/servers 2>&1''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''cat > /opt/gameserver-monitor/backend/config.json << \"\"CONFIGEOF\"\"\n{\n \"\"servers\"\": [\n {\n \"\"id\"\": \"\"minecraft\"\",\n \"\"name\"\": \"\"All the Mods 10 | Minecraft\"\",\n \"\"host\"\": \"\"192.168.2.51\"\",\n \"\"type\"\": \"\"minecraft\"\",\n \"\"runtime\"\": \"\"screen\"\",\n \"\"rconPort\"\": 25575,\n \"\"rconPassword\"\": \"\"gsm-mc-2026\"\",\n \"\"screenName\"\": \"\"minecraft\"\",\n \"\"workDir\"\": \"\"/opt/minecraft\"\",\n \"\"startCmd\"\": \"\"./run.sh\"\"\n },\n {\n \"\"id\"\": \"\"factorio\"\",\n \"\"name\"\": \"\"Factorio\"\",\n \"\"host\"\": \"\"192.168.2.50\"\",\n \"\"type\"\": \"\"factorio\"\",\n \"\"runtime\"\": \"\"docker\"\",\n \"\"containerName\"\": \"\"factorio\"\",\n \"\"rconPort\"\": 27015,\n \"\"rconPassword\"\": \"\"jieTig6IkixaKuu\"\"\n },\n {\n \"\"id\"\": \"\"vrising\"\",\n \"\"name\"\": \"\"V Rising\"\",\n \"\"host\"\": \"\"192.168.2.52\"\",\n \"\"type\"\": \"\"vrising\"\",\n \"\"runtime\"\": \"\"systemd\"\",\n \"\"serviceName\"\": \"\"vrising\"\",\n \"\"rconPort\"\": 25575,\n \"\"rconPassword\"\": \"\"changeme\"\",\n \"\"workDir\"\": \"\"/home/steam/vrising\"\"\n },\n {\n \"\"id\"\": \"\"zomboid\"\",\n \"\"name\"\": \"\"Project Zomboid\"\",\n \"\"host\"\": \"\"10.0.30.66\"\",\n \"\"type\"\": \"\"zomboid\"\",\n \"\"runtime\"\": \"\"screen\"\",\n \"\"rconPort\"\": 27015,\n \"\"rconPassword\"\": \"\"ShkeloAufNettoParkplatzSchlagen47139\"\",\n \"\"screenName\"\": \"\"zomboid\"\",\n \"\"workDir\"\": \"\"/opt/pzserver\"\",\n \"\"startCmd\"\": \"\"./start-server.sh -servername Project\"\",\n \"\"sshUser\"\": \"\"pzuser\"\",\n \"\"logFile\"\": \"\"/home/pzuser/Zomboid/server-console.txt\"\"\n }\n ]\n}\nCONFIGEOF\npkill -f \"\"node server.js\"\" 2>/dev/null; cd /opt/gameserver-monitor/backend && node server.js >> /var/log/gsm-backend.log 2>&1 &''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''cat /opt/gameserver-monitor/backend/config.json | head -5''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''cat > /tmp/routefix.js << \"\"FIXEOF\"\"\nconst fs = require\\(\"\"fs\"\"\\);\nconst file = \"\"/opt/gameserver-monitor/backend/routes/servers.js\"\";\nlet content = fs.readFileSync\\(file, \"\"utf8\"\"\\);\n\n// Add import for isHostFailed\ncontent = content.replace\\(\n \"\"import { getServerStatus, startServer, stopServer, restartServer, getConsoleLog, getProcessUptime, listFactorioSaves, createFactorioWorld, deleteFactorioSave, getFactorioCurrentSave } from \\\\\"\"../services/ssh.js\\\\\"\";\"\",\n \"\"import { getServerStatus, startServer, stopServer, restartServer, getConsoleLog, getProcessUptime, listFactorioSaves, createFactorioWorld, deleteFactorioSave, getFactorioCurrentSave, isHostFailed } from \\\\\"\"../services/ssh.js\\\\\"\";\"\"\n\\);\n\n// Find and update the server list endpoint\nconst oldMapCode = \"\"const servers = await Promise.all\\(config.servers.map\\(async \\(server\\) => {\"\";\nconst newMapCode = \\\\`const servers = await Promise.all\\(config.servers.map\\(async \\(server\\) => {\n // Quick check if host is unreachable - skip expensive operations\n const hostUnreachable = isHostFailed\\(server.host, server.sshUser\\);\\\\`;\n\ncontent = content.replace\\(oldMapCode, newMapCode\\);\n\n// Update the status call to use the quick check\nconst oldStatusCall = \"\"const [status, metrics, players, playerList, processUptime] = await Promise.all\\([\"\";\nconst newStatusCall = \\\\`// If host is unreachable, return immediately with minimal data\n if \\(hostUnreachable\\) {\n const metrics = await getCurrentMetrics\\(server.id\\).catch\\(\\(\\) => \\({\n cpu: 0, cpuCores: 1, memory: 0, memoryUsed: 0, memoryTotal: 0, uptime: 0\n }\\)\\);\n const memTotal = formatBytes\\(metrics.memoryTotal\\);\n const memUsed = formatBytes\\(metrics.memoryUsed, memTotal.unit\\);\n return {\n id: server.id,\n name: server.name,\n type: server.type,\n status: \"\"unreachable\"\",\n running: false,\n metrics: {\n cpu: metrics.cpu,\n cpuCores: metrics.cpuCores,\n memory: metrics.memory,\n memoryUsed: memUsed.value,\n memoryTotal: memTotal.value,\n memoryUnit: memTotal.unit,\n uptime: 0\n },\n players: { online: 0, max: null, list: [] },\n hasRcon: !!server.rconPassword\n };\n }\n\n const [status, metrics, players, playerList, processUptime] = await Promise.all\\([\\\\`;\n\ncontent = content.replace\\(oldStatusCall, newStatusCall\\);\n\nfs.writeFileSync\\(file, content\\);\nconsole.log\\(\"\"Done\"\"\\);\nFIXEOF\nnode /tmp/routefix.js''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''cat > /opt/gameserver-monitor/backend/config.json << \"\"CONFIGEOF\"\"\n{\n \"\"servers\"\": [\n {\n \"\"id\"\": \"\"minecraft\"\",\n \"\"name\"\": \"\"All the Mods 10 | Minecraft\"\",\n \"\"host\"\": \"\"192.168.2.51\"\",\n \"\"type\"\": \"\"minecraft\"\",\n \"\"runtime\"\": \"\"screen\"\",\n \"\"rconPort\"\": 25575,\n \"\"rconPassword\"\": \"\"gsm-mc-2026\"\",\n \"\"screenName\"\": \"\"minecraft\"\",\n \"\"workDir\"\": \"\"/opt/minecraft\"\",\n \"\"startCmd\"\": \"\"./run.sh\"\"\n },\n {\n \"\"id\"\": \"\"factorio\"\",\n \"\"name\"\": \"\"Factorio\"\",\n \"\"host\"\": \"\"192.168.2.50\"\",\n \"\"type\"\": \"\"factorio\"\",\n \"\"runtime\"\": \"\"docker\"\",\n \"\"containerName\"\": \"\"factorio\"\",\n \"\"rconPort\"\": 27015,\n \"\"rconPassword\"\": \"\"jieTig6IkixaKuu\"\"\n },\n {\n \"\"id\"\": \"\"vrising\"\",\n \"\"name\"\": \"\"V Rising\"\",\n \"\"host\"\": \"\"192.168.2.52\"\",\n \"\"type\"\": \"\"vrising\"\",\n \"\"runtime\"\": \"\"systemd\"\",\n \"\"serviceName\"\": \"\"vrising\"\",\n \"\"rconPort\"\": 25575,\n \"\"rconPassword\"\": \"\"changeme\"\",\n \"\"workDir\"\": \"\"/home/steam/vrising\"\"\n },\n {\n \"\"id\"\": \"\"zomboid\"\",\n \"\"name\"\": \"\"Project Zomboid\"\",\n \"\"host\"\": \"\"10.0.30.66\"\",\n \"\"type\"\": \"\"zomboid\"\",\n \"\"runtime\"\": \"\"screen\"\",\n \"\"rconPort\"\": 27015,\n \"\"rconPassword\"\": \"\"ShkeloAufNettoParkplatzSchlagen47139\"\",\n \"\"screenName\"\": \"\"zomboid\"\",\n \"\"workDir\"\": \"\"/opt/pzserver\"\",\n \"\"startCmd\"\": \"\"./start-server.sh -servername Project\"\",\n \"\"sshUser\"\": \"\"pzuser\"\",\n \"\"logFile\"\": \"\"/home/pzuser/Zomboid/server-console.txt\"\"\n }\n ]\n}\nCONFIGEOF''\")",
|
|
"Bash(ssh alex@192.168.2.10 \"ssh root@192.168.2.30 ''wg show 2>&1 || echo \"\"WireGuard nicht installiert/aktiv\"\"''\")"
|
|
]
|
|
}
|
|
}
|