feat: refactor trigger crud (#6472)

* base

* base crate

* websocket updated

* crud refactored

* fix and nits

* fix compiler warning, nits and update repo ref

* fix oss

* fix compilation

* update ref

* fix

* update feature

* listener base

* add listener

* refactor logic done and implemented for postgres

* fix capture

* websocket

* implem for all triggers

* update sqlx,repo ref and fix

* fix oss

* unify struct fix websocket

* nits and fix oss runtime axum error

* perf cache query

* update .sqlx

* update .sqlx

* fix

* fix unused

* fix

* fix

* nits and fix http handler update endpoint

* update .sqlx

* update repo ref

* nits

* fix

* update ref

* fix

* update .sqlx
This commit is contained in:
dieriba
2025-09-02 13:28:06 +02:00
committed by GitHub
parent c08282a36f
commit f3fd1e90b0
133 changed files with 6183 additions and 7895 deletions
@@ -0,0 +1,26 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO kafka_trigger (\n workspace_id,\n path,\n kafka_resource_path,\n group_id,\n topics,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, now(), $11, $12, $13\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "0382065b3dfd78b384e26f81317af91de289f52462e74343770a8b0d47d0577d"
}
@@ -1,39 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n mqtt_trigger \n SET\n mqtt_resource_path = $1,\n subscribe_topics = $2,\n client_version = $3,\n client_id = $4,\n v3_config = $5,\n v5_config = $6,\n is_flow = $7, \n edited_by = $8, \n email = $9,\n script_path = $10,\n path = $11,\n edited_at = now(), \n error = NULL,\n server_id = NULL,\n error_handler_path = $14,\n error_handler_args = $15,\n retry = $16\n WHERE \n workspace_id = $12 AND \n path = $13\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"JsonbArray",
{
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
},
"Varchar",
"Jsonb",
"Jsonb",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "04a8482180a3f8e07761742f13ac30afc081eeed1151a0b5e043d785baebfc9d"
}
@@ -0,0 +1,26 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO postgres_trigger (\n workspace_id,\n path,\n postgres_resource_path,\n replication_slot_name,\n publication_name,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, now(), $11, $12, $13\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "06af027f6ed10200de2006a2fc48771a8f42c28c87b78220eec1bddeae1f648f"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n gcp_trigger \n SET \n enabled = $1, \n email = $2, \n edited_by = $3, \n edited_at = now(), \n server_id = NULL, \n error = NULL\n WHERE \n path = $4 AND \n workspace_id = $5 \n RETURNING 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "070b8ad0b59f485fa5bf68082b060f5c3561c37e9c6f2834d234a862a475a6eb"
}
@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n nats_trigger\n SET\n nats_resource_path = $1,\n subjects = $2,\n stream_name = $3,\n consumer_name = $4,\n use_jetstream = $5,\n script_path = $6,\n path = $7,\n is_flow = $8,\n edited_by = $9,\n email = $10,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $13,\n error_handler_args = $14,\n retry = $15\n WHERE\n workspace_id = $11 AND path = $12\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "0d8415a79d8312db4d46da46fdf348ab17dee7b8358b6719fa399511962bc3e9"
}
@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE nats_trigger \n SET \n nats_resource_path = $1,\n subjects = $2,\n stream_name = $3,\n consumer_name = $4,\n use_jetstream = $5,\n script_path = $6,\n path = $7,\n is_flow = $8,\n edited_by = $9,\n email = $10,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $13,\n error_handler_args = $14,\n retry = $15\n WHERE \n workspace_id = $11 AND path = $12\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "0ef1e5bbbefc117a4cdaf414b3652354641c2f735d071540f858bc064f2432cd"
}
@@ -0,0 +1,39 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n mqtt_trigger \n SET\n mqtt_resource_path = $1,\n subscribe_topics = $2,\n client_version = $3,\n client_id = $4,\n v3_config = $5,\n v5_config = $6,\n is_flow = $7, \n edited_by = $8, \n email = $9,\n script_path = $10,\n path = $11,\n edited_at = now(), \n error = NULL,\n server_id = NULL,\n error_handler_path = $14,\n error_handler_args = $15,\n retry = $16\n WHERE \n workspace_id = $12 AND \n path = $13\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"JsonbArray",
{
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
},
"Varchar",
"Jsonb",
"Jsonb",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "0f697b1ab3105e2ea036f8ecace2d54f97bc2d0ef52f5812244a97c289523592"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM sqs_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "13444bbd5547e101c41206c5f97ac4dded0536faf52c370d704ed9a451041caf"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n sqs_trigger \n SET \n enabled = $1, \n email = $2, \n edited_by = $3, \n edited_at = now(), \n server_id = NULL, \n error = NULL\n WHERE \n path = $4 AND \n workspace_id = $5 \n RETURNING 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "1625a84fbcf8c5f77eb0519f60d9418f85d4d3d599f4177403fad5ad99380715"
}
@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO nats_trigger (\n workspace_id,\n path,\n nats_resource_path,\n subjects,\n stream_name,\n consumer_name,\n use_jetstream,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), $13, $14, $15\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "1e333ccb7657bc721d18ea2230cb20f15e4a7839c87c853f280623bafb30b80c"
}
@@ -1,153 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n mqtt_resource_path,\n subscribe_topics as \"subscribe_topics!: Vec<SqlxJson<SubscribeTopic>>\",\n v3_config as \"v3_config!: Option<SqlxJson<MqttV3Config>>\",\n v5_config as \"v5_config!: Option<SqlxJson<MqttV5Config>>\",\n client_version AS \"client_version: _\",\n client_id,\n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n mqtt_trigger\n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "mqtt_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "subscribe_topics!: Vec<SqlxJson<SubscribeTopic>>",
"type_info": "JsonbArray"
},
{
"ordinal": 2,
"name": "v3_config!: Option<SqlxJson<MqttV3Config>>",
"type_info": "Jsonb"
},
{
"ordinal": 3,
"name": "v5_config!: Option<SqlxJson<MqttV5Config>>",
"type_info": "Jsonb"
},
{
"ordinal": 4,
"name": "client_version: _",
"type_info": {
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
}
},
{
"ordinal": 5,
"name": "client_id",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 15,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 16,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 17,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 18,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 19,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 20,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
true,
true,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "208f30f8a570db41ee52f01a4402d76f7e174e39c45ede29dcd6aa9c65850fef"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM kafka_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "2139f1fb1877294bbf55d786000c5c32f582a3911efcf88e437aa90d7d5a49b5"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM websocket_trigger WHERE path = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "2238aaed46031f71b17c1cabcef935a0d3b2ca6d057f446ed9b02d4386e2ddd9"
}
@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO websocket_trigger (\n workspace_id,\n path,\n url,\n script_path,\n is_flow,\n enabled,\n filters,\n initial_messages,\n url_runnable_args,\n edited_by,\n can_return_message,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), $13, $14, $15\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Bool",
"JsonbArray",
"JsonbArray",
"Jsonb",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "23eb4d45bf2df21e22fc6c9590b96b0a7dbdd27f85c7d886eded79b3af83731a"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE websocket_trigger SET enabled = $1, email = $2, edited_by = $3, edited_at = now(), server_id = NULL, error = NULL\n WHERE path = $4 AND workspace_id = $5 RETURNING 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "25975935d59f88df117bae0fa5016cf95ad56f790f0eddb6e2fbe3d83d3accaa"
}
@@ -1,140 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n aws_auth_resource_type AS \"aws_auth_resource_type: _\",\n aws_resource_path,\n message_attributes,\n queue_url,\n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n sqs_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "aws_auth_resource_type: _",
"type_info": {
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
}
},
{
"ordinal": 1,
"name": "aws_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "message_attributes",
"type_info": "TextArray"
},
{
"ordinal": 3,
"name": "queue_url",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 8,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 10,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 11,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 14,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 15,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 16,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 17,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 18,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
false,
true,
true,
true
]
},
"hash": "264bc51ec372dfc6c1c4eb3608b32d8a250bd0d65ce33d7eb19eaea62466a803"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM websocket_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "2e6165543e34216dfaedf6e10729f733cff812e62dea1c1bce8cefd3a3979b14"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM http_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "31bc3dcea29be9cc0242771d25a232f173446d29c08fc29ddb8d55294f2c070e"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT EXISTS(\n SELECT \n 1 \n FROM \n gcp_trigger \n WHERE \n path = $1 AND \n workspace_id = $2\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "33ee913ce263600a3f94f90e4a42cf0e4086030f3b7994e4892392765cbe1517"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM kafka_trigger WHERE workspace_id = $1 AND path = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "3997dcf2c11817e59bf50fd896381d870b847a8ba07e6197212fdf85ec901b09"
}
@@ -1,125 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n replication_slot_name,\n publication_name,\n postgres_resource_path,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n postgres_trigger\n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 7,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 9,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 10,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 11,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 12,
"name": "replication_slot_name",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "publication_name",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "postgres_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 16,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 17,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
false,
false,
false,
false,
true,
true,
true
]
},
"hash": "3a6c93a91d9a21aaf9e9709932ac810221c5fc8fc29ca4f1984c819e64e29437"
}
@@ -0,0 +1,26 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE kafka_trigger \n SET \n kafka_resource_path = $1,\n group_id = $2,\n topics = $3,\n script_path = $4,\n path = $5,\n is_flow = $6,\n edited_by = $7,\n email = $8,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $11,\n error_handler_args = $12,\n retry = $13\n WHERE \n workspace_id = $9 AND path = $10\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "3b6bd7b41f130ce6df62fdecb351a3e01be0726d02d3f863e0ea5c476a8e785e"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE nats_trigger SET enabled = $1, email = $2, edited_by = $3, edited_at = now(), server_id = NULL, error = NULL\n WHERE path = $4 AND workspace_id = $5 RETURNING 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "3d8fdf7adf42b27808a5b223df3a660bfd5a8c0a451a0deac24632f0ccf66165"
}
@@ -1,124 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n replication_slot_name,\n publication_name,\n postgres_resource_path,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n postgres_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 7,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 9,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 10,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 11,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 12,
"name": "replication_slot_name",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "publication_name",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "postgres_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 16,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 17,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
false,
false,
false,
false,
true,
true,
true
]
},
"hash": "3ebf788b86d6aed59b8c61c08f1d9323e6c66107a1b7b37dadbbb7b91339e9d5"
}
@@ -1,125 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT \n workspace_id,\n path,\n kafka_resource_path,\n group_id,\n topics,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n kafka_trigger \n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "kafka_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "group_id",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "topics",
"type_info": "VarcharArray"
},
{
"ordinal": 5,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 7,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 10,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 12,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 13,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 14,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 15,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 16,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 17,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "494d49e92dce7a1cd7074156704ccbbff020a2042409fc318e045852323cef5e"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE kafka_trigger\n SET\n kafka_resource_path = $1,\n group_id = $2,\n topics = $3,\n script_path = $4,\n path = $5,\n is_flow = $6,\n edited_by = $7,\n email = $8,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $11,\n error_handler_args = $12,\n retry = $13\n WHERE\n workspace_id = $9 AND path = $10\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "4bfa42153df81184e02ffc7ab6c8c591605211c070e52b2919cf9d7dede0ea16"
}
@@ -1,124 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT \n workspace_id,\n path,\n kafka_resource_path,\n group_id,\n topics,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM kafka_trigger\n WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "kafka_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "group_id",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "topics",
"type_info": "VarcharArray"
},
{
"ordinal": 5,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 7,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 10,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 12,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 13,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 14,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 15,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 16,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 17,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "4c6fbed80ba44defe3d125c258bc3449b02925c8caf85d9203529471479fdde8"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE postgres_trigger \n SET \n script_path = $1, \n path = $2, \n is_flow = $3, \n edited_by = $4, \n email = $5, \n postgres_resource_path = $6, \n replication_slot_name = $7,\n publication_name = $8,\n edited_at = now(), \n error = NULL,\n server_id = NULL,\n error_handler_path = $11,\n error_handler_args = $12,\n retry = $13\n WHERE \n workspace_id = $9 AND \n path = $10\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "4eab48b7e86788835c3ba739cca764231013b32e7dc26fb3b775e872d2222005"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT EXISTS(\n SELECT \n 1 \n FROM \n mqtt_trigger \n WHERE \n path = $1 AND \n workspace_id = $2\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "4ed74bbda2ad0ca5e4648787fe2d9c89e9b83571e30059861b6998935b35f78b"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE FROM postgres_trigger \n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "508d267b0d77fd12446654a502bf4968ecebec1614580e55de3d5895f0595e52"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO kafka_trigger (\n workspace_id,\n path,\n kafka_resource_path,\n group_id,\n topics,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, now(), $11, $12, $13\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "5140cfccd4a8fb7d64087de34bc2fbe1f9e0172b38492a99be19147d04a961fe"
}
@@ -15,7 +15,7 @@
]
},
"nullable": [
true
null
]
},
"hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55"
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO http_trigger (\n workspace_id, \n path, \n route_path, \n route_path_key,\n workspaced_route,\n authentication_resource_path,\n wrap_body,\n raw_string,\n script_path, \n summary,\n description,\n is_flow, \n is_async, \n authentication_method, \n http_method, \n static_asset_config, \n edited_by, \n email, \n edited_at, \n is_static_website,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, now(), $19, $20, $21, $22\n )\n ",
"query": "\n INSERT INTO http_trigger (\n workspace_id, \n path, \n route_path, \n route_path_key,\n workspaced_route,\n authentication_resource_path,\n wrap_body,\n raw_string,\n script_path, \n summary,\n description,\n is_flow, \n is_async, \n authentication_method, \n http_method, \n static_asset_config, \n edited_by, \n email, \n edited_at, \n is_static_website,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, now(), $19, $20, $21, $22\n )\n ",
"describe": {
"columns": [],
"parameters": {
@@ -58,5 +58,5 @@
},
"nullable": []
},
"hash": "aaa8dde748e5bcd462122d3235e54c784399b2cac7b27f0de33e78bd77661565"
"hash": "5cc0d9e3dcd9c20e6e6ec1acf38c8f97b5ece60bfe24fc3783a83de47e3aa583"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM gcp_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "6a19c440a7a8064f3969cf6f48adea0bfdb683de9555e374ce5731e0b3c379f9"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n http_trigger \n SET \n workspaced_route = $1,\n wrap_body = $2,\n raw_string = $3,\n authentication_resource_path = $4,\n script_path = $5, \n path = $6, \n is_flow = $7, \n http_method = $8, \n static_asset_config = $9, \n edited_by = $10, \n email = $11, \n is_async = $12, \n authentication_method = $13, \n edited_at = now(), \n is_static_website = $14,\n error_handler_path = $15,\n error_handler_args = $16,\n retry = $17\n WHERE \n workspace_id = $18 AND \n path = $19\n ",
"query": "\n UPDATE \n http_trigger \n SET \n workspaced_route = $1,\n wrap_body = $2,\n raw_string = $3,\n authentication_resource_path = $4,\n script_path = $5, \n path = $6, \n is_flow = $7, \n http_method = $8, \n static_asset_config = $9, \n edited_by = $10, \n email = $11, \n is_async = $12, \n authentication_method = $13, \n summary = $14,\n description = $15,\n edited_at = now(), \n is_static_website = $16,\n error_handler_path = $17,\n error_handler_args = $18,\n retry = $19\n WHERE \n workspace_id = $20 AND \n path = $21\n ",
"describe": {
"columns": [],
"parameters": {
@@ -45,6 +45,8 @@
}
}
},
"Varchar",
"Text",
"Bool",
"Varchar",
"Jsonb",
@@ -55,5 +57,5 @@
},
"nullable": []
},
"hash": "d580bac9f4be4329da29781efa00cd0b5379955a42b7e070c7e11f8479441482"
"hash": "6ca3ae85ddeb2334c9ae4bd7682daef744a1b10b4f47bc7355a97011bc366aae"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM kafka_trigger WHERE path = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "6d418b5cd7a4df54cfe3ec06e2a957c87f2307a218115ca749ea0e71eca2002e"
}
@@ -1,136 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n workspace_id,\n path,\n nats_resource_path,\n subjects,\n stream_name,\n consumer_name,\n use_jetstream,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n nats_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "nats_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "subjects",
"type_info": "VarcharArray"
},
{
"ordinal": 4,
"name": "stream_name",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "consumer_name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "use_jetstream",
"type_info": "Bool"
},
{
"ordinal": 7,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 9,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 12,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 14,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 15,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 16,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 18,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 19,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "711e665344873454428d84e35f300edb7e0ebad5de40ba5645c1ce3d4a6b84be"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM nats_trigger WHERE path = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "746ee16a04267cd251d4cefbc44a37fcc985bf61978cc07167ed35d7dbf92d11"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO postgres_trigger (\n publication_name,\n replication_slot_name,\n workspace_id, \n path, \n script_path, \n is_flow, \n email, \n enabled, \n postgres_resource_path, \n edited_by,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, \n $2, \n $3, \n $4, \n $5, \n $6, \n $7, \n $8, \n $9, \n $10,\n $11,\n $12,\n $13\n )",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "7f039cc86874128ee8c9f577897340a155562fd6cde328298a66496c90d8cd59"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n http_trigger \n SET \n route_path = $1, \n route_path_key = $2, \n workspaced_route = $3,\n wrap_body = $4,\n raw_string = $5,\n authentication_resource_path = $6,\n script_path = $7, \n path = $8, \n is_flow = $9, \n http_method = $10, \n static_asset_config = $11, \n edited_by = $12, \n email = $13, \n is_async = $14, \n authentication_method = $15, \n summary = $16,\n description = $17,\n edited_at = now(), \n is_static_website = $18,\n error_handler_path = $19,\n error_handler_args = $20,\n retry = $21\n WHERE \n workspace_id = $22 AND \n path = $23\n ",
"query": "\n UPDATE \n http_trigger \n SET \n route_path = $1, \n route_path_key = $2,\n workspaced_route = $3,\n wrap_body = $4,\n raw_string = $5,\n authentication_resource_path = $6,\n script_path = $7, \n path = $8, \n is_flow = $9, \n http_method = $10, \n static_asset_config = $11, \n edited_by = $12, \n email = $13, \n is_async = $14, \n authentication_method = $15, \n summary = $16,\n description = $17,\n edited_at = now(), \n is_static_website = $18,\n error_handler_path = $19,\n error_handler_args = $20,\n retry = $21\n WHERE \n workspace_id = $22 AND \n path = $23\n ",
"describe": {
"columns": [],
"parameters": {
@@ -59,5 +59,5 @@
},
"nullable": []
},
"hash": "f2a78401a363442f165d018d61a294b4575e2cdc31e8da3d453addd0edc3edf6"
"hash": "85d945cf5ade707291a161078ff96ddb29140dd72ce5115657418eec503b205d"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM nats_trigger WHERE workspace_id = $1 AND path = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "870b12a46f26c9e29889dd28a5c7832c5a674a5553674fd9762c981e0d03bb57"
}
@@ -1,187 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n workspace_id, \n workspaced_route,\n path, \n route_path, \n route_path_key, \n authentication_resource_path,\n script_path, \n is_flow, \n summary,\n description,\n edited_by, \n edited_at, \n email, \n extra_perms, \n is_async, \n authentication_method AS \"authentication_method: _\", \n http_method AS \"http_method: _\", \n static_asset_config AS \"static_asset_config: _\", \n is_static_website,\n wrap_body,\n raw_string,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n http_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "workspaced_route",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "route_path",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "route_path_key",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "authentication_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 8,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "description",
"type_info": "Text"
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 12,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 14,
"name": "is_async",
"type_info": "Bool"
},
{
"ordinal": 15,
"name": "authentication_method: _",
"type_info": {
"Custom": {
"name": "authentication_method",
"kind": {
"Enum": [
"none",
"windmill",
"api_key",
"basic_http",
"custom_script",
"signature"
]
}
}
}
},
{
"ordinal": 16,
"name": "http_method: _",
"type_info": {
"Custom": {
"name": "http_method",
"kind": {
"Enum": [
"get",
"post",
"put",
"delete",
"patch"
]
}
}
}
},
{
"ordinal": 17,
"name": "static_asset_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 18,
"name": "is_static_website",
"type_info": "Bool"
},
{
"ordinal": 19,
"name": "wrap_body",
"type_info": "Bool"
},
{
"ordinal": 20,
"name": "raw_string",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 22,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 23,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
true,
true
]
},
"hash": "89be9b595a892c82f2a9f3cfa4da213e360ebe8827d5b4680d3c227fb8ddec82"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n mqtt_trigger \n SET \n enabled = $1, \n email = $2, \n edited_by = $3, \n edited_at = now(), \n server_id = NULL, \n error = NULL\n WHERE \n path = $4 AND \n workspace_id = $5 \n RETURNING 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "8d31b4a531c59a2385210d1213c205100d6673a94e90000c8db4eb5809f17365"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM postgres_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "8e1afb488096330890b1675d2b3052d2064fcc8f373fecfebd40914768b2b1cf"
}
@@ -1,137 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n workspace_id,\n path,\n nats_resource_path,\n subjects,\n stream_name,\n consumer_name,\n use_jetstream,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM nats_trigger\n WHERE workspace_id = $1 AND path = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "nats_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "subjects",
"type_info": "VarcharArray"
},
{
"ordinal": 4,
"name": "stream_name",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "consumer_name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "use_jetstream",
"type_info": "Bool"
},
{
"ordinal": 7,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 9,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 12,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 14,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 15,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 16,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 18,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 19,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "8ffd68b82cfce337fc32a6e80c8d56c53acd02eb350b46f6b815a5ddbb69d163"
}
@@ -0,0 +1,37 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO sqs_trigger (\n workspace_id,\n path,\n queue_url,\n aws_resource_path,\n message_attributes,\n aws_auth_resource_type,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, now(), $12, $13, $14\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"TextArray",
{
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
},
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "9abbb75c238372cc3dbaebf1dbc50ff78df6c5dcf92b08d611afe23c5b865521"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE \n FROM \n mqtt_trigger \n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "9e88a43de7315052668619002321aadbc27ff5bd0c554bf5339060cc35797d3f"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM http_trigger \n WHERE workspace_id = $1 \n AND path = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "a269c388056eabe4b045948f451ea74ffbb4c0ed7e694f8f03d92f2a7c118af9"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM mqtt_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "a8b470b463ca4b7c00c7ef6e9f36c23f8bbcefc288a56d61122bfd6fe5ca7e8d"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT EXISTS(\n SELECT 1 \n FROM postgres_trigger \n WHERE \n path = $1 AND \n workspace_id = $2\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "aae8699bbaa4d6111eabee715a6f4a3600c1ccfe6847bd526a751bc7baf825c5"
}
@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM nats_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "ad07b57ad928a4e5260833f4fe2a4bf51211f2f73d78c546c894c8e147677ac7"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(\n SELECT 1 FROM http_trigger \n WHERE path = $1 AND workspace_id = $2\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "adb0090afd3ce918d8b80ff51d9f6104a430a11d7c5cb9447025d11506585708"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT EXISTS(\n SELECT \n 1 \n FROM \n sqs_trigger \n WHERE \n path = $1 AND \n workspace_id = $2\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "b386d320f9fe1d569a16e6626b723b4376a93342702856da2ac70f6bbfc7933e"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE \n FROM \n gcp_trigger \n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "c19a60a9dc3f95af218baf40c62f14572ac204cfe377166aa1d91cf58f731f50"
}
@@ -1,37 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO sqs_trigger (\n aws_auth_resource_type,\n aws_resource_path,\n queue_url,\n message_attributes,\n workspace_id, \n path, \n script_path, \n is_flow, \n email, \n enabled, \n edited_by,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, \n $2, \n $3, \n $4, \n $5, \n $6, \n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14\n )",
"describe": {
"columns": [],
"parameters": {
"Left": [
{
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
},
"Varchar",
"Varchar",
"TextArray",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "c22438f9bff27ccd3228a186a8093c551c30ed85eabe8ec11cafa6358f354c8b"
}
@@ -1,136 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n workspace_id,\n path,\n url,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n filters AS \"filters: _\",\n initial_messages AS \"initial_messages: _\",\n url_runnable_args AS \"url_runnable_args: _\",\n can_return_message,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n websocket_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "url",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 10,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 13,
"name": "filters: _",
"type_info": "JsonbArray"
},
{
"ordinal": 14,
"name": "initial_messages: _",
"type_info": "JsonbArray"
},
{
"ordinal": 15,
"name": "url_runnable_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 16,
"name": "can_return_message",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 18,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 19,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
false,
true,
true,
false,
true,
true,
true
]
},
"hash": "c287f025c77c34e4d521204e7a787e794b461a7a965912bcb598619451eced31"
}
@@ -1,37 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n sqs_trigger \n SET \n aws_auth_resource_type = $1,\n aws_resource_path = $2,\n queue_url = $3,\n message_attributes = $4, \n is_flow = $5, \n edited_by = $6, \n email = $7,\n script_path = $8,\n path = $9,\n edited_at = now(), \n error = NULL,\n server_id = NULL,\n error_handler_path = $12,\n error_handler_args = $13,\n retry = $14\n WHERE \n workspace_id = $10 AND \n path = $11\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
{
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
},
"Varchar",
"Varchar",
"TextArray",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "c3730ae025a4dcc25b2713e3e670ce006b1ceed26e29d812d524c711d178167e"
}
@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO websocket_trigger (\n workspace_id,\n path,\n url,\n script_path,\n is_flow,\n enabled,\n filters,\n initial_messages,\n url_runnable_args,\n edited_by,\n can_return_message,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), $13, $14, $15\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Bool",
"JsonbArray",
"JsonbArray",
"Jsonb",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "c4cd9668733b2b439ac7a911d15041ac728553e20adf722eb795d01d6650ff0f"
}
@@ -1,168 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n gcp_resource_path,\n subscription_id,\n topic_id,\n workspace_id,\n delivery_type AS \"delivery_type: _\",\n delivery_config AS \"delivery_config: _\",\n subscription_mode AS \"subscription_mode: _\",\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\",\n auto_acknowledge_msg\n FROM \n gcp_trigger\n WHERE \n workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "gcp_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "subscription_id",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "topic_id",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "delivery_type: _",
"type_info": {
"Custom": {
"name": "delivery_mode",
"kind": {
"Enum": [
"push",
"pull"
]
}
}
}
},
{
"ordinal": 5,
"name": "delivery_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "subscription_mode: _",
"type_info": {
"Custom": {
"name": "gcp_subscription_mode",
"kind": {
"Enum": [
"create_update",
"existing"
]
}
}
}
},
{
"ordinal": 7,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 15,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 16,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 17,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 18,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 19,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 20,
"name": "retry: _",
"type_info": "Jsonb"
},
{
"ordinal": 21,
"name": "auto_acknowledge_msg",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true,
true
]
},
"hash": "c61df65f2e4f8bc146b0f70e605f5243ec9aa66ea1a9da9662fc877f4becb04e"
}
@@ -1,141 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n aws_auth_resource_type AS \"aws_auth_resource_type: _\",\n aws_resource_path,\n message_attributes,\n queue_url,\n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n sqs_trigger\n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "aws_auth_resource_type: _",
"type_info": {
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
}
},
{
"ordinal": 1,
"name": "aws_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "message_attributes",
"type_info": "TextArray"
},
{
"ordinal": 3,
"name": "queue_url",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 8,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 10,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 11,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 14,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 15,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 16,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 17,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 18,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true,
false,
true,
true,
true
]
},
"hash": "d3bc837633eb92cd9a8d37ad09a72e8da54885cdd135e0877dec9cf407064158"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM websocket_trigger WHERE workspace_id = $1 AND path = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "d54840373df5da9662ed11ed0a605cddac517bdc06dca0a8be071330338e948a"
}
@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE \n FROM \n sqs_trigger \n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "dea056c89313f4facd62cbbc9fa33ba30fa85efcc83fafe4dd7b4e535b96a8d8"
}
@@ -0,0 +1,26 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE postgres_trigger \n SET \n postgres_resource_path = $1,\n replication_slot_name = $2,\n publication_name = $3,\n script_path = $4,\n path = $5,\n is_flow = $6,\n edited_by = $7,\n email = $8,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $11,\n error_handler_args = $12,\n retry = $13\n WHERE \n workspace_id = $9 AND path = $10\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "e56c71de41ba0750ae9ae8540c903cb0bf241d959a6c8f7bb896160001a6672b"
}
@@ -0,0 +1,37 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE sqs_trigger \n SET \n queue_url = $1,\n aws_resource_path = $2,\n message_attributes = $3,\n aws_auth_resource_type = $4,\n script_path = $5,\n path = $6,\n is_flow = $7,\n edited_by = $8,\n email = $9,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $12,\n error_handler_args = $13,\n retry = $14\n WHERE \n workspace_id = $10 AND path = $11\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"TextArray",
{
"Custom": {
"name": "aws_auth_resource_type",
"kind": {
"Enum": [
"oidc",
"credentials"
]
}
}
},
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "e9941e580a21848fa71b38c58030078a25f117a3bfec78d5270a4c4970f2465e"
}
@@ -1,39 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO mqtt_trigger (\n mqtt_resource_path,\n subscribe_topics,\n client_version,\n client_id,\n v3_config,\n v5_config,\n workspace_id,\n path, \n script_path, \n is_flow, \n email, \n enabled, \n edited_by,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, \n $2, \n $3, \n $4, \n $5, \n $6, \n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n $16\n )",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"JsonbArray",
{
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
},
"Varchar",
"Jsonb",
"Jsonb",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "e9b4938b8c5fbd57845cf560fc2fd2d5749015c66d7de277081598ba3bb6dd8f"
}
@@ -1,188 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n workspace_id, \n path, \n route_path, \n route_path_key,\n workspaced_route,\n script_path, \n summary,\n description,\n is_flow, \n http_method as \"http_method: _\", \n edited_by, \n email, \n edited_at, \n extra_perms, \n is_async, \n authentication_method as \"authentication_method: _\", \n static_asset_config as \"static_asset_config: _\", \n is_static_website,\n authentication_resource_path,\n wrap_body,\n raw_string,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n http_trigger\n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "route_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "route_path_key",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "workspaced_route",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "description",
"type_info": "Text"
},
{
"ordinal": 8,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 9,
"name": "http_method: _",
"type_info": {
"Custom": {
"name": "http_method",
"kind": {
"Enum": [
"get",
"post",
"put",
"delete",
"patch"
]
}
}
}
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 14,
"name": "is_async",
"type_info": "Bool"
},
{
"ordinal": 15,
"name": "authentication_method: _",
"type_info": {
"Custom": {
"name": "authentication_method",
"kind": {
"Enum": [
"none",
"windmill",
"api_key",
"basic_http",
"custom_script",
"signature"
]
}
}
}
},
{
"ordinal": 16,
"name": "static_asset_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 17,
"name": "is_static_website",
"type_info": "Bool"
},
{
"ordinal": 18,
"name": "authentication_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 19,
"name": "wrap_body",
"type_info": "Bool"
},
{
"ordinal": 20,
"name": "raw_string",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 22,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 23,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
true,
false,
false,
true,
true,
true
]
},
"hash": "ea59131c1fba8fb14a95b4a486db29ba44c4ff4d2c5b38369f0ede61d4708a21"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET enabled = $1, email = $2, edited_by = $3, edited_at = now(), server_id = NULL, error = NULL\n WHERE path = $4 AND workspace_id = $5 RETURNING 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "eda1e5d1109a13feb14be254eaca630be29176bd5d1246c974642d40201782fc"
}
@@ -1,150 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n mqtt_resource_path,\n subscribe_topics as \"subscribe_topics: _\",\n v3_config as \"v3_config: _\",\n v5_config as \"v5_config: _\",\n client_version AS \"client_version: _\",\n client_id,\n workspace_id,\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\"\n FROM \n mqtt_trigger\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "mqtt_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "subscribe_topics: _",
"type_info": "JsonbArray"
},
{
"ordinal": 2,
"name": "v3_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 3,
"name": "v5_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 4,
"name": "client_version: _",
"type_info": {
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
}
},
{
"ordinal": 5,
"name": "client_id",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 15,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 16,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 17,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 18,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 19,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 20,
"name": "retry: _",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
true,
true,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true
]
},
"hash": "eebc9b609d9b595524223ada91e0f7fa1ca50b45cc82e2fd9d4e61768b258735"
}
@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO nats_trigger (\n workspace_id,\n path,\n nats_resource_path,\n subjects,\n stream_name,\n consumer_name,\n use_jetstream,\n script_path,\n is_flow,\n enabled,\n edited_by,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), $13, $14, $15\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "f28b71a304721643dd90fa468f61f351d6df8282415e54f0ea4f905417657ba8"
}
@@ -1,169 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n gcp_resource_path,\n subscription_id,\n topic_id,\n workspace_id,\n delivery_type AS \"delivery_type: _\",\n delivery_config AS \"delivery_config: _\",\n subscription_mode AS \"subscription_mode: _\",\n path,\n script_path,\n is_flow,\n edited_by,\n email,\n edited_at,\n server_id,\n last_server_ping,\n extra_perms,\n error,\n enabled,\n error_handler_path,\n error_handler_args as \"error_handler_args: _\",\n retry as \"retry: _\",\n auto_acknowledge_msg\n FROM \n gcp_trigger\n WHERE \n workspace_id = $1 AND \n path = $2\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "gcp_resource_path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "subscription_id",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "topic_id",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "delivery_type: _",
"type_info": {
"Custom": {
"name": "delivery_mode",
"kind": {
"Enum": [
"push",
"pull"
]
}
}
}
},
{
"ordinal": 5,
"name": "delivery_config: _",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "subscription_mode: _",
"type_info": {
"Custom": {
"name": "gcp_subscription_mode",
"kind": {
"Enum": [
"create_update",
"existing"
]
}
}
}
},
{
"ordinal": 7,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 8,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 12,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 13,
"name": "server_id",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "last_server_ping",
"type_info": "Timestamptz"
},
{
"ordinal": 15,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 16,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 17,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 18,
"name": "error_handler_path",
"type_info": "Varchar"
},
{
"ordinal": 19,
"name": "error_handler_args: _",
"type_info": "Jsonb"
},
{
"ordinal": 20,
"name": "retry: _",
"type_info": "Jsonb"
},
{
"ordinal": 21,
"name": "auto_acknowledge_msg",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
true,
false,
true,
true,
true,
true
]
},
"hash": "f434cac3a8eded700b09a8c99dcc5f7c93fbdb1e7d090b11612aa284342e86a1"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE postgres_trigger \n SET \n enabled = $1, \n email = $2, \n edited_by = $3, \n edited_at = now(), \n server_id = NULL, \n error = NULL\n WHERE \n path = $4 AND \n workspace_id = $5 \n RETURNING 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "fd1db7530acf3c84b2ab696504905a50d1ed4f69629c43de7d874769c340d909"
}
@@ -0,0 +1,39 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO mqtt_trigger (\n mqtt_resource_path,\n subscribe_topics,\n client_version,\n client_id,\n v3_config,\n v5_config,\n workspace_id,\n path, \n script_path, \n is_flow, \n email, \n enabled, \n edited_by,\n error_handler_path,\n error_handler_args,\n retry\n ) \n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16\n )",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"JsonbArray",
{
"Custom": {
"name": "mqtt_client_version",
"kind": {
"Enum": [
"v3",
"v5"
]
}
}
},
"Varchar",
"Jsonb",
"Jsonb",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
"Jsonb"
]
},
"nullable": []
},
"hash": "fe78796c5ea2384bdb6191b66943d746de874ca6600178f5db9797eda44f1733"
}
+1
View File
@@ -15166,6 +15166,7 @@ dependencies = [
"async-oauth2",
"async-recursion",
"async-stream",
"async-trait",
"async_zip",
"aws-config",
"aws-sdk-sqs",
+1
View File
@@ -248,6 +248,7 @@ itertools = "^0"
regex = "^1"
semver = "^1"
duckdb = { version = "1.3.2", features = ["bundled"] }
async-trait = "0.1.88"
v8 = "=130.0.7" # Exact version NOTE: Do not forget to update version and hash in flake.nix
deno_fetch = "0.214.0"
+1 -1
View File
@@ -1 +1 @@
a5911739330d09cdc084bb277e7e3db8f8d86801
66381121ea7ba806a54cd44416870c354e461098
+1 -1
View File
@@ -919,7 +919,7 @@ Windmill Community Edition {GIT_VERSION}
#[cfg(feature = "http_trigger")]
"notify_http_trigger_change" => {
tracing::info!("HTTP trigger change detected: {}", n.payload());
match windmill_api::http_triggers::refresh_routers(&db).await {
match windmill_api::triggers::http::refresh_routers(&db).await {
Ok((true, _)) => {
tracing::info!("Refreshed HTTP routers (trigger change)");
},
+1
View File
@@ -146,6 +146,7 @@ aws-sdk-sts = { workspace = true, optional = true }
rustls = { workspace = true }
aws-config = { workspace = true, optional = true }
async-trait.workspace = true
google-cloud-pubsub = { workspace = true, optional = true }
google-cloud-googleapis = { workspace = true , optional = true }
tonic = { workspace = true, optional = true }
+1 -1
View File
@@ -20,7 +20,7 @@ use windmill_queue::PushArgsOwned;
use crate::{
db::ApiAuthed,
trigger_helpers::{get_runnable_format, RunnableId},
triggers::trigger_helpers::{get_runnable_format, RunnableId},
};
#[derive(Debug)]
+72 -3
View File
@@ -3,12 +3,13 @@ use crate::ee_oss::ExternalJwks;
use axum::{
async_trait,
extract::{FromRequestParts, OriginalUri, Query},
Extension,
Extension, Json,
};
use chrono::TimeZone;
use http::{request::Parts, StatusCode};
use quick_cache::sync::Cache;
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use tower_cookies::Cookies;
use tracing::Span;
@@ -22,7 +23,7 @@ use tokio::sync::RwLock;
use windmill_common::{
auth::{get_folders_for_user, get_groups_for_user, JWTAuthClaims, TOKEN_PREFIX_LEN},
error::Error,
error::{Error, JsonResult},
jwt,
users::{COOKIE_NAME, SUPERADMIN_SECRET_EMAIL},
};
@@ -641,3 +642,71 @@ fn username_override_from_label(label: Option<String>) -> Option<String> {
_ => None,
}
}
#[derive(FromRow, Serialize)]
pub struct TruncatedTokenWithEmail {
pub label: Option<String>,
pub token_prefix: Option<String>,
pub expiration: Option<chrono::DateTime<chrono::Utc>>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub last_used_at: chrono::DateTime<chrono::Utc>,
pub scopes: Option<Vec<String>>,
pub email: Option<String>,
}
pub async fn list_tokens_internal(
db: &DB,
w_id: &str,
path: &str,
is_flow: bool,
) -> JsonResult<Vec<TruncatedTokenWithEmail>> {
let tokens = if is_flow {
sqlx::query_as!(
TruncatedTokenWithEmail,
r#"
SELECT label,
concat(substring(token for 10)) AS token_prefix,
expiration,
created_at,
last_used_at,
scopes,
email
FROM token
WHERE workspace_id = $1
AND (
scopes @> ARRAY['jobs:run:flows:' || $2]::text[]
OR scopes @> ARRAY['run:flow/' || $2]::text[]
)
"#,
w_id,
path
)
.fetch_all(db)
.await?
} else {
sqlx::query_as!(
TruncatedTokenWithEmail,
r#"
SELECT label,
concat(substring(token for 10)) AS token_prefix,
expiration,
created_at,
last_used_at,
scopes,
email
FROM token
WHERE workspace_id = $1
AND (
scopes @> ARRAY['jobs:run:scripts:' || $2]::text[]
OR scopes @> ARRAY['run:script/' || $2]::text[]
)
"#,
w_id,
path
)
.fetch_all(db)
.await?
};
Ok(Json(tokens))
}
+31 -31
View File
@@ -8,54 +8,54 @@
#[cfg(feature = "http_trigger")]
use {
crate::http_trigger_args::{HttpMethod, RawHttpTriggerArgs},
crate::triggers::http::{http_trigger_args::RawHttpTriggerArgs, HttpMethod},
axum::response::{IntoResponse, Response},
std::collections::HashMap,
};
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
use {
crate::gcp_triggers_oss::{
crate::triggers::gcp::{
manage_google_subscription, process_google_push_request, validate_jwt_token,
CreateUpdateConfig, SubscriptionMode,
CreateUpdateConfig, GcpSubscriptionMode,
},
axum::extract::Request,
http::HeaderMap,
};
#[cfg(any(
all(feature = "enterprise", feature = "gcp_trigger"),
all(feature = "enterprise", feature = "gcp_trigger", feature = "private"),
feature = "postgres_trigger"
))]
use windmill_common::utils::empty_as_none;
#[cfg(all(feature = "enterprise", feature = "sqs_trigger"))]
#[cfg(all(feature = "enterprise", feature = "sqs_trigger", feature = "private"))]
use windmill_common::auth::aws::AwsAuthResourceType;
#[cfg(any(
feature = "http_trigger",
all(feature = "enterprise", feature = "gcp_trigger")
all(feature = "enterprise", feature = "gcp_trigger", feature = "private")
))]
use serde::de::DeserializeOwned;
#[cfg(any(
feature = "http_trigger",
feature = "postgres_trigger",
all(feature = "enterprise", feature = "gcp_trigger")
all(feature = "enterprise", feature = "gcp_trigger", feature = "private")
))]
use windmill_common::error::Error;
#[cfg(all(feature = "enterprise", feature = "kafka"))]
use crate::kafka_triggers_oss::KafkaTriggerConfigConnection;
#[cfg(all(feature = "enterprise", feature = "kafka", feature = "private"))]
use crate::kafka_triggers_ee::KafkaTriggerConfigConnection;
#[cfg(feature = "mqtt_trigger")]
use crate::mqtt_triggers::{MqttClientVersion, MqttV3Config, MqttV5Config, SubscribeTopic};
#[cfg(all(feature = "enterprise", feature = "nats"))]
use crate::nats_triggers_oss::NatsTriggerConfigConnection;
#[cfg(all(feature = "enterprise", feature = "nats", feature = "private"))]
use crate::triggers::nats::NatsTriggerConfigConnection;
#[cfg(feature = "postgres_trigger")]
use crate::postgres_triggers::{
use crate::triggers::postgres::{
create_logical_replication_slot, create_pg_publication, generate_random_string,
get_default_pg_connection, PublicationData,
};
@@ -122,7 +122,7 @@ pub fn workspaced_unauthed_service() -> Router {
head(|| async {}).fallback(http_payload)
});
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
let router = router.route("/gcp/:runnable_kind/*path", post(gcp_payload));
router
@@ -146,7 +146,7 @@ struct HttpTriggerConfig {
wrap_body: Option<bool>,
}
#[cfg(all(feature = "enterprise", feature = "kafka"))]
#[cfg(all(feature = "enterprise", feature = "kafka", feature = "private"))]
#[derive(Serialize, Deserialize)]
pub struct KafkaTriggerConfig {
#[serde(flatten)]
@@ -155,7 +155,7 @@ pub struct KafkaTriggerConfig {
pub group_id: String,
}
#[cfg(all(feature = "enterprise", feature = "sqs_trigger"))]
#[cfg(all(feature = "enterprise", feature = "sqs_trigger", feature = "private"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct SqsTriggerConfig {
pub queue_url: String,
@@ -164,11 +164,11 @@ pub struct SqsTriggerConfig {
pub aws_auth_resource_type: AwsAuthResourceType,
}
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct GcpTriggerConfig {
pub gcp_resource_path: String,
pub subscription_mode: SubscriptionMode,
pub subscription_mode: GcpSubscriptionMode,
#[serde(default, deserialize_with = "empty_as_none")]
pub subscription_id: Option<String>,
#[serde(default, deserialize_with = "empty_as_none")]
@@ -179,7 +179,7 @@ pub struct GcpTriggerConfig {
pub auto_acknowledge_msg: Option<bool>,
}
#[cfg(all(feature = "enterprise", feature = "nats"))]
#[cfg(all(feature = "enterprise", feature = "nats", feature = "private"))]
#[derive(Serialize, Deserialize)]
pub struct NatsTriggerConfig {
#[serde(flatten)]
@@ -231,15 +231,15 @@ enum TriggerConfig {
Postgres(PostgresTriggerConfig),
#[cfg(feature = "websocket")]
Websocket(WebsocketTriggerConfig),
#[cfg(all(feature = "enterprise", feature = "sqs_trigger"))]
#[cfg(all(feature = "enterprise", feature = "sqs_trigger", feature = "private"))]
Sqs(SqsTriggerConfig),
#[cfg(all(feature = "enterprise", feature = "kafka"))]
#[cfg(all(feature = "enterprise", feature = "kafka", feature = "private"))]
Kafka(KafkaTriggerConfig),
#[cfg(all(feature = "enterprise", feature = "nats"))]
#[cfg(all(feature = "enterprise", feature = "nats", feature = "private"))]
Nats(NatsTriggerConfig),
#[cfg(feature = "mqtt_trigger")]
Mqtt(MqttTriggerConfig),
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
Gcp(GcpTriggerConfig),
}
@@ -365,7 +365,7 @@ async fn set_postgres_trigger_config(
Ok(capture_config)
}
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
async fn set_gcp_trigger_config(
w_id: &str,
authed: ApiAuthed,
@@ -392,14 +392,14 @@ async fn set_gcp_trigger_config(
)
.await?;
gcp_config.create_update = Some(config);
gcp_config.subscription_mode = SubscriptionMode::CreateUpdate;
gcp_config.subscription_mode = GcpSubscriptionMode::CreateUpdate;
capture_config.trigger_config = Some(TriggerConfig::Gcp(gcp_config));
Ok(capture_config)
}
#[inline]
#[cfg(not(all(feature = "enterprise", feature = "gcp_trigger")))]
#[cfg(not(all(feature = "enterprise", feature = "gcp_trigger", feature = "private")))]
async fn set_gcp_trigger_config(
_w_id: &str,
_authed: ApiAuthed,
@@ -721,7 +721,7 @@ pub async fn get_active_capture_owner_and_email(
#[cfg(any(
feature = "http_trigger",
all(feature = "enterprise", feature = "gcp_trigger")
all(feature = "enterprise", feature = "gcp_trigger", feature = "private")
))]
async fn get_capture_trigger_config_and_owner<T: DeserializeOwned>(
db: &DB,
@@ -900,7 +900,7 @@ async fn webhook_payload(
Ok(StatusCode::NO_CONTENT)
}
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(feature = "enterprise", feature = "gcp_trigger", feature = "private"))]
async fn gcp_payload(
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
@@ -908,7 +908,7 @@ async fn gcp_payload(
headers: HeaderMap,
request: Request,
) -> Result<StatusCode> {
use crate::{gcp_triggers_oss::GcpTrigger, trigger_helpers::TriggerJobArgs};
use crate::triggers::{gcp::GcpTrigger, trigger_helpers::TriggerJobArgs};
let is_flow = matches!(runnable_kind, RunnableKind::Flow);
let (gcp_trigger_config, owner, email): (GcpTriggerConfig, _, _) =
@@ -931,9 +931,9 @@ async fn gcp_payload(
)
.await?;
let (payload, gcp) = process_google_push_request(headers, request).await?;
let (payload, trigger_info) = process_google_push_request(headers, request).await?;
let (main_args, preprocessor_args) = GcpTrigger::build_capture_payloads(payload, gcp);
let (main_args, preprocessor_args) = GcpTrigger::build_capture_payloads(&payload, trigger_info);
let _ = insert_capture_payload(
&db,
+3 -4
View File
@@ -10,19 +10,18 @@ use futures::FutureExt;
use sqlx::{
migrate::{Migrate, MigrateError},
pool::PoolConnection,
Executor, PgConnection, Pool, Postgres,
Executor, PgConnection, Postgres,
};
use tokio::task::JoinHandle;
use windmill_audit::audit_oss::{AuditAuthor, AuditAuthorable};
use windmill_common::utils::generate_lock_id;
pub use windmill_common::db::DB;
use windmill_common::{
db::{Authable, Authed},
error::Error,
utils::generate_lock_id,
};
pub type DB = Pool<Postgres>;
async fn current_database(conn: &mut PgConnection) -> Result<String, MigrateError> {
// language=SQL
Ok(sqlx::query_scalar("SELECT current_database()")
+23
View File
@@ -1,6 +1,12 @@
#[cfg(feature = "private")]
#[allow(unused)]
pub use crate::ee::*;
#[cfg(all(
feature = "enterprise",
any(feature = "nats", feature = "kafka", feature = "sqs_trigger"),
not(feature = "private")
))]
use {crate::db::ApiAuthed, windmill_common::DB};
#[cfg(not(feature = "private"))]
use anyhow::anyhow;
@@ -36,3 +42,20 @@ impl ExternalJwks {
None
}
}
#[cfg(all(
feature = "enterprise",
any(feature = "nats", feature = "kafka", feature = "sqs_trigger"),
not(feature = "private")
))]
pub async fn interpolate(
_authed: &ApiAuthed,
_db: &DB,
_w_id: &str,
_s: String,
) -> Result<String, anyhow::Error> {
// Implementation is not open source
Err(anyhow!(
"Interpolation is not available in open source version"
))
}
+2 -3
View File
@@ -10,11 +10,10 @@ use std::collections::HashMap;
use crate::utils::WithStarredInfoQuery;
use crate::{
auth::{list_tokens_internal, TruncatedTokenWithEmail},
db::{ApiAuthed, DB},
schedule::clear_schedule,
triggers::{
get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail,
},
triggers::{get_triggers_count_internal, TriggersCount},
users::{maybe_refresh_folders, require_owner_of_path},
utils::check_scopes,
webhook_util::{WebhookMessage, WebhookShared},
+11 -66
View File
@@ -2,27 +2,19 @@
#[allow(unused)]
pub use crate::gcp_triggers_ee::*;
use serde_json::value::RawValue;
use sqlx::prelude::FromRow;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use sqlx::types::Json as SqlxJson;
use windmill_common::worker::to_raw_value;
use windmill_common::triggers::TriggerKind;
use crate::trigger_helpers::TriggerJobArgs;
#[cfg(not(feature = "private"))]
use {
crate::db::{ApiAuthed, DB},
axum::{extract::Request, Router},
http::HeaderMap,
windmill_common::db::UserDB,
windmill_common::{
error::{Error as WindmillError, Result as WindmillResult},
utils::empty_as_none,
},
crate::{db::DB, trigger_helpers::TriggerJobArgs},
serde::{Deserialize, Serialize},
serde_json::value::RawValue,
sqlx::FromRow,
std::collections::HashMap,
windmill_common::{triggers::TriggerKind, utils::empty_as_none, worker::to_raw_value},
};
#[cfg(not(feature = "private"))]
type SqlxJson<T> = sqlx::types::Json<T>;
#[derive(sqlx::Type, Debug, Deserialize, Serialize)]
#[serde(rename_all(serialize = "lowercase", deserialize = "lowercase"))]
#[sqlx(type_name = "DELIVERY_MODE", rename_all = "lowercase")]
@@ -77,11 +69,6 @@ pub enum SubscriptionMode {
CreateUpdate,
}
#[cfg(not(feature = "private"))]
pub fn workspaced_service() -> Router {
Router::new()
}
#[cfg(not(feature = "private"))]
pub fn start_consuming_gcp_pubsub_event(
_db: DB,
@@ -91,49 +78,6 @@ pub fn start_consuming_gcp_pubsub_event(
}
#[cfg(not(feature = "private"))]
pub async fn manage_google_subscription(
_authed: ApiAuthed,
_db: &DB,
_workspace_id: &str,
_gcp_resource_path: &str,
_path: &str,
_topic_id: &str,
_subscription_id: &mut Option<String>,
_base_endpoint: &mut Option<String>,
_subscription_mode: SubscriptionMode,
_create_update_config: Option<CreateUpdateConfig>,
_trigger_mode: bool,
_is_flow: bool,
) -> WindmillResult<CreateUpdateConfig> {
Ok(CreateUpdateConfig::default())
}
#[cfg(not(feature = "private"))]
pub async fn process_google_push_request(
_headers: HeaderMap,
_request: Request,
) -> Result<(String, HashMap<String, Box<RawValue>>), WindmillError> {
Ok((String::new(), HashMap::new()))
}
#[cfg(not(feature = "private"))]
pub async fn validate_jwt_token(
_db: &DB,
_user_db: UserDB,
_authed: ApiAuthed,
_headers: &HeaderMap,
_gcp_resource_path: &str,
_workspace_id: &str,
_delivery_config: &PushConfig,
) -> Result<(), windmill_common::error::Error> {
Ok(())
}
#[cfg(not(feature = "private"))]
pub fn gcp_push_route_handler() -> Router {
Router::new()
}
#[derive(FromRow, Deserialize, Serialize, Debug)]
pub struct GcpTrigger {
pub gcp_resource_path: String,
@@ -164,6 +108,7 @@ pub struct GcpTrigger {
pub auto_acknowledge_msg: Option<bool>,
}
#[cfg(not(feature = "private"))]
impl TriggerJobArgs<String> for GcpTrigger {
fn v1_payload_fn(payload: String) -> HashMap<String, Box<RawValue>> {
HashMap::from([("payload".to_string(), to_raw_value(&payload))])
@@ -172,4 +117,4 @@ impl TriggerJobArgs<String> for GcpTrigger {
fn trigger_kind() -> TriggerKind {
TriggerKind::Gcp
}
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -48,7 +48,7 @@ use crate::{
auth::{OptTokened, Tokened},
concurrency_groups::join_concurrency_key,
db::{ApiAuthed, DB},
trigger_helpers::RunnableId,
triggers::trigger_helpers::RunnableId,
users::{get_scope_tags, require_owner_of_path, OptAuthed},
utils::{check_scopes, content_plain, require_super_admin},
};
@@ -5,19 +5,12 @@ pub use crate::kafka_triggers_ee::*;
#[cfg(not(feature = "private"))]
use crate::db::DB;
#[cfg(not(feature = "private"))]
use axum::Router;
#[cfg(not(feature = "private"))]
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[cfg(not(feature = "private"))]
pub struct KafkaResourceSecurity {}
#[cfg(not(feature = "private"))]
pub fn workspaced_service() -> Router {
Router::new()
}
#[cfg(not(feature = "private"))]
pub fn start_kafka_consumers(
_db: DB,
@@ -54,7 +47,9 @@ pub struct KafkaTrigger {
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<sqlx::types::Json<std::collections::HashMap<String, Box<serde_json::value::RawValue>>>>,
pub error_handler_args: Option<
sqlx::types::Json<std::collections::HashMap<String, Box<serde_json::value::RawValue>>>,
>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry: Option<sqlx::types::Json<windmill_common::flows::Retry>>,
}
+18 -110
View File
@@ -89,12 +89,6 @@ mod flows;
mod folders;
mod granular_acls;
mod groups;
#[cfg(feature = "http_trigger")]
mod http_trigger_args;
#[cfg(feature = "http_trigger")]
mod http_trigger_auth;
#[cfg(feature = "http_trigger")]
pub mod http_triggers;
#[cfg(feature = "private")]
pub mod indexer_ee;
mod indexer_oss;
@@ -106,6 +100,7 @@ mod integration;
mod live_migrations;
#[cfg(feature = "postgres_trigger")]
mod postgres_triggers;
mod trigger_helpers;
pub mod openapi;
@@ -170,7 +165,6 @@ mod sqs_triggers_oss;
#[cfg(feature = "private")]
pub mod teams_approvals_ee;
mod teams_approvals_oss;
mod trigger_helpers;
mod static_assets;
#[cfg(all(feature = "stripe", feature = "enterprise", feature = "private"))]
@@ -182,7 +176,7 @@ pub mod teams_ee;
mod teams_oss;
mod token;
mod tracing_init;
mod triggers;
pub mod triggers;
mod users;
#[cfg(feature = "private")]
pub mod users_ee;
@@ -381,101 +375,14 @@ pub async fn run_server(
}
};
let kafka_triggers_service = {
#[cfg(all(feature = "enterprise", feature = "kafka"))]
{
kafka_triggers_oss::workspaced_service()
}
#[cfg(not(all(feature = "enterprise", feature = "kafka")))]
{
Router::new()
}
};
let nats_triggers_service = {
#[cfg(all(feature = "enterprise", feature = "nats"))]
{
nats_triggers_oss::workspaced_service()
}
#[cfg(not(all(feature = "enterprise", feature = "nats")))]
{
Router::new()
}
};
let mqtt_triggers_service = {
#[cfg(all(feature = "mqtt_trigger"))]
{
mqtt_triggers::workspaced_service()
}
#[cfg(not(feature = "mqtt_trigger"))]
{
Router::new()
}
};
let gcp_triggers_service = {
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
{
gcp_triggers_oss::workspaced_service()
}
#[cfg(not(all(feature = "enterprise", feature = "gcp_trigger")))]
{
Router::new()
}
};
let sqs_triggers_service = {
#[cfg(all(feature = "enterprise", feature = "sqs_trigger"))]
{
sqs_triggers_oss::workspaced_service()
}
#[cfg(not(all(feature = "enterprise", feature = "sqs_trigger")))]
{
Router::new()
}
};
let websocket_triggers_service = {
#[cfg(feature = "websocket")]
{
websocket_triggers::workspaced_service()
}
#[cfg(not(feature = "websocket"))]
Router::new()
};
let http_triggers_service = {
#[cfg(feature = "http_trigger")]
{
http_triggers::workspaced_service()
}
#[cfg(not(feature = "http_trigger"))]
Router::new()
};
// Initialize HTTP trigger refresh loop
#[cfg(feature = "http_trigger")]
{
let http_killpill_rx = killpill_rx.resubscribe();
http_triggers::refresh_routers_loop(&db, http_killpill_rx).await;
triggers::http::refresh_routers_loop(&db, http_killpill_rx).await;
}
let postgres_triggers_service = {
#[cfg(feature = "postgres_trigger")]
{
postgres_triggers::workspaced_service()
}
#[cfg(not(feature = "postgres_trigger"))]
Router::new()
};
let triggers_service = triggers::generate_trigger_routers();
if !*CLOUD_HOSTED && server_mode && !mcp_mode {
#[cfg(feature = "websocket")]
@@ -619,14 +526,7 @@ pub async fn run_server(
.nest("/workspaces", workspaces::workspaced_service())
.nest("/oidc", oidc_oss::workspaced_service())
.nest("/openapi", openapi::openapi_service())
.nest("/http_triggers", http_triggers_service)
.nest("/websocket_triggers", websocket_triggers_service)
.nest("/kafka_triggers", kafka_triggers_service)
.nest("/nats_triggers", nats_triggers_service)
.nest("/mqtt_triggers", mqtt_triggers_service)
.nest("/sqs_triggers", sqs_triggers_service)
.nest("/gcp_triggers", gcp_triggers_service)
.nest("/postgres_triggers", postgres_triggers_service),
.merge(triggers_service),
)
.nest("/workspaces", workspaces::global_service())
.nest(
@@ -775,7 +675,7 @@ pub async fn run_server(
{
#[cfg(feature = "http_trigger")]
{
http_triggers::routes_global_service()
triggers::http::handler::http_route_trigger_handler()
}
#[cfg(not(feature = "http_trigger"))]
@@ -788,11 +688,19 @@ pub async fn run_server(
.nest(
"/gcp/w/:workspace_id",
{
#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))]
#[cfg(all(
feature = "enterprise",
feature = "gcp_trigger",
feature = "private"
))]
{
gcp_triggers_oss::gcp_push_route_handler()
triggers::gcp::handler_oss::gcp_push_route_handler()
}
#[cfg(not(all(feature = "enterprise", feature = "gcp_trigger")))]
#[cfg(not(all(
feature = "enterprise",
feature = "gcp_trigger",
feature = "private"
)))]
{
Router::new()
}
+90 -722
View File
@@ -4,22 +4,11 @@ use crate::{
resources::try_get_resource_from_db_as,
trigger_helpers::{trigger_runnable, TriggerJobArgs},
users::fetch_api_authed,
utils::check_scopes,
};
use windmill_git_sync::{handle_deployment_metadata, DeployedObject};
use axum::{
async_trait,
extract::{Path, Query},
Extension, Json,
};
use axum::{
routing::{delete, get, post},
Router,
};
use axum::async_trait;
use base64::{engine, prelude::*};
use bytes::Bytes;
use http::StatusCode;
use itertools::Itertools;
use rumqttc::{
v5::{
@@ -35,17 +24,15 @@ use rumqttc::{
TlsConfiguration, Transport,
};
use serde::{Deserialize, Serialize};
use sql_builder::{bind::Bind, SqlBuilder};
use sqlx::{FromRow, Type};
use std::collections::HashMap;
use std::time::Duration;
use windmill_audit::{audit_oss::audit_log, ActionKind};
use windmill_common::{
db::UserDB,
error::{self, JsonResult},
error::{to_anyhow, Error, Result},
triggers::TriggerKind,
utils::{not_found_if_none, paginate, report_critical_error, Pagination, StripPath},
worker::{to_raw_value, CLOUD_HOSTED},
utils::report_critical_error,
worker::to_raw_value,
INSTANCE_NAME,
};
@@ -53,34 +40,6 @@ use rand::seq::SliceRandom;
use serde_json::value::RawValue;
use sqlx::types::Json as SqlxJson;
pub fn workspaced_service() -> Router {
Router::new()
.route("/create", post(create_mqtt_trigger))
.route("/list", get(list_mqtt_triggers))
.route("/get/*path", get(get_mqtt_trigger))
.route("/update/*path", post(update_mqtt_trigger))
.route("/delete/*path", delete(delete_mqtt_trigger))
.route("/exists/*path", get(exists_mqtt_trigger))
.route("/setenabled/*path", post(set_enabled))
.route("/test", post(test_mqtt_connection))
}
#[derive(Debug, thiserror::Error)]
enum Error {
#[error("{0}")]
Common(#[from] windmill_common::error::Error),
#[error("{0}")]
V5RumqttClient(#[from] rumqttc::v5::ClientError),
#[error("{0}")]
V5ConnectionError(#[from] rumqttc::v5::ConnectionError),
#[error("{0}")]
V3RumqttClient(#[from] rumqttc::ClientError),
#[error("{0}")]
V3ConnectionError(#[from] rumqttc::ConnectionError),
#[error("{0}")]
Base64Decode(#[from] base64::DecodeError),
}
async fn run_job(
payload: &[u8],
trigger_info: HashMap<String, Box<RawValue>>,
@@ -124,6 +83,18 @@ async fn run_job(
Ok(())
}
#[derive(Debug, Deserialize, Serialize)]
pub struct MqttV3Config {
clean_session: Option<bool>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct MqttV5Config {
clean_start: Option<bool>,
session_expiry_interval: Option<u32>,
topic_alias_maximum: Option<u16>,
}
#[derive(Clone, Debug, Deserialize, Serialize, Type)]
#[serde(rename_all = "lowercase")]
pub enum QualityOfService {
@@ -152,18 +123,6 @@ impl From<QualityOfService> for V5QoS {
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct MqttV3Config {
clean_session: Option<bool>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct MqttV5Config {
clean_start: Option<bool>,
session_expiry_interval: Option<u32>,
topic_alias_maximum: Option<u16>,
}
#[derive(Debug, Deserialize, Serialize, Type)]
#[sqlx(type_name = "MQTT_CLIENT_VERSION")]
#[sqlx(rename_all = "lowercase")]
@@ -201,87 +160,6 @@ pub struct SubscribeTopic {
topic: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct NewMqttTrigger {
mqtt_resource_path: String,
subscribe_topics: Vec<SubscribeTopic>,
v3_config: Option<MqttV3Config>,
v5_config: Option<MqttV5Config>,
#[serde(skip_serializing_if = "Option::is_none")]
client_version: Option<MqttClientVersion>,
client_id: Option<String>,
path: String,
script_path: String,
is_flow: bool,
enabled: bool,
error_handler_path: Option<String>,
error_handler_args: Option<SqlxJson<HashMap<String, Box<RawValue>>>>,
retry: Option<SqlxJson<windmill_common::flows::Retry>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EditMqttTrigger {
mqtt_resource_path: String,
subscribe_topics: Vec<SubscribeTopic>,
v3_config: Option<MqttV3Config>,
v5_config: Option<MqttV5Config>,
client_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
client_version: Option<MqttClientVersion>,
path: String,
script_path: String,
is_flow: bool,
error_handler_path: Option<String>,
error_handler_args: Option<SqlxJson<HashMap<String, Box<RawValue>>>>,
retry: Option<SqlxJson<windmill_common::flows::Retry>>,
}
#[derive(Debug, Serialize, Deserialize, FromRow)]
pub struct MqttTrigger {
pub mqtt_resource_path: String,
pub subscribe_topics: Vec<SqlxJson<SubscribeTopic>>,
pub v3_config: Option<SqlxJson<MqttV3Config>>,
pub v5_config: Option<SqlxJson<MqttV5Config>>,
pub client_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub client_version: Option<MqttClientVersion>,
pub path: String,
pub script_path: String,
pub is_flow: bool,
pub workspace_id: String,
pub edited_by: String,
pub email: String,
pub edited_at: chrono::DateTime<chrono::Utc>,
pub extra_perms: Option<serde_json::Value>,
pub error: Option<String>,
pub server_id: Option<String>,
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub enabled: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<SqlxJson<HashMap<String, Box<RawValue>>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry: Option<SqlxJson<windmill_common::flows::Retry>>,
}
#[derive(Deserialize, Serialize)]
pub struct ListMqttTriggerQuery {
page: Option<usize>,
per_page: Option<usize>,
path: Option<String>,
is_flow: Option<bool>,
path_start: Option<String>,
}
#[derive(Deserialize)]
pub struct SetEnabled {
enabled: bool,
}
const KEEP_ALIVE: u64 = 60;
const CLIENT_CONNECTION_TIMEOUT: u64 = 60;
const TOPIC_ALIAS_MAXIMUM: u16 = 65535;
struct MqttClientBuilder<'client> {
mqtt_resource: MqttResource,
client_id: &'client str,
@@ -310,14 +188,14 @@ impl<'client> MqttClientBuilder<'client> {
}
}
async fn build_client(&self) -> Result<MqttClientResult, Error> {
async fn build_client(&self) -> Result<MqttClientResult> {
match self.mqtt_client_version {
Some(MqttClientVersion::V5) | None => self.build_v5_client().await,
Some(MqttClientVersion::V3) => self.build_v3_client().await,
}
}
fn get_tls_configuration(&self) -> Result<Option<Transport>, Error> {
fn get_tls_configuration(&self) -> Result<Option<Transport>> {
let transport = match self.mqtt_resource.tls {
Some(ref tls) if tls.enabled => {
let transport = match tls.ca_certificate.trim().is_empty() {
@@ -329,8 +207,9 @@ impl<'client> MqttClientBuilder<'client> {
Some(client_certificate)
if !client_certificate.trim().is_empty() =>
{
let client_certificate =
BASE64_STANDARD.decode(client_certificate)?;
let client_certificate = BASE64_STANDARD
.decode(client_certificate)
.map_err(to_anyhow)?;
let password = tls
.pkcs12_certificate_password
.clone()
@@ -351,7 +230,7 @@ impl<'client> MqttClientBuilder<'client> {
Ok(transport)
}
async fn build_v5_client(&self) -> Result<MqttClientResult, Error> {
async fn build_v5_client(&self) -> Result<MqttClientResult> {
let mut mqtt_options = V5MqttOptions::new(
self.client_id,
&self.mqtt_resource.broker,
@@ -398,12 +277,15 @@ impl<'client> MqttClientBuilder<'client> {
.map(|topic| Filter::new(topic.topic.clone(), topic.qos.clone().into()))
.collect_vec();
async_client.subscribe_many(subscribe_filters).await?;
async_client
.subscribe_many(subscribe_filters)
.await
.map_err(to_anyhow)?;
}
Ok(MqttClientResult::V5((V5MqttHandler, event_loop)))
}
async fn build_v3_client(&self) -> Result<MqttClientResult, Error> {
async fn build_v3_client(&self) -> Result<MqttClientResult> {
let mut mqtt_options = V3MqttOptions::new(
self.client_id,
&self.mqtt_resource.broker,
@@ -435,574 +317,62 @@ impl<'client> MqttClientBuilder<'client> {
.map(|topic| SubscribeFilter::new(topic.topic.clone(), topic.qos.clone().into()))
.collect_vec();
async_client.subscribe_many(subscribe_filters).await?;
async_client
.subscribe_many(subscribe_filters)
.await
.map_err(to_anyhow)?;
}
Ok(MqttClientResult::V3((V3MqttHandler, event_loop)))
}
}
fn convert_disconnect_packet_into_string(
disconnect: rumqttc::v5::mqttbytes::v5::Disconnect,
) -> String {
#[derive(Debug, Serialize, Deserialize, FromRow)]
pub struct MqttTrigger {
pub mqtt_resource_path: String,
pub subscribe_topics: Vec<SqlxJson<SubscribeTopic>>,
pub v3_config: Option<SqlxJson<MqttV3Config>>,
pub v5_config: Option<SqlxJson<MqttV5Config>>,
pub client_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub client_version: Option<MqttClientVersion>,
pub path: String,
pub script_path: String,
pub is_flow: bool,
pub workspace_id: String,
pub edited_by: String,
pub email: String,
pub edited_at: chrono::DateTime<chrono::Utc>,
pub extra_perms: Option<serde_json::Value>,
pub error: Option<String>,
pub server_id: Option<String>,
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub enabled: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<SqlxJson<HashMap<String, Box<RawValue>>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry: Option<SqlxJson<windmill_common::flows::Retry>>,
}
const KEEP_ALIVE: u64 = 60;
const CLIENT_CONNECTION_TIMEOUT: u64 = 60;
const TOPIC_ALIAS_MAXIMUM: u16 = 65535;
fn convert_disconnect_packet_into_err(disconnect: rumqttc::v5::mqttbytes::v5::Disconnect) -> Error {
let err_message = disconnect
.properties
.map(|properties| properties.reason_string)
.flatten();
let reason_code = disconnect.reason_code as u8;
format!(
anyhow::anyhow!(
"Disconnected by the broker, reason code: {}, {}",
reason_code,
err_message
.map(|err| format!("message: {}", err))
.unwrap_or("".to_string())
)
}
#[derive(Debug, Deserialize)]
pub struct TestMqttConnection {
mqtt_resource_path: String,
client_version: Option<MqttClientVersion>,
v3_config: Option<MqttV3Config>,
v5_config: Option<MqttV5Config>,
}
pub async fn test_mqtt_connection(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path(workspace_id): Path<String>,
Json(test_postgres): Json<TestMqttConnection>,
) -> error::Result<()> {
let TestMqttConnection { mqtt_resource_path, client_version, v3_config, v5_config } =
test_postgres;
let mqtt_resource = try_get_resource_from_db_as::<MqttResource>(
&authed,
Some(user_db),
&db,
&mqtt_resource_path,
&workspace_id,
)
.await?;
let connect_f = async {
let client_builder = MqttClientBuilder::new(
mqtt_resource,
Some(""),
vec![],
v3_config.as_ref(),
v5_config.as_ref(),
client_version.as_ref(),
);
client_builder.build_client().await.map_err(|err| {
error::Error::BadConfig(format!(
"Error connecting to mqtt broker: {}",
err.to_string()
))
})
};
tokio::time::timeout(tokio::time::Duration::from_secs(30), connect_f)
.await
.map_err(|_| {
error::Error::BadConfig(format!(
"Timeout occurred while trying to connect to mqtt broker after 30 seconds"
))
})??;
Ok(())
}
pub async fn create_mqtt_trigger(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path(w_id): Path<String>,
Json(new_mqtt_trigger): Json<NewMqttTrigger>,
) -> error::Result<(StatusCode, String)> {
check_scopes(&authed, || {
format!("mqtt_triggers:write:{}", &new_mqtt_trigger.path)
})?;
if *CLOUD_HOSTED {
return Err(error::Error::BadRequest(
"MQTT triggers are not supported on multi-tenant cloud, use dedicated cloud or self-host".to_string(),
));
}
let NewMqttTrigger {
mqtt_resource_path,
subscribe_topics,
path,
script_path,
enabled,
is_flow,
v3_config,
v5_config,
client_version,
client_id,
error_handler_path,
error_handler_args,
retry,
} = new_mqtt_trigger;
let mut tx = user_db.begin(&authed).await?;
let subscribe_topics = subscribe_topics.into_iter().map(SqlxJson).collect_vec();
let v3_config = v3_config.map(SqlxJson);
let v5_config = v5_config.map(SqlxJson);
sqlx::query!(
r#"
INSERT INTO mqtt_trigger (
mqtt_resource_path,
subscribe_topics,
client_version,
client_id,
v3_config,
v5_config,
workspace_id,
path,
script_path,
is_flow,
email,
enabled,
edited_by,
error_handler_path,
error_handler_args,
retry
)
VALUES (
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10,
$11,
$12,
$13,
$14,
$15,
$16
)"#,
mqtt_resource_path,
subscribe_topics.as_slice() as &[SqlxJson<SubscribeTopic>],
client_version as Option<MqttClientVersion>,
client_id,
v3_config as Option<SqlxJson<MqttV3Config>>,
v5_config as Option<SqlxJson<MqttV5Config>>,
&w_id,
&path,
script_path,
is_flow,
&authed.email,
enabled,
&authed.username,
error_handler_path,
error_handler_args as _,
retry as _
)
.execute(&mut *tx)
.await?;
audit_log(
&mut *tx,
&authed,
"mqtt_triggers.create",
ActionKind::Create,
&w_id,
Some(path.as_str()),
None,
)
.await?;
tx.commit().await?;
handle_deployment_metadata(
&authed.email,
&authed.username,
&db,
&w_id,
DeployedObject::MqttTrigger { path: path.to_string() },
Some(format!("MQTT trigger '{}' created", path)),
true,
)
.await?;
Ok((StatusCode::CREATED, format!("{}", path.to_string())))
}
pub async fn list_mqtt_triggers(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Path(w_id): Path<String>,
Query(lst): Query<ListMqttTriggerQuery>,
) -> error::JsonResult<Vec<MqttTrigger>> {
let mut tx = user_db.begin(&authed).await?;
let (per_page, offset) = paginate(Pagination { per_page: lst.per_page, page: lst.page });
let mut sqlb = SqlBuilder::select_from("mqtt_trigger");
sqlb.fields(&[
"mqtt_resource_path",
"subscribe_topics",
"v3_config",
"v5_config",
"client_version",
"client_id",
"workspace_id",
"path",
"script_path",
"is_flow",
"edited_by",
"email",
"edited_at",
"server_id",
"last_server_ping",
"extra_perms",
"error",
"enabled",
"error_handler_path",
"error_handler_args",
"retry",
])
.order_by("edited_at", true)
.and_where("workspace_id = ?".bind(&w_id))
.offset(offset)
.limit(per_page);
if let Some(path) = lst.path {
sqlb.and_where_eq("script_path", "?".bind(&path));
}
if let Some(is_flow) = lst.is_flow {
sqlb.and_where_eq("is_flow", "?".bind(&is_flow));
}
if let Some(path_start) = &lst.path_start {
sqlb.and_where_like_left("path", path_start);
}
let sql = sqlb
.sql()
.map_err(|e| error::Error::InternalErr(e.to_string()))?;
let rows = sqlx::query_as::<_, MqttTrigger>(&sql)
.fetch_all(&mut *tx)
.await
.map_err(|e| {
tracing::debug!("Error fetching mqtt_trigger: {:#?}", e);
windmill_common::error::Error::InternalErr("server error".to_string())
})?;
tx.commit().await.map_err(|e| {
tracing::debug!("Error committing mqtt_trigger: {:#?}", e);
windmill_common::error::Error::InternalErr("server error".to_string())
})?;
Ok(Json(rows))
}
pub async fn get_mqtt_trigger(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<MqttTrigger> {
let path = path.to_path();
check_scopes(&authed, || format!("mqtt_triggers:read:{}", path))?;
let mut tx = user_db.begin(&authed).await?;
let trigger = sqlx::query_as!(
MqttTrigger,
r#"
SELECT
mqtt_resource_path,
subscribe_topics as "subscribe_topics!: Vec<SqlxJson<SubscribeTopic>>",
v3_config as "v3_config!: Option<SqlxJson<MqttV3Config>>",
v5_config as "v5_config!: Option<SqlxJson<MqttV5Config>>",
client_version AS "client_version: _",
client_id,
workspace_id,
path,
script_path,
is_flow,
edited_by,
email,
edited_at,
server_id,
last_server_ping,
extra_perms,
error,
enabled,
error_handler_path,
error_handler_args as "error_handler_args: _",
retry as "retry: _"
FROM
mqtt_trigger
WHERE
workspace_id = $1 AND
path = $2
"#,
w_id,
&path
)
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
let trigger = not_found_if_none(trigger, "Mqtt Trigger", path)?;
Ok(Json(trigger))
}
pub async fn update_mqtt_trigger(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path((w_id, path)): Path<(String, StripPath)>,
Json(mqtt_trigger): Json<EditMqttTrigger>,
) -> error::Result<String> {
let workspace_path = path.to_path();
check_scopes(&authed, || {
format!("mqtt_triggers:write:{}", workspace_path)
})?;
let EditMqttTrigger {
mqtt_resource_path,
subscribe_topics,
script_path,
path,
is_flow,
v3_config,
v5_config,
client_version,
client_id,
error_handler_path,
error_handler_args,
retry,
} = mqtt_trigger;
let mut tx = user_db.begin(&authed).await?;
let subscribe_topics = subscribe_topics.into_iter().map(SqlxJson).collect_vec();
let v3_config = v3_config.map(SqlxJson);
let v5_config = v5_config.map(SqlxJson);
sqlx::query!(
r#"
UPDATE
mqtt_trigger
SET
mqtt_resource_path = $1,
subscribe_topics = $2,
client_version = $3,
client_id = $4,
v3_config = $5,
v5_config = $6,
is_flow = $7,
edited_by = $8,
email = $9,
script_path = $10,
path = $11,
edited_at = now(),
error = NULL,
server_id = NULL,
error_handler_path = $14,
error_handler_args = $15,
retry = $16
WHERE
workspace_id = $12 AND
path = $13
"#,
mqtt_resource_path,
subscribe_topics.as_slice() as &[SqlxJson<SubscribeTopic>],
client_version as Option<MqttClientVersion>,
client_id,
v3_config as Option<SqlxJson<MqttV3Config>>,
v5_config as Option<SqlxJson<MqttV5Config>>,
is_flow,
&authed.username,
&authed.email,
script_path,
path,
w_id,
workspace_path,
error_handler_path,
error_handler_args as _,
retry as _
)
.execute(&mut *tx)
.await?;
audit_log(
&mut *tx,
&authed,
"mqtt_triggers.update",
ActionKind::Update,
&w_id,
Some(&path),
None,
)
.await?;
tx.commit().await?;
handle_deployment_metadata(
&authed.email,
&authed.username,
&db,
&w_id,
DeployedObject::MqttTrigger { path: path.clone() },
Some(format!("MQTT trigger '{}' updated", path)),
true,
)
.await?;
Ok(path.to_string())
}
pub async fn delete_mqtt_trigger(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> error::Result<String> {
let path = path.to_path();
check_scopes(&authed, || format!("mqtt_triggers:write:{}", path))?;
let mut tx = user_db.begin(&authed).await?;
sqlx::query!(
r#"
DELETE
FROM
mqtt_trigger
WHERE
workspace_id = $1 AND
path = $2
"#,
w_id,
path,
)
.execute(&mut *tx)
.await?;
audit_log(
&mut *tx,
&authed,
"mqtt_triggers.delete",
ActionKind::Delete,
&w_id,
Some(path),
None,
)
.await?;
tx.commit().await?;
handle_deployment_metadata(
&authed.email,
&authed.username,
&db,
&w_id,
DeployedObject::MqttTrigger { path: path.to_string() },
Some(format!("MQTT trigger '{}' deleted", path)),
true,
)
.await?;
Ok(format!("MQTT trigger {path} deleted"))
}
pub async fn exists_mqtt_trigger(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<bool> {
let path = path.to_path();
let exists = sqlx::query_scalar!(
r#"
SELECT EXISTS(
SELECT
1
FROM
mqtt_trigger
WHERE
path = $1 AND
workspace_id = $2
)"#,
path,
w_id,
)
.fetch_one(&db)
.await?
.unwrap_or(false);
Ok(Json(exists))
}
pub async fn set_enabled(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path((w_id, path)): Path<(String, StripPath)>,
Json(payload): Json<SetEnabled>,
) -> error::Result<String> {
let path = path.to_path();
check_scopes(&authed, || format!("mqtt_triggers:write:{}", path))?;
let mut tx = user_db.begin(&authed).await?;
// important to set server_id, last_server_ping and error to NULL to stop current mqtt listener
let one_o = sqlx::query_scalar!(
r#"
UPDATE
mqtt_trigger
SET
enabled = $1,
email = $2,
edited_by = $3,
edited_at = now(),
server_id = NULL,
error = NULL
WHERE
path = $4 AND
workspace_id = $5
RETURNING 1
"#,
payload.enabled,
&authed.email,
&authed.username,
path,
w_id,
)
.fetch_optional(&mut *tx)
.await?
.flatten();
not_found_if_none(one_o, "Mqtt trigger", path)?;
audit_log(
&mut *tx,
&authed,
"mqtt_triggers.setenabled",
ActionKind::Update,
&w_id,
Some(path),
Some([("enabled", payload.enabled.to_string().as_ref())].into()),
)
.await?;
tx.commit().await?;
handle_deployment_metadata(
&authed.email,
&authed.username,
&db,
&w_id,
DeployedObject::MqttTrigger { path: path.to_string() },
Some(format!("MQTT trigger '{}' updated", path)),
true,
)
.await?;
Ok(format!(
"successfully updated mqtt trigger at path {} to status {}",
path, payload.enabled
))
.into()
}
async fn loop_ping(db: &DB, mqtt: &MqttConfig, error: Option<&str>) {
@@ -1026,7 +396,7 @@ trait MqttEvent {
type Event;
fn handle_publish_packet(publish_packet: Self::PublishPacket) -> PublishData;
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>, String>;
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>>;
}
struct V5MqttHandler;
@@ -1046,7 +416,7 @@ impl MqttEvent for V5MqttHandler {
)
}
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>, String> {
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>> {
tracing::debug!("Inside V5 event");
match event {
Self::Event::Incoming(packet) => match packet {
@@ -1057,7 +427,7 @@ impl MqttEvent for V5MqttHandler {
)))
}
Self::IncomingPacket::Disconnect(disconnect) => {
return Err(convert_disconnect_packet_into_string(disconnect));
return Err(convert_disconnect_packet_into_err(disconnect));
}
packet => {
tracing::debug!("Received = {:#?}", packet);
@@ -1089,7 +459,7 @@ impl MqttEvent for V3MqttHandler {
)
}
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>, String> {
fn handle_event(&self, event: Self::Event) -> Result<Option<(Bytes, PublishData)>> {
tracing::debug!("Inside V3 event");
match event {
Self::Event::Incoming(packet) => match packet {
@@ -1116,67 +486,65 @@ const TIMEOUT_DURATION: u64 = 10;
const CONNECTION_TIMEOUT: Duration = Duration::from_secs(TIMEOUT_DURATION);
#[async_trait]
trait EventLoop {
pub trait EventLoop {
type Event;
type Error;
async fn poll(&mut self) -> Result<Self::Event, Self::Error>;
async fn verify_connection(&mut self) -> Result<(), Error>;
async fn poll(&mut self) -> Result<Self::Event>;
async fn verify_connection(&mut self) -> Result<()>;
}
#[async_trait]
impl EventLoop for V5EventLoop {
type Event = V5Event;
type Error = rumqttc::v5::ConnectionError;
async fn poll(&mut self) -> Result<Self::Event, Self::Error> {
self.poll().await
async fn poll(&mut self) -> Result<Self::Event> {
self.poll().await.map_err(|err| to_anyhow(err).into())
}
async fn verify_connection(&mut self) -> Result<(), Error> {
async fn verify_connection(&mut self) -> Result<()> {
let start = std::time::Instant::now();
while start.elapsed() < CONNECTION_TIMEOUT {
match self.poll().await? {
match self.poll().await.map_err(to_anyhow)? {
Self::Event::Incoming(V5Incoming::ConnAck(_)) => return Ok(()),
Self::Event::Incoming(V5Incoming::Disconnect(disconnect)) => {
return Err(Error::Common(error::Error::BadConfig(
convert_disconnect_packet_into_string(disconnect),
)));
return Err(convert_disconnect_packet_into_err(disconnect));
}
_ => continue,
}
}
Err(Error::Common(error::Error::BadConfig(format!(
Err(Error::BadConfig(format!(
"Timeout occurred while trying to connect to mqtt broker after {} seconds",
TIMEOUT_DURATION
))))
)))
}
}
#[async_trait]
impl EventLoop for V3EventLoop {
type Event = V3Event;
type Error = rumqttc::ConnectionError;
type Error = Error;
async fn poll(&mut self) -> Result<Self::Event, Self::Error> {
self.poll().await
async fn poll(&mut self) -> Result<Self::Event> {
self.poll().await.map_err(|err| to_anyhow(err).into())
}
async fn verify_connection(&mut self) -> Result<(), Error> {
async fn verify_connection(&mut self) -> Result<()> {
let start = std::time::Instant::now();
while start.elapsed() < CONNECTION_TIMEOUT {
match self.poll().await? {
match self.poll().await.map_err(to_anyhow)? {
Self::Event::Incoming(rumqttc::Packet::ConnAck(_)) => return Ok(()),
_ => continue,
}
}
Err(Error::Common(error::Error::BadConfig(format!(
Err(Error::BadConfig(format!(
"Timeout occurred while trying to connect to mqtt broker after {} seconds",
TIMEOUT_DURATION
))))
)))
}
}
@@ -1479,7 +847,7 @@ impl MqttTrigger {
}
}
async fn fetch_authed(&self, db: &DB) -> error::Result<ApiAuthed> {
async fn fetch_authed(&self, db: &DB) -> Result<ApiAuthed> {
fetch_api_authed(
self.edited_by.clone(),
self.email.clone(),
@@ -1722,7 +1090,7 @@ impl CaptureConfigForMqttTrigger {
Some(())
}
async fn fetch_authed(&self, db: &DB) -> error::Result<ApiAuthed> {
async fn fetch_authed(&self, db: &DB) -> Result<ApiAuthed> {
fetch_api_authed(
self.owner.clone(),
self.email.clone(),
@@ -5,19 +5,12 @@ pub use crate::nats_triggers_ee::*;
#[cfg(not(feature = "private"))]
use crate::db::DB;
#[cfg(not(feature = "private"))]
use axum::Router;
#[cfg(not(feature = "private"))]
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "private"))]
#[derive(Serialize, Deserialize)]
pub struct NatsResourceAuth {}
#[cfg(not(feature = "private"))]
pub fn workspaced_service() -> Router {
Router::new()
}
#[cfg(not(feature = "private"))]
pub fn start_nats_consumers(_db: DB, mut _killpill_rx: tokio::sync::broadcast::Receiver<()>) -> () {
// implementation is not open source
+5 -2
View File
@@ -25,8 +25,11 @@ use crate::db::ApiAuthed;
#[cfg(feature = "http_trigger")]
use {
crate::{
http_trigger_args::HttpMethod, http_trigger_auth::ApiKeyAuthentication,
http_triggers::AuthenticationMethod, resources::try_get_resource_from_db_as,
resources::try_get_resource_from_db_as,
triggers::http::{
http_trigger_args::HttpMethod, http_trigger_auth::ApiKeyAuthentication,
AuthenticationMethod,
},
},
itertools::Itertools,
};
+66 -234
View File
@@ -1,47 +1,28 @@
use crate::{
db::{ApiAuthed, DB},
resources::try_get_resource_from_db_as,
trigger_helpers::{trigger_runnable, TriggerJobArgs},
users::fetch_api_authed,
};
use chrono::Utc;
use itertools::Itertools;
use native_tls::{Certificate, TlsConnector};
use pg_escape::quote_identifier;
use rand::Rng;
use rust_postgres::{config::SslMode, Client, Config, NoTls};
use rust_postgres_native_tls::MakeTlsConnector;
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue;
use sqlx::FromRow;
use std::collections::HashMap;
use axum::{
routing::{delete, get, post},
Router,
};
pub use handler::PostgresTrigger;
use handler::{
alter_publication, create_postgres_trigger, create_publication, create_slot,
create_template_script, delete_postgres_trigger, delete_publication, drop_slot_name,
exists_postgres_trigger, get_postgres_trigger, get_postgres_version,
get_postgres_version_internal, get_publication_info, get_template_script,
is_database_in_logical_level, list_database_publication, list_postgres_triggers,
list_slot_name, set_enabled, test_postgres_connection, update_postgres_trigger, Postgres,
Relations,
};
use windmill_common::{
db::UserDB,
error::{to_anyhow, Error, Result},
utils::empty_as_none,
};
mod bool;
mod converter;
mod handler;
mod hex;
mod mapper;
mod relation;
mod replication_message;
mod trigger;
pub use handler::PublicationData;
pub use trigger::start_database;
const ERROR_REPLICATION_SLOT_NOT_EXISTS: &str = r#"The replication slot associated with this trigger no longer exists. Recreate a new replication slot or select an existing one in the advanced tab, or delete and recreate a new trigger"#;
@@ -88,6 +69,19 @@ fn build_tls_connector(
)))
}
#[derive(FromRow, Serialize, Deserialize, Debug)]
pub struct Postgres {
pub user: String,
pub password: String,
pub host: String,
pub port: Option<u16>,
pub dbname: String,
#[serde(default)]
pub sslmode: String,
#[serde(default, deserialize_with = "empty_as_none")]
pub root_certificate_pem: Option<String>,
}
pub async fn get_raw_postgres_connection(
database: &Postgres,
logical_mode: bool,
@@ -174,124 +168,65 @@ pub async fn get_default_pg_connection(
get_pg_connection(authed, user_db, db, postgres_resource_path, w_id, false).await
}
pub async fn create_logical_replication_slot(tx: &Client, slot_name: &str) -> Result<()> {
tx.execute(
&format!("SELECT * FROM pg_create_logical_replication_slot($1, 'pgoutput')"),
&[&slot_name],
)
.await
.map_err(to_anyhow)?;
Ok(())
#[derive(FromRow, Deserialize, Serialize, Debug)]
pub struct PostgresTrigger {
pub path: String,
pub script_path: String,
pub is_flow: bool,
pub workspace_id: String,
pub edited_by: String,
pub email: String,
pub edited_at: chrono::DateTime<chrono::Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_perms: Option<serde_json::Value>,
pub postgres_resource_path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub server_id: Option<String>,
pub replication_slot_name: String,
pub publication_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub enabled: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<sqlx::types::Json<HashMap<String, Box<RawValue>>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry: Option<sqlx::types::Json<windmill_common::flows::Retry>>,
}
async fn check_if_valid_publication_for_postgres_version(
pg_connection: &Client,
table_to_track: Option<&[Relations]>,
) -> Result<bool> {
let postgres_version = get_postgres_version_internal(pg_connection).await?;
pub async fn drop_logical_replication_slot(pg_connection: &Client, slot_name: &str) -> Result<()> {
let row = pg_connection
.query_opt(
r#"
SELECT
active_pid
FROM
pg_replication_slots
WHERE
slot_name = $1
"#,
&[&slot_name],
)
.await
.map_err(to_anyhow)?;
let pg_14 = postgres_version.starts_with("14");
if pg_14 {
let unsupported_publication = table_to_track
.and_then(|relations| {
relations.iter().find(|relation| {
let invalid_relation = relation.table_to_track.iter().find(|table_to_track| {
table_to_track.where_clause.is_some()
|| table_to_track.columns_name.is_some()
});
let active_pid = row.map(|r| r.get::<_, Option<i32>>(0)).flatten();
relation.table_to_track.is_empty() || invalid_relation.is_some()
})
})
.is_some();
if unsupported_publication {
return Err(Error::BadRequest(
"Your PostgreSQL database is running version 14, which does not support the following publication features: \
- WHERE clause filtering, \
- selective column tracking, and \
- tracking all tables within a schema.\n\
These features are only available in PostgreSQL 15 and above.".to_string(),
));
}
}
Ok(pg_14)
}
pub async fn create_pg_publication(
pg_connection: &Client,
publication_name: &str,
table_to_track: Option<&[Relations]>,
transaction_to_track: &[String],
) -> Result<()> {
let pg_14 =
check_if_valid_publication_for_postgres_version(pg_connection, table_to_track).await?;
let mut query = String::from("CREATE PUBLICATION ");
query.push_str(&quote_identifier(publication_name));
match table_to_track {
Some(database_component) if !database_component.is_empty() => {
query.push_str(" FOR");
let mut first = true;
for (i, schema) in database_component.iter().enumerate() {
if schema.table_to_track.is_empty() {
query.push_str(" TABLES IN SCHEMA ");
query.push_str(&quote_identifier(&schema.schema_name));
} else {
if pg_14 && first {
query.push_str(" TABLE ONLY ");
first = false
} else if !pg_14 {
query.push_str(" TABLE ONLY ");
}
for (j, table) in schema.table_to_track.iter().enumerate() {
let table_name = quote_identifier(&table.table_name);
let schema_name = quote_identifier(&schema.schema_name);
let full_name = format!("{}.{}", &schema_name, &table_name);
query.push_str(&full_name);
if let Some(columns) = table.columns_name.as_ref() {
query.push_str(" (");
let columns = columns
.iter()
.map(|column| quote_identifier(column))
.join(", ");
query.push_str(&columns);
query.push_str(")");
}
if let Some(where_clause) = &table.where_clause {
query.push_str(" WHERE (");
query.push_str(where_clause);
query.push(')');
}
if j + 1 != schema.table_to_track.len() {
query.push_str(", ");
}
}
}
if i < database_component.len() - 1 {
query.push_str(", ");
}
}
}
_ => {
query.push_str(" FOR ALL TABLES ");
}
};
if !transaction_to_track.is_empty() {
let transactions = || transaction_to_track.iter().join(", ");
query.push_str(" WITH (publish = '");
query.push_str(&transactions());
query.push_str("');");
if let Some(pid) = active_pid {
pg_connection
.execute("SELECT pg_terminate_backend($1)", &[&pid])
.await
.map_err(to_anyhow)?;
}
pg_connection
.execute(&query, &[])
.execute("SELECT pg_drop_replication_slot($1)", &[&slot_name])
.await
.map_err(to_anyhow)?;
Ok(())
}
@@ -307,106 +242,3 @@ pub async fn drop_publication(pg_connection: &Client, publication_name: &str) ->
Ok(())
}
pub fn generate_random_string() -> String {
let timestamp = Utc::now().timestamp_millis().to_string();
let mut rng = rand::rng();
let charset = "abcdefghijklmnopqrstuvwxyz0123456789";
let random_part = (0..10)
.map(|_| {
charset
.chars()
.nth(rng.random_range(0..charset.len()))
.unwrap()
})
.collect::<String>();
format!("{}_{}", timestamp, random_part)
}
fn publication_service() -> Router {
Router::new()
.route("/get/:publication_name/*path", get(get_publication_info))
.route("/create/:publication_name/*path", post(create_publication))
.route("/update/:publication_name/*path", post(alter_publication))
.route(
"/delete/:publication_name/*path",
delete(delete_publication),
)
.route("/list/*path", get(list_database_publication))
}
fn slot_service() -> Router {
Router::new()
.route("/list/*path", get(list_slot_name))
.route("/create/*path", post(create_slot))
.route("/delete/*path", delete(drop_slot_name))
}
fn postgres_service() -> Router {
Router::new().route("/version/*path", get(get_postgres_version))
}
pub fn workspaced_service() -> Router {
Router::new()
.route("/test", post(test_postgres_connection))
.route("/create", post(create_postgres_trigger))
.route("/list", get(list_postgres_triggers))
.route("/get/*path", get(get_postgres_trigger))
.route("/update/*path", post(update_postgres_trigger))
.route("/delete/*path", delete(delete_postgres_trigger))
.route("/exists/*path", get(exists_postgres_trigger))
.route("/setenabled/*path", post(set_enabled))
.route("/get_template_script/:id", get(get_template_script))
.route("/create_template_script", post(create_template_script))
.route(
"/is_valid_postgres_configuration/*path",
get(is_database_in_logical_level),
)
.nest("/publication", publication_service())
.nest("/slot", slot_service())
.nest("/postgres", postgres_service())
}
async fn run_job(
payload: HashMap<String, Box<RawValue>>,
db: &DB,
trigger: &PostgresTrigger,
) -> anyhow::Result<()> {
let args = PostgresTrigger::build_job_args(
&trigger.script_path,
trigger.is_flow,
&trigger.workspace_id,
db,
payload,
HashMap::new(),
)
.await?;
let authed = fetch_api_authed(
trigger.edited_by.clone(),
trigger.email.clone(),
&trigger.workspace_id,
db,
Some(format!("postgres-{}", trigger.path)),
)
.await?;
trigger_runnable(
db,
None,
authed,
&trigger.workspace_id,
&trigger.script_path,
trigger.is_flow,
args,
trigger.retry.as_ref(),
trigger.error_handler_path.as_deref(),
trigger.error_handler_args.as_ref(),
format!("postgres_trigger/{}", trigger.path),
)
.await?;
Ok(())
}
@@ -9,10 +9,9 @@ use crate::{
LogicalReplicationMessage::{Begin, Commit, Delete, Insert, Relation, Type, Update},
ReplicationMessage,
},
run_job,
},
resources::try_get_resource_from_db_as,
trigger_helpers::TriggerJobArgs,
trigger_helpers::{trigger_runnable, TriggerJobArgs},
users::fetch_api_authed,
};
@@ -36,10 +35,9 @@ use windmill_common::{
};
use super::{
drop_publication, get_default_pg_connection, get_raw_postgres_connection,
handler::{drop_logical_replication_slot, Postgres, PostgresTrigger},
replication_message::PrimaryKeepAliveBody,
Error, ERROR_PUBLICATION_NAME_NOT_EXISTS, ERROR_REPLICATION_SLOT_NOT_EXISTS,
drop_logical_replication_slot, drop_publication, get_default_pg_connection,
get_raw_postgres_connection, replication_message::PrimaryKeepAliveBody, Error, Postgres,
PostgresTrigger, ERROR_PUBLICATION_NAME_NOT_EXISTS, ERROR_REPLICATION_SLOT_NOT_EXISTS,
};
pub struct LogicalReplicationSettings {
@@ -350,6 +348,48 @@ impl TriggerJobArgs<HashMap<String, Box<RawValue>>> for PostgresTrigger {
}
}
async fn run_job(
payload: HashMap<String, Box<RawValue>>,
db: &DB,
trigger: &PostgresTrigger,
) -> anyhow::Result<()> {
let args = PostgresTrigger::build_job_args(
&trigger.script_path,
trigger.is_flow,
&trigger.workspace_id,
db,
payload,
HashMap::new(),
)
.await?;
let authed = fetch_api_authed(
trigger.edited_by.clone(),
trigger.email.clone(),
&trigger.workspace_id,
db,
Some(format!("postgres-{}", trigger.path)),
)
.await?;
trigger_runnable(
db,
None,
authed,
&trigger.workspace_id,
&trigger.script_path,
trigger.is_flow,
args,
trigger.retry.as_ref(),
trigger.error_handler_path.as_deref(),
trigger.error_handler_args.as_ref(),
format!("postgres_trigger/{}", trigger.path),
)
.await?;
Ok(())
}
struct PgInfo<'a> {
postgres_resource_path: &'a str,
publication_name: &'a str,
+6 -1
View File
@@ -1270,7 +1270,12 @@ async fn update_resource_type(
feature = "mqtt_trigger",
all(
feature = "enterprise",
any(feature = "sqs_trigger", feature = "gcp_trigger")
any(
feature = "sqs_trigger",
feature = "gcp_trigger",
feature = "kafka",
feature = "nats"
)
)
))]
pub async fn try_get_resource_from_db_as<T>(
+2 -3
View File
@@ -10,9 +10,8 @@ use crate::{
auth::AuthCache,
db::{ApiAuthed, DB},
schedule::clear_schedule,
triggers::{
get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail,
},
triggers::{get_triggers_count_internal, TriggersCount},
auth::{list_tokens_internal, TruncatedTokenWithEmail},
users::{maybe_refresh_folders, require_owner_of_path},
utils::{check_scopes, WithStarredInfoQuery},
webhook_util::{WebhookMessage, WebhookShared},
+3 -8
View File
@@ -5,17 +5,10 @@ pub use crate::sqs_triggers_ee::*;
#[cfg(not(feature = "private"))]
use crate::db::DB;
#[cfg(not(feature = "private"))]
use axum::Router;
#[cfg(not(feature = "private"))]
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "private"))]
use windmill_common::auth::aws::AwsAuthResourceType;
#[cfg(not(feature = "private"))]
pub fn workspaced_service() -> Router {
Router::new()
}
#[cfg(not(feature = "private"))]
pub fn start_sqs(_db: DB, mut _killpill_rx: tokio::sync::broadcast::Receiver<()>) -> () {
// implementation is not open source
@@ -43,7 +36,9 @@ pub struct SqsTrigger {
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<sqlx::types::Json<std::collections::HashMap<String, Box<serde_json::value::RawValue>>>>,
pub error_handler_args: Option<
sqlx::types::Json<std::collections::HashMap<String, Box<serde_json::value::RawValue>>>,
>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry: Option<sqlx::types::Json<windmill_common::flows::Retry>>,
}
@@ -60,6 +60,7 @@ pub enum RunnableId {
}
impl RunnableId {
#[allow(dead_code)]
pub fn from_script_hash(hash: ScriptHash) -> Self {
Self::ScriptId(ScriptId::ScriptHash(hash))
}
@@ -78,6 +79,7 @@ impl RunnableId {
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[allow(unused)]
pub enum ScriptId {
ScriptPath(String),
ScriptHash(ScriptHash),
-249
View File
@@ -1,249 +0,0 @@
use axum::Json;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use windmill_common::error::JsonResult;
use crate::db::DB;
#[derive(Serialize, Deserialize, Debug)]
pub struct TriggerPrimarySchedule {
schedule: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct TriggersCount {
primary_schedule: Option<TriggerPrimarySchedule>,
schedule_count: i64,
http_routes_count: i64,
webhook_count: i64,
email_count: i64,
websocket_count: i64,
kafka_count: i64,
nats_count: i64,
postgres_count: i64,
mqtt_count: i64,
sqs_count: i64,
gcp_count: i64,
}
pub(crate) async fn get_triggers_count_internal(
db: &DB,
w_id: &str,
path: &str,
is_flow: bool,
) -> JsonResult<TriggersCount> {
let primary_schedule = sqlx::query_scalar!(
"SELECT schedule FROM schedule WHERE path = $1 AND script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_optional(db)
.await?;
let schedule_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM schedule WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let http_routes_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM http_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let websocket_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM websocket_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let kafka_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM kafka_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let nats_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM nats_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let postgres_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM postgres_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let mqtt_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM mqtt_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let sqs_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM sqs_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let gcp_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM gcp_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);
let webhook_count = (if is_flow {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]",
w_id,
path,
)
} else {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:' || $2]::text[]",
w_id,
path,
)
}).fetch_one(db)
.await?
.unwrap_or(0);
let email_count = (if is_flow {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]",
w_id,
path,
)
} else {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]",
w_id,
path,
)
}).fetch_one(db)
.await?
.unwrap_or(0);
Ok(Json(TriggersCount {
primary_schedule: primary_schedule.map(|s| TriggerPrimarySchedule { schedule: s }),
schedule_count,
http_routes_count,
webhook_count,
email_count,
websocket_count,
kafka_count,
nats_count,
postgres_count,
mqtt_count,
gcp_count,
sqs_count,
}))
}
#[derive(FromRow, Serialize)]
pub struct TruncatedTokenWithEmail {
pub label: Option<String>,
pub token_prefix: Option<String>,
pub expiration: Option<chrono::DateTime<chrono::Utc>>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub last_used_at: chrono::DateTime<chrono::Utc>,
pub scopes: Option<Vec<String>>,
pub email: Option<String>,
}
pub async fn list_tokens_internal(
db: &DB,
w_id: &str,
path: &str,
is_flow: bool,
) -> JsonResult<Vec<TruncatedTokenWithEmail>> {
let tokens = if is_flow {
sqlx::query_as!(
TruncatedTokenWithEmail,
r#"
SELECT label,
concat(substring(token for 10)) AS token_prefix,
expiration,
created_at,
last_used_at,
scopes,
email
FROM token
WHERE workspace_id = $1
AND (
scopes @> ARRAY['jobs:run:flows:' || $2]::text[]
OR scopes @> ARRAY['run:flow/' || $2]::text[]
)
"#,
w_id,
path
)
.fetch_all(db)
.await?
} else {
sqlx::query_as!(
TruncatedTokenWithEmail,
r#"
SELECT label,
concat(substring(token for 10)) AS token_prefix,
expiration,
created_at,
last_used_at,
scopes,
email
FROM token
WHERE workspace_id = $1
AND (
scopes @> ARRAY['jobs:run:scripts:' || $2]::text[]
OR scopes @> ARRAY['run:script/' || $2]::text[]
)
"#,
w_id,
path
)
.fetch_all(db)
.await?
};
Ok(Json(tokens))
}
@@ -0,0 +1,64 @@
#[cfg(feature = "private")]
pub use super::handler_ee::*;
#[cfg(not(feature = "private"))]
use {
super::GcpTrigger,
crate::{
db::{ApiAuthed, DB},
triggers::{TriggerCrud, TriggerData},
},
axum::async_trait,
sqlx::PgConnection,
windmill_common::error::{Error, Result},
windmill_git_sync::DeployedObject,
};
#[cfg(not(feature = "private"))]
#[async_trait]
impl TriggerCrud for GcpTrigger {
type Trigger = ();
type TriggerConfig = ();
type TriggerConfigRequest = ();
type TestConnectionConfig = ();
const TABLE_NAME: &'static str = "";
const TRIGGER_TYPE: &'static str = "";
const SUPPORTS_ENABLED: bool = false;
const SUPPORTS_SERVER_STATE: bool = false;
const SUPPORTS_TEST_CONNECTION: bool = false;
const ROUTE_PREFIX: &'static str = "/gcp_triggers";
const DEPLOYMENT_NAME: &'static str = "";
const IS_CLOUD_HOSTED: bool = false;
fn get_deployed_object(path: String) -> DeployedObject {
DeployedObject::GcpTrigger { path }
}
async fn create_trigger(
&self,
_db: &DB,
_executor: &mut PgConnection,
_authed: &ApiAuthed,
_w_id: &str,
_trigger: TriggerData<Self::TriggerConfigRequest>,
) -> Result<()> {
Err(Error::BadRequest(
"GCP triggers are not available in open source version".to_string(),
))
}
async fn update_trigger(
&self,
_db: &DB,
_executor: &mut PgConnection,
_authed: &ApiAuthed,
_workspace_id: &str,
_path: &str,
_trigger: TriggerData<Self::TriggerConfigRequest>,
) -> Result<()> {
Err(Error::BadRequest(
"GCP triggers are not available in open source version".to_string(),
))
}
}
@@ -0,0 +1,11 @@
#[cfg(feature = "private")]
mod handler_ee;
pub mod handler_oss;
#[cfg(feature = "private")]
mod mod_ee;
#[cfg(feature = "private")]
pub use mod_ee::*;
#[derive(Clone, Copy)]
pub struct GcpTrigger;

Some files were not shown because too many files have changed in this diff Show More