mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-19 00:03:19 +00:00
feat: add trashbin system for soft-deleting items (#8519)
This commit is contained in:
@@ -2240,33 +2240,58 @@ async fn delete_script_by_path(
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
|
||||
let script = if !draft_only {
|
||||
if !draft_only {
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path",
|
||||
}
|
||||
|
||||
// Capture all script versions and drafts for trashbin before deleting
|
||||
let trash_scripts: Vec<serde_json::Value> = sqlx::query_scalar(
|
||||
"SELECT to_jsonb(t) FROM script t WHERE path = $1 AND workspace_id = $2",
|
||||
)
|
||||
.bind(path)
|
||||
.bind(&w_id)
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
|
||||
let trash_drafts: Vec<serde_json::Value> = sqlx::query_scalar(
|
||||
"SELECT to_jsonb(t) FROM draft t WHERE path = $1 AND workspace_id = $2 AND typ = 'script'",
|
||||
)
|
||||
.bind(path)
|
||||
.bind(&w_id)
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
|
||||
let script = sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting script by path {w_id}: {e:#}")))?;
|
||||
|
||||
if !trash_scripts.is_empty() {
|
||||
let mut trash_data = serde_json::json!({"scripts": trash_scripts});
|
||||
if !trash_drafts.is_empty() {
|
||||
trash_data["drafts"] = serde_json::Value::Array(trash_drafts);
|
||||
}
|
||||
windmill_common::trashbin::move_to_trash(
|
||||
&mut *tx,
|
||||
&w_id,
|
||||
"script",
|
||||
path,
|
||||
w_id
|
||||
trash_data,
|
||||
&authed.username,
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting script by path {w_id}: {e:#}")))?
|
||||
} else {
|
||||
sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting script by path {w_id}: {e:#}")))?
|
||||
};
|
||||
.await?;
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"DELETE FROM draft WHERE path = $1 AND workspace_id = $2 AND typ = 'script'",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.execute(&db)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
if !query.keep_captures.unwrap_or(false) {
|
||||
@@ -2275,7 +2300,7 @@ async fn delete_script_by_path(
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.execute(&db)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
@@ -2283,7 +2308,7 @@ async fn delete_script_by_path(
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.execute(&db)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -2370,6 +2395,30 @@ async fn delete_scripts_bulk(
|
||||
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
// Capture scripts for trashbin per path before bulk delete
|
||||
for path in &request.paths {
|
||||
let trash_scripts: Vec<serde_json::Value> = sqlx::query_scalar(
|
||||
"SELECT to_jsonb(t) FROM script t WHERE path = $1 AND workspace_id = $2",
|
||||
)
|
||||
.bind(path)
|
||||
.bind(&w_id)
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
|
||||
if !trash_scripts.is_empty() {
|
||||
let trash_data = serde_json::json!({"scripts": trash_scripts});
|
||||
windmill_common::trashbin::move_to_trash(
|
||||
&mut *tx,
|
||||
&w_id,
|
||||
"script",
|
||||
path,
|
||||
trash_data,
|
||||
&authed.username,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut deleted_paths = sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE workspace_id = $1 AND path = ANY($2) RETURNING path",
|
||||
w_id,
|
||||
|
||||
Reference in New Issue
Block a user