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
This commit is contained in:
Guillaume Bouvignies
2024-01-24 09:26:23 +01:00
committed by GitHub
parent a0ace85bb2
commit 32254203d8
15 changed files with 464 additions and 113 deletions
@@ -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
]
},
@@ -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"
}
@@ -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
]
},
@@ -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"
}
@@ -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"
}
+83 -95
View File
@@ -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",
@@ -0,0 +1,2 @@
-- Add down migration script here
ALTER TABLE workspace_settings DROP COLUMN default_app;
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE workspace_settings ADD COLUMN default_app VARCHAR(255);
+54 -3
View File
@@ -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
+51 -3
View File
@@ -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
+81
View File
@@ -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<bool>,
pub large_file_storage: Option<serde_json::Value>, // effectively: DatasetsStorage
pub git_sync: Option<serde_json::Value>, // effectively: WorkspaceGitRepo
pub default_app: Option<String>,
}
#[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<String>,
}
async fn edit_default_app(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Path(w_id): Path<String>,
ApiAuthed { is_admin, username, .. }: ApiAuthed,
Json(new_config): Json<EditDefaultApp>,
) -> Result<String> {
#[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<String>,
}
async fn get_default_app(
Extension(db): Extension<DB>,
Path(w_id): Path<String>,
) -> JsonResult<WorkspaceDefaultApp> {
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<DB>,
@@ -1,5 +1,5 @@
<script lang="ts">
import { ScriptService, FlowService, Script } from '$lib/gen'
import { ScriptService, FlowService, Script, AppService } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
@@ -22,7 +22,7 @@
export let initialPath: string | undefined = undefined
export let scriptPath: string | undefined = undefined
export let allowFlow = false
export let itemKind: 'script' | 'flow' = 'script'
export let itemKind: 'script' | 'flow' | 'app' = 'script'
export let kinds: Script.kind[] = [Script.kind.SCRIPT]
export let disabled = false
export let allowRefresh = false
@@ -50,6 +50,11 @@
value: script.path,
label: `${script.path}${script.summary ? ` | ${truncate(script.summary, 20)}` : ''}`
}))
} else if (itemKind == 'app') {
items = (await AppService.listApps({ workspace: $workspaceStore! })).map((app) => ({
value: app.path,
label: `${app.path}${app.summary ? ` | ${truncate(app.summary, 20)}` : ''}`
}))
}
}
@@ -98,7 +103,7 @@
}}
bind:justValue={scriptPath}
{items}
placeholder="Pick a {itemKind}"
placeholder="Pick {itemKind === 'app' ? 'an' : 'a'} {itemKind}"
inputStyles={SELECT_INPUT_DEFAULT_STYLE.inputStyles}
containerStyles={darkMode
? SELECT_INPUT_DEFAULT_STYLE.containerStylesDark
@@ -140,6 +145,29 @@
View
</Button>
</div>
{:else if itemKind == 'app'}
<div class="flex gap-2">
<Button
startIcon={{ icon: Pen }}
target="_blank"
color="light"
size="xs"
href="/apps/edit/{scriptPath}"
variant="border"
>
Edit
</Button>
<Button
color="light"
size="xs"
variant="border"
target="_blank"
startIcon={{ icon: Code }}
href="/apps/get/{scriptPath}"
>
View
</Button>
</div>
{:else}
<div class="flex gap-2">
<Button
@@ -10,7 +10,7 @@
import { onMount } from 'svelte'
import { OauthService, UserService, WorkspaceService } from '$lib/gen'
import { usersWorkspaceStore, workspaceStore, userStore } from '$lib/stores'
import { classNames, parseQueryParams } from '$lib/utils'
import { classNames, emptyString, parseQueryParams } from '$lib/utils'
import { getUserExt } from '$lib/user'
import { Button, Skeleton } from '$lib/components/common'
import { WindmillIcon } from '$lib/components/icons'
@@ -115,8 +115,21 @@
const allWorkspaces = $usersWorkspaceStore?.workspaces.filter((x) => x.id != 'admins')
if (allWorkspaces?.length == 1) {
$workspaceStore = allWorkspaces[0].id
goto(rd ?? '/')
workspaceStore.set(allWorkspaces[0].id)
$userStore = await getUserExt($workspaceStore!)
if (!$userStore?.is_super_admin && $userStore?.operator) {
let defaultApp = await WorkspaceService.getWorkspaceDefaultApp({
workspace: $workspaceStore!
})
if (!emptyString(defaultApp.default_app_path)) {
goto(`/apps/get/${defaultApp.default_app_path}`)
} else {
goto(rd ?? '/')
}
} else {
goto(rd ?? '/')
}
} else if (rd?.startsWith('/user/workspaces')) {
goto(rd)
} else if (rd == '/#user-settings') {
@@ -4,7 +4,13 @@
import { sendUserToast } from '$lib/toast'
import { logout, logoutWithRedirect } from '$lib/logout'
import { UserService, type WorkspaceInvite, WorkspaceService } from '$lib/gen'
import { superadmin, usersWorkspaceStore, userWorkspaces, workspaceStore } from '$lib/stores'
import {
superadmin,
usersWorkspaceStore,
userWorkspaces,
workspaceStore,
userStore
} from '$lib/stores'
import { Button, Skeleton } from '$lib/components/common'
import Toggle from '$lib/components/Toggle.svelte'
import UserSettings from '$lib/components/UserSettings.svelte'
@@ -15,6 +21,8 @@
import { switchWorkspace } from '$lib/storeUtils'
import { Cog, Crown } from 'lucide-svelte'
import { isCloudHosted } from '$lib/cloud'
import { emptyString } from '$lib/utils'
import { getUserExt } from '$lib/user'
let invites: WorkspaceInvite[] = []
let list_all_as_super_admin: boolean = false
@@ -92,6 +100,26 @@
loadWorkspaces()
let loading = false
async function speakFriendAndEnterWorkspace(workspaceId: string) {
loading = true
workspaceStore.set(undefined)
workspaceStore.set(workspaceId)
$userStore = await getUserExt($workspaceStore!)
if (!$userStore?.is_super_admin && $userStore?.operator) {
let defaultApp = await WorkspaceService.getWorkspaceDefaultApp({
workspace: $workspaceStore!
})
if (!emptyString(defaultApp.default_app_path)) {
goto(`/apps/get/${defaultApp.default_app_path}`)
} else {
await goto(rd ?? '/')
}
} else {
await goto(rd ?? '/')
}
loading = false
}
</script>
{#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)
}}
><span class="font-mono">{workspace.id}</span> - {workspace.name} as
<span class="font-mono">{workspace.username}</span>
@@ -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<void> {
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<void> {
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 @@
<Tab size="xs" value="windmill_lfs">
<div class="flex gap-2 items-center my-1"> S3 Storage </div>
</Tab>
<Tab size="xs" value="default_app">
<div class="flex gap-2 items-center my-1"> Default App </div>
</Tab>
<Tab size="xs" value="export_delete">
<div class="flex gap-2 items-center my-1"> Delete Workspace </div>
</Tab>
@@ -930,6 +955,32 @@ git push</code
}}>Save Git sync settings</Button
>
</div>
{:else if tab == 'default_app'}
<PageHeader
title="Workspace default app"
tooltip="Users who are operators in this workspace will be redirected to this app automatically when login into this workspace."
primary={false}
/>
{#if !$enterpriseLicense}
<Alert type="info" title="Windmill EE only feature">
Default app can only be set on Windmill Enterprise Edition.
</Alert>
{/if}
<Alert type="info" title="Default app must be accessible to all operators">
Make sure the default app is shared with all the operators of this workspace before turning
this feature on.
</Alert>
<div class="mt-5 flex gap-1">
{#key workspaceDefaultAppPath}
<ScriptPicker
initialPath={workspaceDefaultAppPath}
itemKind="app"
on:select={(ev) => {
editWorkspaceDefaultApp(ev?.detail?.path)
}}
/>
{/key}
</div>
{/if}
{:else}
<div class="bg-red-100 border-l-4 border-red-600 text-orange-700 p-4 m-4" role="alert">