mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 00:02:19 +00:00
feat: extend get_draft overlay to flow, app, resource, variable, schedule, triggers
This commit is contained in:
@@ -20,6 +20,7 @@ use windmill_api_auth::{
|
||||
};
|
||||
use windmill_common::workspaces::{check_deploy_rules, RuleCheckResult};
|
||||
use windmill_common::{
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
utils::{WithStarredInfoQuery, HTTP_CLIENT},
|
||||
webhook::{WebhookMessage, WebhookShared},
|
||||
DB,
|
||||
@@ -1357,16 +1358,25 @@ async fn get_deployment_status(
|
||||
Ok(Json(deployment_status))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct GetFlowByPathQuery {
|
||||
#[serde(flatten)]
|
||||
starred: WithStarredInfoQuery,
|
||||
#[serde(flatten)]
|
||||
draft: WithDraftQuery,
|
||||
}
|
||||
|
||||
async fn get_flow_by_path(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
Query(query): Query<WithStarredInfoQuery>,
|
||||
) -> JsonResult<FlowWithStarred> {
|
||||
Query(query): Query<GetFlowByPathQuery>,
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("flows:read:{}", path))?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let flow_o = if query.with_starred_info.unwrap_or(false) {
|
||||
let flow_o = if query.starred.with_starred_info.unwrap_or(false) {
|
||||
sqlx::query_as::<_, FlowWithStarred>(
|
||||
r#"
|
||||
SELECT
|
||||
@@ -1403,7 +1413,7 @@ async fn get_flow_by_path(
|
||||
"#,
|
||||
)
|
||||
.bind(path)
|
||||
.bind(w_id)
|
||||
.bind(&w_id)
|
||||
.bind(&authed.username)
|
||||
.fetch_optional(&mut *tx)
|
||||
.await?
|
||||
@@ -1439,7 +1449,7 @@ async fn get_flow_by_path(
|
||||
"#,
|
||||
)
|
||||
.bind(path)
|
||||
.bind(w_id)
|
||||
.bind(&w_id)
|
||||
.fetch_optional(&mut *tx)
|
||||
.await?
|
||||
};
|
||||
@@ -1447,7 +1457,17 @@ async fn get_flow_by_path(
|
||||
tx.commit().await?;
|
||||
|
||||
let flow = not_found_if_none(flow_o, "Flow", path)?;
|
||||
Ok(Json(flow))
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&w_id,
|
||||
&authed.email,
|
||||
UserDraftItemKind::Flow,
|
||||
path,
|
||||
query.draft.get_draft,
|
||||
flow,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
async fn exists_flow_by_path(
|
||||
|
||||
@@ -25,6 +25,7 @@ use windmill_common::{
|
||||
db::UserDB,
|
||||
error::{Error, JsonResult, Result},
|
||||
schedule::Schedule,
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
utils::{
|
||||
escape_ilike_pattern, not_found_if_none, paginate, Pagination, ScheduleType, StripPath,
|
||||
},
|
||||
@@ -808,8 +809,10 @@ async fn list_schedule_with_jobs(
|
||||
async fn get_schedule(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<Schedule> {
|
||||
Query(q): Query<WithDraftQuery>,
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("schedules:read:{}", path))?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
@@ -817,7 +820,17 @@ async fn get_schedule(
|
||||
let schedule_o = windmill_queue::schedule::get_schedule_opt(&mut *tx, &w_id, path).await?;
|
||||
let schedule = not_found_if_none(schedule_o, "Schedule", path)?;
|
||||
tx.commit().await?;
|
||||
Ok(Json(schedule))
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&w_id,
|
||||
&authed.email,
|
||||
UserDraftItemKind::TriggerSchedule,
|
||||
path,
|
||||
q.get_draft,
|
||||
schedule,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
async fn exists_schedule(
|
||||
|
||||
@@ -5324,13 +5324,16 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: variable
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ListableVariable"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/ListableVariable"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/variables/get_value/{path}:
|
||||
get:
|
||||
@@ -6647,13 +6650,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: resource
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Resource"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/ListableResource"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/resources/get_value_interpolated/{path}:
|
||||
get:
|
||||
@@ -9676,13 +9682,16 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: flow details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Flow"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/Flow"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/flows/deployment_status/p/{path}:
|
||||
get:
|
||||
@@ -10459,13 +10468,16 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: app details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AppWithLastVersion"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/AppWithLastVersion"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/apps/get/lite/{path}:
|
||||
get:
|
||||
@@ -13604,13 +13616,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: schedule deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Schedule"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/Schedule"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/schedules/exists/{path}:
|
||||
get:
|
||||
@@ -13893,13 +13908,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HttpTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/HttpTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/http_triggers/list:
|
||||
get:
|
||||
@@ -14099,13 +14117,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: websocket trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WebsocketTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/WebsocketTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/websocket_triggers/list:
|
||||
get:
|
||||
@@ -14304,13 +14325,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: kafka trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/KafkaTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/KafkaTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/kafka_triggers/list:
|
||||
get:
|
||||
@@ -14550,13 +14574,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: nats trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/NatsTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/NatsTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/nats_triggers/list:
|
||||
get:
|
||||
@@ -14750,13 +14777,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: sqs trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SqsTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/SqsTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/sqs_triggers/list:
|
||||
get:
|
||||
@@ -15543,13 +15573,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: mqtt trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MqttTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/MqttTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/mqtt_triggers/list:
|
||||
get:
|
||||
@@ -15743,13 +15776,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: gcp trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GcpTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/GcpTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/gcp_triggers/list:
|
||||
get:
|
||||
@@ -16010,13 +16046,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: azure trigger
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AzureTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/AzureTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/azure_triggers/list:
|
||||
get:
|
||||
@@ -16553,13 +16592,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: get postgres trigger
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/PostgresTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/PostgresTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/postgres_triggers/list:
|
||||
get:
|
||||
@@ -16753,13 +16795,16 @@ paths:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- $ref: "#/components/parameters/GetDraft"
|
||||
responses:
|
||||
"200":
|
||||
description: email trigger retrieved
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EmailTrigger"
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/EmailTrigger"
|
||||
- $ref: "#/components/schemas/UserDraftOverlay"
|
||||
|
||||
/w/{workspace}/email_triggers/list:
|
||||
get:
|
||||
|
||||
@@ -58,6 +58,7 @@ use windmill_common::{
|
||||
get_payload_tag_from_prefixed_path, resolve_delete_after_secs, schedule_job_deletion,
|
||||
JobPayload, RawCode,
|
||||
},
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
users::username_to_permissioned_as,
|
||||
utils::{
|
||||
http_get_from_hub, not_found_if_none, paginate, query_elems_from_hub, require_admin,
|
||||
@@ -535,17 +536,26 @@ async fn get_raw_app_data(
|
||||
// Ok(Json(version))
|
||||
// }
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct GetAppQuery {
|
||||
#[serde(flatten)]
|
||||
starred: WithStarredInfoQuery,
|
||||
#[serde(flatten)]
|
||||
draft: WithDraftQuery,
|
||||
}
|
||||
|
||||
async fn get_app(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
Query(query): Query<WithStarredInfoQuery>,
|
||||
) -> JsonResult<AppWithLastVersionAndStarred> {
|
||||
Query(query): Query<GetAppQuery>,
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("apps:read:{}", path))?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
let app_o = if query.with_starred_info.unwrap_or(false) {
|
||||
let app_o = if query.starred.with_starred_info.unwrap_or(false) {
|
||||
sqlx::query_as::<_, AppWithLastVersionAndStarred>(
|
||||
"SELECT app.id, app.path, app.summary, app.versions, app.policy, app.custom_path,
|
||||
app.extra_perms, app_version.value,
|
||||
@@ -554,9 +564,9 @@ async fn get_app(
|
||||
JOIN app_version
|
||||
ON app_version.id = app.versions[array_upper(app.versions, 1)]
|
||||
LEFT JOIN favorite
|
||||
ON favorite.favorite_kind = 'app'
|
||||
AND favorite.workspace_id = app.workspace_id
|
||||
AND favorite.path = app.path
|
||||
ON favorite.favorite_kind = 'app'
|
||||
AND favorite.workspace_id = app.workspace_id
|
||||
AND favorite.path = app.path
|
||||
AND favorite.usr = $3
|
||||
WHERE app.path = $1 AND app.workspace_id = $2",
|
||||
)
|
||||
@@ -581,7 +591,24 @@ async fn get_app(
|
||||
tx.commit().await?;
|
||||
|
||||
let app = not_found_if_none(app_o, "App", path)?;
|
||||
Ok(Json(app))
|
||||
// The same `app` table backs both regular apps and raw apps; the
|
||||
// `raw_app` flag on the row picks which draft kind to look up.
|
||||
let kind = if app.app.raw_app {
|
||||
UserDraftItemKind::RawApp
|
||||
} else {
|
||||
UserDraftItemKind::App
|
||||
};
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&w_id,
|
||||
&authed.email,
|
||||
kind,
|
||||
path,
|
||||
query.draft.get_draft,
|
||||
app,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
async fn get_app_lite(
|
||||
|
||||
@@ -43,6 +43,7 @@ use windmill_common::{
|
||||
db::{DbWithOptAuthed, UserDB},
|
||||
error::{self, Error, JsonResult, Result},
|
||||
get_database_url,
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
utils::{not_found_if_none, paginate, require_admin, Pagination, StripPath},
|
||||
variables,
|
||||
worker::{CLOUD_HOSTED, WINDMILL_DIR},
|
||||
@@ -360,7 +361,8 @@ async fn get_resource(
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<ListableResource> {
|
||||
Query(q): Query<WithDraftQuery>,
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("resources:read:{}", path))?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
@@ -391,7 +393,17 @@ async fn get_resource(
|
||||
explain_resource_perm_error(&path, &w_id, &db, &authed).await?;
|
||||
}
|
||||
let resource = not_found_if_none(resource_o, "Resource", path)?;
|
||||
Ok(Json(resource))
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&w_id,
|
||||
&authed.email,
|
||||
UserDraftItemKind::Resource,
|
||||
path,
|
||||
q.get_draft,
|
||||
resource,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
async fn exists_resource(
|
||||
|
||||
@@ -35,6 +35,7 @@ use windmill_common::{
|
||||
db::{DbWithOptAuthed, UserDB},
|
||||
error::{Error, JsonResult, Result},
|
||||
scripts::ScriptHash,
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
utils::{not_found_if_none, paginate, Pagination, StripPath, WarnAfterExt},
|
||||
variables::{
|
||||
build_crypt, get_reserved_variables, ContextualVariable, CreateVariable, ListableVariable,
|
||||
@@ -207,6 +208,8 @@ async fn list_variables(
|
||||
struct GetVariableQuery {
|
||||
decrypt_secret: Option<bool>,
|
||||
include_encrypted: Option<bool>,
|
||||
#[serde(flatten)]
|
||||
draft: WithDraftQuery,
|
||||
}
|
||||
|
||||
async fn get_variable(
|
||||
@@ -215,7 +218,7 @@ async fn get_variable(
|
||||
Extension(db): Extension<DB>,
|
||||
Query(q): Query<GetVariableQuery>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<ListableVariable> {
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || format!("variables:read:{}", path))?;
|
||||
|
||||
@@ -302,7 +305,17 @@ async fn get_variable(
|
||||
variable
|
||||
};
|
||||
|
||||
Ok(Json(r))
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&w_id,
|
||||
&authed.email,
|
||||
UserDraftItemKind::Variable,
|
||||
path,
|
||||
q.draft.get_draft,
|
||||
r,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@@ -16,6 +16,7 @@ use windmill_api_auth::{check_scopes, ApiAuthed};
|
||||
use windmill_common::{
|
||||
db::UserDB,
|
||||
error::{Error, JsonResult, Result},
|
||||
user_drafts::{maybe_overlay_draft, UserDraftItemKind, WithDraftOverlay, WithDraftQuery},
|
||||
utils::{paginate, Pagination, StripPath},
|
||||
worker::CLOUD_HOSTED,
|
||||
DB,
|
||||
@@ -106,6 +107,29 @@ pub trait TriggerCrud: Send + Sync + 'static {
|
||||
&Self::ROUTE_PREFIX[1..]
|
||||
}
|
||||
|
||||
/// `UserDraftItemKind` for the per-user `draft` table lookup. Defaults
|
||||
/// to derive from `TRIGGER_TYPE` so each impl gets it for free as long
|
||||
/// as the string matches the canonical kind (e.g. `"http"` →
|
||||
/// `TriggerHttp`). Override only when the mapping isn't 1:1.
|
||||
fn user_draft_item_kind() -> UserDraftItemKind {
|
||||
match Self::TRIGGER_TYPE {
|
||||
"http" => UserDraftItemKind::TriggerHttp,
|
||||
"websocket" => UserDraftItemKind::TriggerWebsocket,
|
||||
"kafka" => UserDraftItemKind::TriggerKafka,
|
||||
"nats" => UserDraftItemKind::TriggerNats,
|
||||
"sqs" => UserDraftItemKind::TriggerSqs,
|
||||
"mqtt" => UserDraftItemKind::TriggerMqtt,
|
||||
"gcp" => UserDraftItemKind::TriggerGcp,
|
||||
"azure" => UserDraftItemKind::TriggerAzure,
|
||||
"postgres" => UserDraftItemKind::TriggerPostgres,
|
||||
"email" => UserDraftItemKind::TriggerEmail,
|
||||
other => panic!(
|
||||
"TriggerCrud impl with TRIGGER_TYPE = {:?} must override user_draft_item_kind()",
|
||||
other
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_trigger(
|
||||
&self,
|
||||
db: &DB,
|
||||
@@ -551,8 +575,10 @@ async fn get_trigger<T: TriggerCrud>(
|
||||
Extension(handler): Extension<Arc<T>>,
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((workspace_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<T::Trigger> {
|
||||
Query(q): Query<WithDraftQuery>,
|
||||
) -> JsonResult<WithDraftOverlay> {
|
||||
let path = path.to_path();
|
||||
check_scopes(&authed, || {
|
||||
format!("{}:read:{}", T::scope_domain_name(), &path)
|
||||
@@ -565,7 +591,17 @@ async fn get_trigger<T: TriggerCrud>(
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(Json(trigger))
|
||||
let overlay = maybe_overlay_draft(
|
||||
&db,
|
||||
&workspace_id,
|
||||
&authed.email,
|
||||
T::user_draft_item_kind(),
|
||||
path,
|
||||
q.get_draft,
|
||||
trigger,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(overlay))
|
||||
}
|
||||
|
||||
async fn update_trigger<T: TriggerCrud>(
|
||||
|
||||
@@ -219,9 +219,7 @@
|
||||
const s: ResourceState = {
|
||||
path: '',
|
||||
description: '',
|
||||
args: (defaultValues && Object.keys(defaultValues).length > 0
|
||||
? defaultValues
|
||||
: {}) as any,
|
||||
args: (defaultValues && Object.keys(defaultValues).length > 0 ? defaultValues : {}) as any,
|
||||
labels: undefined,
|
||||
wsSpecific: false
|
||||
}
|
||||
@@ -238,9 +236,12 @@
|
||||
if (ws in states) return
|
||||
untrack(() => {
|
||||
Promise.all([
|
||||
ResourceService.getResource({ workspace: ws, path: initialPath }),
|
||||
ResourceService.getResource({ workspace: ws, path: initialPath, getDraft: true }),
|
||||
getUserExt(ws)
|
||||
]).then(([r, user]) => {
|
||||
if (r.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
fetchedResources[ws] = r
|
||||
fetchedRev[ws] = r.edited_at
|
||||
const s: ResourceState = {
|
||||
|
||||
@@ -154,9 +154,17 @@
|
||||
if (ws in states) return
|
||||
untrack(() => {
|
||||
Promise.all([
|
||||
VariableService.getVariable({ workspace: ws, path: p, decryptSecret: false }),
|
||||
VariableService.getVariable({
|
||||
workspace: ws,
|
||||
path: p,
|
||||
decryptSecret: false,
|
||||
getDraft: true
|
||||
}),
|
||||
getUserExt(ws)
|
||||
]).then(([v, user]) => {
|
||||
if (v.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
fetchedRev[ws] = v.edited_at
|
||||
const s: VariableState = {
|
||||
path: v.path,
|
||||
|
||||
@@ -1081,10 +1081,7 @@ async function readWorkspaceItem(
|
||||
true
|
||||
)
|
||||
case 'resource':
|
||||
return resourceToItem(
|
||||
(await ResourceService.getResource({ workspace, path })) as ListableResource,
|
||||
true
|
||||
)
|
||||
return resourceToItem(await ResourceService.getResource({ workspace, path }), true)
|
||||
case 'variable':
|
||||
// Never expose the value, even when read directly. Pass decryptSecret=false
|
||||
// to avoid materializing secret values server-side.
|
||||
@@ -2568,9 +2565,10 @@ async function patchAppFile(
|
||||
}
|
||||
|
||||
async function recomputeAppPolicy(value: AppDraftValue): Promise<void> {
|
||||
const policy = (await updateRawAppPolicy(value.runnables as any, value.policy as any)) as NonNullable<
|
||||
AppDraftValue['policy']
|
||||
>
|
||||
const policy = (await updateRawAppPolicy(
|
||||
value.runnables as any,
|
||||
value.policy as any
|
||||
)) as NonNullable<AppDraftValue['policy']>
|
||||
if (!policy.execution_mode) {
|
||||
policy.execution_mode = 'publisher'
|
||||
}
|
||||
@@ -3045,7 +3043,8 @@ export function prepareGlobalUserMessage(
|
||||
(context) => context.type === 'workspace_script' || context.type === 'workspace_flow'
|
||||
)
|
||||
const activeEditor =
|
||||
options.activeEditor ?? (options.workspace ? getActiveGlobalEditorContext(options.workspace) : undefined)
|
||||
options.activeEditor ??
|
||||
(options.workspace ? getActiveGlobalEditorContext(options.workspace) : undefined)
|
||||
let content = ''
|
||||
|
||||
if (activeEditor) {
|
||||
|
||||
@@ -191,8 +191,12 @@
|
||||
try {
|
||||
const s = await AzureTriggerService.getAzureTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
} catch (error) {
|
||||
sendUserToast(`Could not load Azure trigger: ${error.body}`, true)
|
||||
|
||||
@@ -212,8 +212,12 @@
|
||||
} else {
|
||||
const s = await EmailTriggerService.getEmailTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
|
||||
@@ -195,8 +195,12 @@
|
||||
try {
|
||||
const s = await GcpTriggerService.getGcpTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
} catch (error) {
|
||||
sendUserToast(`Could not load GCP Pub/Sub trigger: ${error.body}`, true)
|
||||
|
||||
@@ -345,8 +345,12 @@
|
||||
} else {
|
||||
const s = await HttpTriggerService.getHttpTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
|
||||
@@ -251,8 +251,12 @@
|
||||
} else {
|
||||
const s = await KafkaTriggerService.getKafkaTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +251,12 @@
|
||||
} else {
|
||||
const s = await MqttTriggerService.getMqttTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -233,8 +233,12 @@
|
||||
} else {
|
||||
const s = await NatsTriggerService.getNatsTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,8 +377,12 @@
|
||||
} else {
|
||||
const s = await PostgresTriggerService.getPostgresTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
|
||||
const publication_data = await PostgresTriggerService.getPostgresPublication({
|
||||
path: s.postgres_resource_path,
|
||||
|
||||
@@ -285,10 +285,15 @@
|
||||
try {
|
||||
let s: Schedule | undefined
|
||||
if (schedule_path) {
|
||||
s = await ScheduleService.getSchedule({
|
||||
const resp = await ScheduleService.getSchedule({
|
||||
workspace: $workspaceStore!,
|
||||
path: schedule_path
|
||||
path: schedule_path,
|
||||
getDraft: true
|
||||
})
|
||||
if (resp.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
s = resp
|
||||
initNewPath = true
|
||||
} else if (defaultValues) {
|
||||
s = defaultValues
|
||||
@@ -451,8 +456,12 @@
|
||||
try {
|
||||
const s = await ScheduleService.getSchedule({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
await loadScheduleCfg(s)
|
||||
} catch (err) {
|
||||
sendUserToast(`Could not load schedule: ${err}`, true)
|
||||
|
||||
@@ -228,8 +228,12 @@
|
||||
} else {
|
||||
const s = await SqsTriggerService.getSqsTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -308,8 +308,12 @@
|
||||
} else {
|
||||
const s = await WebsocketTriggerService.getWebsocketTrigger({
|
||||
workspace: $workspaceStore!,
|
||||
path: initialPath
|
||||
path: initialPath,
|
||||
getDraft: true
|
||||
})
|
||||
if (s?.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
loadTriggerConfig(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,9 +90,13 @@
|
||||
const tok = ++loadAppToken
|
||||
const backendApp = await AppService.getAppByPath({
|
||||
path: page.params.path ?? '',
|
||||
workspace: $workspaceStore!
|
||||
workspace: $workspaceStore!,
|
||||
getDraft: true
|
||||
})
|
||||
if (tok !== loadAppToken) return
|
||||
if (backendApp.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
const backendApp_ = structuredClone(stateSnapshot(backendApp))
|
||||
savedApp = {
|
||||
summary: backendApp_.summary,
|
||||
|
||||
@@ -177,9 +177,13 @@
|
||||
const tok = ++loadAppToken
|
||||
const backendApp = await AppService.getAppByPath({
|
||||
path: page.params.path ?? '',
|
||||
workspace: $workspaceStore!
|
||||
workspace: $workspaceStore!,
|
||||
getDraft: true
|
||||
})
|
||||
if (tok !== loadAppToken) return
|
||||
if (backendApp.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
const backendApp_ = structuredClone(stateSnapshot(backendApp))
|
||||
savedApp = {
|
||||
summary: backendApp_.summary,
|
||||
|
||||
@@ -145,9 +145,13 @@
|
||||
|
||||
const backendFlow = await FlowService.getFlowByPath({
|
||||
workspace: $workspaceStore!,
|
||||
path: page.params.path ?? ''
|
||||
path: page.params.path ?? '',
|
||||
getDraft: true
|
||||
})
|
||||
if (tok !== loadFlowToken) return
|
||||
if (backendFlow.is_draft) {
|
||||
sendUserToast('Loaded your saved draft')
|
||||
}
|
||||
savedFlow = structuredClone($state.snapshot(backendFlow)) as Flow
|
||||
|
||||
const localDraft = flowHandle.draft
|
||||
|
||||
Reference in New Issue
Block a user