mirror of
https://github.com/trailbaseio/trailbase.git
synced 2025-12-21 09:29:44 -06:00
Update Axum to 0.8.
This commit is contained in:
193
Cargo.lock
generated
193
Cargo.lock
generated
@@ -469,16 +469,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"axum-core 0.4.5",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"itoa",
|
||||
"matchit 0.7.3",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"sync_wrapper",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8"
|
||||
dependencies = [
|
||||
"axum-core 0.5.0",
|
||||
"bytes",
|
||||
"form_urlencoded",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"matchit 0.8.4",
|
||||
"memchr",
|
||||
"mime",
|
||||
"multer",
|
||||
@@ -499,11 +528,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum-client-ip"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eefda7e2b27e1bda4d6fa8a06b50803b8793769045918bc37ad062d48a6efac"
|
||||
checksum = "dff8ee1869817523c8f91c20bf17fd932707f66c2e7e0b0f811b29a227289562"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.8.1",
|
||||
"forwarded-header-value",
|
||||
"serde",
|
||||
]
|
||||
@@ -526,17 +555,14 @@ dependencies = [
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.9.6"
|
||||
name = "axum-core"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04"
|
||||
checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
@@ -544,7 +570,29 @@ dependencies = [
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"prost 0.12.6",
|
||||
"rustversion",
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fc6f625a1f7705c6cf62d0d070794e94668988b1c38111baeec177c715f7b"
|
||||
dependencies = [
|
||||
"axum 0.8.1",
|
||||
"axum-core 0.5.0",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"prost",
|
||||
"serde",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
@@ -553,14 +601,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum-test"
|
||||
version = "16.4.1"
|
||||
version = "17.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e3a443d2608936a02a222da7b746eb412fede7225b3030b64fe9be99eab8dc"
|
||||
checksum = "53f1009889890a439cbf67a4071a2593d027c65209da4faeac5582f28ca9e6c3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert-json-diff",
|
||||
"auto-future",
|
||||
"axum",
|
||||
"axum 0.8.1",
|
||||
"bytes",
|
||||
"bytesize",
|
||||
"cookie",
|
||||
@@ -1252,7 +1300,7 @@ dependencies = [
|
||||
name = "custom-binary"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.8.1",
|
||||
"env_logger",
|
||||
"tokio",
|
||||
"tracing-subscriber",
|
||||
@@ -2891,15 +2939,6 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
@@ -3168,6 +3207,12 @@ version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||
|
||||
[[package]]
|
||||
name = "maxminddb"
|
||||
version = "0.24.0"
|
||||
@@ -3575,7 +3620,7 @@ dependencies = [
|
||||
"opentelemetry-http",
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry_sdk",
|
||||
"prost 0.13.4",
|
||||
"prost",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
@@ -3592,7 +3637,7 @@ dependencies = [
|
||||
"hex",
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"prost 0.13.4",
|
||||
"prost",
|
||||
"serde",
|
||||
"tonic",
|
||||
]
|
||||
@@ -4019,16 +4064,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive 0.12.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.13.4"
|
||||
@@ -4036,7 +4071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive 0.13.4",
|
||||
"prost-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4052,26 +4087,13 @@ dependencies = [
|
||||
"once_cell",
|
||||
"petgraph",
|
||||
"prettyplease",
|
||||
"prost 0.13.4",
|
||||
"prost-types 0.13.4",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"regex",
|
||||
"syn 2.0.95",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.12.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.13.4"
|
||||
@@ -4085,29 +4107,17 @@ dependencies = [
|
||||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-reflect"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f5eec97d5d34bdd17ad2db2219aabf46b054c6c41bd5529767c9ce55be5898f"
|
||||
dependencies = [
|
||||
"logos",
|
||||
"once_cell",
|
||||
"prost 0.12.6",
|
||||
"prost-reflect-derive 0.13.0",
|
||||
"prost-types 0.12.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-reflect"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20ae544fca2892fd4b7e9ff26cba1090cedf1d4d95c2aded1af15d2f93f270b8"
|
||||
dependencies = [
|
||||
"logos",
|
||||
"once_cell",
|
||||
"prost 0.13.4",
|
||||
"prost-reflect-derive 0.14.0",
|
||||
"prost-types 0.13.4",
|
||||
"prost",
|
||||
"prost-reflect-derive",
|
||||
"prost-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4117,18 +4127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50e2537231d94dd2778920c2ada37dd9eb1ac0325bb3ee3ee651bd44c1134123"
|
||||
dependencies = [
|
||||
"prost-build",
|
||||
"prost-reflect 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-reflect-derive"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64c3f519df051f8a700c5aa42b53f9c42d54959506b7ed58ac7a6af7991fdc22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.95",
|
||||
"prost-reflect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4142,22 +4141,13 @@ dependencies = [
|
||||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0"
|
||||
dependencies = [
|
||||
"prost 0.12.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc"
|
||||
dependencies = [
|
||||
"prost 0.13.4",
|
||||
"prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5951,7 +5941,7 @@ checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"axum 0.7.9",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"h2",
|
||||
@@ -5963,7 +5953,7 @@ dependencies = [
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"prost 0.13.4",
|
||||
"prost",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
@@ -6011,12 +6001,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-cookies"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d"
|
||||
checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"axum-core 0.5.0",
|
||||
"cookie",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
@@ -6132,7 +6121,7 @@ dependencies = [
|
||||
"argon2",
|
||||
"async-channel 2.3.1",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"axum 0.8.1",
|
||||
"axum-client-ip",
|
||||
"axum-extra",
|
||||
"axum-test",
|
||||
@@ -6158,9 +6147,9 @@ dependencies = [
|
||||
"oauth2",
|
||||
"object_store",
|
||||
"parking_lot",
|
||||
"prost 0.12.6",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-reflect 0.13.1",
|
||||
"prost-reflect",
|
||||
"prost-reflect-build",
|
||||
"quoted_printable",
|
||||
"rand",
|
||||
@@ -6202,7 +6191,7 @@ dependencies = [
|
||||
name = "trailbase-cli"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.8.1",
|
||||
"chrono",
|
||||
"clap",
|
||||
"env_logger",
|
||||
@@ -6524,7 +6513,7 @@ version = "8.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db4b5ac679cc6dfc5ea3f2823b0291c777750ffd5e13b21137e0f7ac0e8f9617"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.7.9",
|
||||
"base64 0.22.1",
|
||||
"mime_guess",
|
||||
"regex",
|
||||
|
||||
@@ -33,7 +33,7 @@ addRoute(
|
||||
|
||||
addRoute(
|
||||
"GET",
|
||||
"/test/:table",
|
||||
"/test/{table}",
|
||||
stringHandler(async (req: StringRequestType) => {
|
||||
const table = req.params["table"];
|
||||
if (table) {
|
||||
|
||||
@@ -5,7 +5,7 @@ edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "^0.7.5" }
|
||||
axum = "^0.8.1"
|
||||
env_logger = "^0.11.3"
|
||||
tokio = { version = "^1.38.0", features=["macros", "rt-multi-thread"] }
|
||||
tracing-subscriber = "0.3.18"
|
||||
|
||||
@@ -12,7 +12,7 @@ name = "trail"
|
||||
openapi = ["dep:utoipa", "dep:utoipa-swagger-ui"]
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "^0.7.5", features=["multipart"] }
|
||||
axum = { version = "^0.8.1", features=["multipart"] }
|
||||
chrono = "^0.4.38"
|
||||
clap = { version = "^4.4.11", features=["derive", "env"] }
|
||||
env_logger = "^0.11.3"
|
||||
|
||||
@@ -27,9 +27,9 @@ arc-swap = "1.7.1"
|
||||
argon2 = { version = "^0.5.3", default-features = false, features = ["alloc", "password-hash"] }
|
||||
async-channel = "2.3.1"
|
||||
async-trait = "0.1.80"
|
||||
axum = { version = "^0.7.5", features = ["multipart"] }
|
||||
axum-client-ip = "0.6.0"
|
||||
axum-extra = { version = "^0.9.3", default-features = false, features = ["protobuf"] }
|
||||
axum = { version = "^0.8.1", features = ["multipart"] }
|
||||
axum-client-ip = "0.7.0"
|
||||
axum-extra = { version = "^0.10.0", default-features = false, features = ["protobuf"] }
|
||||
base64 = { version = "0.22.1", default-features = false }
|
||||
bytes = { version = "1.8.0", features = ["serde"] }
|
||||
chrono = "^0.4.38"
|
||||
@@ -51,8 +51,8 @@ minijinja = "2.1.2"
|
||||
oauth2 = { version = "5.0.0-alpha.4", default-features = false, features = ["reqwest", "rustls-tls"] }
|
||||
object_store = { version = "0.11.0", default-features = false, features = ["aws"] }
|
||||
parking_lot = "0.12.3"
|
||||
prost = "^0.12.6"
|
||||
prost-reflect = { version = "^0.13.0", features = ["derive", "text-format"] }
|
||||
prost = "^0.13.4"
|
||||
prost-reflect = { version = "^0.14.3", features = ["derive", "text-format"] }
|
||||
rand = "0.8.5"
|
||||
trailbase-refinery-core = { workspace = true }
|
||||
trailbase-refinery-macros = { workspace = true }
|
||||
@@ -71,7 +71,7 @@ sqlite3-parser = "0.13.0"
|
||||
thiserror = "2.0.1"
|
||||
thread_local = "1.1.8"
|
||||
tokio = { version = "^1.38.0", features = ["macros", "rt-multi-thread", "fs", "signal", "time"] }
|
||||
tower-cookies = { version = "0.10.0" }
|
||||
tower-cookies = "0.11.0"
|
||||
tower-http = { version = "^0.6.0", features = ["cors", "trace", "fs", "limit"] }
|
||||
tower-service = "0.3.3"
|
||||
tracing = "0.1.40"
|
||||
@@ -91,7 +91,7 @@ prost-reflect-build = "0.14.0"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "^1.0.86"
|
||||
axum-test = "16.3.0"
|
||||
axum-test = "17.0.1"
|
||||
criterion = { version = "0.5", features = ["html_reports", "async_tokio"] }
|
||||
trailbase-extension = { workspace = true }
|
||||
quoted_printable = "0.5.1"
|
||||
|
||||
@@ -21,19 +21,22 @@ use axum::{
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
// Row actions.
|
||||
.route("/table/:table_name/rows", get(rows::list_rows_handler))
|
||||
.route("/table/:table_name/files", get(rows::read_files_handler))
|
||||
.route("/table/:table_name/rows", delete(rows::delete_rows_handler))
|
||||
.route("/table/:table_name", patch(rows::update_row_handler))
|
||||
.route("/table/:table_name", post(rows::insert_row_handler))
|
||||
.route("/table/:table_name", delete(rows::delete_row_handler))
|
||||
.route("/table/{table_name}/rows", get(rows::list_rows_handler))
|
||||
.route("/table/{table_name}/files", get(rows::read_files_handler))
|
||||
.route(
|
||||
"/table/{table_name}/rows",
|
||||
delete(rows::delete_rows_handler),
|
||||
)
|
||||
.route("/table/{table_name}", patch(rows::update_row_handler))
|
||||
.route("/table/{table_name}", post(rows::insert_row_handler))
|
||||
.route("/table/{table_name}", delete(rows::delete_row_handler))
|
||||
// Index actions.
|
||||
.route("/index", post(table::create_index_handler))
|
||||
.route("/index", patch(table::alter_index_handler))
|
||||
.route("/index", delete(table::drop_index_handler))
|
||||
// Table actions.
|
||||
.route(
|
||||
"/table/:table_name/schema.json",
|
||||
"/table/{table_name}/schema.json",
|
||||
get(table::get_table_schema_handler),
|
||||
)
|
||||
.route("/table", post(table::create_table_handler))
|
||||
|
||||
@@ -133,6 +133,7 @@ mod tests {
|
||||
Part::bytes(body_slice.to_vec()).file_name(filename),
|
||||
);
|
||||
let content_type = form.content_type();
|
||||
|
||||
let body: axum::body::Body = form.into();
|
||||
|
||||
http::Request::builder()
|
||||
|
||||
@@ -22,6 +22,8 @@ pub use jwt::{JwtHelper, TokenClaims};
|
||||
pub(crate) use ui::auth_ui_router;
|
||||
pub use user::User;
|
||||
|
||||
use crate::constants::AUTH_API_PATH;
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
paths(
|
||||
@@ -82,68 +84,101 @@ pub(super) fn router() -> Router<crate::AppState> {
|
||||
// * vacuum expired pending registrations.
|
||||
return Router::new()
|
||||
// Sign-up new users.
|
||||
.route("/register", post(api::register::register_user_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/register"),
|
||||
post(api::register::register_user_handler),
|
||||
)
|
||||
// E-mail verification and change flows.
|
||||
.route(
|
||||
"/verify_email/trigger",
|
||||
&format!("/{AUTH_API_PATH}/verify_email/trigger"),
|
||||
get(api::verify_email::request_email_verification_handler),
|
||||
)
|
||||
.route(
|
||||
"/verify_email/confirm/:email_verification_code",
|
||||
&format!("/{AUTH_API_PATH}/verify_email/confirm/{{email_verification_code}}"),
|
||||
get(api::verify_email::verify_email_handler),
|
||||
)
|
||||
.route(
|
||||
"/change_email/request",
|
||||
&format!("/{AUTH_API_PATH}/change_email/request"),
|
||||
post(api::change_email::change_email_request_handler),
|
||||
)
|
||||
.route(
|
||||
"/change_email/confirm/:email_verification_code",
|
||||
&format!("/{AUTH_API_PATH}/change_email/confirm/{{email_verification_code}}"),
|
||||
get(api::change_email::change_email_confirm_handler),
|
||||
)
|
||||
// Password-reset flow.
|
||||
.route(
|
||||
"/reset_password/request",
|
||||
&format!("/{AUTH_API_PATH}/reset_password/request"),
|
||||
post(api::reset_password::reset_password_request_handler),
|
||||
)
|
||||
.route(
|
||||
"/reset_password/update/:password_reset_code",
|
||||
&format!("/{AUTH_API_PATH}/reset_password/update/{{password_reset_code}}"),
|
||||
post(api::reset_password::reset_password_update_handler),
|
||||
)
|
||||
// Change password flow.
|
||||
.route(
|
||||
"/change_password",
|
||||
&format!("/{AUTH_API_PATH}/change_password"),
|
||||
post(api::change_password::change_password_handler),
|
||||
)
|
||||
// Token refresh flow.
|
||||
.route("/refresh", post(api::refresh::refresh_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/refresh"),
|
||||
post(api::refresh::refresh_handler),
|
||||
)
|
||||
// Login
|
||||
.route("/login", post(api::login::login_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/login"),
|
||||
post(api::login::login_handler),
|
||||
)
|
||||
// Converts auth code (+pkce code verifier) to auth tokens
|
||||
.route("/token", post(api::token::auth_code_to_token_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/token"),
|
||||
post(api::token::auth_code_to_token_handler),
|
||||
)
|
||||
// Login status (also let's one lift tokens from cookies).
|
||||
.route("/status", get(api::login::login_status_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/status"),
|
||||
get(api::login::login_status_handler),
|
||||
)
|
||||
// Logout [get]: deletes all sessions for the current user.
|
||||
.route("/logout", get(api::logout::logout_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/logout"),
|
||||
get(api::logout::logout_handler),
|
||||
)
|
||||
// Logout [post]: deletes given session
|
||||
.route("/logout", post(api::logout::post_logout_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/logout"),
|
||||
post(api::logout::post_logout_handler),
|
||||
)
|
||||
// Get a user's avatar.
|
||||
.route(
|
||||
"/avatar/:b64_user_id",
|
||||
&format!("/{AUTH_API_PATH}/avatar/{{b64_user_id}}"),
|
||||
get(api::avatar::get_avatar_url_handler),
|
||||
)
|
||||
// User delete.
|
||||
.route("/delete", delete(api::delete::delete_handler))
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/delete"),
|
||||
delete(api::delete::delete_handler),
|
||||
)
|
||||
// OAuth flows: list providers, login+callback
|
||||
.nest("/oauth", oauth::oauth_router());
|
||||
.nest(&format!("/{AUTH_API_PATH}/oauth"), oauth::oauth_router());
|
||||
}
|
||||
|
||||
/// Replicating minimal functionality of the above main router in case the admin dash is routed
|
||||
/// from a different port to prevent cross-origin requests.
|
||||
pub(super) fn admin_auth_router() -> Router<crate::AppState> {
|
||||
return Router::new()
|
||||
.route("/login", post(api::login::login_handler))
|
||||
.route("/status", get(api::login::login_status_handler))
|
||||
.route("/logout", get(api::logout::logout_handler));
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/login"),
|
||||
post(api::login::login_handler),
|
||||
)
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/status"),
|
||||
get(api::login::login_status_handler),
|
||||
)
|
||||
.route(
|
||||
&format!("/{AUTH_API_PATH}/logout"),
|
||||
get(api::logout::logout_handler),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -23,11 +23,11 @@ pub fn oauth_router() -> Router<AppState> {
|
||||
get(list_providers::list_configured_providers_handler),
|
||||
)
|
||||
.route(
|
||||
"/:provider/login",
|
||||
"/{provider}/login",
|
||||
get(login::login_with_external_auth_provider),
|
||||
)
|
||||
.route(
|
||||
"/:provider/callback",
|
||||
"/{provider}/callback",
|
||||
get(callback::callback_from_external_auth_provider),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use axum::{
|
||||
async_trait,
|
||||
extract::{FromRef, FromRequestParts},
|
||||
extract::{FromRef, FromRequestParts, OptionalFromRequestParts},
|
||||
http::{header, request::Parts},
|
||||
};
|
||||
use chrono::Duration;
|
||||
@@ -25,7 +24,6 @@ pub(crate) struct Tokens {
|
||||
pub refresh_token: Option<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for Tokens
|
||||
where
|
||||
AppState: FromRef<S>,
|
||||
@@ -45,6 +43,28 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> OptionalFromRequestParts<S> for Tokens
|
||||
where
|
||||
AppState: FromRef<S>,
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = AuthError;
|
||||
|
||||
async fn from_request_parts(
|
||||
parts: &mut Parts,
|
||||
state: &S,
|
||||
) -> Result<Option<Self>, Self::Rejection> {
|
||||
let state = AppState::from_ref(state);
|
||||
|
||||
if let Ok(tokens) = extract_tokens_from_headers(&state, &parts.headers).await {
|
||||
return Ok(Some(tokens));
|
||||
}
|
||||
|
||||
let cookies = extract_cookies_from_parts(parts)?;
|
||||
return Ok(extract_tokens_from_cookies(&state, &cookies).await.ok());
|
||||
}
|
||||
}
|
||||
|
||||
async fn extract_tokens_from_headers(
|
||||
state: &AppState,
|
||||
headers: &header::HeaderMap,
|
||||
|
||||
@@ -233,20 +233,20 @@ pub(crate) fn auth_ui_router() -> Router<crate::AppState> {
|
||||
);
|
||||
|
||||
return Router::new()
|
||||
.route("/login", get(ui_login_handler))
|
||||
.route("/logout", get(ui_logout_handler))
|
||||
.route("/register", get(ui_register_handler))
|
||||
.route("/_/auth/login", get(ui_login_handler))
|
||||
.route("/_/auth/logout", get(ui_logout_handler))
|
||||
.route("/_/auth/register", get(ui_register_handler))
|
||||
.route(
|
||||
"/reset_password/request",
|
||||
"/_/auth/reset_password/request",
|
||||
get(ui_reset_password_request_handler),
|
||||
)
|
||||
.route(
|
||||
"/reset_password/update",
|
||||
"/_/auth/reset_password/update",
|
||||
get(ui_reset_password_update_handler),
|
||||
)
|
||||
.route("/change_password", get(ui_change_password_handler))
|
||||
.route("/change_email", get(ui_change_email_handler))
|
||||
.nest_service("/", serve_auth_assets);
|
||||
.route("/_/auth/change_password", get(ui_change_password_handler))
|
||||
.route("/_/auth/change_email", get(ui_change_email_handler))
|
||||
.nest_service("/_/auth/", serve_auth_assets);
|
||||
}
|
||||
|
||||
fn hidden_input(name: &str, value: Option<&String>) -> String {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use axum::{
|
||||
async_trait,
|
||||
extract::{FromRef, FromRequestParts},
|
||||
extract::{FromRef, FromRequestParts, OptionalFromRequestParts},
|
||||
http::request::Parts,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -110,7 +109,6 @@ impl User {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for User
|
||||
where
|
||||
AppState: FromRef<S>,
|
||||
@@ -119,10 +117,30 @@ where
|
||||
type Rejection = AuthError;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||
let tokens = Tokens::from_request_parts(parts, state).await?;
|
||||
let tokens = <Tokens as FromRequestParts<S>>::from_request_parts(parts, state).await?;
|
||||
return User::from_token_claims(tokens.auth_token_claims);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> OptionalFromRequestParts<S> for User
|
||||
where
|
||||
AppState: FromRef<S>,
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = AuthError;
|
||||
|
||||
async fn from_request_parts(
|
||||
parts: &mut Parts,
|
||||
state: &S,
|
||||
) -> Result<Option<Self>, Self::Rejection> {
|
||||
let tokens = <Tokens as OptionalFromRequestParts<S>>::from_request_parts(parts, state).await?;
|
||||
if let Some(tokens) = tokens {
|
||||
return Ok(Some(User::from_token_claims(tokens.auth_token_claims)?));
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -165,6 +183,8 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
let (mut parts, _body) = request.into_parts();
|
||||
User::from_request_parts(&mut parts, &state).await.unwrap();
|
||||
<User as FromRequestParts<AppState>>::from_request_parts(&mut parts, &state)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,24 +107,27 @@ pub(crate) fn remove_all_cookies(cookies: &Cookies) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn extract_cookies_from_parts(parts: &mut Parts) -> Result<Cookies, AuthError> {
|
||||
let cookies = Cookies::default();
|
||||
|
||||
for ref header in parts.headers.get_all(axum::http::header::COOKIE) {
|
||||
cookies.add(Cookie::parse(header.to_str().unwrap().to_string()).unwrap());
|
||||
}
|
||||
|
||||
return Ok(cookies);
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub(crate) fn extract_cookies_from_parts(parts: &mut Parts) -> Result<Cookies, AuthError> {
|
||||
if let Some(cookies) = parts.extensions.get::<Cookies>() {
|
||||
return Ok(cookies.clone());
|
||||
};
|
||||
log::error!("Failed to get Cookies");
|
||||
return Err(AuthError::Internal("cookie error".into()));
|
||||
|
||||
// Fallback code for when handlers are called directly in unit tests w/o tower::Cookies
|
||||
// middleware to parse the cookies header for us.
|
||||
#[cfg(test)]
|
||||
{
|
||||
let cookies = Cookies::default();
|
||||
for ref header in parts.headers.get_all(axum::http::header::COOKIE) {
|
||||
cookies.add(Cookie::parse(header.to_str().unwrap().to_string()).unwrap());
|
||||
}
|
||||
return Ok(cookies);
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
log::error!("Failed to get Cookies");
|
||||
return Err(AuthError::Internal("cookie error".into()));
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn user_by_email(state: &AppState, email: &str) -> Result<DbUser, AuthError> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use axum::async_trait;
|
||||
use axum::extract::{rejection::*, Form, FromRequest, Request};
|
||||
use axum::http::header::CONTENT_TYPE;
|
||||
use axum::http::StatusCode;
|
||||
@@ -43,7 +42,6 @@ pub enum Either<T> {
|
||||
// Proto(DynamicMessage),
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S, T> FromRequest<S> for Either<T>
|
||||
where
|
||||
T: DeserializeOwned + Sync + Send + 'static,
|
||||
|
||||
@@ -758,21 +758,20 @@ pub(crate) async fn load_routes_from_js_modules(
|
||||
}
|
||||
};
|
||||
|
||||
let mut js_router = Some(Router::new());
|
||||
let mut js_router = Router::new();
|
||||
for module in modules {
|
||||
let fname = module.filename().to_owned();
|
||||
let router = install_routes(state.script_runtime(), module).await?;
|
||||
|
||||
if let Some(router) = router {
|
||||
js_router = Some(js_router.take().unwrap().nest("/", router));
|
||||
js_router = js_router.merge(router);
|
||||
} else {
|
||||
log::debug!("Skipping js module '{fname:?}': no routes");
|
||||
}
|
||||
}
|
||||
|
||||
let router = js_router.take().unwrap();
|
||||
if router.has_routes() {
|
||||
return Ok(Some(router));
|
||||
if js_router.has_routes() {
|
||||
return Ok(Some(js_router));
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
|
||||
@@ -24,6 +24,7 @@ pub(crate) use validate::validate_record_api_config;
|
||||
|
||||
use crate::config::proto::{PermissionFlag, RecordApiConfig};
|
||||
use crate::config::ConfigError;
|
||||
use crate::constants::RECORD_API_PATH;
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(OpenApi)]
|
||||
@@ -44,26 +45,38 @@ pub(super) struct RecordOpenApi;
|
||||
|
||||
pub(crate) fn router() -> Router<AppState> {
|
||||
return Router::new()
|
||||
.route("/:name/:record", get(read_record::read_record_handler))
|
||||
.route("/:name", post(create_record::create_record_handler))
|
||||
.route(
|
||||
"/:name/:record",
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/{{record}}"),
|
||||
get(read_record::read_record_handler),
|
||||
)
|
||||
.route(
|
||||
&format!("/{RECORD_API_PATH}/{{name}}"),
|
||||
post(create_record::create_record_handler),
|
||||
)
|
||||
.route(
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/{{record}}"),
|
||||
patch(update_record::update_record_handler),
|
||||
)
|
||||
.route(
|
||||
"/:name/:record",
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/{{record}}"),
|
||||
delete(delete_record::delete_record_handler),
|
||||
)
|
||||
.route("/:name", get(list_records::list_records_handler))
|
||||
.route(
|
||||
"/:name/:record/file/:column_name",
|
||||
&format!("/{RECORD_API_PATH}/{{name}}"),
|
||||
get(list_records::list_records_handler),
|
||||
)
|
||||
.route(
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/{{record}}/file/{{column_name}}"),
|
||||
get(read_record::get_uploaded_file_from_record_handler),
|
||||
)
|
||||
.route(
|
||||
"/:name/:record/files/:column_name/:file_index",
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/{{record}}/files/{{column_name}}/{{file_index}}"),
|
||||
get(read_record::get_uploaded_files_from_record_handler),
|
||||
)
|
||||
.route("/:name/schema", get(json_schema::json_schema_handler));
|
||||
.route(
|
||||
&format!("/{RECORD_API_PATH}/{{name}}/schema"),
|
||||
get(json_schema::json_schema_handler),
|
||||
);
|
||||
}
|
||||
|
||||
// Since this is for APIs access control, we'll use the API- space CRUD terminology instead of
|
||||
|
||||
@@ -19,9 +19,10 @@ use crate::app_state::AppState;
|
||||
use crate::assets::AssetService;
|
||||
use crate::auth::util::is_admin;
|
||||
use crate::auth::{self, AuthError, User};
|
||||
use crate::constants::{ADMIN_API_PATH, AUTH_API_PATH, HEADER_CSRF_TOKEN, RECORD_API_PATH};
|
||||
use crate::constants::{ADMIN_API_PATH, HEADER_CSRF_TOKEN};
|
||||
use crate::data_dir::DataDir;
|
||||
use crate::logging;
|
||||
use crate::records;
|
||||
use crate::scheduler;
|
||||
|
||||
pub use init::{init_app_state, InitArgs, InitError};
|
||||
@@ -114,7 +115,7 @@ impl Server {
|
||||
.map_err(|err| InitError::ScriptError(err.to_string()))?;
|
||||
|
||||
if let Some(js_routes) = js_routes {
|
||||
Some(custom_routes.unwrap_or_default().nest("/", js_routes))
|
||||
Some(custom_routes.unwrap_or_default().merge(js_routes))
|
||||
} else {
|
||||
custom_routes
|
||||
}
|
||||
@@ -233,8 +234,8 @@ impl Server {
|
||||
}
|
||||
|
||||
let router = Router::new()
|
||||
.nest(&format!("/{AUTH_API_PATH}"), auth::admin_auth_router())
|
||||
.nest("/", Self::build_admin_router(state));
|
||||
.merge(auth::admin_auth_router())
|
||||
.merge(Self::build_admin_router(state));
|
||||
|
||||
return Some((
|
||||
address.clone(),
|
||||
@@ -249,20 +250,20 @@ impl Server {
|
||||
) -> (String, Router<()>) {
|
||||
let mut router = Router::new()
|
||||
// Public, stable and versioned APIs.
|
||||
.nest(&format!("/{RECORD_API_PATH}"), crate::records::router())
|
||||
.nest(&format!("/{AUTH_API_PATH}"), auth::router())
|
||||
.merge(records::router())
|
||||
.merge(auth::router())
|
||||
.route("/api/healthcheck", get(healthcheck_handler));
|
||||
|
||||
if !has_indepenedent_admin_router(opts) {
|
||||
router = router.nest("/", Self::build_admin_router(state));
|
||||
router = router.merge(Self::build_admin_router(state));
|
||||
}
|
||||
|
||||
if !opts.disable_auth_ui {
|
||||
router = router.nest("/_/auth", crate::auth::auth_ui_router());
|
||||
router = router.merge(auth::auth_ui_router());
|
||||
}
|
||||
|
||||
if let Some(custom_router) = custom_router {
|
||||
router = router.nest("/", custom_router);
|
||||
router = router.merge(custom_router);
|
||||
}
|
||||
|
||||
if let Some(public_dir) = &opts.public_dir {
|
||||
|
||||
Reference in New Issue
Block a user