diff --git a/Assemblies/Scripts/Examples/Write_Canary.txt_to_C_.json b/Assemblies/Scripts/Examples/Write_Canary.txt_to_C_.json index 208be71..bace9c0 100644 --- a/Assemblies/Scripts/Examples/Write_Canary.txt_to_C_.json +++ b/Assemblies/Scripts/Examples/Write_Canary.txt_to_C_.json @@ -5,14 +5,6 @@ "category": "script", "type": "powershell", "script": "# Define the file path\n$filePath = \"C:\\Canary.txt\"\n\n# Write some content into the file\n\"SYSTEM Canary is alive.\"ddss | Out-File -FilePath $filePath -Encoding UTF8\n", - "script_lines": [ - "# Define the file path", - "$filePath = \"C:\\Canary.txt\"", - "", - "# Write some content into the file", - "\"SYSTEM Canary is alive.\"ddss | Out-File -FilePath $filePath -Encoding UTF8", - "" - ], "timeout_seconds": 3600, "sites": { "mode": "specific", diff --git a/Data/Server/WebUI/src/Assemblies/Assembly_Editor.jsx b/Data/Server/WebUI/src/Assemblies/Assembly_Editor.jsx index f64f631..9d13a3e 100644 --- a/Data/Server/WebUI/src/Assemblies/Assembly_Editor.jsx +++ b/Data/Server/WebUI/src/Assemblies/Assembly_Editor.jsx @@ -212,13 +212,11 @@ function fromServerDocument(doc = {}, defaultType = "powershell") { assembly.description = doc.description || ""; assembly.category = doc.category || assembly.category; assembly.type = doc.type || assembly.type; - if (Array.isArray(doc.script_lines)) { - assembly.script = doc.script_lines - .map((line) => (line == null ? "" : String(line))) - .join("\n"); - } else { - assembly.script = doc.script ?? doc.content ?? ""; - } + const legacyScript = Array.isArray(doc.script_lines) + ? doc.script_lines.map((line) => (line == null ? "" : String(line))).join("\n") + : ""; + const script = doc.script ?? doc.content ?? legacyScript; + assembly.script = typeof script === "string" ? script : legacyScript; const timeout = doc.timeout_seconds ?? doc.timeout ?? assembly.timeoutSeconds; assembly.timeoutSeconds = Number.isFinite(Number(timeout)) ? Number(timeout) @@ -238,7 +236,6 @@ function toServerDocument(assembly) { const normalizedScript = typeof assembly.script === "string" ? assembly.script.replace(/\r\n/g, "\n") : ""; - const scriptLines = normalizedScript ? normalizedScript.split("\n") : []; const timeoutNumeric = Number(assembly.timeoutSeconds); const timeoutSeconds = Number.isFinite(timeoutNumeric) ? Math.max(0, Math.round(timeoutNumeric)) : 3600; return { @@ -248,7 +245,6 @@ function toServerDocument(assembly) { category: assembly.category || "script", type: assembly.type || "powershell", script: normalizedScript, - script_lines: scriptLines, timeout_seconds: timeoutSeconds, sites: { mode: assembly.sites?.mode === "specific" ? "specific" : "all", @@ -728,12 +724,16 @@ export default function AssemblyEditor({ value={assembly.description} onChange={(e) => updateAssembly({ description: e.target.value })} multiline - minRows={3} + minRows={2} + maxRows={8} fullWidth variant="outlined" sx={{ ...INPUT_BASE_SX, - "& .MuiOutlinedInput-inputMultiline": { padding: "4px 8px" } + "& .MuiOutlinedInput-inputMultiline": { + padding: "6px 12px", + lineHeight: 1.4 + } }} /> @@ -906,109 +906,162 @@ export default function AssemblyEditor({ sx={{ display: "flex", flexWrap: "wrap", - alignItems: "center", - gap: 2 + alignItems: "stretch", + gap: { xs: 2, lg: 1.5 }, + pt: 1 }} > - - updateVariable(variable.id, { name: e.target.value })} - fullWidth - variant="outlined" - sx={INPUT_BASE_SX} - /> - - - updateVariable(variable.id, { label: e.target.value })} - fullWidth - variant="outlined" - sx={INPUT_BASE_SX} - /> - - - updateVariable(variable.id, { type: e.target.value })} - sx={SELECT_BASE_SX} - SelectProps={{ MenuProps: MENU_PROPS }} + + \". For example, a variable named \"message\" would be written in the script as \"$env:message\"." + arrow + placement="top-start" > - {VARIABLE_TYPE_OPTIONS.map((opt) => ( - {opt.label} - ))} - + updateVariable(variable.id, { name: e.target.value })} + fullWidth + variant="outlined" + sx={INPUT_BASE_SX} + /> + + + + + updateVariable(variable.id, { label: e.target.value })} + fullWidth + variant="outlined" + sx={INPUT_BASE_SX} + /> + + + + + updateVariable(variable.id, { type: e.target.value })} + sx={SELECT_BASE_SX} + SelectProps={{ MenuProps: MENU_PROPS }} + > + {VARIABLE_TYPE_OPTIONS.map((opt) => ( + {opt.label} + ))} + + {variable.type === "boolean" ? ( - updateVariable(variable.id, { defaultValue: e.target.checked })} - sx={{ color: "#58a6ff" }} - /> - } - label="Default Value" - sx={{ - color: "#9ba3b4", - m: 0, - "& .MuiFormControlLabel-label": { fontSize: "0.95rem" } - }} - /> + + updateVariable(variable.id, { defaultValue: e.target.checked })} + sx={{ color: "#58a6ff" }} + /> + } + label="Default Value" + sx={{ + color: "#9ba3b4", + m: 0, + "& .MuiFormControlLabel-label": { fontSize: "0.95rem" } + }} + /> + ) : ( - updateVariable(variable.id, { defaultValue: e.target.value })} - fullWidth - variant="outlined" - sx={INPUT_BASE_SX} - /> + + updateVariable(variable.id, { defaultValue: e.target.value })} + fullWidth + variant="outlined" + sx={INPUT_BASE_SX} + /> + )} - - updateVariable(variable.id, { required: e.target.checked })} - sx={{ color: "#58a6ff" }} + + Required + + updateVariable(variable.id, { required: e.target.checked })} + sx={{ color: "#58a6ff", p: 0.5 }} + inputProps={{ "aria-label": "Required" }} + /> + + + + updateVariable(variable.id, { description: e.target.value })} + fullWidth + variant="outlined" + sx={INPUT_BASE_SX} /> - - updateVariable(variable.id, { description: e.target.value })} - fullWidth - variant="outlined" - sx={INPUT_BASE_SX} - /> - - - removeVariable(variable.id)} sx={{ color: "#ff6b6b" }}> - - + + + removeVariable(variable.id)} sx={{ color: "#ff6b6b" }}> + + + diff --git a/Data/Server/job_scheduler.py b/Data/Server/job_scheduler.py index f236faf..e6fd70e 100644 --- a/Data/Server/job_scheduler.py +++ b/Data/Server/job_scheduler.py @@ -182,7 +182,6 @@ class JobScheduler: "category": "application" if default_type == "ansible" else "script", "type": default_type, "script": "", - "script_lines": [], "variables": [], "files": [], "timeout_seconds": 3600, @@ -217,7 +216,6 @@ class JobScheduler: doc["script"] = content_val normalized_script = (doc["script"] or "").replace("\r\n", "\n") doc["script"] = normalized_script - doc["script_lines"] = normalized_script.split("\n") if normalized_script else [] try: timeout_raw = data.get("timeout_seconds", data.get("timeout")) if timeout_raw is None: @@ -271,7 +269,6 @@ class JobScheduler: content = "" normalized_script = (content or "").replace("\r\n", "\n") doc["script"] = normalized_script - doc["script_lines"] = normalized_script.split("\n") if normalized_script else [] return doc def _ansible_root(self) -> str: diff --git a/Data/Server/server.py b/Data/Server/server.py index 6c80221..631eb86 100644 --- a/Data/Server/server.py +++ b/Data/Server/server.py @@ -682,7 +682,6 @@ def _empty_assembly_document(default_type: str = "powershell") -> Dict[str, Any] "category": "application" if (default_type or "").lower() == "ansible" else "script", "type": default_type or "powershell", "script": "", - "script_lines": [], "timeout_seconds": 3600, "sites": {"mode": "all", "values": []}, "variables": [], @@ -718,7 +717,6 @@ def _normalize_assembly_document(obj: Any, default_type: str, base_name: str) -> doc["script"] = content_val normalized_script = (doc["script"] or "").replace("\r\n", "\n") doc["script"] = normalized_script - doc["script_lines"] = normalized_script.split("\n") if normalized_script else [] timeout_val = obj.get("timeout_seconds", obj.get("timeout")) if timeout_val is not None: try: @@ -798,7 +796,6 @@ def _load_assembly_document(abs_path: str, island: str, type_hint: str = "") -> doc["name"] = base_name normalized_script = (content or "").replace("\r\n", "\n") doc["script"] = normalized_script - doc["script_lines"] = normalized_script.split("\n") if normalized_script else [] if default_type == "ansible": doc["category"] = "application" return doc