From d4d4bda5190a40cbb7c22d17eff72a261ede5996 Mon Sep 17 00:00:00 2001 From: sadnub Date: Mon, 15 Apr 2024 13:33:50 -0400 Subject: [PATCH] fix vuex in the cmd placeholder computed function and cleanup the scriptDropdowns and actually filter by platform everywhere --- src/components/agents/ChecksTab.vue | 1 + src/components/checks/ScriptCheck.vue | 10 +-- src/components/modals/agents/BulkAction.vue | 64 +++++++++---------- src/components/modals/agents/RunScript.vue | 11 ++-- src/components/tasks/AutomatedTaskForm.vue | 19 +++--- src/composables/agents.js | 13 ++-- src/composables/scripts.ts | 71 +++++++++++---------- 7 files changed, 100 insertions(+), 89 deletions(-) diff --git a/src/components/agents/ChecksTab.vue b/src/components/agents/ChecksTab.vue index d9dffcc..eeb96f5 100644 --- a/src/components/agents/ChecksTab.vue +++ b/src/components/agents/ChecksTab.vue @@ -666,6 +666,7 @@ export default { componentProps: { check: check, parent: !check ? { agent: selectedAgent.value } : undefined, + plat: type === "script" ? agentPlatform.value : undefined, }, }).onOk(getChecks); } diff --git a/src/components/checks/ScriptCheck.vue b/src/components/checks/ScriptCheck.vue index 9556fdc..e16802a 100644 --- a/src/components/checks/ScriptCheck.vue +++ b/src/components/checks/ScriptCheck.vue @@ -8,7 +8,7 @@ Close - +

You need to upload a script first

Settings -> Script Manager

