diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 160273bd7a..292dfd591f 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -3290,6 +3290,8 @@ paths: schema: type: object properties: + component: + type: string #script: script/ #flow: flow/ path: @@ -3311,6 +3313,7 @@ paths: type: object required: - args + - component responses: "200": diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index b9b658f63f..987d4ab012 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -667,6 +667,7 @@ pub struct ExecuteApp { // - script: script/ // - flow: flow/ pub path: Option, + pub component: String, pub raw_code: Option, // if set, the app is executed as viewer with the given static fields pub force_viewer_static_fields: Option, @@ -705,11 +706,16 @@ async fn execute_component( let policy = if let Some(static_fields) = payload.clone().force_viewer_static_fields { let mut hm = HashMap::new(); + if let Some(path) = payload.path.clone() { - hm.insert(path, static_fields); + hm.insert(format!("{}:{path}", payload.component), static_fields); } else { hm.insert( - digest(payload.raw_code.clone().unwrap().content.as_str()), + format!( + "{}:{}", + payload.component, + digest(payload.raw_code.clone().unwrap().content.as_str()) + ), static_fields, ); } @@ -761,14 +767,14 @@ async fn execute_component( }; let (job_payload, args, tag) = match &payload { - ExecuteApp { args, raw_code: Some(raw_code), path: None, .. } => { + ExecuteApp { args, component, raw_code: Some(raw_code), path: None, .. } => { let content = &raw_code.content; let payload = JobPayload::Code(raw_code.clone()); let path = digest(content); - let args = build_args(policy, path, args)?; + let args = build_args(policy, component, path, args)?; (payload, args, None) } - ExecuteApp { args, raw_code: None, path: Some(path), .. } => { + ExecuteApp { args, component, raw_code: None, path: Some(path), .. } => { let (payload, tag) = if path.starts_with("script/") { script_path_to_payload( path.strip_prefix("script/").unwrap(), @@ -787,7 +793,7 @@ async fn execute_component( path ))); }; - let args = build_args(policy, path.to_string(), args)?; + let args = build_args(policy, component, path.to_string(), args)?; (payload, args, tag) } _ => unreachable!(), @@ -860,15 +866,18 @@ async fn exists_app( fn build_args( policy: Policy, + component: &str, path: String, args: &Map, ) -> Result> { // disallow var and res access in args coming from the user for security reasons args.into_iter() .try_for_each(|x| disallow_var_res_access(x.1))?; + let key = format!("{}:{}", component, &path); let static_args = policy .triggerables - .get(&path) + .get(&key) + .or_else(|| policy.triggerables.get(&path)) .map(|x| x.clone()) .or_else(|| { if matches!(policy.execution_mode, ExecutionMode::Viewer) { diff --git a/backend/windmill-api/src/favorite.rs b/backend/windmill-api/src/favorite.rs index 84a23b6ad8..01e6b9a57a 100644 --- a/backend/windmill-api/src/favorite.rs +++ b/backend/windmill-api/src/favorite.rs @@ -29,6 +29,7 @@ pub enum FavoriteKind { Script, Flow, App, + #[allow(non_camel_case_types)] Raw_App, } #[derive(Deserialize)] diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte index 54da05d290..6ca3b9a143 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte @@ -229,6 +229,7 @@ const requestBody = { args: nonStaticRunnableInputs, + component: id, force_viewer_static_fields: !isEditor ? undefined : staticRunnableInputs } diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte index 0a4c112e1a..ace1ea488d 100644 --- a/frontend/src/lib/components/apps/editor/AppEditor.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -44,7 +44,7 @@ import SettingsPanel from './SettingsPanel.svelte' import { secondaryMenu, SecondaryMenu } from './settingsPanel/secondaryMenu' import Popover from '../../Popover.svelte' - import { migrateApp } from '../utils' + import { BG_PREFIX, migrateApp } from '../utils' export let app: App export let path: string @@ -148,7 +148,7 @@ selectedTab = 'settings' if (befSelected) { - if (!['ctx', 'state'].includes(befSelected) && !befSelected?.startsWith('bg_')) { + if (!['ctx', 'state'].includes(befSelected) && !befSelected?.startsWith(BG_PREFIX)) { let item = findGridItem($appStore, befSelected) if (item?.data.type === 'containercomponent') { $focusedGrid = { diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index 43a7d62326..7ab037e7d2 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -39,7 +39,7 @@ UserAppInput } from '../inputType' import type { AppEditorContext, AppViewerContext } from '../types' - import { allItems, toStatic } from '../utils' + import { BG_PREFIX, allItems, toStatic } from '../utils' import AppExportButton from './AppExportButton.svelte' import AppInputs from './AppInputs.svelte' import type { AppComponent } from './component/components' @@ -139,16 +139,17 @@ if (c.type === 'tablecomponent') { r.push(...c.actionButtons.map((x) => x.componentInput)) } - return r.filter((x) => x) - }) - .map(async (input) => { - if (input?.type == 'runnable') { - return await processRunnable(input.runnable, input.fields) - } + return r + .filter((x) => x) + .map(async (input) => { + if (input?.type == 'runnable') { + return await processRunnable(x.id, input.runnable, input.fields) + } + }) }) .concat( - Object.values($app.hiddenInlineScripts ?? {}).map(async (v) => { - return await processRunnable(v, v.fields) + Object.values($app.hiddenInlineScripts ?? {}).map(async (v, i) => { + return await processRunnable(BG_PREFIX + i, v, v.fields) }) ) )) as ([string, Record] | undefined)[] @@ -158,16 +159,17 @@ } async function processRunnable( + id: string, runnable: Runnable, fields: Record ): Promise<[string, Record] | undefined> { const staticInputs = collectStaticFields(fields) if (runnable?.type == 'runnableByName') { let hex = await hash(runnable.inlineScript?.content) - return [`rawscript/${hex}`, staticInputs] + return [`${id}:rawscript/${hex}`, staticInputs] } else if (runnable?.type == 'runnableByPath') { let prefix = runnable.runType !== 'hubscript' ? runnable.runType : 'script' - return [`${prefix}/${runnable.path}`, staticInputs] + return [`${id}:${prefix}/${runnable.path}`, staticInputs] } } async function createApp(path: string) { diff --git a/frontend/src/lib/components/apps/editor/AppInputs.svelte b/frontend/src/lib/components/apps/editor/AppInputs.svelte index 38329dbc2a..323b15628a 100644 --- a/frontend/src/lib/components/apps/editor/AppInputs.svelte +++ b/frontend/src/lib/components/apps/editor/AppInputs.svelte @@ -3,7 +3,7 @@ import Toggle from '$lib/components/Toggle.svelte' import { getContext } from 'svelte' import type { AppViewerContext } from '../types' - import { allItems } from '../utils' + import { BG_PREFIX, allItems } from '../utils' import AppComponentInput from './AppComponentInput.svelte' import InputsSpecsEditor from './settingsPanel/InputsSpecsEditor.svelte' @@ -50,7 +50,7 @@ No resource input {:else} + {/if} {/each} {/if} diff --git a/frontend/src/lib/components/apps/editor/GridEditor.svelte b/frontend/src/lib/components/apps/editor/GridEditor.svelte index b50aa542c3..67ad99bdad 100644 --- a/frontend/src/lib/components/apps/editor/GridEditor.svelte +++ b/frontend/src/lib/components/apps/editor/GridEditor.svelte @@ -16,6 +16,7 @@ import { classNames } from '$lib/utils' import Toggle from '$lib/components/Toggle.svelte' import Tooltip from '$lib/components/Tooltip.svelte' + import { BG_PREFIX } from '../utils' export let policy: Policy @@ -129,7 +130,7 @@ {#if $app.hiddenInlineScripts} {#each $app.hiddenInlineScripts as runnable, index} {#if runnable} - + {/if} {/each} {/if} diff --git a/frontend/src/lib/components/apps/editor/SettingsPanel.svelte b/frontend/src/lib/components/apps/editor/SettingsPanel.svelte index 855cd8a978..e3c01eae2c 100644 --- a/frontend/src/lib/components/apps/editor/SettingsPanel.svelte +++ b/frontend/src/lib/components/apps/editor/SettingsPanel.svelte @@ -1,7 +1,7 @@ {#each $app.hiddenInlineScripts as action, index} {#if !action.hidden} - + {/if} {/each} diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte index 9b6a3a62be..dbbe795fc3 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte @@ -8,6 +8,7 @@ import InlineScriptsPanelWithTable from './InlineScriptsPanelWithTable.svelte' import { findGridItem } from '../appUtils' import InlineScriptHiddenRunnable from './InlineScriptHiddenRunnable.svelte' + import { BG_PREFIX } from '../../utils' const { app, runnableComponents } = getContext('AppViewerContext') const { selectedComponentInEditor } = getContext('AppEditorContext') @@ -30,16 +31,16 @@ } $selectedComponentInEditor = undefined - delete $runnableComponents[`bg_${index}`] + delete $runnableComponents[BG_PREFIX + index] } $: gridItem = - $selectedComponentInEditor && !$selectedComponentInEditor.startsWith('bg_') + $selectedComponentInEditor && !$selectedComponentInEditor.startsWith(BG_PREFIX) ? findGridItem($app, $selectedComponentInEditor?.split('_')?.[0]) : undefined $: hiddenInlineScript = $app?.hiddenInlineScripts?.findIndex( - (k_, index) => `bg_${index}` === $selectedComponentInEditor + (k_, index) => BG_PREFIX + index === $selectedComponentInEditor ) $: unusedInlineScript = $app?.unusedInlineScripts?.findIndex( @@ -79,7 +80,7 @@ {#if $app.hiddenInlineScripts?.[hiddenInlineScript]} deleteBackgroundScript(hiddenInlineScript)} - id={`bg_${hiddenInlineScript}`} + id={BG_PREFIX + hiddenInlineScript} bind:runnable={$app.hiddenInlineScripts[hiddenInlineScript]} />{/if}{/key} {:else} diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte index 881f13d5f1..5ba032ca0d 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte @@ -4,7 +4,7 @@ import { getContext } from 'svelte' import Tooltip from '../../../Tooltip.svelte' import type { AppEditorContext, AppViewerContext } from '../../types' - import { getAllScriptNames } from '../../utils' + import { BG_PREFIX, getAllScriptNames } from '../../utils' import PanelSection from '../settingsPanel/common/PanelSection.svelte' import { getAppScripts } from './utils' @@ -15,7 +15,7 @@ function selectScript(id: string) { $selectedComponentInEditor = id - if (!id.startsWith('unused-') || !id.startsWith('bg_')) { + if (!id.startsWith('unused-') || !id.startsWith(BG_PREFIX)) { $selectedComponent = [$selectedComponentInEditor.split('_transformer')[0]] } } @@ -39,7 +39,7 @@ if (script.hidden) { delete script.hidden $app.hiddenInlineScripts = $app.hiddenInlineScripts - selectScript(`bg_${index}`) + selectScript(BG_PREFIX + index) return } } @@ -66,7 +66,7 @@ recomputeIds: undefined }) $app.hiddenInlineScripts = $app.hiddenInlineScripts - selectScript(`bg_${$app.hiddenInlineScripts.length - 1}`) + selectScript(`${BG_PREFIX}${$app.hiddenInlineScripts.length - 1}`) } @@ -181,7 +181,7 @@ {#if $app.hiddenInlineScripts?.length > 0} {#each $app.hiddenInlineScripts as { name, hidden }, index (index)} {#if !hidden} - {@const id = `bg_${index}`} + {@const id = BG_PREFIX + index}