mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 00:03:00 +00:00
fix: delete only the scope-checked triggers when disconnecting
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
33719ae1f1
commit
b552922036
+8
-2
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT script_path FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND connection_path = $3",
|
||||
"query": "SELECT external_id, script_path FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND connection_path = $3",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "external_id",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
@@ -28,8 +33,9 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "387aebd876ef240f9c7c99c977d0b66587f50a70c24f331aa5838a754d13ada9"
|
||||
"hash": "4c12e63ddcf4e8cfe2227421db8869c4fb77e2fa3b98d6b054995875f3fd5a10"
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT external_id, connection_path FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND ($3::text IS NULL OR connection_path = $3)",
|
||||
"query": "SELECT external_id, connection_path FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND ($3::text[] IS NULL OR external_id = ANY($3))",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Text"
|
||||
"TextArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
@@ -37,5 +37,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "1ecd50aa13f5d4babdfaaba6ff56940ac9e6d7a28a27e576b5dda4d7e709ad1a"
|
||||
"hash": "c0a782d90433c27c97eeb49cf620e993320337f046e95efbd5bc21adf69e3d7d"
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND ($3::text IS NULL OR connection_path = $3)\n RETURNING webhook_token_hash",
|
||||
"query": "DELETE FROM native_trigger\n WHERE workspace_id = $1 AND service_name = $2 AND ($3::text[] IS NULL OR external_id = ANY($3))\n RETURNING webhook_token_hash",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -24,12 +24,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Text"
|
||||
"TextArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "6e1231d0db1d3736b05a41aa0a3f125cb2f383a53645d7c48cbd0478c3364663"
|
||||
"hash": "e4407cb73d41652088bb6dcef2503e91a190217cc7875ebb07928b25720ae20b"
|
||||
}
|
||||
@@ -348,22 +348,22 @@ async fn fetch_nextcloud_user_id(base_url: &str, access_token: &str) -> anyhow::
|
||||
Ok(ocs.ocs.data.id)
|
||||
}
|
||||
|
||||
/// Delete the native triggers of a workspace+service — only those using `connection_path` when
|
||||
/// given — including remote webhook cleanup.
|
||||
/// Delete the native triggers of a workspace+service — only those in `external_ids` when given —
|
||||
/// including remote webhook cleanup.
|
||||
/// This is best-effort: errors during remote cleanup or token deletion are logged but ignored.
|
||||
#[cfg(feature = "native_trigger")]
|
||||
async fn delete_triggers_for_service(
|
||||
db: &DB,
|
||||
workspace_id: &str,
|
||||
service_name: ServiceName,
|
||||
connection_path: Option<&str>,
|
||||
external_ids: Option<&[String]>,
|
||||
) {
|
||||
let triggers = sqlx::query!(
|
||||
"SELECT external_id, connection_path FROM native_trigger
|
||||
WHERE workspace_id = $1 AND service_name = $2 AND ($3::text IS NULL OR connection_path = $3)",
|
||||
WHERE workspace_id = $1 AND service_name = $2 AND ($3::text[] IS NULL OR external_id = ANY($3))",
|
||||
workspace_id,
|
||||
service_name as ServiceName,
|
||||
connection_path,
|
||||
external_ids,
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await;
|
||||
@@ -423,11 +423,11 @@ async fn delete_triggers_for_service(
|
||||
// disconnected integration keep starting jobs.
|
||||
let deleted_token_hashes = sqlx::query_scalar!(
|
||||
"DELETE FROM native_trigger
|
||||
WHERE workspace_id = $1 AND service_name = $2 AND ($3::text IS NULL OR connection_path = $3)
|
||||
WHERE workspace_id = $1 AND service_name = $2 AND ($3::text[] IS NULL OR external_id = ANY($3))
|
||||
RETURNING webhook_token_hash",
|
||||
workspace_id,
|
||||
service_name as ServiceName,
|
||||
connection_path,
|
||||
external_ids,
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
@@ -1084,9 +1084,10 @@ async fn delete_connection(
|
||||
)));
|
||||
}
|
||||
|
||||
// Disconnecting deletes these triggers, so a path-scoped token must cover each of them.
|
||||
let trigger_paths = sqlx::query_scalar!(
|
||||
"SELECT script_path FROM native_trigger
|
||||
// Disconnecting deletes these triggers, so a path-scoped token must cover each of them. Only
|
||||
// the rows checked here are deleted: one created meanwhile is never removed unchecked.
|
||||
let triggers = sqlx::query!(
|
||||
"SELECT external_id, script_path FROM native_trigger
|
||||
WHERE workspace_id = $1 AND service_name = $2 AND connection_path = $3",
|
||||
workspace_id,
|
||||
service_name as ServiceName,
|
||||
@@ -1094,12 +1095,15 @@ async fn delete_connection(
|
||||
)
|
||||
.fetch_all(&db)
|
||||
.await?;
|
||||
for script_path in &trigger_paths {
|
||||
check_scopes(&authed, || format!("native_triggers:write:{script_path}"))?;
|
||||
for trigger in &triggers {
|
||||
check_scopes(&authed, || {
|
||||
format!("native_triggers:write:{}", trigger.script_path)
|
||||
})?;
|
||||
}
|
||||
let external_ids: Vec<String> = triggers.into_iter().map(|t| t.external_id).collect();
|
||||
|
||||
// Before the connection goes: removing the registrations needs its token.
|
||||
delete_triggers_for_service(&db, &workspace_id, service_name, Some(&path)).await;
|
||||
delete_triggers_for_service(&db, &workspace_id, service_name, Some(&external_ids)).await;
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let account = cleanup_connection(&mut *tx, &workspace_id, &path).await?;
|
||||
|
||||
Reference in New Issue
Block a user