diff --git a/Cargo.lock b/Cargo.lock index 46a0ab8..4319a5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags", + "bitflags 2.9.1", "bytes", "futures-core", "futures-sink", @@ -29,8 +29,8 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "base64", - "bitflags", + "base64 0.22.1", + "bitflags 2.9.1", "brotli", "bytes", "bytestring", @@ -239,6 +239,20 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.3", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -524,12 +538,30 @@ dependencies = [ "windows-targets 0.52.6", ] +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.1" @@ -633,6 +665,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-link", ] @@ -783,6 +816,12 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + [[package]] name = "deranged" version = "0.4.0" @@ -1101,6 +1140,7 @@ dependencies = [ "actix-multipart", "actix-web", "dotenv", + "jmap-client", "log", "minio", "serde", @@ -1256,6 +1296,17 @@ 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" @@ -1275,7 +1326,7 @@ dependencies = [ "bytes", "futures-core", "http 1.3.1", - "http-body", + "http-body 1.0.1", "pin-project-lite", ] @@ -1291,6 +1342,30 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[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", + "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.6.0" @@ -1302,7 +1377,7 @@ dependencies = [ "futures-util", "h2 0.4.10", "http 1.3.1", - "http-body", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -1312,6 +1387,20 @@ dependencies = [ "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.32", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1320,7 +1409,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.6.0", "hyper-util", "native-tls", "tokio", @@ -1334,14 +1423,14 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", "http 1.3.1", - "http-body", - "hyper", + "http-body 1.0.1", + "hyper 1.6.0", "ipnet", "libc", "percent-encoding", @@ -1557,6 +1646,28 @@ dependencies = [ "syn 2.0.103", ] +[[package]] +name = "jmap-client" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12c697483ad894a8184d0fd61848e057f86b16642049993b3e6a80c959dbc90a" +dependencies = [ + "ahash", + "async-stream", + "base64 0.13.1", + "chrono", + "futures-util", + "maybe-async", + "parking_lot", + "reqwest 0.11.27", + "rustls 0.22.4", + "rustls-pki-types", + "serde", + "serde_json", + "tokio", + "tokio-tungstenite", +] + [[package]] name = "jobserver" version = "0.1.33" @@ -1652,6 +1763,17 @@ dependencies = [ "value-bag", ] +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "md5" version = "0.7.0" @@ -1679,7 +1801,7 @@ dependencies = [ "async-std", "async-stream", "async-trait", - "base64", + "base64 0.22.1", "byteorder", "bytes", "chrono", @@ -1692,7 +1814,7 @@ dependencies = [ "hex", "hmac", "http 1.3.1", - "hyper", + "hyper 1.6.0", "lazy_static", "log", "md5", @@ -1700,7 +1822,7 @@ dependencies = [ "percent-encoding", "rand 0.8.5", "regex", - "reqwest", + "reqwest 0.12.20", "serde", "serde_json", "sha2", @@ -1807,7 +1929,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -2064,7 +2186,7 @@ version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ - "bitflags", + "bitflags 2.9.1", ] [[package]] @@ -2102,20 +2224,63 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[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.32", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + [[package]] name = "reqwest" version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-core", "futures-util", "http 1.3.1", - "http-body", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.6.0", "hyper-tls", "hyper-util", "js-sys", @@ -2127,7 +2292,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tokio-native-tls", "tokio-util", @@ -2141,6 +2306,20 @@ dependencies = [ "web-sys", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -2162,13 +2341,48 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] +[[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.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[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.12.0" @@ -2178,6 +2392,27 @@ dependencies = [ "zeroize", ] +[[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.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -2205,13 +2440,23 @@ 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 = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.9.1", "core-foundation", "core-foundation-sys", "libc", @@ -2395,6 +2640,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -2415,6 +2666,27 @@ dependencies = [ "syn 2.0.103", ] +[[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.20.0" @@ -2428,6 +2700,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -2517,6 +2809,27 @@ dependencies = [ "tokio", ] +[[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.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -2528,6 +2841,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +dependencies = [ + "futures-util", + "log", + "rustls 0.22.4", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tungstenite", + "webpki-roots 0.26.11", +] + [[package]] name = "tokio-util" version = "0.7.15" @@ -2550,7 +2879,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower-layer", "tower-service", @@ -2562,11 +2891,11 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags", + "bitflags 2.9.1", "bytes", "futures-util", "http 1.3.1", - "http-body", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -2650,6 +2979,27 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.3.1", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.22.4", + "rustls-pki-types", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typenum" version = "1.18.0" @@ -2668,6 +3018,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.4" @@ -2685,6 +3041,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -2839,6 +3201,30 @@ dependencies = [ "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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.1", +] + +[[package]] +name = "webpki-roots" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2920,6 +3306,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -2947,6 +3342,21 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -2979,6 +3389,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2991,6 +3407,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3003,6 +3425,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3027,6 +3455,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3039,6 +3473,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3051,6 +3491,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3063,6 +3509,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3075,13 +3527,23 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[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 = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags", + "bitflags 2.9.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e863c8d..aff314a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" minio = { git = "https://github.com/minio/minio-rs", branch = "master" } tokio-stream = "0.1.17" +jmap-client = "0.3.2" diff --git a/src/main.rs b/src/main.rs index e9ef551..913dfa2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,163 +1,17 @@ - use actix_web::{middleware, web, App, HttpServer}; use tracing_subscriber::fmt::format::FmtSpan; use dotenv::dotenv; -use actix_multipart::Multipart; -use actix_web::{post, HttpResponse}; -use minio::s3::builders::ObjectContent; -use minio::s3::Client; -use std::io::Write; -use tempfile::NamedTempFile; -use minio::s3::types::ToStream; -use tokio_stream::StreamExt; - -use minio::s3::client::{Client as MinioClient, ClientBuilder as MinioClientBuilder}; -use minio::s3::creds::StaticProvider; -use minio::s3::http::BaseUrl; -use std::str::FromStr; - use services::config::*; +use services::file::*; +use services::state::*; mod services; -// App state shared across all handlers -pub struct AppState { - pub minio_client: Option, - pub config: Option, - -} - -pub async fn init_minio(config: &AppConfig) -> Result { - let scheme = if config.minio.use_ssl { "https" } else { "http" }; - let base_url = format!("{}://{}", scheme, config.minio.endpoint); - let base_url = BaseUrl::from_str(&base_url)?; - let credentials = StaticProvider::new( - &config.minio.access_key, - &config.minio.secret_key, - None, - ); - - let minio_client = MinioClientBuilder::new(base_url) - .provider(Some(credentials)) - .build()?; - - Ok(minio_client) -} - -#[post("/files/upload/{folder_path}")] -pub async fn upload_file( - folder_path: web::Path, - mut payload: Multipart, - state: web::Data, -) -> Result { - let folder_path = folder_path.into_inner(); - - // Create a temporary file to store the uploaded file. - - let mut temp_file = NamedTempFile::new().map_err(|e| { - actix_web::error::ErrorInternalServerError(format!("Failed to create temp file: {}", e)) - })?; - - let mut file_name = None; - - // Iterate over the multipart stream. - - while let Some(mut field) = payload.try_next().await? { - let content_disposition = field.content_disposition(); - file_name = content_disposition - .get_filename() - .map(|name| name.to_string()); - - // Write the file content to the temporary file. - while let Some(chunk) = field.try_next().await? { - temp_file.write_all(&chunk).map_err(|e| { - actix_web::error::ErrorInternalServerError(format!( - "Failed to write to temp file: {}", - e - )) - })?; - } - } - - // Get the file name or use a default name - let file_name = file_name.unwrap_or_else(|| "unnamed_file".to_string()); - - // Construct the object name using the folder path and file name - let object_name = format!("{}/{}", folder_path, file_name); - - // Upload the file to the MinIO bucket - let client: Client = state.minio_client.clone().unwrap(); - let bucket_name = "file-upload-rust-bucket"; - - let content = ObjectContent::from(temp_file.path()); - client - .put_object_content(bucket_name, &object_name, content) - .send() - .await - .map_err(|e| { - actix_web::error::ErrorInternalServerError(format!( - "Failed to upload file to MinIO: {}", - e - )) - })?; - - // Clean up the temporary file - temp_file.close().map_err(|e| { - actix_web::error::ErrorInternalServerError(format!("Failed to close temp file: {}", e)) - })?; - - Ok(HttpResponse::Ok().body(format!( - "Uploaded file '{}' to folder '{}'", - file_name, folder_path - ))) -} - - - -#[post("/files/list/{folder_path}")] -pub async fn list_file( - folder_path: web::Path, - state: web::Data, -) -> Result { - let folder_path = folder_path.into_inner(); - - let client: Client = state.minio_client.clone().unwrap(); - let bucket_name = "file-upload-rust-bucket"; - - // Create the stream using the to_stream() method - let mut objects_stream = client - .list_objects(bucket_name) - .prefix(Some(folder_path)) - .to_stream() - .await; - - let mut file_list = Vec::new(); - - // Use StreamExt::next() to iterate through the stream - while let Some(items) = objects_stream.next().await { - match items { - Ok(result) => { - for item in result.contents { - file_list.push(item.name); - } - }, - Err(e) => { - return Err(actix_web::error::ErrorInternalServerError( - format!("Failed to list files in MinIO: {}", e) - )); - } - } - } - - Ok(HttpResponse::Ok().json(file_list)) -} - #[actix_web::main] async fn main() -> std::io::Result<()> { dotenv().ok(); - // Initialize tracing tracing_subscriber::fmt() .with_span_events(FmtSpan::CLOSE) .init(); @@ -178,8 +32,10 @@ async fn main() -> std::io::Result<()> { .wrap(middleware::Logger::default()) .wrap(middleware::Compress::default()) .app_data(app_state.clone()) - .service(upload_file) // Uncomment and import or define upload_file below - }) + .service(upload_file) + .service(list_file) + + }) .bind((config.server.host.clone(), config.server.port))? .run() .await diff --git a/src/services.rs b/src/services.rs index ef68c36..5c6ea42 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1 +1,4 @@ pub mod config; +pub mod file; +pub mod state; +pub mod email; \ No newline at end of file diff --git a/src/services/email.rs b/src/services/email.rs new file mode 100644 index 0000000..67eb5f0 --- /dev/null +++ b/src/services/email.rs @@ -0,0 +1,81 @@ + +use jmap_client::{ + client::Client, + core::query::Filter, + email::{self, Property}, + mailbox::{self, Role}, +}; + + +pub async fn list_emails( +) -> Result, jmap_client::Error> { + + // 1. Authenticate with JMAP server + let client = Client::new() + .credentials(("test@", "")) + .connect("https://mail/jmap/") + .await + .unwrap(); + + let inbox_id = client + .mailbox_query( + mailbox::query::Filter::role(Role::Inbox).into(), + None::>, + ) + .await + .unwrap() + .take_ids() + .pop() + .unwrap(); + + let email_id = client + .email_query( + Filter::and([ + // email::query::Filter::subject("test"), + email::query::Filter::in_mailbox(&inbox_id), + // email::query::Filter::has_keyword("$draft"), + ]) + .into(), + [email::query::Comparator::from()].into(), + ) + .await + .unwrap() + .take_ids() + .pop() + .unwrap(); + + // Fetch message + let email = client + .email_get( + &email_id, + [Property::Subject, Property::Preview, Property::Keywords].into(), + ) + .await + .unwrap(); + + let mut emails = client + .email_query( + Filter::and([email::query::Filter::in_mailbox(inbox_id)]) + .into(), + [email::query::Comparator::from()].into(), + ) + .await?; + + let email_ids = emails.take_ids(); + let mut email_list = Vec::new(); + + for email_id in email_ids { + if let Some(email) = client + .email_get( + &email_id, + [Property::Subject, Property::Preview, Property::Keywords].into(), + ) + .await? + { + email_list.push(email); + } + } + + Ok(email_list) + +} \ No newline at end of file diff --git a/src/services/file.rs b/src/services/file.rs new file mode 100644 index 0000000..77cbf32 --- /dev/null +++ b/src/services/file.rs @@ -0,0 +1,143 @@ +use actix_web::{ web}; + +use actix_multipart::Multipart; +use actix_web::{post, HttpResponse}; +use minio::s3::builders::ObjectContent; +use minio::s3::Client; +use std::io::Write; +use tempfile::NamedTempFile; +use minio::s3::types::ToStream; +use tokio_stream::StreamExt; + +use minio::s3::client::{Client as MinioClient, ClientBuilder as MinioClientBuilder}; +use minio::s3::creds::StaticProvider; +use minio::s3::http::BaseUrl; +use std::str::FromStr; + +use crate::services::config::{AppConfig}; +use crate::services::state::AppState; + +pub async fn init_minio(config: &AppConfig) -> Result { + let scheme = if config.minio.use_ssl { "https" } else { "http" }; + let base_url = format!("{}://{}", scheme, config.minio.endpoint); + let base_url = BaseUrl::from_str(&base_url)?; + let credentials = StaticProvider::new( + &config.minio.access_key, + &config.minio.secret_key, + None, + ); + + let minio_client = MinioClientBuilder::new(base_url) + .provider(Some(credentials)) + .build()?; + + Ok(minio_client) +} + +#[post("/files/upload/{folder_path}")] +pub async fn upload_file( + folder_path: web::Path, + mut payload: Multipart, + state: web::Data, +) -> Result { + let folder_path = folder_path.into_inner(); + + // Create a temporary file to store the uploaded file. + + let mut temp_file = NamedTempFile::new().map_err(|e| { + actix_web::error::ErrorInternalServerError(format!("Failed to create temp file: {}", e)) + })?; + + let mut file_name = None; + + // Iterate over the multipart stream. + + while let Some(mut field) = payload.try_next().await? { + let content_disposition = field.content_disposition(); + file_name = content_disposition + .get_filename() + .map(|name| name.to_string()); + + // Write the file content to the temporary file. + while let Some(chunk) = field.try_next().await? { + temp_file.write_all(&chunk).map_err(|e| { + actix_web::error::ErrorInternalServerError(format!( + "Failed to write to temp file: {}", + e + )) + })?; + } + } + + // Get the file name or use a default name + let file_name = file_name.unwrap_or_else(|| "unnamed_file".to_string()); + + // Construct the object name using the folder path and file name + let object_name = format!("{}/{}", folder_path, file_name); + + // Upload the file to the MinIO bucket + let client: Client = state.minio_client.clone().unwrap(); + let bucket_name = "file-upload-rust-bucket"; + + let content = ObjectContent::from(temp_file.path()); + client + .put_object_content(bucket_name, &object_name, content) + .send() + .await + .map_err(|e| { + actix_web::error::ErrorInternalServerError(format!( + "Failed to upload file to MinIO: {}", + e + )) + })?; + + // Clean up the temporary file + temp_file.close().map_err(|e| { + actix_web::error::ErrorInternalServerError(format!("Failed to close temp file: {}", e)) + })?; + + Ok(HttpResponse::Ok().body(format!( + "Uploaded file '{}' to folder '{}'", + file_name, folder_path + ))) +} + + + +#[post("/files/list/{folder_path}")] +pub async fn list_file( + folder_path: web::Path, + state: web::Data, +) -> Result { + let folder_path = folder_path.into_inner(); + + let client: Client = state.minio_client.clone().unwrap(); + let bucket_name = "file-upload-rust-bucket"; + + // Create the stream using the to_stream() method + let mut objects_stream = client + .list_objects(bucket_name) + .prefix(Some(folder_path)) + .to_stream() + .await; + + let mut file_list = Vec::new(); + + // Use StreamExt::next() to iterate through the stream + while let Some(items) = objects_stream.next().await { + match items { + Ok(result) => { + for item in result.contents { + file_list.push(item.name); + } + }, + Err(e) => { + return Err(actix_web::error::ErrorInternalServerError( + format!("Failed to list files in MinIO: {}", e) + )); + } + } + } + + Ok(HttpResponse::Ok().json(file_list)) +} diff --git a/src/services/state.rs b/src/services/state.rs new file mode 100644 index 0000000..9499697 --- /dev/null +++ b/src/services/state.rs @@ -0,0 +1,12 @@ +use minio::s3::Client; + +use crate::services::config::AppConfig; + + +// App state shared across all handlers +pub struct AppState { + pub minio_client: Option, + pub config: Option, + +} +