diff --git a/Cargo.lock b/Cargo.lock index 909d903..1839426 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -142,10 +142,10 @@ dependencies = [ "axum-macros", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "itoa", "matchit", @@ -176,8 +176,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -199,8 +199,8 @@ dependencies = [ "bytes", "futures-util", "headers", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -238,12 +238,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -356,6 +350,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[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 = "concurrent-queue" version = "2.5.0" @@ -371,16 +375,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -547,9 +541,9 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -710,25 +704,6 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" -[[package]] -name = "h2" -version = "0.3.26" -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", -] - [[package]] name = "h2" version = "0.4.5" @@ -740,7 +715,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http", "indexmap", "slab", "tokio", @@ -776,7 +751,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 1.1.0", + "http", "httpdate", "mime", "sha1", @@ -788,7 +763,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.1.0", + "http", ] [[package]] @@ -842,17 +817,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -864,17 +828,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.0.1" @@ -882,7 +835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -893,8 +846,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -910,30 +863,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.4.1" @@ -943,48 +872,15 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "smallvec", "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.30", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "rustls 0.23.12", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.0", - "tower-service", - "webpki-roots 0.26.3", ] [[package]] @@ -994,17 +890,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", - "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http", + "http-body", + "hyper", "pin-project-lite", - "socket2", "tokio", - "tower", - "tower-service", - "tracing", ] [[package]] @@ -1052,10 +943,13 @@ dependencies = [ ] [[package]] -name = "ipnet" -version = "2.9.0" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] [[package]] name = "itoa" @@ -1223,7 +1117,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http", "httparse", "memchr", "mime", @@ -1314,26 +1208,6 @@ dependencies = [ "libm", ] -[[package]] -name = "oauth2" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" -dependencies = [ - "base64 0.13.1", - "chrono", - "getrandom", - "http 0.2.12", - "rand", - "reqwest 0.11.27", - "serde", - "serde_json", - "serde_path_to_error", - "sha2", - "thiserror", - "url", -] - [[package]] name = "object" version = "0.36.2" @@ -1384,12 +1258,33 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + [[package]] name = "pem" version = "3.0.4" @@ -1482,11 +1377,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy 0.6.6", + "zerocopy", ] [[package]] @@ -1533,11 +1428,13 @@ dependencies = [ "dotenvy", "futures", "jsonwebtoken", - "oauth2", - "reqwest 0.12.5", + "rand", + "scrypt", "serde", + "serde_json", "sha2", "sqlx", + "subtle", "tokio", "tokio-util", "tower", @@ -1549,52 +1446,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "quinn" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls 0.23.12", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls 0.23.12", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" -dependencies = [ - "libc", - "once_cell", - "socket2", - "windows-sys 0.52.0", -] - [[package]] name = "quote" version = "1.0.36" @@ -1654,9 +1505,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1696,90 +1547,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-rustls 0.24.2", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-rustls 0.24.1", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.4", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.2", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls 0.23.12", - "rustls-pemfile 2.1.2", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tokio-rustls 0.26.0", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.26.3", - "winreg 0.52.0", -] - [[package]] name = "ring" version = "0.17.8" @@ -1821,12 +1588,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustix" version = "0.38.34" @@ -1846,26 +1607,11 @@ version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "log", "ring", - "rustls-webpki 0.101.7", + "rustls-webpki", "sct", ] -[[package]] -name = "rustls" -version = "0.23.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.6", - "subtle", - "zeroize", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -1875,22 +1621,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" - [[package]] name = "rustls-webpki" version = "0.101.7" @@ -1901,17 +1631,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "rustls-webpki" -version = "0.102.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -1924,12 +1643,33 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + [[package]] name = "sct" version = "0.7.1" @@ -2145,8 +1885,8 @@ dependencies = [ "once_cell", "paste", "percent-encoding", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", + "rustls", + "rustls-pemfile", "serde", "serde_json", "sha2", @@ -2158,7 +1898,7 @@ dependencies = [ "tracing", "url", "uuid", - "webpki-roots 0.25.4", + "webpki-roots", ] [[package]] @@ -2359,35 +2099,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] @@ -2496,27 +2216,6 @@ dependencies = [ "syn 2.0.72", ] -[[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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls 0.23.12", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -2567,8 +2266,8 @@ dependencies = [ "bitflags 2.6.0", "bytes", "futures-core", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "pin-project-lite", "tokio", @@ -2654,12 +2353,6 @@ 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" @@ -2714,7 +2407,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -2803,15 +2495,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[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.11.0+wasi-snapshot-preview1" @@ -2849,18 +2532,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -2890,31 +2561,12 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-roots" version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "whoami" version = "1.5.1" @@ -3095,54 +2747,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "zerocopy" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" -dependencies = [ - "byteorder", - "zerocopy-derive 0.6.6", -] - [[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy-derive" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", + "byteorder", + "zerocopy-derive", ] [[package]] @@ -3173,18 +2785,18 @@ dependencies = [ [[package]] name = "zstd-safe" -version = "7.2.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.12+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 54eda93..52f661d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,13 +25,10 @@ chrono = { version = "0.4", features = ["serde"] } dotenvy = "0.15" futures = "0.3" jsonwebtoken = "9" -oauth2 = "4" -reqwest = { version = "0.12", features = [ - "http2", - "rustls-tls", - "json", -], default-features = false } +rand = "0.8" +scrypt = { version = "0.11", default-features = false, features = ["std"] } serde = { version = "1", features = ["derive"] } +serde_json = "1" sha2 = "0.10" sqlx = { version = "0.8", features = [ "postgres", @@ -41,6 +38,7 @@ sqlx = { version = "0.8", features = [ "chrono", "uuid", ] } +subtle = "2" tokio = { version = "1", features = ["parking_lot", "rt-multi-thread"] } tokio-util = { version = "0.7" } tower = { version = "0.4" } diff --git a/migrations/0001_initial.down.sql b/migrations/0001_initial.down.sql index f5b31f1..72c6d1d 100644 --- a/migrations/0001_initial.down.sql +++ b/migrations/0001_initial.down.sql @@ -1,7 +1,3 @@ -DROP EXTENSION IF EXISTS pg_trgm; - -DROP EXTENSION IF EXISTS pg_uuidv7; - DROP TABLE permissions; DROP TABLE files; @@ -10,4 +6,8 @@ DROP TABLE folders; DROP TABLE users; -DROP TYPE permission; \ No newline at end of file +DROP TYPE permission; + +DROP EXTENSION IF EXISTS pg_trgm; + +DROP EXTENSION IF EXISTS pg_uuidv7; \ No newline at end of file diff --git a/migrations/0001_initial.up.sql b/migrations/0001_initial.up.sql index 3b5bb92..a6dceeb 100644 --- a/migrations/0001_initial.up.sql +++ b/migrations/0001_initial.up.sql @@ -6,7 +6,8 @@ CREATE TABLE users ( user_id SERIAL PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, - email VARCHAR(100) NOT NULL UNIQUE + email VARCHAR(100) NOT NULL UNIQUE, + hashed_password BYTEA NOT NULL ); CREATE TABLE diff --git a/src/auth.rs b/src/auth.rs index 2a972e0..d3d22b7 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,26 +1,173 @@ +use std::{array::TryFromSliceError, sync::LazyLock}; + use axum::{ - extract::{FromRequestParts, Query}, + extract::FromRequestParts, http::{request::Parts, StatusCode}, + response::IntoResponse, RequestPartsExt, }; -use serde::Deserialize; +use axum_extra::{ + headers::{authorization::Bearer, Authorization}, + TypedHeader, +}; +use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; +use rand::{rngs::OsRng, RngCore}; +use serde::{Deserialize, Serialize}; +use subtle::ConstantTimeEq; -#[derive(Deserialize, Debug)] +use crate::{db, Pool}; + +pub const HASH_LENGTH: usize = 64; +pub const SALT_LENGTH: usize = 64; + +static PARAMS: LazyLock = + LazyLock::new(|| scrypt::Params::new(14, 8, 1, HASH_LENGTH).unwrap()); +static KEYS: LazyLock = LazyLock::new(|| { + let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); + Keys::from_secret(secret.as_bytes()) +}); + +struct Keys { + encoding_key: EncodingKey, + decoding_key: DecodingKey, +} + +impl Keys { + fn from_secret(secret: &[u8]) -> Self { + Self { + encoding_key: EncodingKey::from_secret(secret), + decoding_key: DecodingKey::from_secret(secret), + } + } +} + +/// Forces the evaluation of the keys. They will be created upon first use otherwise +pub fn force_init_keys() { + LazyLock::force(&KEYS); +} + +/// Hashes the bytes with Scrypt with the given salt +#[must_use] +fn hash_scrypt(bytes: &[u8], salt: &[u8]) -> [u8; HASH_LENGTH] { + let mut hash = [0; HASH_LENGTH]; + scrypt::scrypt(bytes, salt, &PARAMS, &mut hash).unwrap(); + hash +} + +/// Verifieble scrypt hashed bytes +pub struct HashedBytes { + pub hash: [u8; HASH_LENGTH], + pub salt: [u8; SALT_LENGTH], +} + +impl HashedBytes { + /// Hashes the bytes + #[must_use] + pub fn hash_bytes(bytes: &[u8]) -> Self { + let mut salt = [0; 64]; + OsRng.fill_bytes(&mut salt); + Self { + hash: hash_scrypt(bytes, &salt), + salt, + } + } + + /// Parses the bytes where the first `HASH_LENGTH` bytes are the hash and the latter `SALT_LENGTH` bytes are the salt + pub fn from_bytes(bytes: &[u8]) -> Result { + let (hash, salt) = bytes.split_at(HASH_LENGTH); + let result = Self { + hash: hash.try_into()?, + salt: salt.try_into()?, + }; + Ok(result) + } + + #[must_use] + pub fn verify(&self, bytes: &[u8]) -> bool { + let hash = hash_scrypt(bytes, self.salt.as_ref()); + hash.ct_eq(self.hash.as_ref()).into() + } + + pub fn as_bytes(&self) -> Vec { + let mut result = Vec::with_capacity(self.hash.len() + self.salt.len()); + result.extend_from_slice(&self.hash); + result.extend_from_slice(&self.salt); + result + } +} + +pub async fn authenticate_user( + username: &str, + password: &str, + pool: &Pool, +) -> anyhow::Result> { + let Some((user_id, hash)) = db::users::get_hash(username, pool).await? else { + return Ok(None); + }; + let hash = HashedBytes::from_bytes(&hash)?; + Ok(hash.verify(password.as_bytes()).then_some(user_id)) +} + +#[derive(Debug, Serialize)] +pub struct Token { + access_token: String, + token_type: &'static str, +} + +#[derive(Serialize, Deserialize, Debug)] pub struct Claims { pub user_id: i32, + pub exp: i64, +} + +impl Claims { + pub fn encode(self) -> Result { + let access_token = encode( + &Header::new(jsonwebtoken::Algorithm::HS256), + &self, + &KEYS.encoding_key, + ) + .map_err(|_| Error::TokenCreation)?; + let token = Token { + access_token, + token_type: "Bearer", + }; + Ok(token) + } +} + +#[derive(Debug)] +pub enum Error { + WrongCredentials, + TokenCreation, + InvalidToken, +} + +impl IntoResponse for Error { + fn into_response(self) -> axum::response::Response { + let (status, error_message) = match self { + Error::WrongCredentials => (StatusCode::UNAUTHORIZED, "Wrong credentials"), + Error::TokenCreation => (StatusCode::INTERNAL_SERVER_ERROR, "Token creation error"), + Error::InvalidToken => (StatusCode::BAD_REQUEST, "Invalid token"), + }; + (status, error_message).into_response() + } } #[axum::async_trait] impl FromRequestParts for Claims { - type Rejection = StatusCode; + type Rejection = Error; async fn from_request_parts(parts: &mut Parts, _state: &T) -> Result { - match parts.extract().await { - Ok(Query(claims)) => Ok(claims), - Err(err) => { - tracing::debug!(%err, "Autharization failed"); - Err(StatusCode::UNAUTHORIZED) - } - } + let TypedHeader(Authorization(bearer)) = parts + .extract::>>() + .await + .map_err(|_| Error::InvalidToken)?; + // Decode the user data + let token_data = + decode::(bearer.token(), &KEYS.decoding_key, &Validation::default()) + .map_err(|_| Error::InvalidToken)?; + + Ok(token_data.claims) } } diff --git a/src/db/file.rs b/src/db/file.rs index 0641ffa..39f59e6 100644 --- a/src/db/file.rs +++ b/src/db/file.rs @@ -1,3 +1,4 @@ +use futures::Stream; use uuid::Uuid; use crate::Pool; @@ -41,10 +42,12 @@ pub struct FileWithoutParentId { pub updated_at: chrono::NaiveDateTime, } -pub async fn get_files(folder_id: Uuid, pool: &Pool) -> sqlx::Result> { +pub fn get_files( + folder_id: Uuid, + pool: &Pool, +) -> impl Stream> + '_ { sqlx::query_as!(FileWithoutParentId, r#"SELECT file_id, file_name, file_size, encode(sha512, 'base64') as "sha512!", created_at, updated_at FROM files WHERE folder_id = $1"#, folder_id) - .fetch_all(pool) - .await + .fetch(pool) } async fn get_folder_id(file_id: Uuid, pool: &Pool) -> sqlx::Result> { diff --git a/src/db/users.rs b/src/db/users.rs index 7805363..afe3b77 100644 --- a/src/db/users.rs +++ b/src/db/users.rs @@ -5,11 +5,17 @@ use uuid::Uuid; use crate::Pool; /// Creates user and returns its id -pub async fn create_user(user_name: &str, user_email: &str, pool: &Pool) -> sqlx::Result { +pub async fn create_user( + user_name: &str, + user_email: &str, + hashed_password: &[u8], + pool: &Pool, +) -> sqlx::Result { let id = sqlx::query!( - "INSERT INTO users(username, email) VALUES ($1, $2) RETURNING user_id", + "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) RETURNING user_id", user_name, - user_email + user_email, + hashed_password ) .fetch_one(pool) .await? @@ -46,7 +52,7 @@ pub async fn update( ) -> sqlx::Result { sqlx::query_as!( UserInfo, - "UPDATE users SET username = $2, email = $3 WHERE user_id = $1 RETURNING *", + "UPDATE users SET username = $2, email = $3 WHERE user_id = $1 RETURNING user_id, username, email", user_id, username, email @@ -65,6 +71,17 @@ pub async fn get(user_id: i32, pool: &Pool) -> sqlx::Result { .await } +/// Gets the hashed password field by either the email or th username +pub async fn get_hash(search_string: &str, pool: &Pool) -> sqlx::Result)>> { + let record = sqlx::query!( + "SELECT user_id, hashed_password FROM users WHERE username = $1 OR email = $1", + search_string + ) + .fetch_optional(pool) + .await?; + Ok(record.map(|record| (record.user_id, record.hashed_password))) +} + pub fn search_for_user<'a>( search_string: &str, pool: &'a Pool, diff --git a/src/endpoints/authorization/auth_post.rs b/src/endpoints/authorization/auth_post.rs new file mode 100644 index 0000000..7508711 --- /dev/null +++ b/src/endpoints/authorization/auth_post.rs @@ -0,0 +1,34 @@ +use chrono::TimeDelta; + +use crate::{ + auth::{authenticate_user, Error, Token}, + prelude::*, +}; + +#[derive(Deserialize, Debug)] +pub struct Params { + username: String, + password: String, +} + +fn get_exp() -> i64 { + let mut time = chrono::Utc::now(); + time += TimeDelta::minutes(30); + time.timestamp() +} + +pub async fn post( + State(state): State, + Json(payload): Json, +) -> Result, Error> { + let user_id = authenticate_user(&payload.username, &payload.password, &state.pool) + .await + .map_err(|_| Error::WrongCredentials)? + .ok_or(Error::WrongCredentials)?; + Claims { + user_id, + exp: get_exp(), + } + .encode() + .map(Json) +} diff --git a/src/endpoints/authorization/mod.rs b/src/endpoints/authorization/mod.rs new file mode 100644 index 0000000..8052f27 --- /dev/null +++ b/src/endpoints/authorization/mod.rs @@ -0,0 +1 @@ +pub mod auth_post; diff --git a/src/endpoints/folder/get_structure.rs b/src/endpoints/folder/get_structure.rs index 7122eed..3dbb8c7 100644 --- a/src/endpoints/folder/get_structure.rs +++ b/src/endpoints/folder/get_structure.rs @@ -45,10 +45,10 @@ pub async fn structure( folder_id, structure: folder.into(), }; - let mut stack: Vec<&mut FolderStructure> = vec![&mut response.structure]; + let mut stack = vec![&mut response.structure]; while let Some(folder) = stack.pop() { let (files, folders) = try_join!( - db::file::get_files(folder_id, &pool), + db::file::get_files(folder_id, &pool).try_collect(), db::folder::get_folders(folder_id, claims.user_id, &pool) .map_ok(Into::into) .try_collect() diff --git a/src/endpoints/folder/list.rs b/src/endpoints/folder/list.rs index 9156a6d..8c85704 100644 --- a/src/endpoints/folder/list.rs +++ b/src/endpoints/folder/list.rs @@ -26,7 +26,7 @@ pub async fn list( .ok_or(StatusCode::NOT_FOUND)?; let (files, folders) = try_join!( - db::file::get_files(folder_id, &pool), + db::file::get_files(folder_id, &pool).try_collect(), db::folder::get_folders(folder_id, claims.user_id, &pool).try_collect() ) .handle_internal()?; diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index 7e45ca5..904333d 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -1,3 +1,4 @@ +pub mod authorization; pub mod file; pub mod folder; pub mod permissions; diff --git a/src/endpoints/users/create.rs b/src/endpoints/users/create.rs deleted file mode 100644 index 5c2023f..0000000 --- a/src/endpoints/users/create.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::prelude::*; - -#[derive(Deserialize, Debug)] -pub struct Params { - username: String, - email: String, -} - -pub async fn create( - State(pool): State, - Json(params): Json, -) -> Result, StatusCode> { - let id = db::users::create_user(¶ms.username, ¶ms.email, &pool) - .await - .handle_internal()?; - Ok(Json(id)) -} diff --git a/src/endpoints/users/mod.rs b/src/endpoints/users/mod.rs index cb22467..68a65ed 100644 --- a/src/endpoints/users/mod.rs +++ b/src/endpoints/users/mod.rs @@ -1,4 +1,3 @@ -pub mod create; pub mod delete; pub mod get; pub mod put; diff --git a/src/main.rs b/src/main.rs index d6a3d52..5ad79ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,8 @@ mod prelude; use std::{env, net::Ipv4Addr}; -use axum::{extract::FromRef, Router}; +use auth::HashedBytes; +use axum::{extract::FromRef, routing::post, Router}; use file_storage::FileStorage; use tokio::net::TcpListener; @@ -28,10 +29,12 @@ async fn create_test_users(pool: &Pool) -> anyhow::Result<()> { if count > 0 { return Ok(()); } + let hash1 = HashedBytes::hash_bytes(b"Password1").as_bytes(); + let hash2 = HashedBytes::hash_bytes(b"Password2").as_bytes(); tokio::try_join!( - db::users::create_user("Test1", "test1@example.com", pool), - db::users::create_user("Test2", "test2@example.com", pool) + db::users::create_user("Test1", "test1@example.com", &hash1, pool), + db::users::create_user("Test2", "test2@example.com", &hash2, pool) )?; Ok(()) @@ -44,6 +47,8 @@ async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); + auth::force_init_keys(); + let pool = match env::var("DATABASE_URL") { Ok(url) => Pool::connect(&url).await?, Err(err) => anyhow::bail!("Error getting database url: {err}"), @@ -70,7 +75,7 @@ async fn main() -> anyhow::Result<()> { fn app(state: AppState) -> Router { use axum::{http::header, routing::get}; use endpoints::{ - file, folder, + authorization, file, folder, permissions::{self, get_top_level::get_top_level}, users, }; @@ -112,11 +117,11 @@ fn app(state: AppState) -> Router { .route( "/users", get(users::get::get) - .post(users::create::create) .delete(users::delete::delete) .put(users::put::put), ) .route("/users/search", get(users::search::search)) + .route("/authorize", post(authorization::auth_post::post)) .layer(middleware) .with_state(state) }