From 73ff57eaf0fe7900e801f6e9f15a94471ab84d60 Mon Sep 17 00:00:00 2001 From: cynfo3000 Date: Sat, 7 Mar 2026 00:24:29 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20Proxmox=20TunnelTab=20SSH-Copy=20identis?= =?UTF-8?q?ch=20zu=20OPNsense=20(auto-copy=20+=20gr=C3=BCne=20Best=C3=A4ti?= =?UTF-8?q?gung=20+=20SSH-Button=20pro=20Tunnel)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ProxmoxPanel.jsx | 187 ++++++++++++++--------- 1 file changed, 118 insertions(+), 69 deletions(-) diff --git a/frontend/src/components/ProxmoxPanel.jsx b/frontend/src/components/ProxmoxPanel.jsx index b4d64a1..f19a55f 100644 --- a/frontend/src/components/ProxmoxPanel.jsx +++ b/frontend/src/components/ProxmoxPanel.jsx @@ -6,7 +6,7 @@ import TerminalModal from './TerminalModal' import { X, Cpu, MemoryStick, HardDrive, Clock, Network, Server, Monitor, Container, Database, FolderTree, Settings, Download, Trash2, Copy, Check, - MonitorSmartphone, Terminal, Cable, ExternalLink, + MonitorSmartphone, Terminal, Cable, ExternalLink, Plus, Unplug, } from 'lucide-react' const buildTabs = (hasPBS) => [ @@ -679,8 +679,8 @@ function TunnelTab({ agentId, agent, webguiPort = 8006 }) { const [customHost, setCustomHost] = useState('127.0.0.1') const [customPort, setCustomPort] = useState('') const [error, setError] = useState('') + const [sshCopied, setSshCopied] = useState(null) const [terminalOpen, setTerminalOpen] = useState(false) - const [copiedCmd, setCopiedCmd] = useState(false) const backendHost = useSettingsStore.getState().getBackendHost() @@ -709,9 +709,16 @@ function TunnelTab({ agentId, agent, webguiPort = 8006 }) { const resp = await api.openTunnel(agentId, targetHost, targetPort) const data = resp?.data || resp loadTunnels() - if (targetPort === webguiPort && data?.proxy_port) { + if (data?.proxy_port) { setTimeout(() => { - window.open(`https://${backendHost}:${data.proxy_port}`, '_blank') + if (targetPort === webguiPort) { + window.open(`https://${backendHost}:${data.proxy_port}`, '_blank') + } else if (targetPort === 22) { + const cmd = `ssh root@${backendHost} -p ${data.proxy_port}` + navigator.clipboard.writeText(cmd).catch(() => {}) + setSshCopied(data.proxy_port) + setTimeout(() => setSshCopied(null), 4000) + } }, 1000) } return data @@ -739,23 +746,13 @@ function TunnelTab({ agentId, agent, webguiPort = 8006 }) { setCustomPort('') } - const sshTunnel = tunnels.find(t => t.target_port === 22) - const sshCmd = sshTunnel ? `ssh root@${backendHost} -p ${sshTunnel.proxy_port}` : null - - const copySSHCmd = () => { - if (sshCmd) { - navigator.clipboard.writeText(sshCmd) - setCopiedCmd(true) - setTimeout(() => setCopiedCmd(false), 2000) - } - } - return (
{terminalOpen && ( setTerminalOpen(false)} /> )} + {/* Schnellzugriff */}
Schnellzugriff:
- {/* SSH-Copy-Karte wenn SSH-Tunnel aktiv */} - {sshTunnel && ( -
- - {sshCmd} -
)} - {customOpen && ( -
- setCustomHost(e.target.value)} - className="bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white w-36 focus:outline-none focus:border-orange-500" placeholder="Host" /> - : - setCustomPort(e.target.value)} - className="bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white w-20 focus:outline-none focus:border-orange-500" placeholder="Port" - onKeyDown={(e) => e.key === 'Enter' && handleCustom()} /> - + {/* SSH auto-kopiert Bestätigung */} + {sshCopied && ( +
+ + SSH-Befehl kopiert — in CMD/Terminal einfuegen und ausfuehren
)} + {error &&
{error}
} - {error &&
{error}
} - - {tunnels.length > 0 && ( - <> -

Aktive Tunnel ({tunnels.length})

+ {/* Aktive Tunnel */} +
+

Aktive Tunnel

+ {loading ? ( +
Laden...
+ ) : tunnels.length === 0 ? ( +
+ Keine aktiven Tunnel +
+ ) : (
- - - + + + + - {tunnels.map((t) => ( - - - - - - - ))} + {tunnels.map((t) => { + const tid = t.id || t.tunnel_id + const proxyPort = t.proxy_port || t.local_port + const target = t.target_host && t.target_port ? `${t.target_host}:${t.target_port}` : '—' + const isWebGUI = t.target_port === webguiPort || t.target_port === String(webguiPort) + const isSSH = t.target_port === 22 || t.target_port === '22' + + return ( + + + + + + + + ) + })}
ZielProxy PortZugriffLokaler ZugangStatusErstelltAktionen
{t.target_host}:{t.target_port}{t.proxy_port} - - Oeffnen - - - -
{target} +
+ {backendHost}:{proxyPort} + {isWebGUI && proxyPort && ( + + + + )} + {isSSH && proxyPort && ( + + )} +
+
+ + + aktiv + + + {t.created_at ? new Date(t.created_at).toLocaleString('de-DE') : '—'} + + +
- - )} + )} +
+ +
+ Tunnel werden ueber den RMM-Backend-Server ({backendHost}) geroutet. WebGUI-Tunnel oeffnen automatisch ein neues Browserfenster. +
) }