@@ -19,7 +19,7 @@ :rules="[(val) => !!val || '*Required']" outlined v-model="state.script" - :options="scriptOptions" + :options="filterByPlatformOptions" label="Select script" mapOptions :disable="!!check" @@ -140,6 +140,7 @@ export default { props: { check: Object, parent: Object, // {agent: agent.agent_id} or {policy: policy.id} + plat: String, }, setup(props) { // setup quasar dialog @@ -148,12 +149,13 @@ export default { // setup script dropdown const { script, - scriptOptions, + filterByPlatformOptions, defaultTimeout, defaultArgs, defaultEnvVars, } = useScriptDropdown({ script: props.check ? props.check.script : undefined, + plat: props.plat, onMount: true, }); @@ -182,7 +184,7 @@ export default { // non-reactive data failOptions, - scriptOptions, + filterByPlatformOptions, severityOptions, envVarsLabel, diff --git a/src/components/modals/agents/BulkAction.vue b/src/components/modals/agents/BulkAction.vue index 3b017a5..e107c60 100644 --- a/src/components/modals/agents/BulkAction.vue +++ b/src/components/modals/agents/BulkAction.vue @@ -83,7 +83,7 @@ // composition imports -import { ref, computed, watch, onMounted } from "vue"; +import { + ref, + reactive, + computed, + watch, + onMounted, + defineComponent, +} from "vue"; import { useDialogPluginComponent } from "quasar"; import { useScriptDropdown } from "@/composables/scripts"; import { useAgentDropdown } from "@/composables/agents"; @@ -218,7 +225,6 @@ import { useClientDropdown, useSiteDropdown } from "@/composables/clients"; import { runBulkAction } from "@/api/agents"; import { notifySuccess } from "@/utils/notify"; import { cmdPlaceholder } from "@/composables/agents"; -import { removeExtraOptionCategories } from "@/utils/format"; import { envVarsLabel, runAsUserToolTip } from "@/constants/constants"; // ui imports @@ -250,7 +256,7 @@ const patchModeOptions = [ { label: "Install", value: "install" }, ]; -export default { +export default defineComponent({ name: "BulkAction", components: { TacticalDropdown }, emits: [...useDialogPluginComponent.emits], @@ -259,7 +265,7 @@ export default { }, setup(props) { const shellOptions = computed(() => { - if (state.value.osType === "windows") { + if (state.osType === "windows") { return [ { label: "CMD", value: "cmd" }, { label: "Powershell", value: "powershell" }, @@ -286,7 +292,8 @@ export default { // dropdown setup const { script, - scriptOptions, + plat, + filterByPlatformOptions, defaultTimeout, defaultArgs, defaultEnvVars, @@ -297,7 +304,7 @@ export default { const { client, clientOptions, getClientOptions } = useClientDropdown(); // bulk action logic - const state = ref({ + const state = reactive({ mode: props.mode, target: "client", monType: "all", @@ -319,7 +326,7 @@ export default { const loading = ref(false); watch( - () => state.value.target, + () => state.target, () => { client.value = null; site.value = null; @@ -327,17 +334,23 @@ export default { }, ); + plat.value = state.osType; + watch( - () => state.value.osType, + () => state.osType, (newValue) => { - state.value.custom_shell = null; - state.value.run_as_user = false; + state.custom_shell = null; + state.run_as_user = false; if (newValue === "windows") { - state.value.shell = "cmd"; + state.shell = "cmd"; } else { - state.value.shell = "/bin/bash"; + state.shell = "/bin/bash"; } + + // set plat to filter script options + if (newValue === "all") plat.value = undefined; + else plat.value = newValue; }, ); @@ -345,7 +358,7 @@ export default { loading.value = true; try { - const data = await runBulkAction(state.value); + const data = await runBulkAction(state); notifySuccess(data); onDialogHide(); } catch (e) {} @@ -355,9 +368,7 @@ export default { const supportsRunAsUser = () => { const modes = ["script", "command"]; - return ( - state.value.osType === "windows" && modes.includes(state.value.mode) - ); + return state.osType === "windows" && modes.includes(state.mode); }; // set modal title and caption @@ -371,21 +382,6 @@ export default { : ""; }); - const filteredScriptOptions = computed(() => { - if (props.mode !== "script") return []; - if (state.value.osType === "all") return scriptOptions.value; - - return removeExtraOptionCategories( - scriptOptions.value.filter( - (script) => - script.category || - !script.supported_platforms || - script.supported_platforms.length === 0 || - script.supported_platforms.includes(state.value.osType), - ), - ); - }); - // component lifecycle hooks onMounted(() => { getAgentOptions(); @@ -400,7 +396,7 @@ export default { agentOptions, clientOptions, siteOptions, - filteredScriptOptions, + filterByPlatformOptions, loading, shellOptions, filteredOsTypeOptions, @@ -426,5 +422,5 @@ export default { onDialogHide, }; }, -}; +}); diff --git a/src/components/modals/agents/RunScript.vue b/src/components/modals/agents/RunScript.vue index 2ff781a..50f8179 100644 --- a/src/components/modals/agents/RunScript.vue +++ b/src/components/modals/agents/RunScript.vue @@ -39,9 +39,9 @@ @@ -106,13 +106,7 @@ class="col-3" label="Select script" v-model="script" - :options=" - type === 'policy' - ? scriptOptions - : type === 'server' - ? filterByPlatformOptions('linux') - : filterByPlatformOptions(plat) - " + :options="filterByPlatformOptions" filled mapOptions filterable @@ -904,6 +898,7 @@ const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent(); const { script, scriptOptions, + plat, filterByPlatformOptions, defaultTimeout, defaultArgs, @@ -913,6 +908,14 @@ const { onMount: true, }); +// set plat +plat.value = + props.type === "policy" + ? undefined // get all scripts + : props.type === "server" + ? "linux" // get only linux scripts for server + : props.plat; // filter scripts based on supported plat + // set defaultTimeout to 30 defaultTimeout.value = 30; diff --git a/src/composables/agents.js b/src/composables/agents.js index c20abae..f08c6ec 100644 --- a/src/composables/agents.js +++ b/src/composables/agents.js @@ -1,5 +1,5 @@ -import { ref } from "vue"; -import { useDashboardStore } from "@/stores/dashboard"; +import { ref, computed } from "vue"; +import { useStore } from "vuex"; import { fetchAgents } from "@/api/agents"; import { formatAgentOptions } from "@/utils/format"; @@ -29,11 +29,12 @@ export function useAgentDropdown() { } export function cmdPlaceholder(shell) { - const store = useDashboardStore(); + const store = useStore(); + const placeholders = computed(() => store.state.run_cmd_placeholder_text); - if (shell === "cmd") return store.runCmdPlaceholders.cmd; - else if (shell === "powershell") return store.runCmdPlaceholders.powershell; - else return store.runCmdPlaceholders.shell; + if (shell === "cmd") return placeholders.value.cmd; + else if (shell === "powershell") return placeholders.value.powershell; + else return placeholders.value.shell; } export const agentPlatformOptions = [ diff --git a/src/composables/scripts.ts b/src/composables/scripts.ts index 0faff2a..052ef19 100644 --- a/src/composables/scripts.ts +++ b/src/composables/scripts.ts @@ -15,26 +15,32 @@ export interface ScriptOption extends Script { export interface useScriptDropdownParams { script?: number; // set a selected script on init + plat?: AgentPlatformType; // set a platform for filterByPlatform onMount?: boolean; // loads script options on mount } // script dropdown -export function useScriptDropdown(opts: useScriptDropdownParams) { +export function useScriptDropdown(opts?: useScriptDropdownParams) { const scriptOptions = ref([] as ScriptOption[]); const defaultTimeout = ref(30); const defaultArgs = ref([] as string[]); const defaultEnvVars = ref([] as string[]); - const script = ref(opts.script); + const script = ref(opts?.script); const scriptName = ref(""); const syntax = ref(""); const link = ref(""); + const plat = ref(opts?.plat); const baseUrl = "https://github.com/amidaware/community-scripts/blob/main/scripts/"; // specify parameters to filter out community scripts - async function getScriptOptions(showCommunityScripts = false) { + async function getScriptOptions() { scriptOptions.value = Object.freeze( - formatScriptOptions(await fetchScripts({ showCommunityScripts })), + formatScriptOptions( + await fetchScripts({ + showCommunityScripts: showCommunityScripts.value, + }), + ), ) as ScriptOption[]; } @@ -64,33 +70,34 @@ export function useScriptDropdown(opts: useScriptDropdownParams) { const showCommunityScripts = computed(() => store.state.showCommunityScripts); // filter for only getting server tasks - const serverScriptOptions = computed(() => - removeExtraOptionCategories( - scriptOptions.value.filter( - (script) => - script.category || - !script.supported_platforms || - script.supported_platforms.length === 0 || - script.supported_platforms.includes("linux"), - ), - ), + const serverScriptOptions = computed( + () => + removeExtraOptionCategories( + scriptOptions.value.filter( + (script) => + script.category || + !script.supported_platforms || + script.supported_platforms.length === 0 || + script.supported_platforms.includes("linux"), + ), + ) as ScriptOption[], ); - const filterByPlatformOptions = (plat: AgentPlatformType | undefined) => { - if (!plat) { + const filterByPlatformOptions = computed(() => { + if (!plat.value) { return scriptOptions.value; + } else { + return removeExtraOptionCategories( + scriptOptions.value.filter( + (script) => + script.category || + !script.supported_platforms || + script.supported_platforms.length === 0 || + script.supported_platforms.includes(plat.value!), + ), + ) as ScriptOption[]; } - - return removeExtraOptionCategories( - scriptOptions.value.filter( - (script) => - script.category || - !script.supported_platforms || - script.supported_platforms.length === 0 || - script.supported_platforms.includes(plat), - ), - ); - }; + }); function reset() { defaultTimeout.value = 30; @@ -101,8 +108,7 @@ export function useScriptDropdown(opts: useScriptDropdownParams) { link.value = ""; } - if (opts.onMount) - onMounted(() => getScriptOptions(showCommunityScripts.value)); + if (opts?.onMount) onMounted(() => getScriptOptions()); return { //data @@ -113,14 +119,15 @@ export function useScriptDropdown(opts: useScriptDropdownParams) { scriptName, syntax, link, + plat, scriptOptions, // unfiltered options - serverScriptOptions, //only scripts that can run on server + serverScriptOptions, // only scripts that can run on server + filterByPlatformOptions, // use the returned plat to change options //methods getScriptOptions, - filterByPlatformOptions, - reset, + reset, // resets dropdown selection state }; }