feat: let native triggers act through per-user or shared connections

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-10-16 14:36:10 +02:00
co-authored by Claude Opus 5.5
parent c00f00057d
commit 18d0d3ccf0
59 changed files with 1914 additions and 984 deletions
+106 -30
View File
@@ -20641,12 +20641,22 @@ paths:
schema:
$ref: "#/components/schemas/NativeServiceName"
requestBody:
description: redirect_uri
description: >-
redirect_uri, and where to save the connection (defaults to
u/{caller}/native_{resource_type}). Uses the workspace OAuth client, or the instance
one when the instance shares it.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RedirectUri"
type: object
properties:
redirect_uri:
type: string
resource_path:
type: string
required:
- redirect_uri
responses:
"200":
description: native trigger service connect url
@@ -20676,10 +20686,10 @@ paths:
schema:
type: boolean
/w/{workspace}/native_triggers/integrations/{service_name}/generate_instance_connect_url:
post:
summary: generate connect url using instance-level credentials
operationId: generateInstanceConnectUrl
/w/{workspace}/native_triggers/integrations/{service_name}/connections:
get:
summary: list the native trigger connections of a service the caller can use
operationId: listNativeTriggerConnections
tags:
- workspace_integration
parameters:
@@ -20689,16 +20699,37 @@ paths:
required: true
schema:
$ref: "#/components/schemas/NativeServiceName"
requestBody:
description: redirect_uri
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RedirectUri"
responses:
"200":
description: authorization URL using instance credentials
description: connections
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/NativeTriggerConnection"
/w/{workspace}/native_triggers/integrations/{service_name}/connections/delete:
delete:
summary: disconnect a native trigger connection and delete the triggers using it
operationId: deleteNativeTriggerConnection
tags:
- workspace_integration
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: service_name
in: path
required: true
schema:
$ref: "#/components/schemas/NativeServiceName"
- name: path
in: query
required: true
schema:
type: string
responses:
"200":
description: connection deleted
content:
application/json:
schema:
@@ -20752,17 +20783,15 @@ paths:
type: string
redirect_uri:
type: string
resource_path:
type: string
required:
- code
- state
- redirect_uri
responses:
"200":
description: native trigger service oauth completed
description: path of the saved connection
content:
text/plain:
application/json:
schema:
type: string
@@ -21037,6 +21066,12 @@ paths:
required: true
schema:
type: string
- name: connection_path
in: query
description: Connection to browse through; defaults to the caller's only usable one
required: false
schema:
type: string
responses:
"200":
description: list of available NextCloud events
@@ -21059,6 +21094,12 @@ paths:
required: true
schema:
type: string
- name: connection_path
in: query
description: Connection to browse through; defaults to the caller's only usable one
required: false
schema:
type: string
responses:
"200":
description: list of Google Calendars
@@ -21081,6 +21122,12 @@ paths:
required: true
schema:
type: string
- name: connection_path
in: query
description: Connection to browse through; defaults to the caller's only usable one
required: false
schema:
type: string
- name: q
in: query
description: search query to filter files by name
@@ -21122,6 +21169,12 @@ paths:
required: true
schema:
type: string
- name: connection_path
in: query
description: Connection to browse through; defaults to the caller's only usable one
required: false
schema:
type: string
responses:
"200":
description: list of shared drives
@@ -21144,6 +21197,12 @@ paths:
required: true
schema:
type: string
- name: connection_path
in: query
description: Connection to browse through; defaults to the caller's only usable one
required: false
schema:
type: string
responses:
"200":
description: list of GitHub repositories
@@ -39085,6 +39144,10 @@ components:
enabled:
type: boolean
description: Whether the trigger starts a job when it fires
connection_path:
type: string
nullable: true
description: Path of the connection the trigger acts through on the external service
required:
- external_id
- workspace_id
@@ -39127,6 +39190,10 @@ components:
enabled:
type: boolean
description: Whether the trigger starts a job when it fires
connection_path:
type: string
nullable: true
description: Path of the connection the trigger acts through on the external service
external_data:
type: object
nullable: true
@@ -39158,10 +39225,6 @@ components:
oauth_data:
nullable: true
$ref: "#/components/schemas/WorkspaceOAuthConfig"
resource_path:
type: string
nullable: true
description: Path to the resource storing the OAuth token
required:
- service_name
@@ -39207,14 +39270,6 @@ components:
- async
- sync
RedirectUri:
type: object
properties:
redirect_uri:
type: string
required:
- redirect_uri
NativeTriggerData:
type: object
description: Data for creating or updating a native trigger
@@ -39239,11 +39294,32 @@ components:
Whether the trigger starts a job when it fires. Honoured on create only, so a
trigger can be registered already paused; an update ignores it and setenabled is
the only way to change an existing trigger's state. Defaults to true.
connection_path:
type: string
nullable: true
description: >-
Path of the connection the trigger acts through. Honoured on create only; an update
keeps the trigger's connection. When omitted on create, the caller's only usable
connection for the service is used.
required:
- script_path
- is_flow
- service_config
NativeTriggerConnection:
type: object
description: An account connected for native triggers, stored as an OAuth resource
properties:
path:
type: string
description: Path of the resource and variable holding the connection
owner:
type: string
nullable: true
description: Username of whoever connected the account, when the caller can read its resource
required:
- path
CreateTriggerResponse:
type: object
description: Response returned when a native trigger is created
+1 -1
View File
@@ -1188,7 +1188,7 @@ async fn offboard_user_from_workspace<'c>(
// ---- Related path tables ----
sqlx::query!(
r#"UPDATE workspace_integrations SET resource_path = REGEXP_REPLACE(resource_path, 'u/' || $2 || '/(.*)', $1 || '/\1') WHERE resource_path LIKE ('u/' || $2 || '/%') AND workspace_id = $3"#,
r#"UPDATE native_trigger SET connection_path = REGEXP_REPLACE(connection_path, 'u/' || $2 || '/(.*)', $1 || '/\1') WHERE connection_path LIKE ('u/' || $2 || '/%') AND workspace_id = $3"#,
&new_prefix, username, w_id
).execute(&mut **tx).await?;
+2 -3
View File
@@ -297,8 +297,7 @@ async fn rename_user(
// keeps a like-named member of some other workspace out of it.
if let Some(old_username) = old_instance_username.filter(|u| *u != ru.new_username) {
let old_principal = windmill_common::users::username_to_permissioned_as(&old_username);
let new_principal =
windmill_common::users::username_to_permissioned_as(&ru.new_username);
let new_principal = windmill_common::users::username_to_permissioned_as(&ru.new_username);
sqlx::query!(
"UPDATE app SET policy = jsonb_set(policy, ARRAY['on_behalf_of'], to_jsonb($1::text))
WHERE policy->>'on_behalf_of' = $2 AND policy->>'on_behalf_of_email' = $3",
@@ -618,7 +617,7 @@ async fn update_username_in_workpsace<'c>(
.await?;
sqlx::query!(
r#"UPDATE workspace_integrations SET resource_path = REGEXP_REPLACE(resource_path, 'u/' || $2 || '/(.*)', 'u/' || $1 || '/\1') WHERE resource_path LIKE ('u/' || $2 || '/%') AND workspace_id = $3"#,
r#"UPDATE native_trigger SET connection_path = REGEXP_REPLACE(connection_path, 'u/' || $2 || '/(.*)', 'u/' || $1 || '/\1') WHERE connection_path LIKE ('u/' || $2 || '/%') AND workspace_id = $3"#,
new_username,
old_username,
w_id