From 7ee22bb004188b3100c059966fccd7e53253b85a Mon Sep 17 00:00:00 2001 From: KingKDot Date: Tue, 17 Mar 2026 13:27:44 -0500 Subject: [PATCH] add option for specific OS's in scripts. change view in script editor to match the block view (looks much nicer and much more organized). --- Overlord-Server/public/assets/scripts.js | 154 ++++++++- Overlord-Server/public/scripts.html | 295 ++---------------- Overlord-Server/src/db.ts | 21 +- .../src/server/auto-script-dispatch.ts | 7 + .../src/server/routes/auto-scripts-routes.ts | 11 +- .../src/server/validation-constants.ts | 8 + 6 files changed, 217 insertions(+), 279 deletions(-) diff --git a/Overlord-Server/public/assets/scripts.js b/Overlord-Server/public/assets/scripts.js index 744161b..9a4ebc9 100644 --- a/Overlord-Server/public/assets/scripts.js +++ b/Overlord-Server/public/assets/scripts.js @@ -14,6 +14,7 @@ const saveScriptBtn = document.getElementById("save-script-btn"); const savedScriptsList = document.getElementById("saved-scripts-list"); const autoTaskName = document.getElementById("auto-task-name"); const autoTaskTrigger = document.getElementById("auto-task-trigger"); +const autoTaskOsCheckboxes = document.querySelectorAll("input[name='auto-task-os']"); const autoTaskSaveBtn = document.getElementById("auto-task-save-btn"); const autoTaskCancelBtn = document.getElementById("auto-task-cancel-btn"); const autoTaskList = document.getElementById("auto-task-list"); @@ -351,6 +352,7 @@ function resetAutoTaskForm() { autoTaskEditingId = null; autoTaskName.value = ""; autoTaskTrigger.value = "on_connect"; + autoTaskOsCheckboxes.forEach((cb) => (cb.checked = false)); autoTaskCancelBtn.classList.add("hidden"); autoTaskSaveBtn.innerHTML = ' Save Auto Task'; } @@ -362,6 +364,10 @@ function setAutoTaskForm(task) { scriptType.value = task.scriptType || "powershell"; setEditorMode(scriptType.value); setEditorValue(task.script || ""); + const osFilter = Array.isArray(task.osFilter) ? task.osFilter : []; + autoTaskOsCheckboxes.forEach((cb) => { + cb.checked = osFilter.includes(cb.value); + }); autoTaskCancelBtn.classList.remove("hidden"); autoTaskSaveBtn.innerHTML = ' Update Auto Task'; } @@ -393,7 +399,7 @@ function renderAutoTasks() {
${escapeHtml(task.name)}
-
${escapeHtml(triggerLabel(task.trigger))} • ${escapeHtml(task.scriptType)}
+
${escapeHtml(triggerLabel(task.trigger))} • ${escapeHtml(task.scriptType)}${Array.isArray(task.osFilter) && task.osFilter.length > 0 ? ` • ${task.osFilter.map(escapeHtml).join(", ")}` : ""}
diff --git a/Overlord-Server/src/db.ts b/Overlord-Server/src/db.ts index ef100bd..6d6a1ff 100644 --- a/Overlord-Server/src/db.ts +++ b/Overlord-Server/src/db.ts @@ -123,6 +123,9 @@ db.run(` db.run( `CREATE INDEX IF NOT EXISTS idx_auto_scripts_trigger ON auto_scripts(trigger, enabled);`, ); +try { + db.run(`ALTER TABLE auto_scripts ADD COLUMN os_filter TEXT NOT NULL DEFAULT '[]'`); +} catch { /* column already exists */ } db.run(` CREATE TABLE IF NOT EXISTS auto_script_runs ( @@ -482,11 +485,17 @@ export type AutoScript = { script: string; scriptType: string; enabled: boolean; + osFilter: string[]; createdAt: number; updatedAt: number; }; function mapAutoScriptRow(row: any): AutoScript { + let osFilter: string[] = []; + try { + const parsed = JSON.parse(row.os_filter || "[]"); + osFilter = Array.isArray(parsed) ? parsed : []; + } catch { } return { id: row.id, name: row.name, @@ -494,6 +503,7 @@ function mapAutoScriptRow(row: any): AutoScript { script: row.script, scriptType: row.script_type, enabled: row.enabled === 1, + osFilter, createdAt: Number(row.created_at) || 0, updatedAt: Number(row.updated_at) || 0, }; @@ -525,11 +535,12 @@ export function createAutoScript(input: { script: string; scriptType: string; enabled: boolean; + osFilter: string[]; }): AutoScript { const now = Date.now(); db.run( - `INSERT INTO auto_scripts (id, name, trigger, script, script_type, enabled, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)` + `INSERT INTO auto_scripts (id, name, trigger, script, script_type, enabled, os_filter, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)` , input.id, input.name, @@ -537,6 +548,7 @@ export function createAutoScript(input: { input.script, input.scriptType, input.enabled ? 1 : 0, + JSON.stringify(input.osFilter ?? []), now, now, ); @@ -551,6 +563,7 @@ export function updateAutoScript( script: string; scriptType: string; enabled: boolean; + osFilter: string[]; }>, ): AutoScript | null { const current = getAutoScript(id); @@ -562,16 +575,18 @@ export function updateAutoScript( script: input.script ?? current.script, scriptType: input.scriptType ?? current.scriptType, enabled: typeof input.enabled === "boolean" ? input.enabled : current.enabled, + osFilter: Array.isArray(input.osFilter) ? input.osFilter : current.osFilter, }; db.run( - `UPDATE auto_scripts SET name=?, trigger=?, script=?, script_type=?, enabled=?, updated_at=? WHERE id=?` + `UPDATE auto_scripts SET name=?, trigger=?, script=?, script_type=?, enabled=?, os_filter=?, updated_at=? WHERE id=?` , next.name, next.trigger, next.script, next.scriptType, next.enabled ? 1 : 0, + JSON.stringify(next.osFilter), Date.now(), id, ); diff --git a/Overlord-Server/src/server/auto-script-dispatch.ts b/Overlord-Server/src/server/auto-script-dispatch.ts index ff09080..535c2a8 100644 --- a/Overlord-Server/src/server/auto-script-dispatch.ts +++ b/Overlord-Server/src/server/auto-script-dispatch.ts @@ -28,6 +28,13 @@ export function dispatchAutoScriptsForConnection( } for (const script of scripts) { + if (script.osFilter.length > 0) { + const clientOs = (info.os || "").toLowerCase(); + if (!script.osFilter.includes(clientOs)) { + continue; + } + } + if (script.trigger === "on_connect_once") { if (hasAutoScriptRun(script.id, info.id)) { continue; diff --git a/Overlord-Server/src/server/routes/auto-scripts-routes.ts b/Overlord-Server/src/server/routes/auto-scripts-routes.ts index be5d975..cfe266f 100644 --- a/Overlord-Server/src/server/routes/auto-scripts-routes.ts +++ b/Overlord-Server/src/server/routes/auto-scripts-routes.ts @@ -7,7 +7,7 @@ import { updateAutoScript, } from "../../db"; import { requirePermission } from "../../rbac"; -import { AUTO_SCRIPT_TRIGGERS, ALLOWED_SCRIPT_TYPES } from "../validation-constants"; +import { AUTO_SCRIPT_TRIGGERS, ALLOWED_SCRIPT_TYPES, ALLOWED_OS_FILTERS } from "../validation-constants"; import { v4 as uuidv4 } from "uuid"; export async function handleAutoScriptsRoutes( @@ -59,6 +59,8 @@ export async function handleAutoScriptsRoutes( const script = String(body?.script || ""); const scriptTypeRaw = String(body?.scriptType || "powershell").trim(); const enabled = typeof body?.enabled === "boolean" ? body.enabled : true; + const osFilterRaw = Array.isArray(body?.osFilter) ? body.osFilter : []; + const osFilter = osFilterRaw.filter((v: unknown) => typeof v === "string" && ALLOWED_OS_FILTERS.has(v)); if (!name) { return Response.json({ error: "Name is required" }, { status: 400 }); @@ -81,6 +83,7 @@ export async function handleAutoScriptsRoutes( script, scriptType, enabled, + osFilter, }); return Response.json({ ok: true, item }); @@ -121,12 +124,18 @@ export async function handleAutoScriptsRoutes( : "powershell" : undefined; + const osFilterRaw = Array.isArray(body?.osFilter) ? body.osFilter : undefined; + const osFilter = osFilterRaw + ? osFilterRaw.filter((v: unknown) => typeof v === "string" && ALLOWED_OS_FILTERS.has(v)) + : undefined; + const updated = updateAutoScript(autoScriptMatch[1], { name: body?.name ? String(body.name).trim() : undefined, trigger: triggerRaw as AutoScriptTrigger | undefined, script: body?.script ? String(body.script) : undefined, scriptType, enabled: typeof body?.enabled === "boolean" ? body.enabled : undefined, + osFilter, }); if (!updated) { diff --git a/Overlord-Server/src/server/validation-constants.ts b/Overlord-Server/src/server/validation-constants.ts index c2ca0e1..a2a4a96 100644 --- a/Overlord-Server/src/server/validation-constants.ts +++ b/Overlord-Server/src/server/validation-constants.ts @@ -29,3 +29,11 @@ export const ALLOWED_PLATFORMS = new Set([ "android-amd64", "android-armv7", ]); + +export const ALLOWED_OS_FILTERS = new Set([ + "windows", + "linux", + "darwin", + "android", + "freebsd", +]);