From cf995cfc9d3aa6bb36cb95f9d031e506880c8637 Mon Sep 17 00:00:00 2001 From: Nicole Rappe Date: Sun, 7 Dec 2025 19:49:51 -0700 Subject: [PATCH] Updates to Remote Shell and Device Details UI --- .../src/Devices/Device_Details.jsx | 393 +++++++++--------- .../src/Devices/ReverseTunnel/Powershell.jsx | 153 ++++--- 2 files changed, 265 insertions(+), 281 deletions(-) diff --git a/Data/Engine/web-interface/src/Devices/Device_Details.jsx b/Data/Engine/web-interface/src/Devices/Device_Details.jsx index 55810004..dc1962f0 100644 --- a/Data/Engine/web-interface/src/Devices/Device_Details.jsx +++ b/Data/Engine/web-interface/src/Devices/Device_Details.jsx @@ -3,11 +3,11 @@ import React, { useState, useEffect, useMemo, useCallback } from "react"; import { Box, + Stack, Tabs, Tab, Typography, Button, - IconButton, Menu, MenuItem, TextField, @@ -16,8 +16,13 @@ import { DialogContent, DialogActions } from "@mui/material"; +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import StorageRoundedIcon from "@mui/icons-material/StorageRounded"; import MemoryRoundedIcon from "@mui/icons-material/MemoryRounded"; +import LanRoundedIcon from "@mui/icons-material/LanRounded"; +import AppsRoundedIcon from "@mui/icons-material/AppsRounded"; +import ListAltRoundedIcon from "@mui/icons-material/ListAltRounded"; +import TerminalRoundedIcon from "@mui/icons-material/TerminalRounded"; import SpeedRoundedIcon from "@mui/icons-material/SpeedRounded"; import DeveloperBoardRoundedIcon from "@mui/icons-material/DeveloperBoardRounded"; import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; @@ -65,13 +70,13 @@ const SECTION_HEIGHTS = { }; const TOP_TABS = [ - "Device Summary", - "Storage", - "Memory", - "Network", - "Installed Software", - "Activity History", - "Remote Shell", + { label: "Device Summary", icon: InfoOutlinedIcon }, + { label: "Storage", icon: StorageRoundedIcon }, + { label: "Memory", icon: MemoryRoundedIcon }, + { label: "Network", icon: LanRoundedIcon }, + { label: "Installed Software", icon: AppsRoundedIcon }, + { label: "Activity History", icon: ListAltRoundedIcon }, + { label: "Remote Shell", icon: TerminalRoundedIcon }, ]; const myTheme = themeQuartz.withParams({ @@ -377,8 +382,6 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage return now - tsSec <= offlineAfter ? "Online" : "Offline"; }; - const statusColor = (s) => (s === "Online" ? "#00d18c" : "#ff4f4f"); - const resolveAssemblyName = useCallback((scriptName, scriptPath) => { const normalized = String(scriptPath || "").replace(/\\/g, "/").trim(); const base = normalized ? normalized.split("/").pop() || "" : ""; @@ -771,6 +774,8 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage label: "Hostname", value: meta.hostname || summary.hostname || agent.hostname || device?.hostname || "unknown", }, + { label: "Agent ID", value: meta.agentId || summary.agent_id || "unknown" }, + { label: "Agent GUID", value: meta.agentGuid || summary.agent_guid || "unknown" }, { label: "Last User", value: meta.lastUser || summary.last_user || "unknown", @@ -801,8 +806,6 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage value: meta.operatingSystem || summary.operating_system || agent.agent_operating_system || "unknown", }, - { label: "Agent ID", value: meta.agentId || summary.agent_id || "unknown" }, - { label: "Agent GUID", value: meta.agentGuid || summary.agent_guid || "unknown" }, { label: "Agent Hash", value: meta.agentHash || summary.agent_hash || "unknown" }, ], [meta, summary, agent, device, formatDateTime, formatLastSeen] @@ -940,7 +943,7 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage width: 36, height: 36, borderRadius: 2, - background: "rgba(4,7,17,0.4)", + background: "transparent", display: "flex", alignItems: "center", justifyContent: "center", @@ -1084,9 +1087,7 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage - setDescription(e.target.value)} - onBlur={saveDescription} - placeholder="Add a friendly label" + - {connectionType === "ssh" && ( - + > + setConnectionDraft(e.target.value)} - placeholder="user@host or host" + label="Description" + value={description} + onChange={(e) => setDescription(e.target.value)} + onBlur={saveDescription} + placeholder="Add a friendly label" sx={{ - minWidth: 260, - maxWidth: 360, + maxWidth: 420, input: { color: "#fff" }, "& .MuiOutlinedInput-root": { backgroundColor: "rgba(4,7,17,0.65)", @@ -1132,36 +1122,112 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage label: { color: MAGIC_UI.textMuted }, }} /> - - - {connectionMessage && ( - - {connectionMessage} - - )} - {connectionError && ( - - {connectionError} - - )} - + {connectionType === "ssh" && ( + + setConnectionDraft(e.target.value)} + placeholder="user@host or host" + sx={{ + minWidth: 260, + maxWidth: 360, + input: { color: "#fff" }, + "& .MuiOutlinedInput-root": { + backgroundColor: "rgba(4,7,17,0.65)", + "& fieldset": { borderColor: "rgba(148,163,184,0.45)" }, + "&:hover fieldset": { borderColor: MAGIC_UI.accentA }, + }, + label: { color: MAGIC_UI.textMuted }, + }} + /> + + + {connectionMessage && ( + + {connectionMessage} + + )} + {connectionError && ( + + {connectionError} + + )} + + + )} - )} - + *": { + background: "transparent !important", + border: "none !important", + boxShadow: "none !important", + borderRadius: 0, + }, + }} + > + } + title="Processor" + main={deviceMetricData.cpuMain} + sub={deviceMetricData.cpuSub} + /> + } + title="RAM" + main={deviceMetricData.memVal} + sub={deviceMetricData.memSpeed || " "} + /> + } + title="Storage" + main={deviceMetricData.storageMain} + sub={deviceMetricData.storageSub || " "} + /> + } + title="Network" + main={deviceMetricData.netVal} + sub={deviceMetricData.nicLabel} + /> + + + { onPageMetaChange?.({ @@ -1571,7 +1629,6 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage p: { xs: 2, md: 3 }, borderRadius: 0, background: "transparent", - border: `1px solid ${MAGIC_UI.panelBorder}`, boxShadow: "none", display: "flex", flexDirection: "column", @@ -1582,133 +1639,68 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage > - - {onBack && ( - - )} - - - GUID: {meta.agentGuid || summary.agent_guid || "unknown"} - - - - *": { background: "transparent !important", border: "none !important", boxShadow: "none !important", borderRadius: 0 }, - }} - > - } - title="Processor" - main={deviceMetricData.cpuMain} - sub={deviceMetricData.cpuSub} - /> - } - title="RAM" - main={deviceMetricData.memVal} - sub={deviceMetricData.memSpeed || " "} - /> - } - title="Storage" - main={deviceMetricData.storageMain} - sub={deviceMetricData.storageSub || " "} - /> - } - title="Network" - main={deviceMetricData.netVal} - sub={deviceMetricData.nicLabel} - /> - - - - + + + setMenuAnchor(null)} + PaperProps={{ + sx: { + bgcolor: "rgba(8,12,24,0.96)", + color: "#fff", + border: `1px solid ${MAGIC_UI.panelBorder}`, + }, + }} + > + { + setMenuAnchor(null); + if (!canLaunchQuickJob) return; + onQuickJobLaunch && onQuickJobLaunch(quickJobTargets); + }} + > + Quick Job + + { + setMenuAnchor(null); + setClearDialogOpen(true); + }} + > + Clear Device Activity + + setTab(v)} @@ -1748,8 +1740,13 @@ export default function DeviceDetails({ device, onBack, onQuickJobLaunch, onPage }, }} > - {TOP_TABS.map((label) => ( - + {TOP_TABS.map((tabDef) => ( + } + iconPosition="start" + /> ))} diff --git a/Data/Engine/web-interface/src/Devices/ReverseTunnel/Powershell.jsx b/Data/Engine/web-interface/src/Devices/ReverseTunnel/Powershell.jsx index 0b68158d..f7e5db44 100644 --- a/Data/Engine/web-interface/src/Devices/ReverseTunnel/Powershell.jsx +++ b/Data/Engine/web-interface/src/Devices/ReverseTunnel/Powershell.jsx @@ -11,7 +11,6 @@ import { LinearProgress, } from "@mui/material"; import { - TerminalRounded as TerminalIcon, PlayArrowRounded as PlayIcon, StopRounded as StopIcon, ContentCopy as CopyIcon, @@ -50,12 +49,10 @@ const gradientButtonSx = { color: "#0b1220", borderRadius: 999, textTransform: "none", - boxShadow: "0 10px 26px rgba(124,58,237,0.28)", px: 2.2, minWidth: 120, "&:hover": { backgroundImage: "linear-gradient(135deg,#86e1ff,#d1a6ff)", - boxShadow: "0 12px 34px rgba(124,58,237,0.38)", }, }; @@ -614,91 +611,43 @@ export default function ReverseTunnelPowershell({ device }) { - - - - Remote Shell - - - - - setConnectionType(e.target.value)} - sx={{ - minWidth: 180, - "& .MuiInputBase-root": { - backgroundColor: "rgba(12,18,35,0.85)", - color: MAGIC_UI.textBright, - borderRadius: 1.5, - }, - "& fieldset": { borderColor: MAGIC_UI.panelBorder }, - "&:hover fieldset": { borderColor: MAGIC_UI.accentA }, - }} - > - PowerShell - - - - - - - - - - - setConnectionType(e.target.value)} sx={{ - color: milestones.tunnelReady ? MAGIC_UI.accentC : MAGIC_UI.textMuted, - fontWeight: 700, + minWidth: 180, + "& .MuiInputBase-root": { + backgroundColor: "rgba(12,18,35,0.85)", + color: MAGIC_UI.textBright, + borderRadius: 1.5, + }, + "& fieldset": { borderColor: MAGIC_UI.panelBorder }, + "&:hover fieldset": { borderColor: MAGIC_UI.accentA }, }} > - Tunnel:{" "} - - {tunnelSteps.join(" > ")} - - - - Websocket:{" "} - - {websocketSteps.join(" > ")} - - - - Remote Shell:{" "} - - {shellSteps.join(" > ")} - - + PowerShell + + + + + + @@ -804,6 +753,44 @@ export default function ReverseTunnelPowershell({ device }) { /> + + + Tunnel:{" "} + + {tunnelSteps.join(" > ")} + + + + Websocket:{" "} + + {websocketSteps.join(" > ")} + + + + Remote Shell:{" "} + + {shellSteps.join(" > ")} + + + ); }