From 32254203d81d4353fbfb7f6cd7b72f1e237dc45c Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Wed, 24 Jan 2024 09:26:23 +0100 Subject: [PATCH] feat: Set a default app for each workspace (#3014) * feat: workspace default app * sqlx prepare * rebase migration * Redirect from home page * move redirect to the workspaces page * sqlx prepare * auto redirect when only one workspace and load user before redirecting * Add check for operator * refresh userstore before redirecting to workspace app * check for superadmin * revert node_modules * revert package-lock.json --- ...c61296a3ff7489ae12f52a19f9543173ac597.json | 6 + ...140e86fe8fc8d1f20dc76b8ae70b9a3b5833e.json | 14 ++ ...7630a1d7b9deb8d33e9f909061f351f96844e.json | 6 + ...19fd1ca9a8145cc33fa6f912c84fec5eb226e.json | 15 ++ ...3f3be67b6160cd258c86b8e8f22a6d601afd0.json | 22 +++ backend/Cargo.lock | 178 ++++++++---------- ...40119171900_workspace_default_app.down.sql | 2 + ...0240119171900_workspace_default_app.up.sql | 2 + backend/windmill-api/openapi-deref.yaml | 57 +++++- backend/windmill-api/openapi.yaml | 54 +++++- backend/windmill-api/src/workspaces.rs | 81 ++++++++ .../src/lib/components/ScriptPicker.svelte | 34 +++- .../(logged)/user/(user)/login/+page.svelte | 19 +- .../user/(user)/workspaces/+page.svelte | 36 +++- .../(logged)/workspace_settings/+page.svelte | 51 +++++ 15 files changed, 464 insertions(+), 113 deletions(-) create mode 100644 backend/.sqlx/query-36918406736022663b0d33467e2140e86fe8fc8d1f20dc76b8ae70b9a3b5833e.json create mode 100644 backend/.sqlx/query-72b2bc804e1926e1a938ba839a319fd1ca9a8145cc33fa6f912c84fec5eb226e.json create mode 100644 backend/.sqlx/query-ed1a053c7b22d9cb69767be40d33f3be67b6160cd258c86b8e8f22a6d601afd0.json create mode 100644 backend/migrations/20240119171900_workspace_default_app.down.sql create mode 100644 backend/migrations/20240119171900_workspace_default_app.up.sql diff --git a/backend/.sqlx/query-1730f39fd1793d45fbb41b21389c61296a3ff7489ae12f52a19f9543173ac597.json b/backend/.sqlx/query-1730f39fd1793d45fbb41b21389c61296a3ff7489ae12f52a19f9543173ac597.json index 5b50d07303..53ed8cc88b 100644 --- a/backend/.sqlx/query-1730f39fd1793d45fbb41b21389c61296a3ff7489ae12f52a19f9543173ac597.json +++ b/backend/.sqlx/query-1730f39fd1793d45fbb41b21389c61296a3ff7489ae12f52a19f9543173ac597.json @@ -92,6 +92,11 @@ "ordinal": 17, "name": "git_sync", "type_info": "Jsonb" + }, + { + "ordinal": 18, + "name": "default_app", + "type_info": "Varchar" } ], "parameters": { @@ -117,6 +122,7 @@ true, false, true, + true, true ] }, diff --git a/backend/.sqlx/query-36918406736022663b0d33467e2140e86fe8fc8d1f20dc76b8ae70b9a3b5833e.json b/backend/.sqlx/query-36918406736022663b0d33467e2140e86fe8fc8d1f20dc76b8ae70b9a3b5833e.json new file mode 100644 index 0000000000..1cd4a69e7b --- /dev/null +++ b/backend/.sqlx/query-36918406736022663b0d33467e2140e86fe8fc8d1f20dc76b8ae70b9a3b5833e.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE workspace_settings SET default_app = NULL WHERE workspace_id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "36918406736022663b0d33467e2140e86fe8fc8d1f20dc76b8ae70b9a3b5833e" +} diff --git a/backend/.sqlx/query-5445083864b2b092b012e894bff7630a1d7b9deb8d33e9f909061f351f96844e.json b/backend/.sqlx/query-5445083864b2b092b012e894bff7630a1d7b9deb8d33e9f909061f351f96844e.json index a571eb385e..e86be11630 100644 --- a/backend/.sqlx/query-5445083864b2b092b012e894bff7630a1d7b9deb8d33e9f909061f351f96844e.json +++ b/backend/.sqlx/query-5445083864b2b092b012e894bff7630a1d7b9deb8d33e9f909061f351f96844e.json @@ -92,6 +92,11 @@ "ordinal": 17, "name": "git_sync", "type_info": "Jsonb" + }, + { + "ordinal": 18, + "name": "default_app", + "type_info": "Varchar" } ], "parameters": { @@ -117,6 +122,7 @@ true, false, true, + true, true ] }, diff --git a/backend/.sqlx/query-72b2bc804e1926e1a938ba839a319fd1ca9a8145cc33fa6f912c84fec5eb226e.json b/backend/.sqlx/query-72b2bc804e1926e1a938ba839a319fd1ca9a8145cc33fa6f912c84fec5eb226e.json new file mode 100644 index 0000000000..21890f69db --- /dev/null +++ b/backend/.sqlx/query-72b2bc804e1926e1a938ba839a319fd1ca9a8145cc33fa6f912c84fec5eb226e.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE workspace_settings SET default_app = $1 WHERE workspace_id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text" + ] + }, + "nullable": [] + }, + "hash": "72b2bc804e1926e1a938ba839a319fd1ca9a8145cc33fa6f912c84fec5eb226e" +} diff --git a/backend/.sqlx/query-ed1a053c7b22d9cb69767be40d33f3be67b6160cd258c86b8e8f22a6d601afd0.json b/backend/.sqlx/query-ed1a053c7b22d9cb69767be40d33f3be67b6160cd258c86b8e8f22a6d601afd0.json new file mode 100644 index 0000000000..b7c642ef12 --- /dev/null +++ b/backend/.sqlx/query-ed1a053c7b22d9cb69767be40d33f3be67b6160cd258c86b8e8f22a6d601afd0.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT default_app FROM workspace_settings WHERE workspace_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "default_app", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + true + ] + }, + "hash": "ed1a053c7b22d9cb69767be40d33f3be67b6160cd258c86b8e8f22a6d601afd0" +} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 14f2f20471..ce832dc2ef 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "argon2" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9" dependencies = [ "base64ct", "blake2", @@ -399,7 +399,7 @@ checksum = "beec3f8fb8f710b7be84ccd1716e17f38f2868168355cab5f2f168ae988e767e" dependencies = [ "base64 0.21.7", "bytes", - "http 0.2.11", + "http", "rand 0.8.5", "reqwest", "serde", @@ -578,9 +578,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aws-config" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91bb1df3e5f0e47475498570cdd10ab0370bc1d7af3151aa0161d5f5876b6908" +checksum = "7e64b72d4bdbb41a73d27709c65a25b6e4bfc8321bf70fa3a8b19ce7d4eb81b0" dependencies = [ "aws-credential-types", "aws-http", @@ -598,7 +598,7 @@ dependencies = [ "bytes", "fastrand 2.0.1", "hex", - "http 0.2.11", + "http", "hyper", "ring 0.17.7", "time", @@ -609,9 +609,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67c6836a1009b23e3f4cd1457c83e0aa49a490d9c3033b53c3f7b8cf2facc0f" +checksum = "4a7cb3510b95492bd9014b60e2e3bee3e48bc516e220316f8e6b60df18b47331" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -621,15 +621,15 @@ dependencies = [ [[package]] name = "aws-http" -version = "0.60.3" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a081f0c4576f7549dd255987d2d23920eccaa90cdd21d6440f91e0d7537f0e0d" +checksum = "a95d41abe4e941399fdb4bc2f54713eac3c839d98151875948bb24e66ab658f2" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", - "http 0.2.11", + "http", "http-body", "pin-project-lite", "tracing", @@ -637,9 +637,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7bf4b9b083e6dc86e2bb4fb09a4daca97e12cc0bc174a6f51fe624c23aa87f" +checksum = "233cca219c6705d525ace011d6f9bc51aaf32fce5b4c41661d2d7ff22d9b4d49" dependencies = [ "aws-credential-types", "aws-http", @@ -651,7 +651,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "fastrand 2.0.1", - "http 0.2.11", + "http", "percent-encoding", "tracing", "uuid 1.7.0", @@ -659,9 +659,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.13.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f94d9842a304e066d1eddea61c703fb217ce5a1063cc087d07c8de1db4535f7" +checksum = "634fbe5b6591ee2e281cd2ba8641e9bd752dbf5bf338924d6ad4bd5a3304fe31" dependencies = [ "aws-credential-types", "aws-http", @@ -678,7 +678,7 @@ dependencies = [ "aws-smithy-xml", "aws-types", "bytes", - "http 0.2.11", + "http", "http-body", "once_cell", "percent-encoding", @@ -689,9 +689,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865b1b85249196e4868a48a4b6683d60e19b82371b869297bc9982bc9f47de4b" +checksum = "ee41005e0f3a19ae749c7953d9e1f1ef8d2183f76f64966e346fa41c1ba0ed44" dependencies = [ "aws-credential-types", "aws-http", @@ -704,7 +704,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http 0.2.11", + "http", "once_cell", "regex-lite", "tracing", @@ -712,9 +712,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beadaf5c48f5d923329ec87b7db6eea5e4ce2af4cc9f96d9f85d520f34573f40" +checksum = "fa08168f8a27505e7b90f922c32a489feb1f2133878981a15138bebc849ac09c" dependencies = [ "aws-credential-types", "aws-http", @@ -727,7 +727,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http 0.2.11", + "http", "once_cell", "regex-lite", "tracing", @@ -735,9 +735,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262a6d40c8e11eea633ba541a39745cebfcee9c1683020cee63413048b5c6188" +checksum = "29102eff04d50ef70f11a48823db33e33c6cc5f027bfb6ff4864efbd5f1f66f3" dependencies = [ "aws-credential-types", "aws-http", @@ -751,7 +751,7 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "http 0.2.11", + "http", "once_cell", "regex-lite", "tracing", @@ -759,9 +759,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511879249616f30e30fd2fa81edb4833784f65dd5d56053b7de2e2bcb583dda7" +checksum = "b92384b39aedb258aa734fe0e7b2ffcd13f33e68227251a72cd2635e0acc8f1a" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -773,8 +773,7 @@ dependencies = [ "form_urlencoded", "hex", "hmac", - "http 0.2.11", - "http 1.0.0", + "http", "once_cell", "p256 0.11.1", "percent-encoding", @@ -809,7 +808,7 @@ dependencies = [ "crc32c", "crc32fast", "hex", - "http 0.2.11", + "http", "http-body", "md-5 0.10.6", "pin-project-lite", @@ -841,7 +840,7 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", - "http 0.2.11", + "http", "http-body", "once_cell", "percent-encoding", @@ -882,7 +881,7 @@ dependencies = [ "bytes", "fastrand 2.0.1", "h2", - "http 0.2.11", + "http", "http-body", "hyper", "hyper-rustls", @@ -903,7 +902,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-types", "bytes", - "http 0.2.11", + "http", "pin-project-lite", "tokio", "tracing", @@ -920,7 +919,7 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", - "http 0.2.11", + "http", "http-body", "itoa", "num-integer", @@ -944,15 +943,15 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2739d97d47f47cdf0d27982019a405dcc736df25925d1a75049f1faa79df88" +checksum = "8549aa62c5b7db5c57ab915200ee214b4f5d8f19b29a4a8fa0b3ad3bca1380e3" dependencies = [ "aws-credential-types", "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "http 0.2.11", + "http", "rustc_version 0.4.0", "tracing", ] @@ -969,7 +968,7 @@ dependencies = [ "bytes", "futures-util", "headers", - "http 0.2.11", + "http", "http-body", "hyper", "itoa", @@ -999,7 +998,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.11", + "http", "http-body", "mime", "rustversion", @@ -1482,9 +1481,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1492,7 +1491,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.48.5", ] [[package]] @@ -2171,7 +2170,7 @@ dependencies = [ "deno_core", "deno_tls", "dyn-clone", - "http 0.2.11", + "http", "reqwest", "serde", "tokio", @@ -3403,7 +3402,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.11", + "http", "indexmap 2.1.0", "slab", "tokio", @@ -3472,7 +3471,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 0.2.11", + "http", "httpdate", "mime", "sha1", @@ -3484,7 +3483,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.11", + "http", ] [[package]] @@ -3563,17 +3562,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http-body" version = "0.4.6" @@ -3581,7 +3569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http", "pin-project-lite", ] @@ -3601,7 +3589,7 @@ dependencies = [ "async-channel 1.9.0", "base64 0.13.1", "futures-lite 1.13.0", - "http 0.2.11", + "http", "infer", "pin-project-lite", "rand 0.7.3", @@ -3641,7 +3629,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http", "http-body", "httparse", "httpdate", @@ -3661,7 +3649,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", + "http", "hyper", "log", "rustls 0.21.10", @@ -4687,7 +4675,7 @@ dependencies = [ "base64 0.13.1", "chrono", "getrandom 0.2.12", - "http 0.2.11", + "http", "rand 0.8.5", "reqwest", "serde", @@ -4792,7 +4780,7 @@ dependencies = [ "dyn-clone", "ed25519-dalek", "hmac", - "http 0.2.11", + "http", "itertools 0.10.5", "log", "oauth2", @@ -4815,9 +4803,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.63" +version = "0.10.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" dependencies = [ "bitflags 2.4.2", "cfg-if", @@ -4847,9 +4835,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.99" +version = "0.9.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" dependencies = [ "cc", "libc", @@ -5830,9 +5818,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -5877,7 +5865,7 @@ source = "git+https://github.com/oxidecomputer/progenitor?rev=3d96016ae8d422e905 dependencies = [ "getopts", "heck", - "http 0.2.11", + "http", "indexmap 1.9.3", "openapiv3", "proc-macro2", @@ -6235,13 +6223,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", + "regex-automata 0.4.3", "regex-syntax 0.8.2", ] @@ -6256,9 +6244,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -6321,7 +6309,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http", "http-body", "hyper", "hyper-rustls", @@ -7144,9 +7132,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ "base64 0.21.7", "chrono", @@ -7161,9 +7149,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ "darling 0.20.3", "proc-macro2", @@ -7259,9 +7247,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signal-hook-registry" @@ -7327,9 +7315,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3b187f0231d56fe41bfb12034819dd2bf336422a5866de41bc3fec4b2e3883e8" [[package]] name = "smart-default" @@ -8771,7 +8759,7 @@ dependencies = [ "axum-core", "cookie", "futures-util", - "http 0.2.11", + "http", "parking_lot", "pin-project-lite", "tower-layer", @@ -8788,7 +8776,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 0.2.11", + "http", "http-body", "http-range-header", "pin-project-lite", @@ -9614,7 +9602,7 @@ dependencies = [ "hf-hub", "hmac", "hyper", - "itertools 0.12.0", + "itertools 0.9.0", "lazy_static", "magic-crypt", "mail-send", @@ -9706,7 +9694,7 @@ dependencies = [ "hex", "hmac", "hyper", - "itertools 0.12.0", + "itertools 0.9.0", "lazy_static", "magic-crypt", "prometheus", @@ -9765,7 +9753,7 @@ version = "1.251.1" dependencies = [ "anyhow", "gosyn", - "itertools 0.12.0", + "itertools 0.9.0", "lazy_static", "regex", "windmill-parser", @@ -9787,7 +9775,7 @@ name = "windmill-parser-py" version = "1.251.1" dependencies = [ "anyhow", - "itertools 0.12.0", + "itertools 0.9.0", "rustpython-parser", "serde_json", "windmill-parser", @@ -9799,7 +9787,7 @@ version = "1.251.1" dependencies = [ "anyhow", "async-recursion", - "itertools 0.12.0", + "itertools 0.9.0", "lazy_static", "phf 0.11.2", "regex", @@ -9864,14 +9852,14 @@ dependencies = [ "anyhow", "async-recursion", "axum", - "bigdecimal 0.4.2", + "bigdecimal 0.3.1", "chrono", "chrono-tz", "cron", "futures-core", "hex", "hmac", - "itertools 0.12.0", + "itertools 0.9.0", "lazy_static", "prometheus", "regex", @@ -9914,7 +9902,7 @@ dependencies = [ "gcp_auth", "git-version", "hex", - "itertools 0.12.0", + "itertools 0.9.0", "jsonwebtoken", "lazy_static", "mysql_async", diff --git a/backend/migrations/20240119171900_workspace_default_app.down.sql b/backend/migrations/20240119171900_workspace_default_app.down.sql new file mode 100644 index 0000000000..88ed130d17 --- /dev/null +++ b/backend/migrations/20240119171900_workspace_default_app.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +ALTER TABLE workspace_settings DROP COLUMN default_app; diff --git a/backend/migrations/20240119171900_workspace_default_app.up.sql b/backend/migrations/20240119171900_workspace_default_app.up.sql new file mode 100644 index 0000000000..90b9a54c70 --- /dev/null +++ b/backend/migrations/20240119171900_workspace_default_app.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +ALTER TABLE workspace_settings ADD COLUMN default_app VARCHAR(255); diff --git a/backend/windmill-api/openapi-deref.yaml b/backend/windmill-api/openapi-deref.yaml index 9dffa9d5f9..f6c1514fee 100644 --- a/backend/windmill-api/openapi-deref.yaml +++ b/backend/windmill-api/openapi-deref.yaml @@ -847,7 +847,7 @@ paths: '200': description: status content: - 'text/plain:': + text/plain: schema: type: string /settings/test_license_key: @@ -872,7 +872,7 @@ paths: '200': description: status content: - 'text/plain:': + text/plain: schema: type: string /settings/send_stats: @@ -885,7 +885,7 @@ paths: '200': description: status content: - 'text/plain:': + text/plain: schema: type: string /users/email: @@ -1538,6 +1538,8 @@ paths: required: &ref_17 - script_path - git_repo_resource_path + default_app: + type: string required: - code_completion_enabled /w/{workspace}/workspaces/get_deploy_to: @@ -1904,6 +1906,55 @@ paths: content: application/json: schema: {} + /w/{workspace}/workspaces/edit_default_app: + post: + summary: edit default app for workspace + operationId: editWorkspaceDefaultApp + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: Workspace default app + required: true + content: + application/json: + schema: + type: object + properties: + default_app_path: + type: string + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + /w/{workspace}/workspaces/default_app: + get: + summary: get default app for workspace + operationId: getWorkspaceDefaultApp + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: status + content: + application/json: + schema: + type: object + properties: + default_app_path: + type: string /w/{workspace}/workspaces/get_large_file_storage_config: get: summary: get large file storage config diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index f75d1854df..99fd1c2498 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -620,7 +620,7 @@ paths: "200": description: status content: - text/plain:: + text/plain: schema: type: string @@ -646,7 +646,7 @@ paths: "200": description: status content: - text/plain:: + text/plain: schema: type: string @@ -660,7 +660,7 @@ paths: "200": description: status content: - text/plain:: + text/plain: schema: type: string @@ -1196,6 +1196,8 @@ paths: type: array items: $ref: "#/components/schemas/WorkspaceGitSync" + default_app: + type: string required: - code_completion_enabled @@ -1545,6 +1547,52 @@ paths: application/json: schema: {} + /w/{workspace}/workspaces/edit_default_app: + post: + summary: edit default app for workspace + operationId: editWorkspaceDefaultApp + tags: + - workspace + parameters: + - $ref: "#/components/parameters/WorkspaceId" + requestBody: + description: Workspace default app + required: true + content: + application/json: + schema: + type: object + properties: + default_app_path: + type: string + + responses: + "200": + description: status + content: + text/plain: + schema: + type: string + + /w/{workspace}/workspaces/default_app: + get: + summary: get default app for workspace + operationId: getWorkspaceDefaultApp + tags: + - workspace + parameters: + - $ref: "#/components/parameters/WorkspaceId" + responses: + "200": + description: status + content: + application/json: + schema: + type: object + properties: + default_app_path: + type: string + /w/{workspace}/workspaces/get_large_file_storage_config: get: summary: get large file storage config diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index d9e516aba6..4b73e9fb04 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -91,6 +91,8 @@ pub fn workspaced_service() -> Router { post(edit_large_file_storage_config), ) .route("/edit_git_sync_config", post(edit_git_sync_config)) + .route("/edit_default_app", post(edit_default_app)) + .route("/default_app", get(get_default_app)) .route("/leave", post(leave_workspace)); #[cfg(feature = "stripe")] @@ -162,6 +164,7 @@ pub struct WorkspaceSettings { pub error_handler_muted_on_cancel: Option, pub large_file_storage: Option, // effectively: DatasetsStorage pub git_sync: Option, // effectively: WorkspaceGitRepo + pub default_app: Option, } #[derive(FromRow, Serialize, Debug)] @@ -1101,6 +1104,84 @@ async fn edit_git_sync_config( Ok(format!("Edit git sync config for workspace {}", &w_id)) } +#[derive(Deserialize)] +struct EditDefaultApp { + default_app_path: Option, +} + +async fn edit_default_app( + authed: ApiAuthed, + Extension(db): Extension, + Path(w_id): Path, + ApiAuthed { is_admin, username, .. }: ApiAuthed, + Json(new_config): Json, +) -> Result { + #[cfg(not(feature = "enterprise"))] + { + return Err(Error::BadRequest( + "Setting a workspace default app is only available on Windmill Enterprise Edition" + .to_string(), + )); + } + + require_admin(is_admin, &username)?; + + let mut tx = db.begin().await?; + + let args_for_audit = format!("{:?}", new_config.default_app_path); + audit_log( + &mut *tx, + &authed.username, + "workspaces.edit_default_app", + ActionKind::Update, + &w_id, + Some(&authed.email), + Some([("args_for_audit", args_for_audit.as_str())].into()), + ) + .await?; + + if let Some(default_app_path) = new_config.default_app_path { + sqlx::query!( + "UPDATE workspace_settings SET default_app = $1 WHERE workspace_id = $2", + default_app_path, + &w_id + ) + .execute(&mut *tx) + .await?; + } else { + sqlx::query!( + "UPDATE workspace_settings SET default_app = NULL WHERE workspace_id = $1", + &w_id, + ) + .execute(&mut *tx) + .await?; + } + tx.commit().await?; + + Ok(format!("Edit default app for workspace {}", &w_id)) +} + +#[derive(Serialize)] +struct WorkspaceDefaultApp { + pub default_app_path: Option, +} +async fn get_default_app( + Extension(db): Extension, + Path(w_id): Path, +) -> JsonResult { + let mut tx = db.begin().await?; + let default_app_path = sqlx::query_scalar!( + "SELECT default_app FROM workspace_settings WHERE workspace_id = $1", + &w_id + ) + .fetch_one(&mut *tx) + .await + .map_err(|err| Error::InternalErr(format!("getting default_app: {err}")))?; + tx.commit().await?; + + Ok(Json(WorkspaceDefaultApp { default_app_path })) +} + async fn edit_error_handler( authed: ApiAuthed, Extension(db): Extension, diff --git a/frontend/src/lib/components/ScriptPicker.svelte b/frontend/src/lib/components/ScriptPicker.svelte index 064f3b02c7..783f57aee8 100644 --- a/frontend/src/lib/components/ScriptPicker.svelte +++ b/frontend/src/lib/components/ScriptPicker.svelte @@ -1,5 +1,5 @@ {#if $superadmin} @@ -142,11 +170,7 @@ class="block w-full mx-auto py-1 px-2 rounded-md border shadow-sm text-sm font-normal mt-1 hover:ring-1 hover:ring-indigo-300" on:click={async () => { - workspaceStore.set(undefined) - workspaceStore.set(workspace.id) - loading = true - await goto(rd ?? '/') - loading = false + speakFriendAndEnterWorkspace(workspace.id) }} >{workspace.id} - {workspace.name} as {workspace.username} diff --git a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte index 4840192e80..6d14aa520a 100644 --- a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte @@ -68,6 +68,7 @@ jobId: string | undefined status: 'running' | 'success' | 'failure' | undefined }[] + let workspaceDefaultAppPath: string | undefined = undefined let codeCompletionEnabled: boolean = false let tab = ($page.url.searchParams.get('tab') as @@ -228,6 +229,26 @@ } } + async function editWorkspaceDefaultApp(appPath: string | undefined): Promise { + if (emptyString(appPath)) { + await WorkspaceService.editWorkspaceDefaultApp({ + workspace: $workspaceStore!, + requestBody: { + default_app_path: undefined + } + }) + sendUserToast('Workspace default app reset') + } else { + await WorkspaceService.editWorkspaceDefaultApp({ + workspace: $workspaceStore!, + requestBody: { + default_app_path: appPath + } + }) + sendUserToast('Workspace default app set') + } + } + async function loadSettings(): Promise { const settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! }) team_name = settings.slack_name @@ -258,6 +279,7 @@ } errorHandlerExtraArgs = settings.error_handler_extra_args ?? {} codeCompletionEnabled = settings.code_completion_enabled + workspaceDefaultAppPath = settings.default_app s3ResourceInitialPath = settings.large_file_storage?.type === LargeFileStorage.type.S3STORAGE ? settings.large_file_storage?.s3_resource_path?.replace('$res:', '') @@ -434,6 +456,9 @@
S3 Storage
+ +
Default App
+
Delete Workspace
@@ -930,6 +955,32 @@ git pushSave Git sync settings + {:else if tab == 'default_app'} + + {#if !$enterpriseLicense} + + Default app can only be set on Windmill Enterprise Edition. + + {/if} + + Make sure the default app is shared with all the operators of this workspace before turning + this feature on. + +
+ {#key workspaceDefaultAppPath} + { + editWorkspaceDefaultApp(ev?.detail?.path) + }} + /> + {/key} +
{/if} {:else}