diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 354b154a..81cb489c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -26,14 +26,14 @@ jobs: uses: actions/checkout@v7 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Log in to GHCR if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -41,7 +41,7 @@ jobs: - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | @@ -52,7 +52,7 @@ jobs: type=ref,event=pr - name: Build and push - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }} diff --git a/Cargo.lock b/Cargo.lock index 636a1028..c82a6625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "actix-files" -version = "0.6.10" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8c4f30e3272d7c345f88ae0aac3848507ef5ba871f9cc2a41c8085a0f0523b" +checksum = "ed87c765e9e5be096cc29b43d04b932209892ec871d05fe255f0ae1ccfed9a06" dependencies = [ "actix-http", "actix-service", @@ -44,12 +44,11 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.13.1" +version = "3.18.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e2faa3e7418ed780cca54829d32782a4008a077230f67457caa063415e99c2" +checksum = "e2ab7d72c0bb26f10df574ea560177b4de2f27ee8f421b2c1e9b75628bd9db23" dependencies = [ "actix-codec", - "actix-rt", "actix-service", "actix-utils", "bitflags 2.13.1", @@ -84,14 +83,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "actix-multipart" -version = "0.8.0" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560e3dd4eae03837f86d1b6bf6222c508568eff36845ef5ebb3a0dff480e3f64" +checksum = "689ad8dca448cfbcfc32c8988dd411c564ee177d85d724982f6b0a026f382d0a" dependencies = [ "actix-multipart-derive", "actix-utils", @@ -114,15 +113,15 @@ dependencies = [ [[package]] name = "actix-multipart-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8720bceaa6797fd8b2deab968d52e1120b2a8c30950939f6c8cdb42a910bc885" +checksum = "69112d423cd092e024d7a5473b7862b0e5d95247728a5b414545c0251f9df5a7" dependencies = [ "bytesize", "darling", "proc-macro2", "quote", - "syn", + "syn 3.0.7", ] [[package]] @@ -152,17 +151,16 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.6.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" +checksum = "164ab0b702b578c93901482aea90729bcb8b0822b090194372ad2966393778fa" dependencies = [ "actix-rt", "actix-service", - "actix-utils", "futures-core", "futures-util", "mio", - "socket2 0.5.10", + "socket2", "tokio", "tracing", ] @@ -189,9 +187,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.14.0" +version = "4.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df09e2d9239703dd64056359c920c7f3fba6535ec61a0059e0f44e095ffe02b4" +checksum = "bbacab3593b6b4f7be815076fc52d60a83c873426824675417e2abdd229e2e36" dependencies = [ "actix-codec", "actix-http", @@ -224,7 +222,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2 0.6.5", + "socket2", "time", "tracing", "url", @@ -239,18 +237,18 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "actix-web-httpauth" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456348ed9dcd72a13a1f4a660449fafdecee9ac8205552e286809eb5b0b29bd3" +checksum = "7cc7d1a844a6e987662f0cb5a2a7571cde1def4581a8dd2b9ccb1fd326e84cac" dependencies = [ "actix-utils", "actix-web", - "base64", + "base64 0.23.1", "futures-core", "futures-util", "log", @@ -343,7 +341,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -354,14 +352,14 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "askama" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" +checksum = "6024d73179f43f15ccd2b881bfea6fee7f3a46ec53f33b52210dea749ebebaa4" dependencies = [ "askama_macros", "itoa", @@ -372,9 +370,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" +checksum = "071ee5ebf2138e3ad180e0aacf6940c2cab5e6d8333741d9925c7bee2b153f39" dependencies = [ "askama_parser", "basic-toml", @@ -385,23 +383,23 @@ dependencies = [ "rustc-hash", "serde", "serde_derive", - "syn", + "syn 3.0.7", ] [[package]] name = "askama_macros" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" +checksum = "643e1c7cbb6aec1d920332fe51a7c0d8219e273dcb8602db03f5263e4d16487b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" +checksum = "2c5ae75772275d268b03ab8bdccdd12117b6169ee23256942b34e46c9f476583" dependencies = [ "rustc-hash", "serde", @@ -422,6 +420,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "basic-toml" version = "0.1.10" @@ -546,18 +550,6 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" -[[package]] -name = "bytemuck" -version = "1.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - [[package]] name = "bytes" version = "1.12.1" @@ -566,9 +558,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "bytesize" -version = "2.4.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7c8918969267b2932ffd5655509bbbea0833823058c378876953217f5fc50e" +checksum = "7354288c522e7e980fafd2075d63d1285794c3a6a16cdd492f189ea406e5f18b" dependencies = [ "serde_core", ] @@ -656,9 +648,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.2" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd059f9da4f5c36b3787f65d38ccaab1cc315f07b01f89abc8359ee6a8205011" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -666,9 +658,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.2" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -678,14 +670,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.7", ] [[package]] @@ -797,9 +789,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" dependencies = [ "darling_core", "darling_macro", @@ -807,26 +799,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" dependencies = [ "ident_case", "proc-macro2", "quote", "strsim", - "syn", + "syn 3.0.7", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core", "quote", - "syn", + "syn 3.0.7", ] [[package]] @@ -860,7 +852,7 @@ dependencies = [ "defmt-parser", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -897,7 +889,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.119", "unicode-xid", ] @@ -931,7 +923,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -979,7 +971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1011,15 +1003,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -1060,9 +1043,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -1075,9 +1058,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -1085,15 +1068,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -1102,38 +1085,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.7", ] [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -1235,9 +1218,9 @@ dependencies = [ [[package]] name = "html-escape" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c1ff2d1cbf39efe5af0900ced8a069b5e61557a17544eb0c4a50239937389e" +checksum = "c9356095b4b41197bba32173600e1582792cda618f65d12f68e2e77d273413c5" [[package]] name = "http" @@ -1411,19 +1394,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", -] - [[package]] name = "impl-more" version = "0.3.1" @@ -1484,7 +1454,7 @@ checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1516,9 +1486,9 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "libbz2-rs-sys" @@ -1534,9 +1504,9 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libsqlite3-sys" -version = "0.38.1" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c19a05435c21ac299d71b6a9c13db3e3f47c520517d58990a462a1397a61db" +checksum = "f1d20bef17f513b9b3004532233187769cd072d790971f4e4da0e346eb6401e8" dependencies = [ "cc", "pkg-config", @@ -1587,9 +1557,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "lzma-rust2" @@ -1607,7 +1577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a1b6c709c8825d60b6f21ef1228b692f9254a02ff332700ccc38c7609209d7" dependencies = [ "aes", - "base64", + "base64 0.22.1", "cbc", "crc-any", "des", @@ -1668,17 +1638,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", + "windows-sys", ] [[package]] @@ -1787,26 +1747,13 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ - "base64", + "base64 0.22.1", "indexmap", "quick-xml", "serde", "time", ] -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.13.1", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "portable-atomic" version = "1.14.0" @@ -1852,28 +1799,11 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "pxfm" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" - [[package]] name = "qrcode-generator" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0051849b5465059b75f59d388c7318aad6554701b74ecf02afc2573b0306c" -dependencies = [ - "html-escape", - "image", - "qrcodegen", -] - -[[package]] -name = "qrcodegen" -version = "1.8.0" +version = "6.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" +checksum = "892685c7a313d378de4d0897f7c5be347f296933913219201b8320aca5a5fee1" [[package]] name = "quick-xml" @@ -1901,9 +1831,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom", @@ -1972,9 +1902,9 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.40.1" +version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11438310b19e3109b6446c33d1ed5e889428cf2e278407bc7896bc4aaea43323" +checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" dependencies = [ "bitflags 2.13.1", "fallible-iterator", @@ -1987,9 +1917,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.12.0" +version = "8.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e7760e252aaba7b09f4be00e36476cf585bdb68a53552ac954cdf504ab4bc9" +checksum = "19afa5b4b6a611de00bd1bdae6ae6f39084c9399f0679c3f52d8469cf335cc23" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1998,23 +1928,23 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.12.0" +version = "8.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcfc4d6f53af43755f7a723e4b6b8794fcce052a178dd8c6c1dadc5f5343097" +checksum = "e0d8afda6374eac59e066abee06d265247ebbaf3006cf878e2879e8356e34053" dependencies = [ "mime_guess", "proc-macro2", "quote", "rust-embed-utils", - "syn", + "syn 2.0.119", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.12.0" +version = "8.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ffa149f6aa81b58a5b3011d01a857c4ed12c7a732d2c51947a4c7c692185f0" +checksum = "0d84e8ba78bd384263e5922f084cbe1b081c3b7e69add59c8fb097b879ba968a" dependencies = [ "sha2", "walkdir", @@ -2045,7 +1975,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2092,9 +2022,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -2102,29 +2032,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.7", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "1741ab7a6cc54a03a89b5d563ed60075c277d9e3cfa73ad0c1f23f23974703c6" dependencies = [ "itoa", "memchr", @@ -2210,16 +2140,6 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" -[[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", -] - [[package]] name = "socket2" version = "0.6.5" @@ -2227,7 +2147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2265,6 +2185,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d62a2e0561533f2ca2561d0cf27fd9fedb640a1bf2616ff5d5c80d99017faadc" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -2273,7 +2204,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2308,7 +2239,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2328,7 +2259,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2393,8 +2324,8 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.5", - "windows-sys 0.61.2", + "socket2", + "windows-sys", ] [[package]] @@ -2430,7 +2361,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2502,11 +2433,20 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "v_escape-base" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1212fce830b75af194b578e55b3db9049f2c8c45f58d397fb25602fdb50fb3d" + [[package]] name = "v_htmlescape" -version = "0.15.8" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" +checksum = "befb3d53c9e3ec641417685896cbc8cc5bd264d6a2e190c56aaef1af24740d99" +dependencies = [ + "v_escape-base", +] [[package]] name = "vcpkg" @@ -2568,7 +2508,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] @@ -2587,7 +2527,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2611,7 +2551,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2622,7 +2562,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2649,15 +2589,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -2667,70 +2598,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[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.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[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.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[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.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "winnow" version = "1.0.4" @@ -2774,7 +2641,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] @@ -2795,7 +2662,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] @@ -2835,7 +2702,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 407c2fea..b2cb488c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,12 @@ categories = ["pastebins"] [dependencies] -actix-files = "0.6.10" -actix-multipart = "0.8.0" +actix-files = "0.7.0" +actix-multipart = "0.8.5" actix-web = { version = "4", default-features = false, features = ["compat","compress-brotli", "compress-gzip", "cookies", "http2", "macros", "unicode"] } -actix-web-httpauth = "0.8.2" +actix-web-httpauth = "0.8.3" askama = "0.16" -bytesize = { version = "2.4", features = ["serde"] } +bytesize = { version = "2.7", features = ["serde"] } chrono = "0.4.19" clap = { version = "4.5.7", features = ["derive", "env"] } @@ -33,8 +33,8 @@ log = "0.4.21" magic-crypt = "5.0.1" mime_guess = "2.0.4" once_cell = "1.19.0" -qrcode-generator = "5.0.0" -rand = "0.10.2" +qrcode-generator = { version = "6.1.2", default-features = false, features = ["qr"] } +rand = "0.10.3" rusqlite = { version = "0.40", features = ["bundled"], optional = true } rust-embed = "8.3.0" sanitize-filename = "0.6.0" diff --git a/README.md b/README.md index 0454dd61..63569d28 100644 --- a/README.md +++ b/README.md @@ -173,9 +173,18 @@ Secret values (`BITVAULT_ADMIN_USERNAME`, `BITVAULT_ADMIN_PASSWORD`, `BITVAULT_B BitVault exposes a JSON API under `/api/v1/` for programmatic access and AI agent integration. +The API key is optional. By default (no `BITVAULT_API_KEY`, no Basic Auth) the API needs no authentication at all: + +```bash +curl -X POST http://localhost:8080/api/v1/paste \ + -H "Content-Type: application/json" \ + -d '{"content": "hello world"}' +# {"id":"happy-apple-banana","url":"/upload/happy-apple-banana","expires_at":1748736000,"privacy":"unlisted"} +``` + ### Authentication -Set `BITVAULT_API_KEY` to require a bearer token on all API requests (except `/health`, which is always open): +Optionally, set `BITVAULT_API_KEY` to require a bearer token on all API requests (except `/health`, which is always open): ```bash export BITVAULT_API_KEY=my-secret-token diff --git a/src/args.rs b/src/args.rs index bb2fcd43..504629c0 100644 --- a/src/args.rs +++ b/src/args.rs @@ -9,10 +9,26 @@ use std::fs; use std::net::IpAddr; use std::str::FromStr; +#[cfg(not(test))] lazy_static! { pub static ref ARGS: Args = Args::parse(); } +// Tests must not parse the test harness's own CLI flags; use a fixed config with a throwaway data dir. +#[cfg(test)] +lazy_static! { + pub static ref ARGS: Args = { + let data_dir = std::env::temp_dir().join(format!("bitvault-test-{}", std::process::id())); + fs::create_dir_all(&data_dir).expect("create test data dir"); + Args::parse_from([ + "bitvault", + "--editable", + "--data-dir", + data_dir.to_str().expect("utf-8 temp dir"), + ]) + }; +} + /// Single source of truth for valid expiry option strings, ordered shortest → longest. /// Used by both the CLI value_parser and the server-side validation in `create.rs`. pub const EXPIRATION_OPTIONS: &[&str] = &[ diff --git a/src/endpoints/api.rs b/src/endpoints/api.rs index 0348c24d..d52b4235 100644 --- a/src/endpoints/api.rs +++ b/src/endpoints/api.rs @@ -90,8 +90,13 @@ fn ct_eq(a: &[u8], b: &[u8]) -> bool { == 0 } -fn require_api_key(req: &HttpRequest) -> Result<(), HttpResponse> { - let Some(ref key) = ARGS.api_key else { +fn require_api_key(req: &HttpRequest) -> Result<(), Box> { + check_api_key(ARGS.api_key.as_deref().map(String::as_str), req) +} + +/// No key (or a blank one) configured means the API is open. +fn check_api_key(configured: Option<&str>, req: &HttpRequest) -> Result<(), Box> { + let Some(key) = configured else { return Ok(()); }; let key = key.trim(); @@ -117,7 +122,11 @@ fn require_api_key(req: &HttpRequest) -> Result<(), HttpResponse> { { Ok(()) } else { - Err(api_error(401, "API_KEY_REQUIRED", "Valid API key required")) + Err(Box::new(api_error( + 401, + "API_KEY_REQUIRED", + "Valid API key required", + ))) } } @@ -241,7 +250,7 @@ pub async fn create_paste( body: web::Json, ) -> HttpResponse { if let Err(e) = require_api_key(&req) { - return e; + return *e; } if body.content.is_empty() { @@ -346,7 +355,7 @@ pub async fn get_paste( req: HttpRequest, ) -> HttpResponse { if let Err(e) = require_api_key(&req) { - return e; + return *e; } let password = pasta_password(&req); @@ -395,7 +404,7 @@ pub async fn delete_paste( req: HttpRequest, ) -> HttpResponse { if let Err(e) = require_api_key(&req) { - return e; + return *e; } let password = pasta_password(&req); @@ -462,7 +471,7 @@ pub async fn update_paste( body: web::Json, ) -> HttpResponse { if let Err(e) = require_api_key(&req) { - return e; + return *e; } if body.content.is_empty() { @@ -537,7 +546,7 @@ pub async fn update_paste( pub async fn list_pastes(data: web::Data, req: HttpRequest) -> HttpResponse { if let Err(e) = require_api_key(&req) { - return e; + return *e; } if ARGS.no_listing { @@ -567,3 +576,100 @@ pub async fn list_pastes(data: web::Data, req: HttpRequest) -> HttpRes HttpResponse::Ok().json(list) } + +#[cfg(test)] +mod tests { + use super::*; + use actix_web::{http::StatusCode, test, App}; + use std::sync::Mutex; + + #[actix_web::test] + async fn api_works_without_api_key_or_basic_auth() { + assert!(ARGS.api_key.is_none() && ARGS.auth_basic_username.is_none()); + + let data = web::Data::new(AppState { + pastas: Mutex::new(crate::util::db::read_all()), + }); + // Same /api/v1 routes as main.rs; the Basic Auth wrapper is a no-op without a username. + let app = test::init_service( + App::new().app_data(data).service( + web::scope("/api/v1") + .route("/paste", web::post().to(create_paste)) + .route("/paste/{id}", web::get().to(get_paste)) + .route("/paste/{id}", web::delete().to(delete_paste)) + .route("/paste/{id}", web::patch().to(update_paste)) + .route("/pastes", web::get().to(list_pastes)), + ), + ) + .await; + + let req = test::TestRequest::post() + .uri("/api/v1/paste") + .set_json(serde_json::json!({"content": "hello", "privacy": "public"})) + .to_request(); + let resp = test::call_service(&app, req).await; + assert!(resp.status().is_success(), "create: {}", resp.status()); + let created: serde_json::Value = test::read_body_json(resp).await; + let id = created["id"].as_str().expect("id").to_string(); + + let req = test::TestRequest::get() + .uri(&format!("/api/v1/paste/{id}")) + .to_request(); + let got: serde_json::Value = test::call_and_read_body_json(&app, req).await; + assert_eq!(got["content"], "hello"); + + let req = test::TestRequest::get().uri("/api/v1/pastes").to_request(); + let list: serde_json::Value = test::call_and_read_body_json(&app, req).await; + assert!(list + .as_array() + .unwrap() + .iter() + .any(|p| p["id"] == id.as_str())); + + let req = test::TestRequest::patch() + .uri(&format!("/api/v1/paste/{id}")) + .set_json(serde_json::json!({"content": "updated"})) + .to_request(); + let resp = test::call_service(&app, req).await; + assert!(resp.status().is_success(), "update: {}", resp.status()); + + let req = test::TestRequest::delete() + .uri(&format!("/api/v1/paste/{id}")) + .to_request(); + let resp = test::call_service(&app, req).await; + assert!(resp.status().is_success(), "delete: {}", resp.status()); + + let req = test::TestRequest::get() + .uri(&format!("/api/v1/paste/{id}")) + .to_request(); + assert_eq!( + test::call_service(&app, req).await.status(), + StatusCode::NOT_FOUND + ); + } + + #[actix_web::test] + async fn configured_api_key_is_enforced() { + let req = test::TestRequest::default().to_http_request(); + let resp = + check_api_key(Some("s3cret"), &req).expect_err("missing header must be rejected"); + assert_eq!(resp.status(), StatusCode::UNAUTHORIZED); + let body = actix_web::body::to_bytes(resp.into_body()).await.unwrap(); + let body: serde_json::Value = serde_json::from_slice(&body).unwrap(); + assert_eq!(body["code"], "API_KEY_REQUIRED"); + + let req = test::TestRequest::default() + .insert_header(("Authorization", "Bearer wrong")) + .to_http_request(); + assert!(check_api_key(Some("s3cret"), &req).is_err()); + + let req = test::TestRequest::default() + .insert_header(("Authorization", "Bearer s3cret")) + .to_http_request(); + assert!(check_api_key(Some("s3cret"), &req).is_ok()); + + let req = test::TestRequest::default().to_http_request(); + assert!(check_api_key(None, &req).is_ok()); + assert!(check_api_key(Some(" "), &req).is_ok()); + } +} diff --git a/src/util/misc.rs b/src/util/misc.rs index d7f14c0e..17ccce8d 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -4,7 +4,8 @@ use crate::args::ARGS; use crate::util::{bip39words::to_bip39_words, hashids::to_hashids}; use linkify::{LinkFinder, LinkKind}; use magic_crypt::{new_magic_crypt, MagicCryptTrait}; -use qrcode_generator::QrCodeEcc; +use qrcode_generator::qr::{Encoder, ErrorCorrection}; +use qrcode_generator::Renderer; use std::fs::{self, File}; use std::io::{BufReader, Read, Write}; use std::path::Path; @@ -133,7 +134,10 @@ pub fn resolve_attachment_id(id: u64) -> String { } pub fn string_to_qr_svg(str: &str) -> String { - qrcode_generator::to_svg_to_string(str, QrCodeEcc::Low, 256, None::<&str>).unwrap() + let symbol = Encoder::new(ErrorCorrection::Low).encode_text(str).unwrap(); + Renderer::new(&symbol, 256) + .to_svg_string(None::<&str>) + .unwrap() } pub fn is_valid_url(url: &str) -> bool {