From 55f8281b19ce6070180acdef6677aaaf6f61ea55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bardon?= Date: Wed, 21 Aug 2024 23:30:30 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20WIP=20Migrate=20from=20Rocket=20?= =?UTF-8?q?to=20Axum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serving pages and 404 work, need to finish authentication. --- src/Cargo.lock | 1240 +++++++---------- src/Cargo.toml | 10 +- src/helpers/Cargo.toml | 7 +- src/helpers/src/config.rs | 14 +- src/helpers/src/generate.rs | 8 +- src/helpers/src/lib.rs | 175 ++- src/helpers/src/readers/mod.rs | 1 - src/helpers/src/readers/object_reader.rs | 106 -- src/orangutan-server/Cargo.toml | 1 + src/orangutan-server/src/main.rs | 103 +- src/orangutan-server/src/request_guards.rs | 91 +- .../src/routes/debug_routes.rs | 41 +- src/orangutan-server/src/routes/main_route.rs | 73 +- src/orangutan-server/src/routes/mod.rs | 6 +- .../src/routes/update_content_routes.rs | 8 +- src/orangutan-server/src/util/website_root.rs | 29 +- 16 files changed, 861 insertions(+), 1052 deletions(-) delete mode 100644 src/helpers/src/readers/object_reader.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index f56bf31..2f47407 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -48,58 +83,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] -name = "async-stream" -version = "0.3.5" +name = "async-trait" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", + "proc-macro2", + "quote", + "syn 2.0.75", ] [[package]] -name = "async-stream-impl" -version = "0.3.5" +name = "autocfg" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] -name = "async-trait" -version = "0.1.81" +name = "axum" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", + "async-trait", + "axum-core", + "axum-macros", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "atomic" -version = "0.5.3" +name = "axum-core" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "atomic" -version = "0.6.0" +name = "axum-extra" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" dependencies = [ - "bytemuck", + "axum", + "axum-core", + "bytes", + "cookie", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "serde", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "autocfg" -version = "1.3.0" +name = "axum-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.75", +] [[package]] name = "backtrace" @@ -134,12 +223,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "binascii" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" - [[package]] name = "biscuit-auth" version = "5.0.0" @@ -231,12 +314,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "bytemuck" -version = "1.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" - [[package]] name = "byteorder" version = "1.5.0" @@ -251,9 +328,12 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.8" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -271,8 +351,9 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -297,6 +378,16 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -309,22 +400,26 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ + "aes-gcm", + "base64 0.22.1", "percent-encoding", + "rand", + "subtle", "time", "version_check", ] [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -361,9 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -388,66 +493,69 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] -name = "der" -version = "0.7.9" +name = "darling" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "const-oid", - "zeroize", + "darling_core", + "darling_macro", ] [[package]] -name = "deranged" -version = "0.3.11" +name = "darling_core" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ - "powerfmt", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.75", ] [[package]] -name = "deunicode" -version = "1.6.0" +name = "darling_macro" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.75", +] [[package]] -name = "devise" -version = "0.4.1" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "devise_codegen", - "devise_core", + "const-oid", + "zeroize", ] [[package]] -name = "devise_codegen" -version = "0.4.1" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "devise_core", - "quote", + "powerfmt", + "serde", ] [[package]] -name = "devise_core" -version = "0.4.1" +name = "deunicode" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" -dependencies = [ - "bitflags", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.72", -] +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" [[package]] name = "digest" @@ -499,57 +607,18 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "figment" -version = "0.10.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" -dependencies = [ - "atomic 0.6.0", - "pear", - "serde", - "toml", - "uncased", - "version_check", -] - [[package]] name = "fnv" version = "1.0.7" @@ -557,17 +626,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "futures" -version = "0.3.30" +name = "form_urlencoded" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "percent-encoding", ] [[package]] @@ -577,7 +641,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -586,12 +649,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - [[package]] name = "futures-sink" version = "0.3.30" @@ -610,28 +667,10 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ - "futures-channel", "futures-core", - "futures-io", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", - "slab", -] - -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", ] [[package]] @@ -667,16 +706,20 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.29.0" +name = "ghash" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] [[package]] -name = "glob" -version = "0.3.1" +name = "gimli" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "globset" @@ -703,23 +746,10 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.26" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" @@ -727,6 +757,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -741,9 +777,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -751,27 +787,34 @@ dependencies = [ ] [[package]] -name = "http" -version = "1.1.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "fnv", - "itoa", + "http", ] [[package]] -name = "http-body" -version = "0.4.6" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "http 0.2.12", + "futures-util", + "http", + "http-body", "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" + [[package]] name = "httparse" version = "1.9.4" @@ -795,26 +838,36 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.30" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", - "h2", - "http 0.2.12", + "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", "tokio", - "tower-service", - "tracing", - "want", ] [[package]] @@ -840,6 +893,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "ignore" version = "0.4.22" @@ -858,30 +917,33 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "equivalent", - "hashbrown", + "autocfg", + "hashbrown 0.12.3", "serde", ] [[package]] -name = "inlinable_string" -version = "0.1.15" +name = "indexmap" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] [[package]] -name = "is-terminal" -version = "0.4.12" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", + "generic-array", ] [[package]] @@ -910,9 +972,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -925,9 +987,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -935,43 +997,12 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - [[package]] name = "matchers" version = "0.1.0" @@ -981,6 +1012,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.4" @@ -993,6 +1030,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1010,9 +1057,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", @@ -1020,25 +1067,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.1.0", - "httparse", - "memchr", - "mime", - "spin", - "tokio", - "tokio-util", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -1074,16 +1102,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.36.3" @@ -1107,14 +1125,17 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orangutan-helpers" -version = "0.1.1" +version = "0.2.0" dependencies = [ + "axum", "biscuit-auth", "hex", "lazy_static", - "rocket", + "serde", "serde_json", + "serde_with", "thiserror", + "tower-http", "tracing", ] @@ -1146,20 +1167,27 @@ dependencies = [ [[package]] name = "orangutan-server" -version = "0.4.13" +version = "0.5.0" dependencies = [ + "axum", + "axum-extra", "base64 0.22.1", "biscuit-auth", "chrono", "hex", "lazy_static", + "mime", "orangutan-helpers", "orangutan-refresh-token", - "rocket", + "serde", "serde_json", + "serde_urlencoded", "tera", "thiserror", "time", + "tokio", + "tower 0.5.0", + "tower-http", "tracing", "tracing-subscriber", "urlencoding", @@ -1171,29 +1199,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - [[package]] name = "parse-zoneinfo" version = "0.3.1" @@ -1203,29 +1208,6 @@ dependencies = [ "regex", ] -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.72", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1263,7 +1245,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1315,6 +1297,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1337,6 +1339,18 @@ dependencies = [ "spki", ] +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1385,19 +1399,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "version_check", - "yansi", -] - [[package]] name = "prost" version = "0.10.4" @@ -1447,56 +1448,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags", + "rand_chacha", + "rand_core", ] [[package]] -name = "ref-cast" -version = "1.0.23" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "ref-cast-impl", + "ppv-lite86", + "rand_core", ] [[package]] -name = "ref-cast-impl" -version = "1.0.23" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", + "getrandom 0.2.15", ] [[package]] @@ -1543,87 +1515,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "rocket" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" -dependencies = [ - "async-stream", - "async-trait", - "atomic 0.5.3", - "binascii", - "bytes", - "either", - "figment", - "futures", - "indexmap", - "log", - "memchr", - "multer", - "num_cpus", - "parking_lot", - "pin-project-lite", - "rand", - "ref-cast", - "rocket_codegen", - "rocket_http", - "serde", - "state", - "tempfile", - "time", - "tokio", - "tokio-stream", - "tokio-util", - "ubyte", - "version_check", - "yansi", -] - -[[package]] -name = "rocket_codegen" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" -dependencies = [ - "devise", - "glob", - "indexmap", - "proc-macro2", - "quote", - "rocket_http", - "syn 2.0.72", - "unicode-xid", - "version_check", -] - -[[package]] -name = "rocket_http" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" -dependencies = [ - "cookie", - "either", - "futures", - "http 0.2.12", - "hyper", - "indexmap", - "log", - "memchr", - "pear", - "percent-encoding", - "pin-project-lite", - "ref-cast", - "serde", - "smallvec", - "stable-pattern", - "state", - "time", - "tokio", - "uncased", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1639,19 +1530,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -1673,18 +1551,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "semver" version = "1.0.23" @@ -1693,29 +1559,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -1724,12 +1590,55 @@ dependencies = [ ] [[package]] -name = "serde_spanned" -version = "0.6.7" +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.4.0", "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.75", ] [[package]] @@ -1766,13 +1675,10 @@ dependencies = [ ] [[package]] -name = "signal-hook-registry" -version = "1.4.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signature" @@ -1789,20 +1695,11 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - [[package]] name = "slug" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" dependencies = [ "deunicode", "wasm-bindgen", @@ -1824,12 +1721,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "spki" version = "0.7.3" @@ -1841,22 +1732,10 @@ dependencies = [ ] [[package]] -name = "stable-pattern" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" -dependencies = [ - "memchr", -] - -[[package]] -name = "state" -version = "0.6.0" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -1877,9 +1756,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1887,17 +1766,16 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.12.0" +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "tera" @@ -1938,7 +1816,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1984,16 +1862,15 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", "libc", "mio", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -2007,72 +1884,84 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "tokio-util" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ + "bytes", "futures-core", + "futures-sink", "pin-project-lite", "tokio", ] [[package]] -name = "tokio-util" -version = "0.7.11" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "bytes", "futures-core", - "futures-sink", + "futures-util", + "pin-project", "pin-project-lite", "tokio", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "toml" -version = "0.8.19" +name = "tower" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7" dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "tower-layer", + "tower-service", ] [[package]] -name = "toml_datetime" -version = "0.6.8" +name = "tower-http" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "serde", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "toml_edit" -version = "0.22.20" +name = "tower-layer" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2080,6 +1969,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2093,7 +1983,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -2135,43 +2025,18 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ubyte" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" -dependencies = [ - "serde", -] - [[package]] name = "ucd-trie" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "uncased" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" -dependencies = [ - "serde", - "version_check", -] - [[package]] name = "unic-char-property" version = "0.9.0" @@ -2222,6 +2087,15 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -2229,10 +2103,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-xid" -version = "0.2.4" +name = "universal-hash" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] [[package]] name = "urlencoding" @@ -2262,15 +2140,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -2285,34 +2154,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2320,22 +2190,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "winapi" @@ -2368,22 +2238,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2392,7 +2253,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2401,22 +2262,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -2425,46 +2271,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2477,72 +2305,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" -dependencies = [ - "memchr", -] - -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -dependencies = [ - "is-terminal", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -2561,7 +2347,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] diff --git a/src/Cargo.toml b/src/Cargo.toml index 5f5ce8c..3b0d86e 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -9,17 +9,25 @@ members = [ resolver = "2" [workspace.dependencies] +axum = { version = "0.7", features = ["macros"] } +axum-extra = { version = "0.9", features = ["cookie-private"] } base64 = "0.22" biscuit-auth = "5" chrono = "0.4" hex = "0.4" iso8601-duration = "0.2" lazy_static = "1" -rocket = "0.5" +mime = "0.3" +serde = { version = "1", features = ["derive"] } serde_json = "1" +serde_urlencoded = "0.7" +serde_with = "3" tera = "1" thiserror = "1" time = "0.3" +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tower = "0.5" +tower-http = { version = "0.5", features = ["fs", "trace"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } urlencoding = "2" diff --git a/src/helpers/Cargo.toml b/src/helpers/Cargo.toml index ce5e1d2..ebddf64 100644 --- a/src/helpers/Cargo.toml +++ b/src/helpers/Cargo.toml @@ -1,15 +1,18 @@ [package] name = "orangutan-helpers" -version = "0.1.1" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +axum = { workspace = true } biscuit-auth = { workspace = true } hex = { workspace = true } lazy_static = { workspace = true } -rocket = { workspace = true } +serde = { workspace = true } serde_json = { workspace = true } +serde_with = { workspace = true } thiserror = { workspace = true } +tower-http = { workspace = true } tracing = { workspace = true } diff --git a/src/helpers/src/config.rs b/src/helpers/src/config.rs index 1c45e6d..8ef65aa 100644 --- a/src/helpers/src/config.rs +++ b/src/helpers/src/config.rs @@ -4,26 +4,24 @@ use lazy_static::lazy_static; pub const THEME_NAME: &str = "Orangutan"; pub const DATA_FILE_EXTENSION: &str = "orangutan"; -pub(super) const READ_ALLOWED_FIELD: &str = "read_allowed"; -pub const PATH_FIELD: &str = "path"; pub const DEFAULT_PROFILE: &str = "_default"; pub const ROOT_KEY_NAME: &'static str = "_biscuit_root"; pub(super) const WEBSITE_DIR_NAME: &'static str = "website"; lazy_static! { - static ref WORK_DIR: PathBuf = env::current_dir().unwrap(); pub static ref WEBSITE_REPOSITORY: String = env::var("WEBSITE_REPOSITORY") .expect("Environment variable `WEBSITE_REPOSITORY` is required."); + pub static ref MODE: Result = env::var("MODE"); + pub static ref KEYS_MODE: Result = env::var("KEYS_MODE"); +} +lazy_static! { + static ref WORK_DIR: PathBuf = env::current_dir().unwrap(); pub static ref BASE_DIR: PathBuf = WORK_DIR.join(".orangutan"); pub static ref TMP_DIR: PathBuf = BASE_DIR.join("tmp"); pub static ref KEYS_DIR: PathBuf = BASE_DIR.join("keys"); - pub static ref MODE: Result = env::var("MODE"); - pub static ref KEYS_MODE: Result = env::var("KEYS_MODE"); - pub(super) static ref WEBSITE_ROOT: PathBuf = BASE_DIR.join("website"); + pub(super) static ref WEBSITE_ROOT: PathBuf = BASE_DIR.join("website-src"); pub(super) static ref HUGO_CONFIG_DIR: PathBuf = BASE_DIR.join("hugo-config"); pub static ref DEST_DIR: PathBuf = BASE_DIR.join("out"); pub static ref WEBSITE_DATA_DIR: PathBuf = DEST_DIR.join("data"); - pub(super) static ref SUFFIXED_EXTENSIONS: Vec<&'static str> = - vec!["html", "json", "xml", "css", "js", "txt"]; } diff --git a/src/helpers/src/generate.rs b/src/helpers/src/generate.rs index 315bd1b..1415de0 100644 --- a/src/helpers/src/generate.rs +++ b/src/helpers/src/generate.rs @@ -406,14 +406,14 @@ pub fn trash_outdated_websites() -> Result { hugo_config_generated: HUGO_CONFIG_GENERATED.load(Ordering::Relaxed), data_files_generated: DATA_FILES_GENERATED.load(Ordering::Relaxed), generated_websites: GENERATED_WEBSITES.lock().unwrap().to_owned(), - used_profiles: super::USED_PROFILES.lock().unwrap().to_owned(), + used_profiles: super::USED_PROFILES.read().unwrap().to_owned(), }; // Clear caches HUGO_CONFIG_GENERATED.store(false, Ordering::Relaxed); DATA_FILES_GENERATED.store(false, Ordering::Relaxed); GENERATED_WEBSITES.lock().unwrap().clear(); - *super::USED_PROFILES.lock().unwrap() = None; + *super::USED_PROFILES.write().unwrap() = None; Ok(state) } @@ -428,7 +428,7 @@ pub fn recover_trash(state: State) -> Result<(), Error> { HUGO_CONFIG_GENERATED.store(state.hugo_config_generated, Ordering::Relaxed); DATA_FILES_GENERATED.store(state.data_files_generated, Ordering::Relaxed); *GENERATED_WEBSITES.lock().unwrap() = state.generated_websites; - *super::USED_PROFILES.lock().unwrap() = state.used_profiles; + *super::USED_PROFILES.write().unwrap() = state.used_profiles; Ok(()) } @@ -456,4 +456,6 @@ pub enum Error { CannotCreateHugoConfigFile(io::Error), #[error("IO error: {0}")] IOError(#[from] io::Error), + #[error("Could not read page metadata: JSON error: {0}")] + CannotReadPageMetadata(serde_json::Error), } diff --git a/src/helpers/src/lib.rs b/src/helpers/src/lib.rs index 31c861b..820d090 100644 --- a/src/helpers/src/lib.rs +++ b/src/helpers/src/lib.rs @@ -7,48 +7,61 @@ use std::{ collections::HashSet, fs::{self, File}, io, - path::{Path, PathBuf}, - sync::{Arc, Mutex}, + ops::Deref, + path::PathBuf, + sync::{Arc, RwLock}, }; use lazy_static::lazy_static; -use serde_json::Value; -use tracing::trace; +use serde::{de::DeserializeOwned, Deserialize}; +use serde_with::{serde_as, DefaultOnNull}; +use tracing::{debug, error, trace}; use crate::config::*; lazy_static! { - static ref USED_PROFILES: Arc>>> = - Arc::new(Mutex::new(None)); + static ref USED_PROFILES: Arc>>> = Arc::default(); } pub fn used_profiles<'a>() -> &'a HashSet { - let mut used_profiles = USED_PROFILES.lock().unwrap(); - if let Some(profiles) = used_profiles.clone() { + if let Some(profiles) = *USED_PROFILES.read().unwrap() { trace!("Read used profiles from cache"); return profiles; } - trace!("Reading used profiles…"); + debug!("Reading all used profiles…"); let acc: &'static mut HashSet = Box::leak(Box::new(HashSet::new())); for data_file in find_data_files() { // trace!("Reading <{}>…", data_file.display()); - // Make sure this generator isn't broken (could be replaced by unit tests) - // let html_file = html_file(&data_file).unwrap(); - // trace!("{}", html_file.display()); - - let read_allowed = read_allowed(&data_file).unwrap(); + let metadata: PageMetadata = match deser(&data_file) { + Ok(Some(metadata)) => metadata, + Ok(None) => { + error!( + "Could not read page metadata at <{}>: File not found", + data_file.display(), + ); + continue; + }, + Err(err) => { + error!( + "Could not read page metadata at <{}>: {err}", + data_file.display(), + ); + continue; + }, + }; + let read_allowed = metadata.read_allowed; // trace!(" read_allowed: {:?}", read_allowed); // Store new profiles - read_allowed.iter().for_each(|p| { - acc.insert(p.clone()); + read_allowed.into_iter().for_each(|p| { + acc.insert(p.to_owned()); }); } - *used_profiles = Some(acc); + *USED_PROFILES.write().unwrap() = Some(acc); acc } @@ -76,43 +89,13 @@ pub fn find( } } -fn _html_file(data_file: &PathBuf) -> Option> { - let file = File::open(data_file).ok()?; - let reader = io::BufReader::new(file); - let data: Value = match serde_json::from_reader(reader) { - Ok(data) => data, - Err(_) => return None, - }; - - let path = data.get(PATH_FIELD)?; - - Some(serde_json::from_value(path.to_owned()).ok()) -} - -// fn html_file(data_file: &PathBuf) -> Result { -// match _html_file(data_file) { -// Some(Some(path)) => Ok(path), -// Some(None) => { -// error!("Path not defined"); -// Err(()) -// }, -// None => { -// error!("File not found"); -// Err(()) -// }, -// } -// } - -pub fn data_file(html_file: &PathBuf) -> PathBuf { - let mut data_file_rel = html_file - .strip_prefix(WEBSITE_DATA_DIR.to_path_buf()) - .unwrap_or(html_file) - .with_extension(DATA_FILE_EXTENSION); - data_file_rel = match data_file_rel.strip_prefix("/") { +pub fn data_file_path(page_relpath: &PathBuf) -> PathBuf { + let mut data_file_relpath = page_relpath.with_extension(DATA_FILE_EXTENSION); + data_file_relpath = match data_file_relpath.strip_prefix("/") { Ok(trimmed) => trimmed.to_path_buf(), - Err(_) => data_file_rel, + Err(_) => data_file_relpath, }; - WEBSITE_DATA_DIR.join(data_file_rel) + WEBSITE_DATA_DIR.join(data_file_relpath) } fn find_data_files() -> Vec { @@ -125,35 +108,81 @@ fn find_data_files() -> Vec { data_files } -fn _read_allowed(data_file: &PathBuf) -> Option>> { - let file = File::open(data_file).ok()?; - let reader = io::BufReader::new(file); - let data: Value = match serde_json::from_reader(reader) { - Ok(data) => data, - Err(_) => return None, - }; +#[serde_as] +#[derive(Deserialize)] +pub struct PageMetadata { + // NOTE: Hugo taxonomy term pages contain `read_allowed": null`. + // TODO: Investigate and fix this, to remove the `serde` default which could be in conflict with the user's preference. + #[serde(default)] + #[serde_as(deserialize_as = "DefaultOnNull")] + pub read_allowed: ReadAllowed, + pub path: PathBuf, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct ReadAllowed(Vec); - let read_allowed = data.get(READ_ALLOWED_FIELD)?; +impl Deref for ReadAllowed { + type Target = Vec; - Some(serde_json::from_value(read_allowed.to_owned()).ok()) + fn deref(&self) -> &Self::Target { + &self.0 + } } -// `None` if file not found -pub fn read_allowed(data_file: &PathBuf) -> Option> { - _read_allowed(data_file).map(|o| o.unwrap_or(vec![DEFAULT_PROFILE.to_string()])) +impl Default for ReadAllowed { + fn default() -> Self { + Self(vec![DEFAULT_PROFILE.to_owned()]) + } } -pub fn object_key>( - path: &P, - profile: &str, -) -> String { - let path = path.as_ref(); - if let Some(ext) = path.extension() { - if SUFFIXED_EXTENSIONS.contains(&ext.to_str().unwrap()) { - return format!("{}@{}", path.display(), profile); +impl IntoIterator for ReadAllowed { + type Item = <::Target as IntoIterator>::Item; + type IntoIter = <::Target as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +fn deser(file_path: &PathBuf) -> Result, serde_json::Error> { + let Ok(file) = File::open(file_path) else { + return Ok(None); + }; + let res: T = serde_json::from_reader(file)?; + Ok(Some(res)) +} + +fn deser_first_match( + file_paths: Vec +) -> Result, serde_json::Error> { + for file_path in file_paths.iter() { + trace!("Trying {}…", file_path.display()); + match deser(file_path)? { + Some(res) => { + // TODO: Check if this index is always the same. + // debug!("Found page metadata in match #{i}"); + return Ok(Some(res)); + }, + None => continue, } } - path.display().to_string() + Ok(None) +} + +// `Ok(None)` if file not found. +// `Err(_)` if file found but deserialization error. +// `Ok(Some(_))` if file found. +pub fn page_metadata(page_relpath: &PathBuf) -> Result, serde_json::Error> { + let mut file_paths = vec![ + data_file_path(page_relpath), + data_file_path(&page_relpath.join("index.html")), + ]; + // Don't try parsing the exact path if it points to a directory. + if page_relpath.is_dir() { + file_paths.remove(0); + } + deser_first_match(file_paths) } pub fn copy_directory( diff --git a/src/helpers/src/readers/mod.rs b/src/helpers/src/readers/mod.rs index 134b6d7..1878936 100644 --- a/src/helpers/src/readers/mod.rs +++ b/src/helpers/src/readers/mod.rs @@ -1,2 +1 @@ pub mod keys_reader; -pub mod object_reader; diff --git a/src/helpers/src/readers/object_reader.rs b/src/helpers/src/readers/object_reader.rs deleted file mode 100644 index 621d716..0000000 --- a/src/helpers/src/readers/object_reader.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::{fs, io, path::PathBuf}; - -use rocket::{fs::NamedFile, response::Responder}; -use tracing::trace; - -use crate::{ - generate::{self, generate_website_if_needed}, - website_id::WebsiteId, -}; - -pub type ObjectReader = LocalObjectReader; - -impl ObjectReader { - pub fn new() -> Self { - LocalObjectReader {} - } -} - -pub type ReadObjectResponse = LocalReadObjectResponse; - -pub struct LocalObjectReader; - -#[derive(Responder)] -pub enum LocalReadObjectResponse { - #[response(status = 404)] - NotFound(String), - Found(Result), -} - -impl LocalObjectReader { - async fn serve_file(file_path: PathBuf) -> io::Result { - NamedFile::open(file_path).await - } -} - -impl LocalObjectReader { - pub fn list_objects( - &self, - prefix: &str, - website_id: &WebsiteId, - ) -> Result, Error> { - trace!("Listing files with prefix '{}' for {}…", prefix, website_id); - - let website_dir = - generate_website_if_needed(website_id).map_err(Error::WebsiteGenerationError)?; - - Ok(find_all_files(&website_dir) - .iter() - .map(|path| { - format!( - "/{}", - path.strip_prefix(website_dir.as_path()) - .expect("Could not remove prefix") - .display() - ) - }) - .collect()) - } - - pub async fn read_object<'r>( - &self, - object_key: &str, - website_id: &WebsiteId, - ) -> LocalReadObjectResponse { - let website_dir = match generate_website_if_needed(website_id) { - Ok(dir) => dir, - Err(err) => return LocalReadObjectResponse::NotFound(err.to_string()), - }; - let file_path = website_dir.join(object_key.strip_prefix("/").unwrap()); - trace!( - "Reading '{}' from disk at <{}>…", - object_key, - file_path.display() - ); - - LocalReadObjectResponse::Found(Self::serve_file(file_path).await) - } -} - -fn find_all_files(dir: &PathBuf) -> Vec { - let mut files: Vec = Vec::new(); - find(dir, &mut files); - files -} - -fn find( - dir: &PathBuf, - files: &mut Vec, -) { - for entry in fs::read_dir(dir).unwrap() { - if let Ok(entry) = entry { - let path = entry.path(); - if path.is_file() { - files.push(path); - } else if path.is_dir() { - find(&path, files); - } - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Website generation error: {0}")] - WebsiteGenerationError(generate::Error), -} diff --git a/src/orangutan-server/Cargo.toml b/src/orangutan-server/Cargo.toml index 66ef348..4700720 100644 --- a/src/orangutan-server/Cargo.toml +++ b/src/orangutan-server/Cargo.toml @@ -18,6 +18,7 @@ orangutan-helpers = { path = "../helpers" } orangutan-refresh-token = { path = "../orangutan-refresh-token" } serde = { workspace = true } serde_json = { workspace = true } +serde_urlencoded = { workspace = true } tera = { workspace = true, optional = true } thiserror = { workspace = true } time = { workspace = true } diff --git a/src/orangutan-server/src/main.rs b/src/orangutan-server/src/main.rs index 81fe42f..77199c6 100644 --- a/src/orangutan-server/src/main.rs +++ b/src/orangutan-server/src/main.rs @@ -3,12 +3,16 @@ mod request_guards; mod routes; mod util; +use std::{fs, process::ExitCode}; + use axum::{ - http::{Response, StatusCode}, - response::IntoResponse, - routing::get, + extract::FromRef, + http::StatusCode, + middleware, + response::{IntoResponse, Response}, Router, }; +use axum_extra::extract::cookie::Key; use orangutan_helpers::{ generate::{self, *}, website_id::WebsiteId, @@ -20,32 +24,43 @@ use tower_http::{services::ServeFile, trace::TraceLayer}; use tracing::debug; use tracing::{info, warn}; use tracing_subscriber::{EnvFilter, FmtSubscriber}; +use util::WebsiteRoot; #[cfg(feature = "templating")] use crate::util::templating; -use crate::{ - config::NOT_FOUND_FILE, - routes::{main_route, update_content_routes}, - util::error, -}; +use crate::{config::NOT_FOUND_FILE, routes::update_content_routes, util::error}; -#[derive(Clone, Default)] +#[derive(Clone)] struct AppState { + website_root: WebsiteRoot, + cookie_key: Key, #[cfg(feature = "templating")] tera: Tera, } +impl FromRef for Key { + fn from_ref(state: &AppState) -> Self { + state.cookie_key.clone() + } +} + #[tokio::main] -async fn main() { - // build our application with a single route - let app = Router::new().nest("/", routes::router()).layer( - ServiceBuilder::new() - .layer(TraceLayer::new_for_http()) - .layer(handle_refresh_token), - ); - // .register("/", catchers![unauthorized, forbidden, not_found]) +async fn main() -> ExitCode { + let website_root = match WebsiteRoot::try_from_env() { + Ok(r) => r, + Err(err) => { + tracing::error!("{err}"); + return ExitCode::FAILURE; + }, + }; - let mut app_state = AppState::default(); + let mut app_state = AppState { + website_root, + // FIXME: Use predefined key. + cookie_key: Key::generate(), + #[cfg(feature = "templating")] + tera: Default::default(), + }; info!("Setting up tracing…"); let subscriber = FmtSubscriber::builder() @@ -59,20 +74,31 @@ async fn main() { info!("Initializing templating engine…"); if let Err(err) = app_state.tera.add_raw_templates(routes::templates()) { tracing::error!("{err}"); - std::process::exit(1) + return ExitCode::FAILURE; } } + let app = Router::new() + .nest("/", routes::router()) + .layer(TraceLayer::new_for_http()) + .route_layer(middleware::from_fn_with_state( + app_state.clone(), + handle_refresh_token, + )) + .with_state(app_state); + // .register("/", catchers![unauthorized, forbidden, not_found]) + info!("Generating default website"); if let Err(err) = liftoff() { - panic!("{err}"); + tracing::error!("{err}"); + return ExitCode::FAILURE; } - let app = app.with_state(app_state); - // Run our app with hyper, listening globally on port 8080. let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap(); axum::serve(listener, app).await.unwrap(); + + return ExitCode::SUCCESS; } fn liftoff() -> Result<(), Error> { @@ -102,19 +128,28 @@ async fn not_found() -> Result { let website_dir = match generate_website_if_needed(&website_id) { Ok(dir) => dir, Err(err) => { - error(format!("Could not get default website directory: {}", err)); + error(format!("Could not get default website directory: {err}")); return Err("This page doesn't exist or you are not allowed to see it."); }, }; let file_path = website_dir.join(NOT_FOUND_FILE); - ServeFile::open(file_path.clone()).await.map_err(|err| { - error(format!( - "Could not read \"not found\" file at <{}>: {}", - file_path.display(), - err - )); - "This page doesn't exist or you are not allowed to see it." - }) + match fs::exists(&file_path) { + Ok(true) => Ok(ServeFile::new(file_path.clone())), + Ok(false) => { + error(format!( + "Could not read \"not found\" file at <{}>: File doesn't exist.", + file_path.display(), + )); + Err("This page doesn't exist or you are not allowed to see it.") + }, + Err(err) => { + error(format!( + "Could not read \"not found\" file at <{}>: {err}", + file_path.display(), + )); + Err("This page doesn't exist or you are not allowed to see it.") + }, + } } #[derive(Debug, thiserror::Error)] @@ -143,16 +178,16 @@ impl IntoResponse for Error { match self { Self::Unauthorized => { warn!("{self}"); - StatusCode::UNAUTHORIZED.into() + StatusCode::UNAUTHORIZED.into_response() }, #[cfg(feature = "templating")] Self::ClientError(_) => { debug!("{self}"); - StatusCode::BAD_REQUEST.into() + StatusCode::BAD_REQUEST.into_response() }, _ => { error(format!("{self}")); - StatusCode::INTERNAL_SERVER_ERROR.into() + StatusCode::INTERNAL_SERVER_ERROR.into_response() }, } } diff --git a/src/orangutan-server/src/request_guards.rs b/src/orangutan-server/src/request_guards.rs index ea931c7..3688c98 100644 --- a/src/orangutan-server/src/request_guards.rs +++ b/src/orangutan-server/src/request_guards.rs @@ -1,17 +1,21 @@ use std::{ collections::{HashMap, HashSet}, ops::Deref, + str::FromStr, sync::RwLock, time::SystemTime, }; use axum::{ - extract::{rejection::QueryRejection, FromRequestParts, Query, Request}, - http::{request, HeaderMap, StatusCode, Uri}, + extract::{rejection::QueryRejection, FromRef, FromRequestParts, Query, Request, State}, + http::{request, HeaderMap, HeaderValue, StatusCode, Uri}, middleware::Next, response::{IntoResponse, Redirect, Response}, }; -use axum_extra::extract::PrivateCookieJar; +use axum_extra::{ + either::Either, + extract::{cookie::Key, PrivateCookieJar}, +}; use biscuit_auth::{macros::authorizer, Biscuit}; use lazy_static::lazy_static; use tracing::{debug, trace}; @@ -19,6 +23,7 @@ use tracing::{debug, trace}; use crate::{ config::*, util::{add_cookie, add_padding, error, profiles}, + AppState, }; lazy_static! { @@ -56,7 +61,7 @@ impl IntoResponse for TokenError { fn into_response(self) -> Response { match self { Self::InvalidQuery(err) => err.into_response(), - Self::Unauthorized => StatusCode::UNAUTHORIZED.into(), + Self::Unauthorized => StatusCode::UNAUTHORIZED.into_response(), } } } @@ -65,6 +70,7 @@ impl IntoResponse for TokenError { impl FromRequestParts for Token where S: Send + Sync, + Key: FromRef, { type Rejection = TokenError; @@ -113,7 +119,10 @@ where } // Check cookies - let cookies = PrivateCookieJar::from_request_parts(parts, state).await?; + let cookies = PrivateCookieJar::from_request_parts(parts, state) + .await + .map_err(|err| match err {}) + .unwrap(); if let Some(cookie) = cookies.get(TOKEN_COOKIE_NAME) { debug!("Found token cookie"); let token: &str = cookie.value(); @@ -127,13 +136,24 @@ where } // Check authorization headers - let headers = HeaderMap::from_request_parts(parts, state).await?; - let authorization_headers: Vec<&str> = headers.get("Authorization").collect(); + let headers = HeaderMap::from_request_parts(parts, state) + .await + .map_err(|err| match err {}) + .unwrap(); + let authorization_headers: Vec<&HeaderValue> = + headers.get_all("Authorization").into_iter().collect(); debug!( "{} 'Authorization' headers provided", authorization_headers.len() ); for authorization in authorization_headers { + let authorization = match authorization.to_str() { + Ok(str) => str, + Err(_err) => { + trace!("Skipped 1 authorization header because it contains non visible ASCII chars."); + continue; + }, + }; if authorization.starts_with("Bearer ") { debug!("Bearer Authorization provided"); let token: &str = authorization.trim_start_matches("Bearer "); @@ -162,16 +182,33 @@ where } } -pub fn handle_refresh_token( - uri: Uri, +pub async fn handle_refresh_token( + State(_app_state): State, cookies: PrivateCookieJar, - Query(refresh_token): Query<&str>, - Query(force): Query>, + // Query(refresh_token): Query>, + // Query(force): Query>, token: Option, + req: Request, next: Next, -) -> Result { +) -> Result, StatusCode> { + let refresh_token: Option = None; + let force = None; + let Some(refresh_token) = refresh_token else { + return Ok(Either::E1(next.run(req).await)); + }; + + // NOTE: We're sure there is a query since `refresh_token` is `Some`. + let query = req.uri().query().unwrap(); + let mut query: HashMap = match serde_urlencoded::from_str(query) { + Ok(params) => params, + Err(err) => { + trace!("Invalid query: {err}"); + return Err(StatusCode::BAD_REQUEST); + }, + }; + // URL-decode the string. - let mut refresh_token: String = urlencoding::decode(refresh_token).unwrap().to_string(); + let mut refresh_token: String = urlencoding::decode(&refresh_token).unwrap().to_string(); // Because tokens can be passed as URL query params, // they might have the "=" padding characters removed. @@ -225,22 +262,21 @@ pub fn handle_refresh_token( return Err(StatusCode::UNAUTHORIZED); } - fn redirect_to_same_page_without_query_param(uri: &Uri) -> Result { - let query_segs: Vec = uri - .query() - .unwrap_or_default() - .raw_segments() - .filter(|s| !s.starts_with(format!("{REFRESH_TOKEN_QUERY_PARAM_NAME}=").as_str())) - .map(ToString::to_string) - .collect(); - match Uri::parse_owned(format!("{}?{}", uri.path(), query_segs.join("&"))) { + fn redirect_to_same_page_without_query_param( + uri: &Uri, + query: &mut HashMap, + ) -> Result { + query.remove(REFRESH_TOKEN_QUERY_PARAM_NAME); + // TODO: Check if we need to URL-encode keys and values or if they are still encoded. + let query_segs: Vec = query.iter().map(|(k, v)| format!("{k}={v}")).collect(); + match Uri::from_str(&format!("{}?{}", uri.path(), query_segs.join("&"))) { Ok(redirect_to) => { debug!("Redirecting to <{redirect_to}> from <{uri}>…"); - Ok(Redirect::found(redirect_to.path().to_string())) + Ok(Redirect::to(redirect_to.path().to_string().as_str())) }, Err(err) => { error(format!("{err}")); - Err(StatusCode::InternalServerError) + Err(StatusCode::INTERNAL_SERVER_ERROR) }, } } @@ -252,7 +288,8 @@ pub fn handle_refresh_token( // access link and send it to the super admin's device, which increases the potential // for such a sensitive link to be intercepted. As a safety measure, we don't do anything // if a super admin uses a refresh token link. - return redirect_to_same_page_without_query_param(&uri); + return redirect_to_same_page_without_query_param(req.uri(), &mut query) + .map(Either::E2); } } @@ -264,7 +301,7 @@ pub fn handle_refresh_token( Ok(biscuit) => biscuit, Err(err) => { error(format!("Error: Could not append block to biscuit: {err}")); - return Err(StatusCode::InternalServerError); + return Err(StatusCode::INTERNAL_SERVER_ERROR); }, }; debug!("Successfully created new biscuit from refresh token"); @@ -273,7 +310,7 @@ pub fn handle_refresh_token( add_cookie(&new_biscuit, cookies); // Redirect to the same page without the refresh token query param - redirect_to_same_page_without_query_param(&uri) + redirect_to_same_page_without_query_param(req.uri(), &mut query).map(Either::E2) } fn merge_biscuits( diff --git a/src/orangutan-server/src/routes/debug_routes.rs b/src/orangutan-server/src/routes/debug_routes.rs index 3537c33..ce93b84 100644 --- a/src/orangutan-server/src/routes/debug_routes.rs +++ b/src/orangutan-server/src/routes/debug_routes.rs @@ -7,7 +7,7 @@ use lazy_static::lazy_static; use crate::{ request_guards::{Token, REVOKED_TOKENS}, - Error, + AppState, Error, }; lazy_static! { @@ -22,8 +22,8 @@ lazy_static! { pub(crate) static ref ACCESS_LOGS: Arc>> = Arc::default(); } -pub(super) fn router() -> Router { - let mut router = Router::new() +pub(super) fn router() -> Router { + let mut router = Router::::new() .route("/clear-cookies", get(clear_cookies).put(clear_cookies)) .route("/_info", get(get_user_info)) .route("/_errors", get(errors)) @@ -47,15 +47,17 @@ pub(super) fn templates() -> Vec<(&'static str, &'static str)> { )] } -fn clear_cookies(cookies: PrivateCookieJar) -> &'static str { - for cookie in cookies.iter().map(Clone::clone) { - cookies.remove(cookie); +// #[axum::debug_handler] +async fn clear_cookies(cookie_jar: PrivateCookieJar) -> (PrivateCookieJar, String) { + let mut empty_jar = cookie_jar.clone(); + for cookie in cookie_jar.iter() { + empty_jar = empty_jar.remove(cookie); } - "Success" + (empty_jar, "Success".to_string()) } -fn get_user_info(token: Option) -> String { +async fn get_user_info(token: Option) -> String { match token { Some(Token { biscuit, .. }) => format!( "**Biscuit:**\n\n{}\n\n\ @@ -74,7 +76,7 @@ pub struct ErrorLog { pub line: String, } -fn errors(token: Token) -> Result { +async fn errors(token: Token) -> Result { if !token.profiles().contains(&"*".to_owned()) { Err(Error::Unauthorized)? } @@ -100,7 +102,7 @@ pub struct AccessLog { pub path: String, } -fn access_logs(token: Token) -> Result { +async fn access_logs(token: Token) -> Result { if !token.profiles().contains(&"*".to_owned()) { Err(Error::Unauthorized)? } @@ -138,7 +140,7 @@ pub fn log_access( }) } -fn revoked_tokens(token: Token) -> Result { +async fn revoked_tokens(token: Token) -> Result { if !token.profiles().contains(&"*".to_owned()) { Err(Error::Forbidden)? } @@ -159,12 +161,7 @@ pub mod token_generator { use orangutan_refresh_token::RefreshToken; use serde::Deserialize; - use crate::{ - context, - request_guards::Token, - util::{templating::render, WebsiteRoot}, - AppState, Error, - }; + use crate::{context, request_guards::Token, util::templating::render, AppState, Error}; fn token_generation_form_( tera: &tera::Tera, @@ -180,16 +177,15 @@ pub mod token_generator { Ok(Html(html)) } - pub fn token_generation_form( + pub async fn token_generation_form( token: Token, State(app_state): State, - website_root: WebsiteRoot, ) -> Result, Error> { if !token.profiles().contains(&"*".to_owned()) { Err(Error::Unauthorized)? } - token_generation_form_(&app_state.tera, None, &website_root) + token_generation_form_(&app_state.tera, None, &app_state.website_root) } #[derive(Deserialize)] @@ -200,11 +196,10 @@ pub mod token_generator { url: String, } - pub fn generate_token( + pub async fn generate_token( token: Token, State(app_state): State, Form(form): Form, - website_root: WebsiteRoot, ) -> Result, Error> { if !token.profiles().contains(&"*".to_owned()) { Err(Error::Unauthorized)? @@ -222,6 +217,6 @@ pub mod token_generator { let token_base64 = token.as_base64()?; let link = format!("{}?refresh_token={token_base64}", form.url); - token_generation_form_(&app_state.tera, Some(link), &website_root) + token_generation_form_(&app_state.tera, Some(link), &app_state.website_root) } } diff --git a/src/orangutan-server/src/routes/main_route.rs b/src/orangutan-server/src/routes/main_route.rs index 6bf230a..6e680b5 100644 --- a/src/orangutan-server/src/routes/main_route.rs +++ b/src/orangutan-server/src/routes/main_route.rs @@ -1,35 +1,43 @@ use std::{path::PathBuf, str::FromStr, time::SystemTime}; use axum::{ - extract::Path, - http::{header::ACCEPT, HeaderMap}, + extract::{Request, State}, + http::{ + header::{HeaderMap, ACCEPT}, + StatusCode, Uri, + }, + response::Response, routing::get, Router, }; +use axum_extra::either::Either; use biscuit_auth::macros::authorizer; use mime::Mime; use orangutan_helpers::{ page_metadata, website_id::{website_dir, WebsiteId}, }; -use tower_http::services::{ServeDir, ServeFile}; +use tower::Service; +use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir, ServeFile}; use tracing::{debug, trace}; -use crate::{config::*, request_guards::Token, routes::debug_routes::log_access, util::error}; +use crate::{config::*, request_guards::Token, routes::debug_routes::log_access, AppState, Error}; -pub(super) fn router() -> Router { - Router::new() +pub(super) fn router() -> Router { + Router::::new() .route("/", get(handle_request)) .route("/*path", get(handle_request)) } +// #[axum::debug_handler] async fn handle_request( - Path(path): Path, + State(_app_state): State, + uri: Uri, token: Option, - headers: HeaderMap, -) -> Result, crate::Error> { + headers: HeaderMap, +) -> Result, StatusCode>, Error> { // FIXME: Handle error - let path = path; + let path = uri.path(); trace!("GET {}", &path); let user_profiles: Vec = token.as_ref().map(Token::profiles).unwrap_or_default(); @@ -40,21 +48,42 @@ async fn handle_request( // Log access only if the page is HTML. // WARN: This solution is far from perfect as someone requesting a page without setting the `Accept` header // would not be logged even though they'd get the file back. + let a = "FIXME: Remove force unwrap"; let accept = headers .get(ACCEPT) - .map(|value| value.parse::().ok()) + .map(|value| Mime::from_str(value.to_str().expect("FIXME: Remove this force unwrap")).ok()) .flatten(); if accept.is_some_and(|m| m.type_() == mime::HTML) { log_access(user_profiles.to_owned(), path.to_owned()); } + async fn serve_file( + website_dir: &PathBuf, + path: &Uri, + ) -> Response { + let fallback = website_dir.join(NOT_FOUND_FILE); + trace!( + "Serving {path} at {} falling back to {}…", + website_dir.display(), + fallback.display(), + ); + let mut serve_dir = ServeDir::new(website_dir).not_found_service(ServeFile::new(fallback)); + serve_dir + .call(Request::get(path).body(()).unwrap()) + .await + .map_err(|err| match err {}) + .unwrap() + } + let page_relpath = PathBuf::from_str(&path).unwrap(); - let Some(page_metadata) = page_metadata(&page_relpath)? else { + let Some(page_metadata) = page_metadata(&page_relpath) + .map_err(orangutan_helpers::generate::Error::CannotReadPageMetadata)? + else { // If metadata can't be found, it means it's a static file - trace!("File <{path> did not explicitly allow profiles, serving static file"); + trace!("File <{path}> did not explicitly allow profiles, serving static file"); // TODO: Un-hardcode this value. - return ServeDir::new("static") - .not_found_service(ServeFile::new(website_dir.join(NOT_FOUND_FILE))); + let res = serve_file(&website_dir, &uri).await; + return Ok(Either::E1(res)); }; let allowed_profiles = page_metadata.read_allowed; @@ -102,13 +131,13 @@ async fn handle_request( } if profile.is_none() { debug!("No profile allowed in token"); - return Ok(None); + return Ok(Either::E2(StatusCode::NOT_FOUND)); } - let page_abspath = website_dir.join(page_metadata.path); - - ServeFile::new(page_abspath); - ServeFile::new(website_dir.join(NOT_FOUND_FILE)); - - panic!() + let res = serve_file( + &website_dir, + &Uri::from_str(page_metadata.path.to_str().unwrap()).unwrap(), + ) + .await; + Ok(Either::E1(res)) } diff --git a/src/orangutan-server/src/routes/mod.rs b/src/orangutan-server/src/routes/mod.rs index e3609ce..1649fb8 100644 --- a/src/orangutan-server/src/routes/mod.rs +++ b/src/orangutan-server/src/routes/mod.rs @@ -9,8 +9,10 @@ pub mod update_content_routes; use axum::Router; -pub(super) fn router() -> Router { - Router::new() +use crate::AppState; + +pub(super) fn router() -> Router { + Router::::new() .merge(main_route::router()) .merge(update_content_routes::router()) .merge(debug_routes::router()) diff --git a/src/orangutan-server/src/routes/update_content_routes.rs b/src/orangutan-server/src/routes/update_content_routes.rs index 6091db5..af511ea 100644 --- a/src/orangutan-server/src/routes/update_content_routes.rs +++ b/src/orangutan-server/src/routes/update_content_routes.rs @@ -1,10 +1,10 @@ use axum::{extract::Path, http::StatusCode, routing::post, Router}; use orangutan_helpers::generate::{self, *}; -use crate::{error, request_guards::REVOKED_TOKENS}; +use crate::{error, request_guards::REVOKED_TOKENS, AppState}; -pub(super) fn router() -> Router { - Router::new() +pub(super) fn router() -> Router { + Router::::new() .route("/update-content/github", post(update_content_github)) .route("/update-content/:source", post(update_content_other)) } @@ -34,7 +34,7 @@ async fn update_content_github() -> Result<(), crate::Error> { Ok(()) } -async fn update_content_other(Path(source): Path<&str>) -> (StatusCode, String) { +async fn update_content_other(Path(source): Path) -> (StatusCode, String) { ( StatusCode::BAD_REQUEST, format!("Source '{source}' is not supported."), diff --git a/src/orangutan-server/src/util/website_root.rs b/src/orangutan-server/src/util/website_root.rs index 19a1c34..03c4aa5 100644 --- a/src/orangutan-server/src/util/website_root.rs +++ b/src/orangutan-server/src/util/website_root.rs @@ -1,12 +1,12 @@ use std::ops::Deref; use lazy_static::lazy_static; -use tracing::error; lazy_static! { static ref WEBSITE_ROOT: String = std::env::var("WEBSITE_ROOT").unwrap_or_default(); } +#[derive(Clone)] pub struct WebsiteRoot(String); impl Deref for WebsiteRoot { @@ -17,21 +17,12 @@ impl Deref for WebsiteRoot { } } -warn!("TODO"); -// impl<'r> FromRequest<'r> for WebsiteRoot { -// type Error = &'static str; - -// async fn from_request(_req: &'r Request<'_>) -> Outcome { -// Outcome::Success(Self(WEBSITE_ROOT.to_owned())) -// } -// } - -// impl rocket::Sentinel for WebsiteRoot { -// fn abort(_rocket: &Rocket) -> bool { -// if WEBSITE_ROOT.is_empty() { -// error!("Environment variable `WEBSITE_ROOT` not found."); -// return true; -// } -// false -// } -// } +impl WebsiteRoot { + pub fn try_from_env() -> Result { + if WEBSITE_ROOT.is_empty() { + Err("Environment variable `WEBSITE_ROOT` not found.") + } else { + Ok(Self(WEBSITE_ROOT.to_owned())) + } + } +}