From 64ba3a632eee041d09093e89961f63f2a090fcad Mon Sep 17 00:00:00 2001 From: hugocasa Date: Tue, 14 Apr 2026 22:42:13 +0200 Subject: [PATCH] feat: cascade trigger script_path on runnable rename + fix trigger permissioned_as (#8823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: cascade trigger script_path updates on script/flow rename + fix trigger permissioned_as Backend: When a script or flow path is renamed, automatically update script_path across all trigger tables (http, email, kafka, websocket, postgres, mqtt, nats, sqs, gcp, native). Long-running triggers get server_id reset to force restart. Native triggers additionally get async webhook URL re-registration with external services (Google, Nextcloud) via token rotation + handler.update(). Frontend: Fix permissioned_as handling across all trigger/schedule editors: - Allow setting permissioned_as on trigger creation (not just edit) for admins - Fix hasChanged detection for permissioned_as changes - Fix FolderEditor group selector showing usernames instead of group names Co-Authored-By: Claude Opus 4.6 (1M context) * refactor: rename script_rename -> runnable_rename for consistency "Runnable" is the correct term for both scripts and flows. Co-Authored-By: Claude Opus 4.6 (1M context) * refactor: remove native trigger re-registration from runnable rename Keep it simple — only update script_path in the DB for non-native triggers. Native triggers require external service re-registration (token rotation + webhook URL update) which adds significant complexity; defer to a future PR. sqlx files for the updated CTE query need regenerating. Co-Authored-By: Claude Opus 4.6 (1M context) * sqlx * refactor: call update_triggers_script_path directly, remove windmill-trigger wrapper No need for the extra module/dep — the common function is called directly from scripts.rs and flows.rs with inline error mapping. Co-Authored-By: Claude Opus 4.6 (1M context) * fix: reject empty principal in folder default permissioned_as validation `u/` and `g/` (no name after prefix) were passing validation. Use regex to require at least one character after the prefix. Co-Authored-By: Claude Opus 4.6 (1M context) * fix: prevent async folder-default load from overwriting user's permissioned_as choice Split the initialization effect into two: one that resets on trigger switch (tracks permissionedAs), and one that handles folder default loading (tracks folderDefault.value). The second effect is guarded by a userHasSelected flag set in handleSelect, so a late-arriving folder default doesn't wipe the user's explicit selection. Co-Authored-By: Claude Opus 4.6 (1M context) * lock --------- Co-authored-by: Claude Opus 4.6 (1M context) --- ...026efb056f90e5cc6a505f7164d69ca046a3f.json | 17 +++++++ ...e506f5a5c9c674dce0033fa6140a09f158593.json | 17 +++++++ backend/windmill-api-flows/Cargo.toml | 1 - backend/windmill-api-flows/src/flows.rs | 17 +++++-- backend/windmill-api-scripts/Cargo.toml | 1 - backend/windmill-api-scripts/src/scripts.rs | 12 +++++ backend/windmill-common/src/triggers.rs | 44 +++++++++++++++++++ .../src/lib/components/FolderEditor.svelte | 4 +- .../triggers/PermissionedAsLine.svelte | 36 +++++++++++++-- .../email/EmailTriggerEditorInner.svelte | 7 ++- .../triggers/gcp/GcpTriggerEditorInner.svelte | 7 ++- .../triggers/http/RouteEditorInner.svelte | 7 ++- .../kafka/KafkaTriggerEditorInner.svelte | 7 ++- .../mqtt/MqttTriggerEditorInner.svelte | 7 ++- .../nats/NatsTriggerEditorInner.svelte | 7 ++- .../PostgresTriggerEditorInner.svelte | 7 ++- .../schedules/ScheduleEditorInner.svelte | 7 ++- .../triggers/sqs/SqsTriggerEditorInner.svelte | 7 ++- .../WebsocketTriggerEditorInner.svelte | 7 ++- 19 files changed, 187 insertions(+), 32 deletions(-) create mode 100644 backend/.sqlx/query-38e782610bbabd5902e9b95ea6e026efb056f90e5cc6a505f7164d69ca046a3f.json create mode 100644 backend/.sqlx/query-c67fb61bd500bf1651df37a6ff0e506f5a5c9c674dce0033fa6140a09f158593.json diff --git a/backend/.sqlx/query-38e782610bbabd5902e9b95ea6e026efb056f90e5cc6a505f7164d69ca046a3f.json b/backend/.sqlx/query-38e782610bbabd5902e9b95ea6e026efb056f90e5cc6a505f7164d69ca046a3f.json new file mode 100644 index 0000000000..c921738495 --- /dev/null +++ b/backend/.sqlx/query-38e782610bbabd5902e9b95ea6e026efb056f90e5cc6a505f7164d69ca046a3f.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH t1 AS (UPDATE websocket_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), t2 AS (UPDATE kafka_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), t3 AS (UPDATE postgres_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), t4 AS (UPDATE mqtt_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), t5 AS (UPDATE nats_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), t6 AS (UPDATE sqs_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4) UPDATE gcp_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text", + "Text", + "Bool" + ] + }, + "nullable": [] + }, + "hash": "38e782610bbabd5902e9b95ea6e026efb056f90e5cc6a505f7164d69ca046a3f" +} diff --git a/backend/.sqlx/query-c67fb61bd500bf1651df37a6ff0e506f5a5c9c674dce0033fa6140a09f158593.json b/backend/.sqlx/query-c67fb61bd500bf1651df37a6ff0e506f5a5c9c674dce0033fa6140a09f158593.json new file mode 100644 index 0000000000..b1cfedbafb --- /dev/null +++ b/backend/.sqlx/query-c67fb61bd500bf1651df37a6ff0e506f5a5c9c674dce0033fa6140a09f158593.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH t1 AS (UPDATE http_trigger SET script_path = $1 WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4) UPDATE email_trigger SET script_path = $1 WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text", + "Text", + "Bool" + ] + }, + "nullable": [] + }, + "hash": "c67fb61bd500bf1651df37a6ff0e506f5a5c9c674dce0033fa6140a09f158593" +} diff --git a/backend/windmill-api-flows/Cargo.toml b/backend/windmill-api-flows/Cargo.toml index 5796c8fad8..231c00a159 100644 --- a/backend/windmill-api-flows/Cargo.toml +++ b/backend/windmill-api-flows/Cargo.toml @@ -12,7 +12,6 @@ path = "src/lib.rs" default = [] enterprise = ["windmill-common/enterprise"] private = ["windmill-common/private", "windmill-dep-map/private"] - [dependencies] windmill-common = { workspace = true, default-features = false } windmill-api-auth.workspace = true diff --git a/backend/windmill-api-flows/src/flows.rs b/backend/windmill-api-flows/src/flows.rs index f099f3b6e8..d9d6762017 100644 --- a/backend/windmill-api-flows/src/flows.rs +++ b/backend/windmill-api-flows/src/flows.rs @@ -222,10 +222,7 @@ async fn list_flows( async fn list_hub_flows(Extension(db): Extension) -> impl IntoResponse { let (status_code, headers, response) = query_elems_from_hub( &HTTP_CLIENT, - &format!( - "{}/searchFlowData?approved=true", - **HUB_BASE_URL.load() - ), + &format!("{}/searchFlowData?approved=true", **HUB_BASE_URL.load()), None, &db, ) @@ -1148,6 +1145,18 @@ async fn update_flow( } } + if is_new_path { + windmill_common::triggers::update_triggers_script_path( + &mut tx, &nf.path, &flow_path, &w_id, true, + ) + .await + .map_err(|e| { + error::Error::internal_err(format!( + "Error updating triggers due to runnable path change: {e:#}" + )) + })?; + } + sqlx::query!( "DELETE FROM draft WHERE path = $1 AND workspace_id = $2 AND typ = 'flow'", flow_path, diff --git a/backend/windmill-api-scripts/Cargo.toml b/backend/windmill-api-scripts/Cargo.toml index dcae7b779f..200a2aef64 100644 --- a/backend/windmill-api-scripts/Cargo.toml +++ b/backend/windmill-api-scripts/Cargo.toml @@ -13,7 +13,6 @@ default = [] enterprise = ["windmill-common/enterprise"] private = ["windmill-common/private", "windmill-dep-map/private"] python = ["dep:windmill-parser-py"] - [dependencies] windmill-common = { workspace = true, default-features = false } windmill-object-store.workspace = true diff --git a/backend/windmill-api-scripts/src/scripts.rs b/backend/windmill-api-scripts/src/scripts.rs index ae0b1dcc70..c4b928bcb5 100644 --- a/backend/windmill-api-scripts/src/scripts.rs +++ b/backend/windmill-api-scripts/src/scripts.rs @@ -1151,6 +1151,18 @@ async fn create_script_internal<'c>( .execute(&mut *tx) .await?; + if p_path != &ns.path { + windmill_common::triggers::update_triggers_script_path( + &mut tx, &ns.path, p_path, &w_id, false, + ) + .await + .map_err(|e| { + error::Error::internal_err(format!( + "Error updating triggers due to runnable path change: {e:#}" + )) + })?; + } + for schedule in schedulables { clear_schedule(&mut tx, &schedule.path, &w_id).await?; diff --git a/backend/windmill-common/src/triggers.rs b/backend/windmill-common/src/triggers.rs index 59b827a8cb..b4f8f472cc 100644 --- a/backend/windmill-common/src/triggers.rs +++ b/backend/windmill-common/src/triggers.rs @@ -7,3 +7,47 @@ lazy_static! { pub static ref RUNNABLE_FORMAT_VERSION_CACHE: Cache = Cache::new(1000); } + +/// Update `script_path` across all trigger tables when a runnable (script or flow) is renamed. +/// For long-running triggers (with `server_id`), also resets `server_id = NULL` to force +/// the heartbeat-based restart mechanism to pick up the new config. +pub async fn update_triggers_script_path( + tx: &mut sqlx::Transaction<'_, sqlx::Postgres>, + new_path: &str, + old_path: &str, + w_id: &str, + is_flow: bool, +) -> Result<(), sqlx::Error> { + // Triggers without server_id (request/response or webhook-based) + sqlx::query!( + "WITH \ + t1 AS (UPDATE http_trigger SET script_path = $1 WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4) \ + UPDATE email_trigger SET script_path = $1 WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4", + new_path, + old_path, + w_id, + is_flow, + ) + .execute(&mut **tx) + .await?; + + // Triggers with server_id (long-running listeners, reset server_id to force restart) + sqlx::query!( + "WITH \ + t1 AS (UPDATE websocket_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), \ + t2 AS (UPDATE kafka_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), \ + t3 AS (UPDATE postgres_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), \ + t4 AS (UPDATE mqtt_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), \ + t5 AS (UPDATE nats_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4), \ + t6 AS (UPDATE sqs_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4) \ + UPDATE gcp_trigger SET script_path = $1, server_id = NULL WHERE script_path = $2 AND workspace_id = $3 AND is_flow = $4", + new_path, + old_path, + w_id, + is_flow, + ) + .execute(&mut **tx) + .await?; + + Ok(()) +} diff --git a/frontend/src/lib/components/FolderEditor.svelte b/frontend/src/lib/components/FolderEditor.svelte index 8be3a6e222..d3a0df4e90 100644 --- a/frontend/src/lib/components/FolderEditor.svelte +++ b/frontend/src/lib/components/FolderEditor.svelte @@ -123,7 +123,7 @@ } function isValidPermissionedAs(value: string): boolean { - return value.startsWith('u/') || value.startsWith('g/') || value.includes('@') + return /^[ug]\/.+/.test(value) || value.includes('@') } // Split a permissioned_as value like "u/alice" or "g/prod" into its kind and name. @@ -136,7 +136,7 @@ } function setRulePermissionedAs(idx: number, kind: 'user' | 'group', name: string) { const prefix = kind === 'user' ? 'u/' : 'g/' - defaultPermissionedAs[idx].permissioned_as = name ? prefix + name : '' + defaultPermissionedAs[idx].permissioned_as = prefix + name } const defaultRulesInvalid = $derived( diff --git a/frontend/src/lib/components/triggers/PermissionedAsLine.svelte b/frontend/src/lib/components/triggers/PermissionedAsLine.svelte index a0f3795fd3..33b50eb850 100644 --- a/frontend/src/lib/components/triggers/PermissionedAsLine.svelte +++ b/frontend/src/lib/components/triggers/PermissionedAsLine.svelte @@ -32,6 +32,27 @@ let onBehalfOfChoice = $state(undefined) let customPermissionedAs = $state(undefined) + let userHasSelected = $state(false) + + // Full reset when permissionedAs changes (e.g. switching between edit/create). + $effect(() => { + permissionedAs + userHasSelected = false + customPermissionedAs = undefined + onBehalfOfChoice = undefined + }) + + // On creation with no folder default, default to "me". When the folder default + // loads async, transition to undefined so OnBehalfOfSelector's auto-select applies + // the folder default. Skip if the user has already made an explicit selection. + $effect(() => { + if (userHasSelected) return + if (permissionedAs === undefined && !folderDefault.value) { + onBehalfOfChoice = 'me' + } else { + onBehalfOfChoice = undefined + } + }) const effectivePermissionedAs = $derived.by(() => { if (onBehalfOfChoice === 'target') return permissionedAs @@ -45,12 +66,19 @@ permissionedAs !== effectivePermissionedAs ) - const shouldRender = $derived( - !!$workspaceStore && - (permissionedAs !== undefined || (canPreserve && folderDefault.value !== undefined)) - ) + const shouldRender = $derived(!!$workspaceStore && (permissionedAs !== undefined || canPreserve)) + + // For non-admin users editing a trigger owned by someone else: signal that + // permissioned_as will change to the current user (backend ignores preserve for non-admins). + // Only fires when there's an actual change (DB value differs from current user). + $effect(() => { + if (!canPreserve && permissionedAs !== undefined && permissionedAs !== myPermissionedAs) { + onPermissionedAsChange(undefined, false) + } + }) function handleSelect(choice: OnBehalfOfChoice, details?: OnBehalfOfDetails) { + userHasSelected = true onBehalfOfChoice = choice if (choice === 'target') { customPermissionedAs = undefined diff --git a/frontend/src/lib/components/triggers/email/EmailTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/email/EmailTriggerEditorInner.svelte index 075e60aa74..2cde08dc89 100644 --- a/frontend/src/lib/components/triggers/email/EmailTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/email/EmailTriggerEditorInner.svelte @@ -163,6 +163,9 @@ retry = defaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = defaultValues?.mode ?? 'enabled' + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loader) @@ -186,8 +189,8 @@ errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = cfg?.mode ?? 'enabled' permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function loadTrigger(defaultConfig?: Partial): Promise { diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte index bc04003f44..87b22f3255 100644 --- a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte @@ -165,6 +165,9 @@ auto_acknowledge_msg = defaultValues?.auto_acknowledge_msg ?? true ack_deadline = defaultValues?.ack_deadline errorHandlerSelected = getHandlerType(error_handler_path ?? '') + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { drawerLoading = false @@ -207,8 +210,8 @@ ack_deadline = cfg?.ack_deadline errorHandlerSelected = getHandlerType(error_handler_path ?? '') permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function updateTrigger(): Promise { diff --git a/frontend/src/lib/components/triggers/http/RouteEditorInner.svelte b/frontend/src/lib/components/triggers/http/RouteEditorInner.svelte index 74bfc5cb45..00391437f3 100644 --- a/frontend/src/lib/components/triggers/http/RouteEditorInner.svelte +++ b/frontend/src/lib/components/triggers/http/RouteEditorInner.svelte @@ -277,6 +277,9 @@ error_handler_args = defaultValues?.error_handler_args ?? {} retry = defaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loader) @@ -319,8 +322,8 @@ retry = cfg?.retry errorHandlerSelected = getHandlerType(error_handler_path ?? '') permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function loadTrigger(defaultConfig?: Partial): Promise { diff --git a/frontend/src/lib/components/triggers/kafka/KafkaTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/kafka/KafkaTriggerEditorInner.svelte index 32318888f7..f2bfd02f28 100644 --- a/frontend/src/lib/components/triggers/kafka/KafkaTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/kafka/KafkaTriggerEditorInner.svelte @@ -194,6 +194,9 @@ filterLogic = 'and' errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = nDefaultValues?.mode ?? 'enabled' + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loadingTimeout) @@ -224,8 +227,8 @@ filterLogic = cfg?.filter_logic ?? 'and' errorHandlerSelected = getHandlerType(error_handler_path ?? '') permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function loadTrigger(defaultConfig?: Record): Promise { diff --git a/frontend/src/lib/components/triggers/mqtt/MqttTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/mqtt/MqttTriggerEditorInner.svelte index de81009cc7..537d14bef0 100644 --- a/frontend/src/lib/components/triggers/mqtt/MqttTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/mqtt/MqttTriggerEditorInner.svelte @@ -191,6 +191,9 @@ activateV5Options.session_expiry_interval = Boolean( defaultValues?.v5_config?.session_expiry_interval ) + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loadingTimeout) @@ -220,8 +223,8 @@ activateV5Options.topic_alias_maximum = Boolean(v5_config.topic_alias_maximum) activateV5Options.session_expiry_interval = Boolean(v5_config.session_expiry_interval) permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } catch (error) { sendUserToast(`Could not load mqtt trigger config: ${error.body}`, true) } diff --git a/frontend/src/lib/components/triggers/nats/NatsTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/nats/NatsTriggerEditorInner.svelte index e01ca859d9..135c08b9d8 100644 --- a/frontend/src/lib/components/triggers/nats/NatsTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/nats/NatsTriggerEditorInner.svelte @@ -178,6 +178,9 @@ error_handler_args = nDefaultValues?.error_handler_args ?? {} retry = nDefaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loadingTimeout) @@ -206,8 +209,8 @@ retry = cfg?.retry errorHandlerSelected = getHandlerType(error_handler_path ?? '') permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function loadTrigger(defaultConfig?: Record): Promise { diff --git a/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte index 6bf700769a..4d59b0b68c 100644 --- a/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte @@ -296,6 +296,9 @@ retry = defaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = defaultValues?.mode ?? 'enabled' + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loadingTimeout) @@ -346,8 +349,8 @@ errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = cfg?.mode ?? 'enabled' permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } async function loadTrigger(defaultConfig?: Record): Promise { diff --git a/frontend/src/lib/components/triggers/schedules/ScheduleEditorInner.svelte b/frontend/src/lib/components/triggers/schedules/ScheduleEditorInner.svelte index 76148eba22..85a1ff843d 100644 --- a/frontend/src/lib/components/triggers/schedules/ScheduleEditorInner.svelte +++ b/frontend/src/lib/components/triggers/schedules/ScheduleEditorInner.svelte @@ -311,6 +311,9 @@ retry = s?.retry ?? undefined await setScheduleHandler(s) + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false } finally { clearTimeout(loadingTimeout) drawerLoading = false @@ -516,8 +519,8 @@ can_write = canWrite(cfg.path, cfg.extra_perms, $userStore) tag = cfg.tag permissionedAs = cfg.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg.permissioned_as + preservePermissionedAs = !!cfg.permissioned_as loading = false } diff --git a/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorInner.svelte index b58283fa6b..09f7782e1d 100644 --- a/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorInner.svelte @@ -168,6 +168,9 @@ error_handler_args = defaultValues?.error_handler_args ?? {} retry = defaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { initialConfig = structuredClone($state.snapshot(getSaveCfg())) @@ -194,8 +197,8 @@ retry = cfg?.retry errorHandlerSelected = getHandlerType(error_handler_path ?? '') permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } catch (error) { sendUserToast(`Could not load SQS trigger config: ${error.body}`, true) } diff --git a/frontend/src/lib/components/triggers/websocket/WebsocketTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/websocket/WebsocketTriggerEditorInner.svelte index 51e3e7685e..ce807c7e3c 100644 --- a/frontend/src/lib/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/websocket/WebsocketTriggerEditorInner.svelte @@ -221,6 +221,9 @@ retry = defaultValues?.retry ?? undefined errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = defaultValues?.mode ?? 'enabled' + permissionedAs = undefined + selectedPermissionedAs = undefined + preservePermissionedAs = false originalConfig = undefined } finally { clearTimeout(loadingTimeout) @@ -253,8 +256,8 @@ errorHandlerSelected = getHandlerType(error_handler_path ?? '') mode = cfg?.mode ?? 'enabled' permissionedAs = cfg?.permissioned_as - selectedPermissionedAs = undefined - preservePermissionedAs = false + selectedPermissionedAs = cfg?.permissioned_as + preservePermissionedAs = !!cfg?.permissioned_as } function getSaveCfg() {