diff --git a/backend/windmill-api/src/hub_publish.rs b/backend/windmill-api/src/hub_publish.rs index f864e9f4e3..bdf4bf1093 100644 --- a/backend/windmill-api/src/hub_publish.rs +++ b/backend/windmill-api/src/hub_publish.rs @@ -57,7 +57,6 @@ async fn publish_draft( Json(body): Json, ) -> Result { require_admin(authed.is_admin, &authed.username)?; - // source_id is injected from the trusted `workspace` path by forward_to_hub. forward_to_hub( "/projects", &workspace, @@ -311,11 +310,6 @@ async fn get_project_export( get_from_hub(&format!("/projects/{}/export", slug), &workspace).await } -// `source_id` is the server-trusted workspace from the `{workspace}` path — NOT -// client-supplied — so the Hub can enforce that the targeted project belongs to -// the calling workspace. Without it, any workspace admin could mutate or read -// another workspace's Hub project by passing its `project_slug`, since the Hub -// authenticates every call with the same instance-wide HUB_DEV_TOKEN. async fn get_from_hub(path: &str, source_id: &str) -> Result<(StatusCode, String), Error> { let hub_token = std::env::var("HUB_DEV_TOKEN") .map_err(|_| Error::BadRequest("HUB_DEV_TOKEN not set".into()))?; @@ -349,8 +343,6 @@ async fn forward_to_hub( let url = format!("{}{}", **HUB_BASE_URL.load(), path); - // Stamp the trusted workspace onto the payload so the Hub can verify - // ownership; never trust the client-supplied project_slug alone. let mut payload = serde_json::to_value(body).map_err(to_anyhow)?; let obj = payload .as_object_mut() diff --git a/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte b/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte index eb9b8ebefb..920e5c6488 100644 --- a/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte +++ b/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte @@ -392,6 +392,19 @@ schedulePreviews = {} selectedFolder = undefined manualDeselected = new Set() + phase = 'predeploy' + draftItems = [] + recordings = {} + deploymentStatus = {} + hubItemIds = {} + effectiveSlug = '' + hubVersion = 0 + hubName = '' + hubSummary = '' + hubReadme = '' + bundleName = '' + bundleSummary = '' + bundleReadme = '' loadWorkspace($workspaceStore, seq) loadTriggers($workspaceStore, seq) } diff --git a/frontend/src/routes/(root)/(logged)/projects/install/+page.svelte b/frontend/src/routes/(root)/(logged)/projects/install/+page.svelte index 6aadff78e6..2637d43bca 100644 --- a/frontend/src/routes/(root)/(logged)/projects/install/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/projects/install/+page.svelte @@ -50,7 +50,6 @@ ) if (!res.ok) throw new Error(`export ${res.status}: ${await res.text()}`) data = JSON.parse(await res.text()) - // Default the target folder to the project slug. if (data && !folderName) folderName = data.project.slug } catch (e: any) { loadError = e?.message ?? String(e) @@ -85,9 +84,6 @@ // Minimal non-public policy for re-created apps. const defaultPolicy = { execution_mode: 'publisher', triggerables_v2: {} } as any - // Everything in the bundle lives under `f//`. To import into a different - // folder we swap that prefix everywhere (item paths, `$res:`/script refs, - // schedule runnable paths) by rewriting the serialized bundle in one pass. function retarget(bundle: ProjectExport, fromSlug: string, folder: string): ProjectExport { if (folder === fromSlug) return bundle const json = JSON.stringify(bundle).split(`f/${fromSlug}/`).join(`f/${folder}/`) @@ -101,7 +97,6 @@ results = [] done = false try { - // Ensure the target folder exists (no-op/ignored if it already does). try { await FolderService.createFolder({ workspace, requestBody: { name: folder } }) } catch {}