diff --git a/backend/migrations/20221203080006_apps_2.down.sql b/backend/migrations/20221203080006_apps_2.down.sql new file mode 100644 index 0000000000..d2f607c5b8 --- /dev/null +++ b/backend/migrations/20221203080006_apps_2.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/backend/migrations/20221203080006_apps_2.up.sql b/backend/migrations/20221203080006_apps_2.up.sql new file mode 100644 index 0000000000..95d8fd6c56 --- /dev/null +++ b/backend/migrations/20221203080006_apps_2.up.sql @@ -0,0 +1,3 @@ +-- Add up migration script here +ALTER TABLE app ADD CONSTRAINT unique_path_workspace_id UNIQUE (workspace_id, path); +ALTER TABLE app ENABLE ROW LEVEL SECURITY; diff --git a/backend/sqlx-data.json b/backend/sqlx-data.json index 7f50d7c5e3..6d01492f46 100644 --- a/backend/sqlx-data.json +++ b/backend/sqlx-data.json @@ -1499,6 +1499,27 @@ }, "query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by from app, app_version \n WHERE app_version.id = $1 AND app.id = app_version.flow_id AND app.workspace_id = $2" }, + "5850e0c1f7dee98455027a4c0db6ccea0af2c58aee656ef43964b515de054888": { + "describe": { + "columns": [ + { + "name": "exists", + "ordinal": 0, + "type_info": "Bool" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + } + }, + "query": "SELECT EXISTS(SELECT 1 FROM app WHERE path = $1 AND workspace_id = $2)" + }, "58efbf34ba014b4853ef20ae400929b57c1d9de4262189274badf100d29e0649": { "describe": { "columns": [ diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 0bec142a38..af6f5b6e95 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -2347,6 +2347,23 @@ paths: items: $ref: "#/components/schemas/ListableApp" + /w/{workspace}/apps/exists/{path}: + get: + summary: does an app exisst at path + operationId: existsApp + tags: + - app + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/Path" + responses: + "200": + description: app exists + content: + application/json: + schema: + type: boolean + /w/{workspace}/apps/get/p/{path}: get: summary: get app by path @@ -3260,7 +3277,7 @@ paths: - $ref: "#/components/parameters/Path" responses: "200": - description: schedule deleted + description: schedule exists content: application/json: schema: diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index a773cc5849..41808fa47e 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -36,6 +36,7 @@ pub fn workspaced_service() -> Router { .route("/list", get(list_apps)) .route("/get/p/*path", get(get_app)) .route("/get/v/*id", get(get_app_by_id)) + .route("/exists/*path", post(exists_app)) .route("/update/*path", post(update_app)) .route("/delete/*path", delete(delete_app)) .route("/create", post(create_app)) @@ -540,6 +541,23 @@ async fn execute_component( Ok(uuid.to_string()) } +async fn exists_app( + Extension(db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult { + let path = path.to_path(); + let exists = sqlx::query_scalar!( + "SELECT EXISTS(SELECT 1 FROM app WHERE path = $1 AND workspace_id = $2)", + path, + w_id + ) + .fetch_one(&db) + .await? + .unwrap_or(false); + + Ok(Json(exists)) +} + fn build_args( policy: Policy, path: String,