mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
fix: the move record alone excuses a carried draft at the destination, whoever owns it
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
df2973ffff
commit
baafd1e002
+2
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT d.email IS NULL as \"legacy!\", COALESCE(u.username, p.username) as username\n FROM draft d\n LEFT JOIN usr u ON u.workspace_id = d.workspace_id AND u.email = d.email\n LEFT JOIN password p ON p.email = d.email AND p.super_admin = true\n WHERE d.workspace_id = $1 AND d.path = $2 AND d.typ::text = ANY($3::text[])\n -- A row of the consuming owner's that a move brought here from the very path\n -- being renamed is the draft this deploy carries, not an item in its way. Any\n -- other row of theirs is a second item and still collides.\n AND ($4::text IS NULL OR d.email IS DISTINCT FROM $4 OR NOT EXISTS (\n SELECT 1 FROM draft_move m\n WHERE m.workspace_id = $1 AND m.typ::text = ANY($3::text[])\n AND m.old_path = $5 AND m.new_path = $2\n AND (m.email IS NULL OR m.email = $4)\n ))\n ORDER BY 2",
|
||||
"query": "SELECT d.email IS NULL as \"legacy!\", COALESCE(u.username, p.username) as username\n FROM draft d\n LEFT JOIN usr u ON u.workspace_id = d.workspace_id AND u.email = d.email\n LEFT JOIN password p ON p.email = d.email AND p.super_admin = true\n WHERE d.workspace_id = $1 AND d.path = $2 AND d.typ::text = ANY($3::text[])\n -- A row a move already brought here from the very path being renamed is this\n -- rename's own draft, not an item in its way: the record says which owners\n -- it moved (all of them for an item move, one for a draft-only move). Any\n -- other row is a second item and still collides.\n AND NOT EXISTS (\n SELECT 1 FROM draft_move m\n WHERE m.workspace_id = $1 AND m.typ::text = ANY($3::text[])\n AND m.old_path = $4 AND m.new_path = $2\n AND (m.email IS NULL OR m.email IS NOT DISTINCT FROM d.email)\n )\n ORDER BY 2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -19,7 +19,6 @@
|
||||
"Text",
|
||||
"Text",
|
||||
"TextArray",
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
@@ -28,5 +27,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "e34f4d6a151cc791960c61197a4b00ea9db2f6ee47dc154faefe4c06c41cf1cf"
|
||||
"hash": "fc2081d9077c743bc3978ae1905db558549b2356fc6ac8f0557aa40e1345ff46"
|
||||
}
|
||||
@@ -1426,7 +1426,6 @@ async fn update_flow(
|
||||
&[UserDraftItemKind::Flow],
|
||||
flow_path,
|
||||
&nf.path,
|
||||
(!nf.skip_draft_deletion.unwrap_or(false)).then_some(authed.email.as_str()),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -2322,7 +2322,6 @@ async fn create_script_internal<'c>(
|
||||
&[UserDraftItemKind::Script],
|
||||
p_path,
|
||||
&ns.path,
|
||||
(!skip_draft_deletion).then_some(authed.email.as_str()),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -3770,7 +3770,6 @@ async fn update_app_internal<'a>(
|
||||
&[UserDraftItemKind::App, UserDraftItemKind::RawApp],
|
||||
path,
|
||||
&npath,
|
||||
(!ns.skip_draft_deletion.unwrap_or(false)).then_some(authed.email.as_str()),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -662,16 +662,15 @@ pub async fn delete_own_draft_for_path(
|
||||
///
|
||||
/// A draft already at `new_path` occupies it the way a deployed item does, so the move is
|
||||
/// refused with `BadRequest` inside the deploy's transaction, refusing the rename itself:
|
||||
/// moving onto it would merge two items or strand the row that lost. `consumed_by` names
|
||||
/// the owner whose row there this deploy consumes, which is the draft being deployed after
|
||||
/// an earlier move carried it, and so cannot be in its own way.
|
||||
/// moving onto it would merge two items or strand the row that lost. A row a `draft_move`
|
||||
/// record already brought there from `old_path` is this rename's own draft and does not
|
||||
/// count: deploying it would otherwise be refused against itself, with no way out.
|
||||
pub async fn move_drafts_for_path(
|
||||
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
w_id: &str,
|
||||
kinds: &[UserDraftItemKind],
|
||||
old_path: &str,
|
||||
new_path: &str,
|
||||
consumed_by: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let typs = kinds.iter().map(|k| k.as_str()).collect::<Vec<_>>();
|
||||
// Named by workspace username, as the editors name other users' drafts: the
|
||||
@@ -682,20 +681,20 @@ pub async fn move_drafts_for_path(
|
||||
LEFT JOIN usr u ON u.workspace_id = d.workspace_id AND u.email = d.email
|
||||
LEFT JOIN password p ON p.email = d.email AND p.super_admin = true
|
||||
WHERE d.workspace_id = $1 AND d.path = $2 AND d.typ::text = ANY($3::text[])
|
||||
-- A row of the consuming owner's that a move brought here from the very path
|
||||
-- being renamed is the draft this deploy carries, not an item in its way. Any
|
||||
-- other row of theirs is a second item and still collides.
|
||||
AND ($4::text IS NULL OR d.email IS DISTINCT FROM $4 OR NOT EXISTS (
|
||||
-- A row a move already brought here from the very path being renamed is this
|
||||
-- rename's own draft, not an item in its way: the record says which owners
|
||||
-- it moved (all of them for an item move, one for a draft-only move). Any
|
||||
-- other row is a second item and still collides.
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM draft_move m
|
||||
WHERE m.workspace_id = $1 AND m.typ::text = ANY($3::text[])
|
||||
AND m.old_path = $5 AND m.new_path = $2
|
||||
AND (m.email IS NULL OR m.email = $4)
|
||||
))
|
||||
AND m.old_path = $4 AND m.new_path = $2
|
||||
AND (m.email IS NULL OR m.email IS NOT DISTINCT FROM d.email)
|
||||
)
|
||||
ORDER BY 2"#,
|
||||
w_id,
|
||||
new_path,
|
||||
&typs as &[&str],
|
||||
consumed_by,
|
||||
old_path,
|
||||
)
|
||||
.fetch_all(&mut **tx)
|
||||
|
||||
Reference in New Issue
Block a user