From 44c4853d373c35774709a4f3129133f5d37ca204 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sun, 25 Oct 2026 17:08:08 +0100 Subject: [PATCH] Upgrade to Rocket v0.5.2 (#7890) Upgrade Rocket to v0.5.2 which has updated all the crate dependencies. Also adjusted some code which I changed with Rkt and during that found some small bugs and fixed those too. Adjusted the ETag Caching a bit. Also updated other crates and GHA. Signed-off-by: BlackDex --- .github/workflows/release.yml | 12 +- .github/workflows/zizmor.yml | 2 +- Cargo.lock | 302 ++++++++++++++-------------------- Cargo.toml | 4 +- src/api/mod.rs | 2 +- src/api/notifications.rs | 9 +- src/api/web.rs | 94 +++++++---- src/error.rs | 4 +- src/mail.rs | 4 +- src/main.rs | 2 +- src/util.rs | 87 ++++++---- 11 files changed, 262 insertions(+), 260 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53cf0923..6f80509d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -106,7 +106,7 @@ jobs: # Login to Docker Hub - name: Login to Docker Hub - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -121,7 +121,7 @@ jobs: # Login to GitHub Container Registry - name: Login to GitHub Container Registry - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -137,7 +137,7 @@ jobs: # Login to Quay.io - name: Login to Quay.io - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} @@ -272,7 +272,7 @@ jobs: # Login to Docker Hub - name: Login to Docker Hub - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -287,7 +287,7 @@ jobs: # Login to GitHub Container Registry - name: Login to GitHub Container Registry - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -303,7 +303,7 @@ jobs: # Login to Quay.io - name: Login to Quay.io - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 + uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index c08b9213..7372759b 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -24,7 +24,7 @@ jobs: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@85b2b9fb8e3325e7a23d7d0a9d7ba5ae0f999e3e # v0.7.1 + uses: zizmorcore/zizmor-action@53290badfa369cb0bf7ad16342cb62c2fa47ac7b # v0.8.0 with: # intentionally not scanning the entire repository, # since it contains integration tests. diff --git a/Cargo.lock b/Cargo.lock index 9568e5c7..6cef9e27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,15 +323,9 @@ dependencies = [ [[package]] name = "asyncband" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5161fb43cb8f231f06983cb2b8f9ee9cee14be0b1356d8383398cc0f312800d1" - -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" +checksum = "5d2050892d4691cf110586070786712b504985a4d37ed64a9cd8a402718e1706" [[package]] name = "atomic" @@ -415,7 +409,7 @@ dependencies = [ "bytes-utils", "fastrand", "http 1.5.0", - "http-body 1.1.0", + "http-body", "percent-encoding", "pin-project-lite", "tracing", @@ -424,9 +418,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.116.0" +version = "1.117.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26d2c93a4e6e7c133dc4090dc2273cfd92894fee8b883256427b57cacc3a384" +checksum = "5316813498fa9c403877007934ae448aa44b18136f58051f8fa3c5b79b44bdc6" dependencies = [ "arc-swap", "aws-credential-types", @@ -449,9 +443,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.118.0" +version = "1.119.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6fa86283d1c6d5c82f1fb2d82f7704d8f7a7bf5f0591813114240d296f6a11c" +checksum = "31db35e5662787b786daba15f431e4393c7ea512b70fa112bd048d1f3ecf877a" dependencies = [ "arc-swap", "aws-credential-types", @@ -474,9 +468,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.121.0" +version = "1.122.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ff04fe350fd756c1aa45544128e88f72ffb6281cad628e5a4add464cbbab8b" +checksum = "a10491638d9e560db90c484dbc77d73b8ad202780cdc9b9e92180603acb07ada" dependencies = [ "arc-swap", "aws-credential-types", @@ -500,9 +494,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.6.2" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a3ccec0607ae3839cd76830df5ed62468ac1330acdb3dc4ec0502404113d2b6" +checksum = "9d3d48355cb86b15ccbb38b8bc6b87500c824ee4ed8cbc10a961b435242b5e16" dependencies = [ "aws-credential-types", "aws-smithy-http", @@ -543,7 +537,7 @@ dependencies = [ "futures-core", "futures-util", "http 1.5.0", - "http-body 1.1.0", + "http-body", "http-body-util", "percent-encoding", "pin-project-lite", @@ -598,7 +592,7 @@ dependencies = [ "bytes", "fastrand", "http 1.5.0", - "http-body 1.1.0", + "http-body", "http-body-util", "pin-project-lite", "tokio", @@ -654,7 +648,7 @@ dependencies = [ "bytes", "bytes-utils", "http 1.5.0", - "http-body 1.1.0", + "http-body", "http-body-util", "itoa", "num-integer", @@ -815,9 +809,9 @@ dependencies = [ [[package]] name = "brotli" -version = "9.0.0" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b851b75c23ca7873623d612fe49bd1989aeb03d08fb9432187eb253d3d4c6b" +checksum = "6737ce8b81460bf9407909f73ff50bf13f7cb8577e1e76715f57ed0eba58ba44" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -826,9 +820,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "6.0.1" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941cd9bd4ddab83cb46fa5a2d428f1c857b24ac78cb876cf7beb710840934bd7" +checksum = "34c6783f42c21c952ad7112b354f0ba2f10760e9decea5b1b60523d6e270faaf" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -914,9 +908,9 @@ checksum = "f5813789573ae815c8b4be58c4428e0e7ae05f0227678ba9de332ded585b9159" [[package]] name = "cc" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df" +checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0" dependencies = [ "find-msvc-tools", "jobserver", @@ -1242,9 +1236,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" +checksum = "38d28fb6aa7dd680b3ffd1a3e64e115c177bdba63c0ae7f9cd48129ff05c4fa0" dependencies = [ "cmov", ] @@ -1527,9 +1521,9 @@ dependencies = [ [[package]] name = "devise" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" +checksum = "143afb21c617f66c792ef2d75f9fb4c9dd774ff206bcc24df08a1bda294a37bc" dependencies = [ "devise_codegen", "devise_core", @@ -1537,9 +1531,9 @@ dependencies = [ [[package]] name = "devise_codegen" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" +checksum = "50b3187e4283046e01d16d724ed05326427aa9c1c3a376548ef31820e6eb9717" dependencies = [ "devise_core", "quote", @@ -1547,15 +1541,15 @@ dependencies = [ [[package]] name = "devise_core" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" +checksum = "970e4b2fcd605ffa79715510663a9fe76b87f5483d59857399129cf047f73d27" dependencies = [ "bitflags 2.13.2", "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.11.0", "quote", - "syn 2.0.119", + "syn 3.0.9", ] [[package]] @@ -1893,8 +1887,8 @@ version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ - "atomic 0.6.1", - "pear", + "atomic", + "pear 0.2.9", "serde", "toml 0.8.23", "uncased", @@ -2430,17 +2424,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.1.0" @@ -2460,7 +2443,7 @@ dependencies = [ "bytes", "futures-core", "http 1.5.0", - "http-body 1.1.0", + "http-body", "pin-project-lite", ] @@ -2485,29 +2468,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.12.0" @@ -2520,8 +2480,9 @@ dependencies = [ "futures-core", "h2", "http 1.5.0", - "http-body 1.1.0", + "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -2536,11 +2497,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" dependencies = [ "http 1.5.0", - "hyper 1.12.0", + "hyper", "hyper-util", - "rustls 0.23.46", + "rustls", "tokio", - "tokio-rustls 0.26.6", + "tokio-rustls", "tower-service", ] @@ -2555,14 +2516,14 @@ dependencies = [ "futures-channel", "futures-util", "http 1.5.0", - "http-body 1.1.0", + "http-body", "httparse", - "hyper 1.12.0", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.5", + "socket2", "system-configuration", "tokio", "tower-service", @@ -2739,7 +2700,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.6.5", + "socket2", "widestring", "windows-registry", "windows-result", @@ -2996,12 +2957,12 @@ dependencies = [ "nom 8.0.0", "percent-encoding", "quoted_printable", - "rustls 0.23.46", + "rustls", "rustls-native-certs", "serde", - "socket2 0.6.5", + "socket2", "tokio", - "tokio-rustls 0.26.6", + "tokio-rustls", "tracing", "url", ] @@ -3484,7 +3445,7 @@ dependencies = [ "bytes", "futures", "http 1.5.0", - "http-body 1.1.0", + "http-body", "opendal-core", "reqwest", ] @@ -3715,7 +3676,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" dependencies = [ "inlinable_string", - "pear_codegen", + "pear_codegen 0.2.9", + "yansi", +] + +[[package]] +name = "pear" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bdc582f5ece4663ba62cb9cc81b9f86aa23884ee92cddb1d5e75a94991119cb" +dependencies = [ + "inlinable_string", + "pear_codegen 0.3.0", "yansi", ] @@ -3726,11 +3698,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" dependencies = [ "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.10.1", "quote", "syn 2.0.119", ] +[[package]] +name = "pear_codegen" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b4262794e70dac544a759fd50088c6331e7a2ba4fc204b4b6e29c9b5257f9c4" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics 0.11.0", + "quote", + "syn 3.0.9", +] + [[package]] name = "pem" version = "3.0.6" @@ -4042,6 +4026,18 @@ dependencies = [ "yansi", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df921e1ef974ebc8dd9effdb0c037a96928ae8cbf871438e02d6fd67204b595e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "version_check", +] + [[package]] name = "psl-types" version = "2.0.11" @@ -4250,6 +4246,12 @@ dependencies = [ "syn 3.0.9", ] +[[package]] +name = "ref-swap" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c30c54dffee5b40af088d5d50aa3455c91a0127164b51f0215efc4cb28fb3c" + [[package]] name = "regex" version = "1.13.1" @@ -4379,9 +4381,9 @@ dependencies = [ "futures-util", "h2", "http 1.5.0", - "http-body 1.1.0", + "http-body", "http-body-util", - "hyper 1.12.0", + "hyper", "hyper-rustls", "hyper-util", "js-sys", @@ -4389,7 +4391,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustls 0.23.46", + "rustls", "rustls-pki-types", "rustls-platform-verifier", "serde", @@ -4397,7 +4399,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.6", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -4459,18 +4461,19 @@ dependencies = [ [[package]] name = "rocket" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" +checksum = "c17431360eb641a861453b57107ee1b425a799f49ec1b0fe9b8a45fe437447ce" dependencies = [ "async-stream", "async-trait", - "atomic 0.5.3", "binascii", "bytes", "either", "figment", "futures", + "http-body-util", + "hyper-util", "indexmap 2.14.2", "log", "memchr", @@ -4478,8 +4481,8 @@ dependencies = [ "num_cpus", "parking_lot", "pin-project-lite", - "rand 0.8.8", "ref-cast", + "ref-swap", "rocket_codegen", "rocket_http", "serde", @@ -4497,48 +4500,50 @@ dependencies = [ [[package]] name = "rocket_codegen" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" +checksum = "352bd0b773ca6f5bea6cd18efc2fd7f04fcd34c75c242dad6ef1bbd729cc619d" dependencies = [ "devise", "glob", "indexmap 2.14.2", "proc-macro2", + "proc-macro2-diagnostics 0.11.0", "quote", "rocket_http", - "syn 2.0.119", + "syn 3.0.9", "unicode-xid", "version_check", ] [[package]] name = "rocket_http" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" +checksum = "847886ef963dff77126f110fd2b4401f5149440ab32973bef16c4a2cc83e525f" dependencies = [ "cookie", "either", "futures", "http 0.2.12", - "hyper 0.14.32", + "hyper", "indexmap 2.14.2", "log", "memchr", - "pear", + "pear 0.3.0", "percent-encoding", "pin-project-lite", "ref-cast", - "rustls 0.21.12", - "rustls-pemfile", + "rustls", + "rustls-pki-types", + "rustls-webpki", "serde", "smallvec", "stable-pattern", "state", "time", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "uncased", ] @@ -4643,18 +4648,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.46" @@ -4665,7 +4658,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.16", + "rustls-webpki", "subtle", "zeroize", ] @@ -4682,15 +4675,6 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pki-types" version = "1.15.1" @@ -4711,10 +4695,10 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.46", + "rustls", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.16", + "rustls-webpki", "security-framework", "security-framework-sys", "webpki-root-certs", @@ -4727,16 +4711,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.103.16" @@ -4823,16 +4797,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sec1" version = "0.7.3" @@ -5159,19 +5123,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.3" +version = "1.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8" [[package]] name = "socket2" @@ -5509,7 +5463,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.5", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] @@ -5525,23 +5479,13 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" dependencies = [ - "rustls 0.23.46", + "rustls", "tokio", ] @@ -5715,7 +5659,7 @@ dependencies = [ "futures-core", "futures-util", "http 1.5.0", - "http-body 1.1.0", + "http-body", "http-body-util", "pin-project-lite", "tokio", @@ -5913,9 +5857,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.28.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" +checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -5996,7 +5940,7 @@ dependencies = [ "rocket", "rocket_ws", "rpassword", - "rustls 0.23.46", + "rustls", "semver", "serde", "serde_json", @@ -6228,9 +6172,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ec80e73fd8baf57bf0d9615554c75348bda990d6d5bbeab964dd068319fecb" +checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a" dependencies = [ "rustls-pki-types", ] diff --git a/Cargo.toml b/Cargo.toml index ab30358f..78791730 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,7 +80,7 @@ num-derive = "0.5.1" bigdecimal = "0.4.11" # Web framework -rocket = { version = "0.5.1", default-features = false, features = ["json", "tls"] } +rocket = { version = "0.5.2", default-features = false, features = ["json", "tls"] } rocket_ws = { version = "0.1.1" } # WebSockets libraries @@ -129,7 +129,7 @@ rustls = { version = "0.23.46", features = ["ring", "std"], default-features = f subtle = "2.6.1" # UUID generation -uuid = { version = "1.28.0", features = ["v4"] } +uuid = { version = "1.29.0", features = ["v4"] } # Date and time libraries chrono = { version = "0.4.45", default-features = false, features = ["clock", "serde"] } diff --git a/src/api/mod.rs b/src/api/mod.rs index 8baa221d..0ac78f5c 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -30,7 +30,7 @@ pub use crate::api::{ }, web::catchers as web_catchers, web::routes as web_routes, - web::{invalidate_css_cache, static_files}, + web::{STATIC_FILES, invalidate_css_cache}, }; use crate::{ CONFIG, diff --git a/src/api/notifications.rs b/src/api/notifications.rs index 32204916..3bce7219 100644 --- a/src/api/notifications.rs +++ b/src/api/notifications.rs @@ -212,7 +212,7 @@ fn websockets_hub<'r>( if last_received.elapsed() > WS_CLIENT_TIMEOUT { break; } - yield Message::Ping(create_ping()); + yield Message::Ping(PING.to_vec()); } } } @@ -295,7 +295,7 @@ fn anonymous_websockets_hub<'r>(ws: WebSocket, token: String, ip: ClientIp) -> R if last_received.elapsed() > WS_CLIENT_TIMEOUT { break; } - yield Message::Ping(create_ping()); + yield Message::Ping(PING.to_vec()); } } } @@ -359,6 +359,7 @@ fn convert_option>(option: Option) -> Value { const RECORD_SEPARATOR: u8 = 0x1e; const INITIAL_RESPONSE: [u8; 3] = [0x7b, 0x7d, RECORD_SEPARATOR]; // {, }, +const PING: [u8; 3] = [0x02, 0x91, 0x06]; #[derive(Deserialize, Copy, Clone, Eq, PartialEq)] struct InitialMessage<'a> { @@ -691,10 +692,6 @@ fn create_anonymous_update(payload: Vec<(Value, Value)>, ut: UpdateType, user_id serialize(&value) } -fn create_ping() -> Vec { - serialize(&Value::Array(vec![6.into()])) -} - // https://github.com/bitwarden/server/blob/375af7c43b10d9da03525d41452f95de3f921541/src/Core/Enums/PushType.cs #[derive(Copy, Clone, Eq, PartialEq)] pub enum UpdateType { diff --git a/src/api/web.rs b/src/api/web.rs index aa67e614..e9a8b593 100644 --- a/src/api/web.rs +++ b/src/api/web.rs @@ -1,13 +1,14 @@ use std::{ + collections::HashMap, path::{Path, PathBuf}, - sync::{Arc, RwLock}, + sync::{Arc, LazyLock, RwLock}, }; use rocket::{ Catcher, Route, fs::NamedFile, http::ContentType, - response::{Redirect, content::RawCss as Css, content::RawHtml as Html}, + response::{Redirect, content::RawHtml as Html}, serde::json::Json, }; use serde_json::Value; @@ -79,12 +80,12 @@ pub fn invalidate_css_cache() { } #[get("/css/vaultwarden.css")] -fn vaultwarden_css() -> EtagCached> { +fn vaultwarden_css() -> EtagCached { // If reload_templates is false, and we already have the CSS Cached, return this if !CONFIG.reload_templates() && let Some(cached) = CSS_CACHE.read().unwrap().as_ref() { - return EtagCached::new(Css(cached.css.clone()), &cached.etag); + return EtagCached::new(cached.css.clone(), ContentType::CSS, &cached.etag); } // Else, there is either no cache, or reload_templates is true and we need to rebuild the CSS @@ -147,7 +148,7 @@ fn vaultwarden_css() -> EtagCached> { } // Etag Caching will let the browser send us an etag to verify and send new content if needed - EtagCached::new(Css(cached.css.clone()), &cached.etag) + EtagCached::new(cached.css.clone(), ContentType::CSS, &cached.etag) } #[get("/")] @@ -256,7 +257,7 @@ fn alive_head(_conn: DbConn) -> EmptyResult { // This endpoint/function is used during development and development only. // It allows to easily develop the admin interface by always loading the files from disk instead from a slice of bytes // This will only be active during a debug build and only when `RELOAD_TEMPLATES` is set to `true` -// NOTE: Do not forget to add any new files added to the `static_files` function below! +// NOTE: Do not forget to add any new files added to the `STATIC_FILES` HashMap below! #[cfg(debug_assertions)] #[get("/vw_static/", rank = 1)] pub async fn static_files_dev(filename: PathBuf) -> Option { @@ -276,32 +277,61 @@ pub async fn static_files_dev(filename: PathBuf) -> Option { None } +pub struct StaticFile { + pub content_type: ContentType, + pub bytes: &'static [u8], + pub etag: String, +} + +pub static STATIC_FILES: LazyLock> = LazyLock::new(|| { + [ + ("404.png", ContentType::PNG, &include_bytes!("../static/images/404.png")[..]), + ("mail-github.png", ContentType::PNG, &include_bytes!("../static/images/mail-github.png")[..]), + ("logo-gray.png", ContentType::PNG, &include_bytes!("../static/images/logo-gray.png")[..]), + ("error-x.svg", ContentType::SVG, &include_bytes!("../static/images/error-x.svg")[..]), + ("hibp.png", ContentType::PNG, &include_bytes!("../static/images/hibp.png")[..]), + ("vaultwarden-icon.png", ContentType::PNG, &include_bytes!("../static/images/vaultwarden-icon.png")[..]), + ("vaultwarden-favicon.png", ContentType::PNG, &include_bytes!("../static/images/vaultwarden-favicon.png")[..]), + ("404.css", ContentType::CSS, &include_bytes!("../static/scripts/404.css")[..]), + ("admin.css", ContentType::CSS, &include_bytes!("../static/scripts/admin.css")[..]), + ("admin.js", ContentType::JavaScript, &include_bytes!("../static/scripts/admin.js")[..]), + ("admin_settings.js", ContentType::JavaScript, &include_bytes!("../static/scripts/admin_settings.js")[..]), + ("admin_users.js", ContentType::JavaScript, &include_bytes!("../static/scripts/admin_users.js")[..]), + ( + "admin_organizations.js", + ContentType::JavaScript, + &include_bytes!("../static/scripts/admin_organizations.js")[..], + ), + ( + "admin_diagnostics.js", + ContentType::JavaScript, + &include_bytes!("../static/scripts/admin_diagnostics.js")[..], + ), + ("bootstrap.css", ContentType::CSS, &include_bytes!("../static/scripts/bootstrap.css")[..]), + ("bootstrap.bundle.js", ContentType::JavaScript, &include_bytes!("../static/scripts/bootstrap.bundle.js")[..]), + ("jdenticon-3.3.0.js", ContentType::JavaScript, &include_bytes!("../static/scripts/jdenticon-3.3.0.js")[..]), + ("datatables.js", ContentType::JavaScript, &include_bytes!("../static/scripts/datatables.js")[..]), + ("datatables.css", ContentType::CSS, &include_bytes!("../static/scripts/datatables.css")[..]), + ] + .into_iter() + .map(|(name, content_type, bytes)| { + ( + name, + StaticFile { + content_type, + bytes, + etag: sha256_hex(bytes), + }, + ) + }) + .collect() +}); + #[get("/vw_static/", rank = 2)] -pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Error> { - match filename { - "404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))), - "mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.png"))), - "logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))), - "error-x.svg" => Ok((ContentType::SVG, include_bytes!("../static/images/error-x.svg"))), - "hibp.png" => Ok((ContentType::PNG, include_bytes!("../static/images/hibp.png"))), - "vaultwarden-icon.png" => Ok((ContentType::PNG, include_bytes!("../static/images/vaultwarden-icon.png"))), - "vaultwarden-favicon.png" => Ok((ContentType::PNG, include_bytes!("../static/images/vaultwarden-favicon.png"))), - "404.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/404.css"))), - "admin.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/admin.css"))), - "admin.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin.js"))), - "admin_settings.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_settings.js"))), - "admin_users.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_users.js"))), - "admin_organizations.js" => { - Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_organizations.js"))) - } - "admin_diagnostics.js" => { - Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_diagnostics.js"))) - } - "bootstrap.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/bootstrap.css"))), - "bootstrap.bundle.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/bootstrap.bundle.js"))), - "jdenticon-3.3.0.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jdenticon-3.3.0.js"))), - "datatables.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))), - "datatables.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))), - _ => err!(format!("Static file not found: {filename}")), +pub fn static_files(filename: &str) -> Result, Error> { + if let Some(file) = STATIC_FILES.get(filename) { + Ok(EtagCached::new(file.bytes, file.content_type.clone(), &file.etag)) + } else { + err!(format!("Static file not found: {filename}")) } } diff --git a/src/error.rs b/src/error.rs index d90c38e3..3fee3dc4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -425,12 +425,12 @@ macro_rules! err_json { macro_rules! err_handler { ($expr:expr) => {{ error!(target: "auth", "Unauthorized Error: {}", $expr); - return ::rocket::request::Outcome::Error((rocket::http::Status::Unauthorized, $expr)); + return ::rocket::request::Outcome::Error((::rocket::http::Status::Unauthorized, $expr)); }}; ($usr_msg:expr, $log_value:expr) => {{ let usr_msg = $usr_msg; let log_value = $log_value; error!(target: "auth", "Unauthorized Error: {usr_msg}. {log_value}"); - return ::rocket::request::Outcome::Error((rocket::http::Status::Unauthorized, usr_msg)); + return ::rocket::request::Outcome::Error((::rocket::http::Status::Unauthorized, usr_msg)); }}; } diff --git a/src/mail.rs b/src/mail.rs index 6ebbc806..06aac97f 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -738,8 +738,8 @@ async fn send_email(address: &str, subject: &str, body_html: String, body_text: let smtp_from = Address::from_str(&CONFIG.smtp_from())?; let body = if CONFIG.smtp_embed_images() { - let logo_gray_body = Body::new(crate::api::static_files("logo-gray.png").unwrap().1.to_vec()); - let mail_github_body = Body::new(crate::api::static_files("mail-github.png").unwrap().1.to_vec()); + let logo_gray_body = Body::new(crate::api::STATIC_FILES["logo-gray.png"].bytes.to_vec()); + let mail_github_body = Body::new(crate::api::STATIC_FILES["mail-github.png"].bytes.to_vec()); MultiPart::alternative().singlepart(SinglePart::plain(body_text)).multipart( MultiPart::related() .singlepart(SinglePart::html(body_html)) diff --git a/src/main.rs b/src/main.rs index 6a7f18f3..76c561f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -595,7 +595,7 @@ async fn launch_rocket(pool: db::DbPool, extra_debug: bool) -> Result<(), Error> .manage(Arc::clone(&WS_ANONYMOUS_SUBSCRIPTIONS)) .attach(util::AppHeaders()) .attach(util::Cors()) - .attach(util::BetterLogging(extra_debug)) + .attach(util::BetterLogging::new(extra_debug, basepath)) .ignite() .await?; diff --git a/src/util.rs b/src/util.rs index 644312a5..44d532bf 100644 --- a/src/util.rs +++ b/src/util.rs @@ -259,14 +259,16 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for Cache pub struct EtagCached { response: R, + content_type: ContentType, etag: String, } impl EtagCached { /// An `etag` response should always be quoted - pub fn new(response: R, etag: &str) -> Self { + pub fn new(response: R, content_type: ContentType, etag: &str) -> Self { Self { response, + content_type, etag: format!("\"{etag}\""), } } @@ -288,7 +290,8 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for EtagC self.response.respond_to(request)? }; - // Both 200 (OK) and 304 (Not Modified) need to return the etag and cache-control + // Both 200 (OK) and 304 (Not Modified) need to return the Content-Type Etag and Cache-Control + res.set_header(self.content_type); res.set_raw_header("Etag", self.etag); res.set_raw_header("Cache-Control", "public, no-cache"); Ok(res) @@ -299,19 +302,55 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for EtagC // Effectively ignores, any static file route, and the alive endpoint const LOGGED_ROUTES: [&str; 7] = ["/api", "/admin", "/identity", "/icons", "/attachments", "/events", "/notifications"]; -// Boolean is extra debug, when true, we ignore the whitelist above and also print the mounts -pub struct BetterLogging(pub bool); +// When extra is true, we ignore the whitelist above and also print the mounts +pub struct BetterLogging { + extra: bool, + log_requests: bool, + log_response: bool, + domain_path: String, +} + +impl BetterLogging { + pub fn new(extra: bool, domain_path: &str) -> Self { + Self { + extra, + log_requests: log_enabled!(target: "request", log::Level::Info), + log_response: log_enabled!(target: "response", log::Level::Info), + domain_path: rocket::http::RawStr::new(&domain_path).percent_decode_lossy().into_owned(), + } + } + + fn log_path<'p>(&self, method: Method, path: &'p rocket::http::RawStr) -> Option> { + if !self.extra && method == Method::Options { + return None; + } + let path = path.percent_decode_lossy(); + if self.extra { + return Some(path); + } + let subpath = path.strip_prefix(&self.domain_path).unwrap_or(&path); + LOGGED_ROUTES.iter().any(|r| subpath.starts_with(r)).then_some(path) + } +} + #[rocket::async_trait] impl Fairing for BetterLogging { fn info(&self) -> Info { + let mut kind = Kind::Liftoff; + if self.log_requests { + kind = kind | Kind::Request; + } + if self.log_response { + kind = kind | Kind::Response; + } Info { name: "Better Logging", - kind: Kind::Liftoff | Kind::Request | Kind::Response, + kind, } } async fn on_liftoff(&self, rocket: &Rocket) { - if self.0 { + if self.extra { info!(target: "routes", "Routes loaded:"); let mut routes: Vec<_> = rocket.routes().collect(); routes.sort_by_key(|r| r.uri.path()); @@ -335,36 +374,28 @@ impl Fairing for BetterLogging { } async fn on_request(&self, request: &mut Request<'_>, _data: &mut Data<'_>) { - let method = request.method(); - if !self.0 && method == Method::Options { - return; - } let uri = request.uri(); - let uri_path = uri.path(); - let uri_path_str = uri_path.url_decode_lossy(); - let uri_subpath = uri_path_str.strip_prefix(&CONFIG.domain_path()).unwrap_or(&uri_path_str); - if self.0 || LOGGED_ROUTES.iter().any(|r| uri_subpath.starts_with(r)) { - match uri.query() { - Some(q) => info!(target: "request", "{method} {uri_path_str}?{}", &q[..q.len().min(30)]), - None => info!(target: "request", "{method} {uri_path_str}"), + let method = request.method(); + let Some(path) = self.log_path(method, uri.path().raw()) else { + return; + }; + match uri.query() { + Some(q) => { + let q = q.as_str(); + info!(target: "request", "{method} {}?{}", path.escape_debug(), q[..q.floor_char_boundary(30)].escape_debug()); } + None => info!(target: "request", "{method} {}", path.escape_debug()), } } async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) { - if !self.0 && request.method() == Method::Options { + if self.log_path(request.method(), request.uri().path().raw()).is_none() { return; } - let uri_path = request.uri().path(); - let uri_path_str = uri_path.url_decode_lossy(); - let uri_subpath = uri_path_str.strip_prefix(&CONFIG.domain_path()).unwrap_or(&uri_path_str); - if self.0 || LOGGED_ROUTES.iter().any(|r| uri_subpath.starts_with(r)) { - let status = response.status(); - if let Some(route) = request.route() { - info!(target: "response", "{route} => {status}"); - } else { - info!(target: "response", "{status}"); - } + let status = response.status(); + match request.route() { + Some(r) => info!(target: "response", "{r} => {status}"), + None => info!(target: "response", "{status}"), } } }