From 2540860129a2ef51b076a89c273269fb4415e334 Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 5 Apr 2025 10:45:04 -0700 Subject: [PATCH] feat: Add Mass Mentions to the backend (#394) * feat: create base of push daemon Signed-off-by: IAmTomahawkx * Add outbound senders * Make web_push send to rabbit instead (temp stuff) * feat: stability and friend requests * make vapid fr stuff not suck * swap naming of queue * move pushd into daemons folder * fix cargo file for move into daemons folder * feat: probably working fcm push notifs * comment out fcm webpush stuff since the config keys dont exist * fix fcm, name queues according to their prod status and configure routing keys * add pushd to docker * mix: Remove old code, add stuff to pushd * fix: lockfile * feat: update rocket to 5.0.1 * fix: fix queues and ack bugs * Move rabbit messsage processing into ack queue * chore: update readme * chore: optimizations for ack database hits * pushd flowchart * misc: update flowchart * exit dependancy hell * add rocket_impl flag to authifier * make the tests file of delta actually compile * fix: don't silence every push message * fix: don't silence all messages * add debug logging for sending data to rabbit from message events * validate mentions at a server membership level * put back that import that was actually important * minor fix to lockfile * update delta authifier * feat: proper permissions for push notifications * add unit test for mention sanitization * remove local file dependancy on authifier * update ports to proper defaults * fixTM the node bindings * Theoretically configure docker releases for pushd Signed-off-by: IAmTomahawkx * declare exchange in pushd and delta * fix createbuckets script Signed-off-by: IAmTomahawkx * fix: reference db implementation Signed-off-by: IAmTomahawkx * fix: remove finally redundant code Signed-off-by: IAmTomahawkx * fix: changes Signed-off-by: IAmTomahawkx * fix: other changes Signed-off-by: IAmTomahawkx * fix: make channel name return result Signed-off-by: IAmTomahawkx * Add role mention parsing * feat: update to mongo 3.1, add member generator. * integrate mass mentions into pushd * patch redis-rs with updated versions * feat: chunk role mentions * move permission bits to 37/38 to avoid livekit conflict * change role mention format to <%id> * fix the lockfile from merge * fix: PR change requests * feat: add tests * fix: i am a dumbass * fix: tests, again --------- Signed-off-by: IAmTomahawkx --- .config/nextest.toml | 2 +- Cargo.lock | 4035 ++++++++++------- Cargo.toml | 5 +- crates/bonfire/Cargo.toml | 2 +- crates/core/config/Revolt.toml | 19 +- crates/core/config/src/lib.rs | 11 + crates/core/database/Cargo.toml | 4 +- crates/core/database/src/amqp/amqp.rs | 32 + crates/core/database/src/drivers/mongodb.rs | 18 +- crates/core/database/src/events/rabbit.rs | 6 + .../models/admin_migrations/ops/mongodb.rs | 4 +- .../admin_migrations/ops/mongodb/init.rs | 342 +- .../admin_migrations/ops/mongodb/scripts.rs | 571 +-- .../src/models/channel_invites/ops/mongodb.rs | 9 +- .../src/models/channel_unreads/ops.rs | 8 + .../src/models/channel_unreads/ops/mongodb.rs | 47 +- .../models/channel_unreads/ops/reference.rs | 32 + .../models/channel_webhooks/ops/mongodb.rs | 9 +- .../src/models/channels/ops/mongodb.rs | 44 +- .../database/src/models/emojis/ops/mongodb.rs | 1 - .../src/models/file_hashes/ops/mongodb.rs | 1 - .../database/src/models/files/ops/mongodb.rs | 5 - .../database/src/models/messages/model.rs | 212 +- .../src/models/messages/ops/mongodb.rs | 22 +- .../models/ratelimit_events/ops/mongodb.rs | 15 +- .../database/src/models/server_members/ops.rs | 79 + .../src/models/server_members/ops/mongodb.rs | 142 +- .../models/server_members/ops/reference.rs | 66 +- .../src/models/servers/ops/mongodb.rs | 45 +- .../src/models/user_settings/ops/mongodb.rs | 2 +- .../database/src/models/users/ops/mongodb.rs | 142 +- crates/core/database/src/tasks/ack.rs | 64 +- crates/core/database/src/tasks/mod.rs | 10 +- crates/core/database/src/util/bridge/v0.rs | 2 + .../database/src/util/bulk_permissions.rs | 23 + crates/core/models/Cargo.toml | 4 +- crates/core/models/src/v0/messages.rs | 15 +- crates/core/permissions/src/models/channel.rs | 8 +- crates/core/result/src/axum.rs | 4 +- crates/core/result/src/lib.rs | 7 + crates/core/result/src/rocket.rs | 3 + crates/daemons/pushd/Cargo.toml | 6 +- crates/daemons/pushd/Pushd Flowchart.graffle | Bin 45755 -> 52601 bytes .../pushd/src/consumers/inbound/ack.rs | 10 + .../src/consumers/inbound/mass_mention.rs | 275 ++ .../pushd/src/consumers/inbound/mod.rs | 1 + .../pushd/src/consumers/outbound/apn.rs | 23 +- crates/daemons/pushd/src/main.rs | 26 +- crates/delta/Cargo.toml | 4 +- .../delta/src/routes/channels/message_send.rs | 194 +- crates/delta/src/util/test.rs | 25 +- 51 files changed, 4083 insertions(+), 2553 deletions(-) create mode 100644 crates/daemons/pushd/src/consumers/inbound/mass_mention.rs diff --git a/.config/nextest.toml b/.config/nextest.toml index d50a040b..1f69a63f 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -1,2 +1,2 @@ [profile.default] -slow-timeout = { period = "3s", terminate-after = 2 } +slow-timeout = { period = "5s", terminate-after = 10 } diff --git a/Cargo.lock b/Cargo.lock index ba3bee32..b5cf3477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,22 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -30,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common", - "generic-array 0.14.5", + "generic-array 0.14.7", ] [[package]] @@ -60,9 +54,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -99,9 +93,9 @@ checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "amqp_serde" @@ -109,7 +103,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "787581044ca08ad61cdb3a4e21afba087fb8cdba3bb3e23ce69a7d091808014d" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "serde", "serde_bytes_ng", ] @@ -122,10 +116,10 @@ checksum = "3f1b4afcbd862e16c272b7625b6b057930b052d63c720bc90f6afab0d9abe8a8" dependencies = [ "amqp_serde", "async-trait", - "bytes 1.5.0", + "bytes 1.9.0", "serde", "serde_bytes_ng", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] @@ -143,32 +137,23 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arg_enum_proc_macro" @@ -177,15 +162,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "arrayref" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -199,18 +184,18 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] name = "async-channel" -version = "1.6.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ - "concurrent-queue 1.2.2", - "event-listener 2.5.2", + "concurrent-queue", + "event-listener 2.5.3", "futures-core", ] @@ -220,60 +205,59 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ - "concurrent-queue 2.5.0", + "concurrent-queue", "event-listener-strategy", "futures-core", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", ] [[package]] name = "async-executor" -version = "1.4.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", - "concurrent-queue 1.2.2", - "fastrand 1.7.0", - "futures-lite", - "once_cell", + "concurrent-queue", + "fastrand 2.3.0", + "futures-lite 2.5.0", "slab", ] [[package]] name = "async-global-executor" -version = "2.1.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 1.6.1", + "async-channel 2.3.1", "async-executor", "async-io", - "async-lock 2.8.0", + "async-lock 3.4.0", "blocking", - "futures-lite", + "futures-lite 2.5.0", "once_cell", "tokio 0.2.25", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] name = "async-io" -version = "1.7.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ - "concurrent-queue 1.2.2", - "futures-lite", - "libc", - "log", - "once_cell", + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.5.0", "parking", - "polling", + "polling 3.7.4", + "rustix", "slab", - "socket2 0.4.4", - "waker-fn", - "winapi", + "tracing", + "windows-sys 0.59.0", ] [[package]] @@ -282,7 +266,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener 2.5.2", + "event-listener 2.5.3", ] [[package]] @@ -293,24 +277,26 @@ checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener 5.3.1", "event-listener-strategy", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", ] [[package]] name = "async-process" -version = "1.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ + "async-channel 2.3.1", "async-io", + "async-lock 3.4.0", + "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 2.5.2", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", + "event-listener 5.3.1", + "futures-lite 2.5.0", + "rustix", + "tracing", ] [[package]] @@ -320,89 +306,93 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock 3.4.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", - "async-channel 1.6.1", + "async-channel 1.9.0", "async-global-executor", "async-io", - "async-lock 2.8.0", + "async-lock 3.4.0", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite", + "futures-lite 2.5.0", "gloo-timers", "kv-log-macro", "log", "memchr", "once_cell", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "pin-utils", "slab", "wasm-bindgen-futures", ] -[[package]] -name = "async-std-resolver" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2f8a4a203be3325981310ab243a28e6e4ea55b6519bffce05d41ab60e09ad8" -dependencies = [ - "async-std", - "async-trait", - "futures-io", - "futures-util", - "pin-utils", - "socket2 0.4.4", - "trust-dns-resolver", -] - [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite 0.2.15", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "async-task" -version = "4.2.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -415,24 +405,30 @@ dependencies = [ "futures-io", "futures-util", "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "tungstenite", ] [[package]] name = "atomic" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" dependencies = [ - "autocfg 1.1.0", + "bytemuck", ] [[package]] name = "atomic-waker" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atty" @@ -447,9 +443,9 @@ dependencies = [ [[package]] name = "authifier" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba4df3b5df5cf1a08d4af71c407fb56a675b6aaf4d1fec704da32595497d73d" +checksum = "edfe88c4a9fcf24b18a216b27c9766966af2a40603d24c7782237afd6ca0d5cd" dependencies = [ "async-std", "async-trait", @@ -458,7 +454,7 @@ dependencies = [ "chrono", "futures", "handlebars", - "iso8601-timestamp 0.1.10", + "iso8601-timestamp 0.1.11", "lazy_static", "lettre", "log", @@ -466,7 +462,7 @@ dependencies = [ "nanoid", "rand 0.8.5", "regex", - "reqwest 0.11.10", + "reqwest 0.11.27", "revolt_okapi", "revolt_rocket_okapi", "rocket", @@ -491,14 +487,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.4.0", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "av1-grain" @@ -516,18 +512,18 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" dependencies = [ "arrayvec", ] [[package]] name = "aws-config" -version = "1.5.5" +version = "1.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e95816a168520d72c0e7680c405a5a8c1fb6a035b4bc4b9d7b0de8e1a941697" +checksum = "649316840239f4e58df0b7f620c428f5fababbbca2d504488c641534050bd141" dependencies = [ "aws-credential-types", "aws-runtime", @@ -541,13 +537,13 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", - "bytes 1.5.0", - "fastrand 2.1.1", + "bytes 1.9.0", + "fastrand 2.3.0", "hex", "http 0.2.12", - "ring 0.17.8", + "ring", "time", - "tokio 1.40.0", + "tokio 1.42.0", "tracing", "url", "zeroize", @@ -567,9 +563,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.4.2" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2424565416eef55906f9f8cece2072b6b6a76075e3ff81483ebe938a89a4c05f" +checksum = "44f6f1124d6e19ab6daf7f2e615644305dc6cb2d706892a8a8c0b98db35de020" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -580,24 +576,23 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", - "bytes 1.5.0", - "fastrand 2.1.1", + "bytes 1.9.0", + "fastrand 2.3.0", "http 0.2.12", - "http-body 0.4.5", + "http-body 0.4.6", "once_cell", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "tracing", - "uuid 1.4.1", + "uuid", ] [[package]] name = "aws-sdk-s3" -version = "1.46.0" +version = "1.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abf69a87be33b6f125a93d5046b5f7395c26d1f449bf8d3927f5577463b6de0" +checksum = "bbc644164269a1e38ce7f2f7373629d3fb3d310c0e3feb5573a29744288b24d3" dependencies = [ - "ahash 0.8.11", "aws-credential-types", "aws-runtime", "aws-sigv4", @@ -611,13 +606,13 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "bytes 1.5.0", - "fastrand 2.1.1", + "bytes 1.9.0", + "fastrand 2.3.0", "hex", "hmac", "http 0.2.12", - "http-body 0.4.5", - "lru 0.12.4", + "http-body 0.4.6", + "lru 0.12.5", "once_cell", "percent-encoding", "regex-lite", @@ -628,9 +623,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.39.0" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11822090cf501c316c6f75711d77b96fba30658e3867a7762e5e2f5d32d31e81" +checksum = "cb25f7129c74d36afe33405af4517524df8f74b635af8c2c8e91c1552b8397b2" dependencies = [ "aws-credential-types", "aws-runtime", @@ -641,7 +636,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", - "bytes 1.5.0", + "bytes 1.9.0", "http 0.2.12", "once_cell", "regex-lite", @@ -650,9 +645,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.39.0" +version = "1.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3e48ec239bb734db029ceef83599f4c9b3ce5d25c961b5bcd3f031c15bed54" +checksum = "d03a3d5ef14851625eafd89660a751776f938bf32f309308b20dcca41c44b568" dependencies = [ "aws-credential-types", "aws-runtime", @@ -663,7 +658,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", - "bytes 1.5.0", + "bytes 1.9.0", "http 0.2.12", "once_cell", "regex-lite", @@ -672,9 +667,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.39.0" +version = "1.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20a91795850826a6f456f4a48eff1dfa59a0e69bdbf5b8c50518fd372106574" +checksum = "cf3a9f073ae3a53b54421503063dfb87ff1ea83b876f567d92e8b8d9942ba91b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -695,26 +690,26 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.2.3" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5df1b0fa6be58efe9d4ccc257df0a53b89cd8909e86591a13ca54817c87517be" +checksum = "7d3820e0c08d0737872ff3c7c1f21ebbb6693d832312d6152bf18ef50a5471c2" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", "aws-smithy-http", "aws-smithy-runtime-api", "aws-smithy-types", - "bytes 1.5.0", + "bytes 1.9.0", "crypto-bigint 0.5.5", "form_urlencoded", "hex", "hmac", "http 0.2.12", - "http 1.1.0", + "http 1.2.0", "once_cell", - "p256", + "p256 0.11.1", "percent-encoding", - "ring 0.17.8", + "ring", "sha2", "subtle", "time", @@ -724,31 +719,31 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" +checksum = "427cb637d15d63d6f9aae26358e1c9a9c09d5aa490d64b09354c8217cfef0f28" dependencies = [ "futures-util", - "pin-project-lite 0.2.13", - "tokio 1.40.0", + "pin-project-lite 0.2.15", + "tokio 1.42.0", ] [[package]] name = "aws-smithy-checksums" -version = "0.60.12" +version = "0.60.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598b1689d001c4d4dc3cb386adb07d37786783aee3ac4b324bcadac116bf3d23" +checksum = "ba1a71073fca26775c8b5189175ea8863afb1c9ea2cceb02a5de5ad9dfbaa795" dependencies = [ "aws-smithy-http", "aws-smithy-types", - "bytes 1.5.0", + "bytes 1.9.0", "crc32c", "crc32fast", "hex", "http 0.2.12", - "http-body 0.4.5", + "http-body 0.4.6", "md-5", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "sha1", "sha2", "tracing", @@ -756,41 +751,41 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.4" +version = "0.60.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" +checksum = "cef7d0a272725f87e51ba2bf89f8c21e4df61b9e49ae1ac367a6d69916ef7c90" dependencies = [ "aws-smithy-types", - "bytes 1.5.0", + "bytes 1.9.0", "crc32fast", ] [[package]] name = "aws-smithy-http" -version = "0.60.10" +version = "0.60.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01dbcb6e2588fd64cfb6d7529661b06466419e4c54ed1c62d6510d2d0350a728" +checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", "aws-smithy-types", - "bytes 1.5.0", + "bytes 1.9.0", "bytes-utils", "futures-core", "http 0.2.12", - "http-body 0.4.5", + "http-body 0.4.6", "once_cell", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "pin-utils", "tracing", ] [[package]] name = "aws-smithy-json" -version = "0.60.7" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" +checksum = "ee4e69cc50921eb913c6b662f8d909131bb3e6ad6cb6090d3a39b66fc5c52095" dependencies = [ "aws-smithy-types", ] @@ -807,79 +802,79 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.1" +version = "1.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce695746394772e7000b39fe073095db6d45a862d0767dd5ad0ac0d7f8eb87" +checksum = "a05dd41a70fc74051758ee75b5c4db2c0ca070ed9229c3df50e9475cda1cb985" dependencies = [ "aws-smithy-async", "aws-smithy-http", "aws-smithy-runtime-api", "aws-smithy-types", - "bytes 1.5.0", - "fastrand 2.1.1", + "bytes 1.9.0", + "fastrand 2.3.0", "h2 0.3.26", "http 0.2.12", - "http-body 0.4.5", - "http-body 1.0.0", + "http-body 0.4.6", + "http-body 1.0.1", "httparse", - "hyper 0.14.30", + "hyper 0.14.32", "hyper-rustls 0.24.2", "once_cell", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "pin-utils", "rustls 0.21.12", - "tokio 1.40.0", + "tokio 1.42.0", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" dependencies = [ "aws-smithy-async", "aws-smithy-types", - "bytes 1.5.0", + "bytes 1.9.0", "http 0.2.12", - "http 1.1.0", - "pin-project-lite 0.2.13", - "tokio 1.40.0", + "http 1.2.0", + "pin-project-lite 0.2.15", + "tokio 1.42.0", "tracing", "zeroize", ] [[package]] name = "aws-smithy-types" -version = "1.2.4" +version = "1.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273dcdfd762fae3e1650b8024624e7cd50e484e37abdab73a7a706188ad34543" +checksum = "38ddc9bd6c28aeb303477170ddd183760a956a03e083b3902a990238a7e3792d" dependencies = [ "base64-simd", - "bytes 1.5.0", + "bytes 1.9.0", "bytes-utils", "futures-core", "http 0.2.12", - "http 1.1.0", - "http-body 0.4.5", - "http-body 1.0.0", + "http 1.2.0", + "http-body 0.4.6", + "http-body 1.0.1", "http-body-util", "itoa", "num-integer", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "pin-utils", "ryu", "serde", "time", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-util", ] [[package]] name = "aws-smithy-xml" -version = "0.60.8" +version = "0.60.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d123fbc2a4adc3c301652ba8e149bf4bc1d1725affb9784eb20c953ace06bf55" +checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" dependencies = [ "xmlparser", ] @@ -894,24 +889,24 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "rustc_version 0.4.0", + "rustc_version", "tracing", ] [[package]] name = "axum" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", - "bytes 1.5.0", + "bytes 1.9.0", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.5.2", "hyper-util", "itoa", "matchit", @@ -919,14 +914,14 @@ dependencies = [ "mime", "multer", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "rustversion", "serde", "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio 1.40.0", + "sync_wrapper 1.0.2", + "tokio 1.42.0", "tower", "tower-layer", "tower-service", @@ -935,20 +930,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", - "bytes 1.5.0", + "bytes 1.9.0", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", "mime", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -956,85 +951,85 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" +checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum", "axum-core", - "bytes 1.5.0", + "bytes 1.9.0", + "fastrand 2.3.0", "futures-util", "headers", - "http 1.1.0", - "http-body 1.0.0", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", "mime", - "pin-project-lite 0.2.13", + "multer", + "pin-project-lite 0.2.15", "serde", "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.0", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "axum_typed_multipart" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d097f2fcf54695aea6617d0c1dcc50bf2b7ed50e880fd992e4baf65ab334230e" +checksum = "05679dcdfeccf4cc6a8f45b80318fff8a9908337da1cfeb6acca00562a345b4d" dependencies = [ "anyhow", "axum", "axum_typed_multipart_macros", - "bytes 1.5.0", + "bytes 1.9.0", "chrono", "futures-core", "futures-util", "tempfile", - "thiserror", - "tokio 1.40.0", - "uuid 1.4.1", + "thiserror 1.0.69", + "tokio 1.42.0", + "uuid", ] [[package]] name = "axum_typed_multipart_macros" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe748f9a46f680070920e4a3ef57939503c8d30fe30ca5525b6c63c96b7abfe" +checksum = "11eeb275b20a4c750c9fe7bf5a750e97e7944563003efd1c82e70c229a612ca1" dependencies = [ "darling 0.20.10", - "heck 0.5.0", + "heck", "proc-macro-error", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", "ubyte", ] [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.5.3", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -1043,6 +1038,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base32" version = "0.4.0" @@ -1051,15 +1052,15 @@ checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.3" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" @@ -1100,9 +1101,24 @@ dependencies = [ [[package]] name = "binstring" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e0d60973d9320722cb1206f412740e162a33b8547ea8d6be75d7cff237c7a85" +checksum = "ed79c2a8151273c70956b5e3cdfdc1ff6c1a8b9779ba59c6807d281b32ee2f86" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bit_field" @@ -1130,15 +1146,27 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitstream-io" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c12d1856e42f0d817a835fe55853957c85c8c8a470114029143d3f12671446e" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] [[package]] name = "blake2b_simd" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", @@ -1147,96 +1175,70 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.7.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array 0.14.7", ] [[package]] name = "blocking" -version = "1.2.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 1.6.1", + "async-channel 2.3.1", "async-task", - "atomic-waker", - "fastrand 1.7.0", - "futures-lite", - "once_cell", + "futures-io", + "futures-lite 2.5.0", + "piper", ] [[package]] name = "bson" -version = "2.2.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60a2c7c80a7850b56df4b8e98e8e4932c34877b8add4f13e8350499cc1e4572" +checksum = "068208f2b6fcfa27a7f1ee37488d2bb8ba2640f68f5475d08e1d9130696aba59" dependencies = [ - "ahash 0.7.6", - "base64 0.13.0", - "chrono", + "ahash 0.8.11", + "base64 0.13.1", + "bitvec", "hex", - "indexmap 1.9.3", - "lazy_static", + "indexmap 2.7.0", + "js-sys", + "once_cell", "rand 0.8.5", "serde", "serde_bytes", "serde_json", - "uuid 0.8.2", + "time", + "uuid", ] [[package]] name = "built" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" +checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "byteorder-lite" @@ -1252,9 +1254,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.5.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bytes-utils" @@ -1262,16 +1264,10 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "either", ] -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - [[package]] name = "cached" version = "0.44.0" @@ -1285,8 +1281,8 @@ dependencies = [ "hashbrown 0.13.2", "instant", "once_cell", - "thiserror", - "tokio 1.40.0", + "thiserror 1.0.69", + "tokio 1.42.0", ] [[package]] @@ -1298,15 +1294,15 @@ dependencies = [ "cached_proc_macro_types", "darling 0.14.4", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] name = "cached_proc_macro_types" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" [[package]] name = "castaway" @@ -1316,9 +1312,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.1.15" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", @@ -1333,7 +1329,7 @@ checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" dependencies = [ "byteorder", "fnv", - "uuid 1.4.1", + "uuid", ] [[package]] @@ -1354,14 +1350,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-targets 0.52.6", ] @@ -1387,13 +1384,12 @@ dependencies = [ [[package]] name = "coarsetime" -version = "0.1.23" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90d114103adbc625300f346d4d09dfb4ab1c4a8df6868435dd903392ecf4354" +checksum = "4252bf230cb600c19826a575b31c8c9c84c6f11acfab6dfcad2e941b10b6f8e2" dependencies = [ "libc", - "once_cell", - "wasi", + "wasix", "wasm-bindgen", ] @@ -1405,27 +1401,18 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "combine" -version = "4.6.4" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-core", "memchr", - "pin-project-lite 0.2.13", - "tokio 1.40.0", + "pin-project-lite 0.2.15", + "tokio 1.42.0", "tokio-util", ] -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1437,9 +1424,9 @@ dependencies = [ [[package]] name = "config" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" dependencies = [ "async-trait", "json5", @@ -1450,7 +1437,7 @@ dependencies = [ "rust-ini", "serde", "serde_json", - "toml 0.5.9", + "toml 0.5.11", "yaml-rust", ] @@ -1462,15 +1449,21 @@ checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" @@ -1485,15 +1478,18 @@ dependencies = [ [[package]] name = "cookie-factory" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" +dependencies = [ + "futures", +] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1501,9 +1497,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core_maths" @@ -1516,9 +1512,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1535,7 +1531,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" dependencies = [ - "rustc_version 0.4.0", + "rustc_version", ] [[package]] @@ -1549,18 +1545,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1577,19 +1573,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1603,7 +1598,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.7", "rand_core 0.6.4", "subtle", "zeroize", @@ -1615,8 +1610,10 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ + "generic-array 0.14.7", "rand_core 0.6.4", "subtle", + "zeroize", ] [[package]] @@ -1625,7 +1622,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.7", "rand_core 0.6.4", "typenum", ] @@ -1649,15 +1646,15 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "ct-codecs" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" +checksum = "b916ba8ce9e4182696896f015e8a5ae6081b305f74690baa8465e35f5a142ea4" [[package]] name = "ctr" @@ -1670,24 +1667,24 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.44" +version = "0.4.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", - "socket2 0.4.4", - "winapi", + "socket2 0.5.8", + "windows-sys 0.52.0", ] [[package]] name = "curl-sys" -version = "0.4.65+curl-8.2.1" +version = "0.4.78+curl-8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961ba061c9ef2fe34bbd12b807152d96f0badd2bebe7b90ce6c8c8b7572a0986" +checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" dependencies = [ "cc", "libc", @@ -1696,7 +1693,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -1738,9 +1735,9 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "strsim 0.10.0", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1752,9 +1749,9 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "strsim 0.10.0", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1766,9 +1763,9 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "strsim 0.11.1", - "syn 2.0.76", + "syn 2.0.94", ] [[package]] @@ -1778,8 +1775,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] @@ -1789,8 +1786,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ "darling_core 0.14.4", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] @@ -1800,27 +1797,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "dashmap" -version = "5.3.4" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.12.1", + "hashbrown 0.14.5", "lock_api", + "once_cell", "parking_lot_core", ] [[package]] name = "data-encoding" -version = "2.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-url" @@ -1835,7 +1833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16a2561fd313df162315935989dceb8c99db4ee1933358270a57a3cfb8c957f3" dependencies = [ "crossbeam-queue", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] @@ -1845,14 +1843,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ "serde", - "uuid 1.4.1", + "uuid", ] [[package]] name = "decancer" -version = "1.6.2" +version = "1.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808127a7de612079ec37bfc1abc48ed77a6015a971a8bd7d4178d79147cbc839" +checksum = "080b09f6adad25c23d8c47c54e52e59b0dc09d079c4b23e0f147dac440359d0d" [[package]] name = "der" @@ -1870,8 +1868,19 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" dependencies = [ - "const-oid 0.9.5", - "pem-rfc7468", + "const-oid 0.9.6", + "pem-rfc7468 0.6.0", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid 0.9.6", + "pem-rfc7468 0.7.0", "zeroize", ] @@ -1882,20 +1891,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aed3b3c608dc56cf36c45fe979d04eda51242e6703d8d0bb03426ef7c41db6a" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", - "synstructure", + "quote 1.0.38", + "syn 1.0.109", + "synstructure 0.12.6", ] [[package]] -name = "derivative" -version = "2.2.0" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -1904,9 +1923,11 @@ version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ + "convert_case", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "rustc_version", + "syn 2.0.94", ] [[package]] @@ -1926,7 +1947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" dependencies = [ "devise_core", - "quote 1.0.37", + "quote 1.0.38", ] [[package]] @@ -1938,17 +1959,8 @@ dependencies = [ "bitflags 2.6.0", "proc-macro2", "proc-macro2-diagnostics", - "quote 1.0.37", - "syn 2.0.76", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -1957,12 +1969,23 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.2", - "const-oid 0.9.5", + "block-buffer", + "const-oid 0.9.6", "crypto-common", "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -1986,9 +2009,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.5" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecdsa" @@ -1997,18 +2020,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ "der 0.6.1", - "elliptic-curve", - "rfc6979", - "signature", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der 0.7.9", + "digest", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] name = "ece" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5463ffecc0677adcd786c4481f73b215714d4757edf2eb37a573c03d00459" +checksum = "c2ea1d2f2cc974957a4e2575d8e5bb494549bab66338d6320c2789abcfff5746" dependencies = [ - "base64 0.13.0", + "base64 0.21.7", "byteorder", "hex", "hkdf", @@ -2017,14 +2054,14 @@ dependencies = [ "openssl", "serde", "sha2", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "ed25519-compact" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c" +checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" dependencies = [ "ct-codecs", "getrandom", @@ -2038,9 +2075,9 @@ checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" [[package]] name = "either" -version = "1.6.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -2048,70 +2085,96 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "base16ct", + "base16ct 0.1.1", "crypto-bigint 0.4.9", "der 0.6.1", - "digest 0.10.7", - "ff", - "generic-array 0.14.5", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", + "digest", + "ff 0.12.1", + "generic-array 0.14.7", + "group 0.12.1", + "pkcs8 0.9.0", "rand_core 0.6.4", - "sec1", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.5", + "digest", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", + "hkdf", + "pem-rfc7468 0.7.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", "subtle", "zeroize", ] [[package]] name = "email-encoding" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6690291166824e467790ac08ba42f241791567e8337bbf00c5a6e87889629f98" +checksum = "a87260449b06739ee78d6281c68d2a0ff3e3af64a78df63d3a1aeb3c06997c8a" dependencies = [ - "base64 0.13.0", + "base64 0.22.1", + "memchr", ] [[package]] -name = "encoding_rs" -version = "0.8.34" +name = "email_address" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "enum-as-inner" -version = "0.4.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.4.0", + "heck", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "enum-iterator" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -2135,28 +2198,28 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.20" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad132dd8d0d0b546348d7d86cb3191aad14b34e5f979781fc005c80d4ac67ffd" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" dependencies = [ "serde", ] [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" @@ -2164,57 +2227,61 @@ version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ - "concurrent-queue 2.5.0", + "concurrent-queue", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", ] [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ "event-listener 5.3.1", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", ] [[package]] name = "exr" -version = "1.72.0" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ "bit_field", - "flume", "half", "lebe", - "miniz_oxide 0.7.4", + "miniz_oxide", "rayon-core", "smallvec", "zune-inflate", ] [[package]] -name = "fake-simd" -version = "0.1.2" +name = "fancy-regex" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] [[package]] name = "fastrand" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fcm_v1" @@ -2223,7 +2290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc9ed4ed7618b2f7581edb6ce28794a10fcc335e196fc2bcf56afee99ad63d10" dependencies = [ "async-trait", - "reqwest 0.11.10", + "reqwest 0.11.27", "serde", "serde_json", "yup-oauth2", @@ -2231,9 +2298,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -2248,6 +2315,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "ffprobe" version = "0.4.0" @@ -2260,14 +2337,14 @@ dependencies = [ [[package]] name = "figment" -version = "0.10.6" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790b4292c72618abbab50f787a477014fe15634f96291de45672ce46afe122df" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ - "atomic", + "atomic 0.6.0", "pear", "serde", - "toml 0.5.9", + "toml 0.8.19", "uncased", "version_check", ] @@ -2286,12 +2363,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -2303,21 +2380,18 @@ dependencies = [ "num-traits", ] -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin 0.9.8", -] - [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "fontconfig-parser" version = "0.5.7" @@ -2367,25 +2441,24 @@ dependencies = [ [[package]] name = "fred" -version = "8.0.1" +version = "8.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b2a2ac060e3266004c552235c241b481e438e2b1ea75715ea1176914ef2868" +checksum = "4b8e3a1339ed45ad8fde94530c4bdcbd5f371a3c6bd3bf57682923792830aa37" dependencies = [ "arc-swap", "async-trait", - "bytes 1.5.0", + "bytes 1.9.0", "bytes-utils", "crossbeam-queue", "float-cmp", "futures", - "lazy_static", "log", "parking_lot", "rand 0.8.5", "redis-protocol", - "semver 1.0.23", - "socket2 0.5.5", - "tokio 1.40.0", + "semver", + "socket2 0.5.8", + "tokio 1.42.0", "tokio-stream", "tokio-util", "url", @@ -2398,6 +2471,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -2410,9 +2489,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -2425,9 +2504,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -2435,15 +2514,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -2452,25 +2531,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand 1.7.0", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", "parking", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" +dependencies = [ + "fastrand 2.3.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite 0.2.15", +] + [[package]] name = "futures-locks" version = "0.7.1" @@ -2479,43 +2571,43 @@ checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" dependencies = [ "futures-channel", "futures-task", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2524,7 +2616,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "pin-utils", "slab", ] @@ -2540,34 +2632,48 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", "log", "rustversion", - "winapi", + "windows 0.48.0", ] [[package]] -name = "generic-array" -version = "0.12.4" +name = "generator" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" dependencies = [ - "typenum", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.58.0", ] [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", +] + +[[package]] +name = "generic-array" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb8bc4c28d15ade99c7e90b219f30da4be5c88e586277e8cbe886beeb868ab2" +dependencies = [ + "typenum", ] [[package]] @@ -2581,9 +2687,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -2594,14 +2700,14 @@ dependencies = [ [[package]] name = "getset" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" dependencies = [ - "proc-macro-error", + "proc-macro-error2", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -2610,7 +2716,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ - "opaque-debug 0.3.0", + "opaque-debug", "polyval", ] @@ -2626,15 +2732,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git2" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ "bitflags 1.3.2", "libc", @@ -2645,15 +2751,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gloo-timers" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -2667,7 +2773,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", "rand_core 0.6.4", "subtle", ] @@ -2678,34 +2795,34 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.0.1", + "indexmap 2.7.0", "slab", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-util", "tracing", ] [[package]] name = "h2" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", - "bytes 1.5.0", + "bytes 1.9.0", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.0.1", + "http 1.2.0", + "indexmap 2.7.0", "slab", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-util", "tracing", ] @@ -2722,34 +2839,25 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.3.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d113a9853e5accd30f43003560b5563ffbb007e3f325e8b103fa0d0029c6e6df" +checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" dependencies = [ "log", "pest", "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" -dependencies = [ - "ahash 0.7.6", + "ahash 0.7.8", ] [[package]] @@ -2760,24 +2868,35 @@ checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "headers" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ - "base64 0.21.3", - "bytes 1.5.0", + "base64 0.21.7", + "bytes 1.9.0", "headers-core", - "http 1.1.0", + "http 1.2.0", "httpdate", "mime", "sha1", @@ -2789,15 +2908,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.1.0", + "http 1.2.0", ] -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - [[package]] name = "heck" version = "0.5.0" @@ -2832,10 +2945,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hkdf" -version = "0.12.3" +name = "hickory-proto" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "447afdcdb8afb9d0a852af6dc65d9b285ce720ed7a59e42a8bf2e931c67bc1b5" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 1.0.3", + "ipnet", + "once_cell", + "rand 0.8.5", + "thiserror 1.0.69", + "tinyvec", + "tokio 1.42.0", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror 1.0.69", + "tokio 1.42.0", + "tracing", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] @@ -2846,31 +3004,31 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] name = "hmac-sha1-compact" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9d405ec732fa3fcde87264e54a32a84956a377b3e3107de96e59b798c84a7" +checksum = "18492c9f6f9a560e0d346369b665ad2bdbc89fa9bceca75796584e79042694c3" [[package]] name = "hmac-sha256" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" +checksum = "4a8575493d277c9092b988c780c94737fb9fd8651a1001e16bee3eccfc1baedb" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] name = "hmac-sha512" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ce1f4656bae589a3fab938f9f09bf58645b7ed01a2c5f8a3c238e01a4ef78a" +checksum = "b0b3a0f572aa8389d325f5852b9e0a333a15b0f86ecccbb3fdb6e97cd86dc67c" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -2894,8 +3052,8 @@ dependencies = [ "mac", "markup5ever", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -2904,41 +3062,41 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "fnv", "itoa", ] [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "http 0.2.12", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", ] [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.5.0", - "http 1.1.0", + "bytes 1.9.0", + "http 1.2.0", ] [[package]] @@ -2947,24 +3105,24 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "pin-project-lite 0.2.13", + "http 1.2.0", + "http-body 1.0.1", + "pin-project-lite 0.2.15", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -2977,23 +3135,23 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-channel", "futures-core", "futures-util", "h2 0.3.26", "http 0.2.12", - "http-body 0.4.5", + "http-body 0.4.6", "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.13", - "socket2 0.5.5", - "tokio 1.40.0", + "pin-project-lite 0.2.15", + "socket2 0.5.8", + "tokio 1.42.0", "tower-service", "tracing", "want", @@ -3001,22 +3159,22 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-channel", "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "smallvec", - "tokio 1.40.0", + "tokio 1.42.0", "want", ] @@ -3028,11 +3186,11 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "log", "rustls 0.21.12", "rustls-native-certs", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-rustls 0.24.1", ] @@ -3043,15 +3201,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.3.1", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", "rustls 0.22.4", "rustls-pki-types", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-rustls 0.25.0", "tower-service", - "webpki-roots 0.26.3", + "webpki-roots 0.26.7", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http 1.2.0", + "hyper 1.5.2", + "hyper-util", + "rustls 0.23.20", + "rustls-pki-types", + "tokio 1.42.0", + "tokio-rustls 0.26.1", + "tower-service", ] [[package]] @@ -3060,10 +3235,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes 1.5.0", - "hyper 0.14.30", + "bytes 1.9.0", + "hyper 0.14.32", "native-tls", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-native-tls", ] @@ -3073,48 +3248,47 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.5.2", "hyper-util", "native-tls", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-native-tls", "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", - "pin-project-lite 0.2.13", - "socket2 0.5.5", - "tokio 1.40.0", - "tower", + "http 1.2.0", + "http-body 1.0.1", + "hyper 1.5.2", + "pin-project-lite 0.2.15", + "socket2 0.5.8", + "tokio 1.42.0", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -3126,6 +3300,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3145,14 +3437,45 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ "unicode-bidi", "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "if_chain" version = "1.0.2" @@ -3161,16 +3484,16 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "image" -version = "0.25.2" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", "color_quant", "exr", "gif", - "image-webp", + "image-webp 0.2.0", "num-traits", "png", "qoi", @@ -3192,6 +3515,16 @@ dependencies = [ "quick-error 2.0.1", ] +[[package]] +name = "image-webp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" +dependencies = [ + "byteorder-lite", + "quick-error 2.0.1", +] + [[package]] name = "imagesize" version = "0.13.0" @@ -3200,9 +3533,9 @@ checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" [[package]] name = "imgref" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "impl_ops" @@ -3216,19 +3549,19 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.1.0", - "hashbrown 0.12.1", + "autocfg 1.4.0", + "hashbrown 0.12.3", "serde", ] [[package]] name = "indexmap" -version = "2.0.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.15.2", "serde", ] @@ -3253,14 +3586,14 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.7", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -3272,27 +3605,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "ipconfig" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.4.4", + "socket2 0.5.8", "widestring", - "winapi", - "winreg 0.7.0", + "windows-sys 0.48.0", + "winreg", ] [[package]] name = "ipnet" -version = "2.5.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" @@ -3311,19 +3644,19 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" dependencies = [ - "async-channel 1.6.1", + "async-channel 1.9.0", "castaway", "crossbeam-utils", "curl", "curl-sys", "encoding_rs", - "event-listener 2.5.2", - "futures-lite", + "event-listener 2.5.3", + "futures-lite 1.13.0", "http 0.2.12", "log", "mime", "once_cell", - "polling", + "polling 2.8.0", "serde", "serde_json", "slab", @@ -3336,22 +3669,22 @@ dependencies = [ [[package]] name = "iso8601-timestamp" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56480a7792bfa284a4c7d1781f711de58e357dbb669c1b1a50c37c1777c9be92" +checksum = "b088f3296223f11d6bd70998132653b30b6f39e6ab4be055c0bda486fa8d11c7" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.7", "serde", "time", ] [[package]] name = "iso8601-timestamp" -version = "0.2.11" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd7663ae5b511b3d13c7d374dbe73b03da3da8e66b83950390173bc7c7325cc" +checksum = "24d4e5d712dd664b11e778d1cfc06c79ba2700d6bc1771e44fb7b6a4656b487d" dependencies = [ - "generic-array 0.14.5", + "generic-array 1.1.1", "schemars", "serde", "time", @@ -3368,9 +3701,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -3389,10 +3722,11 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -3409,9 +3743,9 @@ dependencies = [ [[package]] name = "jwt-simple" -version = "0.11.2" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529a00f2d42d7dc349c994e65917c81bf53225831a65361f6c0454124c550f63" +checksum = "357892bb32159d763abdea50733fadcb9a8e1c319a9aa77592db8555d05af83e" dependencies = [ "anyhow", "binstring", @@ -3422,31 +3756,31 @@ dependencies = [ "hmac-sha256", "hmac-sha512", "k256", - "p256", + "p256 0.13.2", "p384", "rand 0.8.5", "rsa", "serde", "serde_json", - "spki", - "thiserror", + "spki 0.6.0", + "thiserror 1.0.69", "zeroize", ] [[package]] name = "jxl-bitstream" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703fcab2fcc410830ee2923e7b343e065ca3373d221917c4e1942c46976f82cf" +checksum = "5855ff16398ffbcf81fee52c41ca65326499c8764b21bb9952c367ace98995fb" dependencies = [ "tracing", ] [[package]] name = "jxl-coding" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fc775c864ae62965f39fd60de5582018d130727fc210a64dae47df1e1f085d" +checksum = "da5b5093904e940bc11ef50e872c7bdf7b6e88653f012b925f8479daf212b5c9" dependencies = [ "jxl-bitstream", "tracing", @@ -3576,14 +3910,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.11.6" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "once_cell", "sha2", + "signature 2.2.0", ] [[package]] @@ -3620,7 +3956,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -3631,47 +3967,48 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "lettre" -version = "0.10.0-rc.6" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f6c70001f7ee6c93b6687a06607c7a38f9a7ae460139a496c23da21e95bc289" +checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d" dependencies = [ - "base64 0.13.0", + "base64 0.21.7", "email-encoding", - "fastrand 1.7.0", + "email_address", + "fastrand 1.9.0", "futures-util", "hostname", "httpdate", - "idna 0.2.3", + "idna 0.3.0", "mime", "native-tls", "nom", "once_cell", "quoted_printable", - "regex", + "socket2 0.4.10", + "tokio 1.42.0", ] [[package]] name = "libc" -version = "0.2.159" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] name = "libgit2-sys" -version = "0.14.1+1.5.0" +version = "0.14.2+1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a07fb2692bc3593bda59de45a502bb3071659f2c515e28c71e728306b038e17" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" dependencies = [ "cc", "libc", @@ -3681,9 +4018,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -3691,15 +4028,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libnghttp2-sys" -version = "0.1.8+1.55.1" +version = "0.1.10+1.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fae956c192dadcdb5dace96db71fa0b827333cce7c7b38dc71446f024d8a340" +checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135" dependencies = [ "cc", "libc", @@ -3717,9 +4054,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -3729,9 +4066,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linkify" @@ -3758,12 +4095,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "lock_api" -version = "0.4.7" +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.4.0", "scopeguard", ] @@ -3783,7 +4126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ "cfg-if", - "generator", + "generator 0.7.5", "scoped-tls", "serde", "serde_json", @@ -3791,6 +4134,19 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator 0.8.4", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "loop9" version = "0.1.5" @@ -3802,29 +4158,29 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8015d95cb7b2ddd3c0d32ca38283ceb1eea09b4713ee380bceb942d85a244228" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" dependencies = [ - "hashbrown 0.11.2", + "hashbrown 0.12.3", ] [[package]] name = "lru" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eedb2bdbad7e0634f83989bf596f497b070130daaa398ab22d84c39e266deec5" +checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.5", ] [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.15.2", ] [[package]] @@ -3848,12 +4204,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "markup5ever" version = "0.12.1" @@ -3885,9 +4235,9 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" @@ -3907,11 +4257,12 @@ dependencies = [ [[package]] name = "md-5" -version = "0.10.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "digest 0.10.7", + "cfg-if", + "digest", ] [[package]] @@ -3931,23 +4282,12 @@ dependencies = [ [[package]] name = "metrics" -version = "0.18.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e52eb6380b6d2a10eb3434aec0885374490f5b82c8aaf5cd487a183c98be834" +checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261" dependencies = [ - "ahash 0.7.6", - "metrics-macros", -] - -[[package]] -name = "metrics-macros" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e30813093f757be5cf21e50389a24dc7dbb22c49f23b7e8f51d69b508a5ffa" -dependencies = [ - "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "ahash 0.8.11", + "portable-atomic", ] [[package]] @@ -3964,39 +4304,20 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", + "adler2", "simd-adler32", ] -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -4004,9 +4325,9 @@ dependencies = [ [[package]] name = "mobc" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc79c4a77e312fee9c7bd4b957c12ad1196db73c4a81e5c0b13f02083c4f7f2f" +checksum = "316a7d198b51958a0ab57248bf5f42d8409551203cb3c821d5925819a8d5415f" dependencies = [ "async-std", "async-trait", @@ -4016,91 +4337,101 @@ dependencies = [ "futures-util", "log", "metrics", - "thiserror", - "tokio 1.40.0", + "thiserror 1.0.69", + "tokio 1.42.0", "tracing", "tracing-subscriber", ] [[package]] name = "mobc-redis" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd8e2fd6bf7e35263b86662e663a9496a0352ceddd413b6c33313c36d5068fd" +checksum = "5e90cc63bd181da5c1f826427d26a63ab0ad1927462b2411aaa86e5f6be3d6b1" dependencies = [ "mobc", - "redis 0.22.3", + "redis", ] [[package]] name = "moka" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" +checksum = "23db87a7f248211f6a7c8644a1b750541f8a4c68ae7de0f908860e44c0c201f6" dependencies = [ "async-lock 3.4.0", - "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "event-listener 5.3.1", "futures-util", - "once_cell", + "loom 0.7.2", "parking_lot", "quanta", - "rustc_version 0.4.0", + "rustc_version", "smallvec", "tagptr", - "thiserror", - "triomphe", - "uuid 1.4.1", + "thiserror 1.0.69", + "uuid", ] [[package]] name = "mongodb" -version = "2.2.2" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f3943e379e9dcaaab9dc319c308a8caaf9e7ff083c6838dff740afbba59df7" +checksum = "ff1f6edf7fe8828429647a2200f684681ca6d5a33b45edc3140c81390d852301" dependencies = [ - "async-std", - "async-std-resolver", "async-trait", - "base64 0.13.0", + "base64 0.13.1", "bitflags 1.3.2", "bson", "chrono", - "derivative", + "derive-where", + "derive_more", "futures-core", "futures-executor", + "futures-io", "futures-util", "hex", + "hickory-proto", + "hickory-resolver", "hmac", - "lazy_static", "md-5", - "os_info", + "mongodb-internal-macros", + "once_cell", "pbkdf2", "percent-encoding", "rand 0.8.5", "rustc_version_runtime", - "rustls 0.20.6", - "rustls-pemfile 0.3.0", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "serde", + "serde_bytes", "serde_with", - "sha-1 0.10.0", + "sha-1", "sha2", - "socket2 0.4.4", + "socket2 0.5.8", "stringprep", - "strsim 0.10.0", + "strsim 0.11.1", "take_mut", - "thiserror", - "tokio 1.40.0", - "tokio-rustls 0.23.4", + "thiserror 1.0.69", + "tokio 1.42.0", + "tokio-rustls 0.24.1", "tokio-util", - "trust-dns-proto", - "trust-dns-resolver", "typed-builder", - "uuid 0.8.2", - "webpki-roots 0.22.3", + "uuid", + "webpki-roots 0.25.4", +] + +[[package]] +name = "mongodb-internal-macros" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b07bfd601af78e39384707a8e80041946c98260e3e0190e294ee7435823e6bf" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4109,15 +4440,15 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "encoding_rs", "futures-util", - "http 1.1.0", + "http 1.2.0", "httparse", "memchr", "mime", - "spin 0.9.8", - "tokio 1.40.0", + "spin", + "tokio 1.42.0", "tokio-util", "version_check", ] @@ -4139,11 +4470,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -4165,7 +4495,7 @@ dependencies = [ "libloading", "neon-macros", "once_cell", - "semver 1.0.23", + "semver", "send_wrapper", "smallvec", ] @@ -4176,8 +4506,8 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6813fde79b646e47e7ad75f480aa80ef76a5d9599e2717407961531169ee38b" dependencies = [ - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", "syn-mid", ] @@ -4200,9 +4530,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -4216,13 +4546,23 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" [[package]] name = "ntapi" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.3" @@ -4272,6 +4612,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.4.2" @@ -4279,8 +4625,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4298,7 +4644,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.4.0", "num-integer", "num-traits", ] @@ -4320,27 +4666,27 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.4.0", "libm", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "num_enum" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive 0.5.7", + "num_enum_derive 0.5.11", ] [[package]] @@ -4354,14 +4700,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] @@ -4372,8 +4718,8 @@ checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4387,38 +4733,32 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -4429,13 +4769,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4446,11 +4786,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ - "autocfg 1.1.0", "cc", "libc", "pkg-config", @@ -4464,18 +4803,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" dependencies = [ "dlv-list", - "hashbrown 0.12.1", + "hashbrown 0.12.3", ] [[package]] name = "os_info" -version = "3.7.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "eb6651f4be5e39563c4fe5cc8326349eb99a25d805a3493f791d5bfd0269e430" dependencies = [ "log", "serde", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4484,39 +4823,58 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "p256" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2", +] + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", "sha2", ] [[package]] name = "p384" -version = "0.11.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", "sha2", ] [[package]] name = "parking" -version = "2.0.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -4524,15 +4882,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.36.1", + "windows-targets 0.52.6", ] [[package]] @@ -4543,17 +4901,17 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pbkdf2" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -4575,8 +4933,8 @@ checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4585,7 +4943,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "once_cell", "regex", ] @@ -4596,7 +4954,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -4618,6 +4976,15 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4626,18 +4993,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.1.3" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ + "memchr", + "thiserror 2.0.9", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -4645,26 +5014,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha2", ] [[package]] @@ -4735,8 +5104,8 @@ dependencies = [ "phf_generator 0.11.2", "phf_shared 0.11.2", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4765,22 +5134,22 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.0.10" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -4791,9 +5160,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -4801,6 +5170,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand 2.3.0", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.4.1" @@ -4808,8 +5188,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" dependencies = [ "der 0.6.1", - "pkcs8", - "spki", + "pkcs8 0.9.0", + "spki 0.6.0", "zeroize", ] @@ -4820,39 +5200,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" dependencies = [ "der 0.6.1", - "spki", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.9", + "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.13" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide", ] [[package]] name = "polling" -version = "2.2.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ + "autocfg 1.4.0", + "bitflags 1.3.2", "cfg-if", + "concurrent-queue", "libc", "log", - "wepoll-ffi", - "winapi", + "pin-project-lite 0.2.15", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite 0.2.15", + "rustix", + "tracing", + "windows-sys 0.59.0", ] [[package]] @@ -4863,15 +5271,30 @@ checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", "universal-hash", ] [[package]] -name = "ppv-lite86" -version = "0.2.16" +name = "portable-atomic" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "precomputed-hash" @@ -4890,13 +5313,22 @@ dependencies = [ ] [[package]] -name = "proc-macro-crate" -version = "1.1.3" +name = "primeorder" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "thiserror", - "toml 0.5.9", + "elliptic-curve 0.13.8", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", ] [[package]] @@ -4907,8 +5339,8 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", "version_check", ] @@ -4919,15 +5351,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "version_check", ] [[package]] -name = "proc-macro2" -version = "1.0.86" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote 1.0.38", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -4939,43 +5393,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", "version_check", "yansi", ] [[package]] name = "profiling" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" dependencies = [ "profiling-procmacros", ] [[package]] name = "profiling-procmacros" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", "parking_lot", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4989,9 +5443,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" dependencies = [ "crossbeam-utils", "libc", @@ -5028,18 +5482,24 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "quoted_printable" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fee2dce59f7a43418e3382c766554c614e06a552d53a8f07ef499ea4b332c0f" +checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -5208,19 +5668,18 @@ dependencies = [ "rand_chacha 0.3.1", "simd_helpers", "system-deps", - "thiserror", + "thiserror 1.0.69", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.6" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85be49d628515bb99a01c44200009f0a4167c252f036445b975b35daf952258c" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" dependencies = [ "avif-serialize", - "bitstream-io", "imgref", "loop9", "quick-error 2.0.1", @@ -5231,9 +5690,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.1.0" +version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ "bitflags 2.6.0", ] @@ -5269,40 +5728,21 @@ dependencies = [ [[package]] name = "redis" -version = "0.22.3" -source = "git+https://github.com/revoltchat/redis-rs?rev=1a41faf356fd21aebba71cea7eb7eb2653e5f0ef#1a41faf356fd21aebba71cea7eb7eb2653e5f0ef" +version = "0.23.3" +source = "git+https://github.com/revoltchat/redis-rs?rev=523b2937367e17bd0073722bf6e23d06042cb4e4#523b2937367e17bd0073722bf6e23d06042cb4e4" dependencies = [ "async-std", "async-trait", - "bytes 1.5.0", + "bytes 1.9.0", "combine", "futures-util", "itoa", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "ryu", "sha1_smol", - "tokio 1.40.0", - "tokio-util", - "url", -] - -[[package]] -name = "redis" -version = "0.23.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba" -dependencies = [ - "async-std", - "async-trait", - "bytes 1.5.0", - "combine", - "futures-util", - "itoa", - "percent-encoding", - "pin-project-lite 0.2.13", - "ryu", - "tokio 1.40.0", + "socket2 0.4.10", + "tokio 1.42.0", "tokio-util", "url", ] @@ -5317,7 +5757,7 @@ dependencies = [ "lazy_static", "mobc", "mobc-redis", - "redis 0.23.3", + "redis", "rmp-serde", "serde", "serde_json", @@ -5329,7 +5769,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c31deddf734dc0a39d3112e73490e88b61a05e83e074d211f348404cee4d2c6" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "bytes-utils", "cookie-factory", "crc16", @@ -5339,42 +5779,42 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "ref-cast" -version = "1.0.7" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.7" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -5384,14 +5824,14 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax 0.6.26", + "regex-syntax 0.6.29", ] [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -5406,9 +5846,9 @@ checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" @@ -5418,56 +5858,61 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.13.0", - "bytes 1.5.0", + "base64 0.21.7", + "bytes 1.9.0", "encoding_rs", "futures-core", "futures-util", "h2 0.3.26", "http 0.2.12", - "http-body 0.4.5", - "hyper 0.14.30", + "http-body 0.4.6", + "hyper 0.14.32", "hyper-tls 0.5.0", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "tokio 1.40.0", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio 1.42.0", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.10.1", + "winreg", ] [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64 0.22.1", - "bytes 1.5.0", + "bytes 1.9.0", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.5.2", + "hyper-rustls 0.27.5", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -5477,21 +5922,22 @@ dependencies = [ "native-tls", "once_cell", "percent-encoding", - "pin-project-lite 0.2.13", - "rustls-pemfile 2.1.2", + "pin-project-lite 0.2.15", + "rustls-pemfile 2.2.0", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio 1.40.0", + "sync_wrapper 1.0.2", + "system-configuration 0.6.1", + "tokio 1.42.0", "tokio-native-tls", + "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.52.0", + "windows-registry", ] [[package]] @@ -5511,7 +5957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a325d5e8d1cebddd070b13f44cec8071594ab67d1012797c121f27a669b7958" dependencies = [ "gif", - "image-webp", + "image-webp 0.1.3", "log", "pico-args", "rgb", @@ -5548,7 +5994,7 @@ dependencies = [ "simdutf8", "strum_macros", "tempfile", - "tokio 1.40.0", + "tokio 1.42.0", "tower-http", "tracing", "tracing-subscriber", @@ -5570,7 +6016,7 @@ dependencies = [ "fred", "futures", "log", - "lru 0.7.6", + "lru 0.7.8", "lru_time_cache", "once_cell", "querystring", @@ -5613,7 +6059,7 @@ dependencies = [ "revolt-database", "revolt-files", "revolt-result", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] @@ -5627,7 +6073,7 @@ dependencies = [ "async-trait", "authifier", "axum", - "base64 0.21.3", + "base64 0.21.7", "bson", "deadqueue", "decancer", @@ -5635,10 +6081,10 @@ dependencies = [ "futures", "indexmap 1.9.3", "isahc", - "iso8601-timestamp 0.2.11", + "iso8601-timestamp 0.2.17", "linkify 0.8.1", "log", - "lru 0.11.0", + "lru 0.11.1", "mongodb", "nanoid", "once_cell", @@ -5661,7 +6107,7 @@ dependencies = [ "ulid 1.1.3", "unicode-segmentation", "url-escape", - "validator 0.16.0", + "validator 0.16.1", "web-push", ] @@ -5670,7 +6116,7 @@ name = "revolt-delta" version = "0.8.4" dependencies = [ "amqprs", - "async-channel 1.6.1", + "async-channel 1.9.0", "async-std", "authifier", "bitfield", @@ -5679,18 +6125,18 @@ dependencies = [ "env_logger", "futures", "impl_ops", - "iso8601-timestamp 0.2.11", + "iso8601-timestamp 0.2.17", "lettre", "linkify 0.6.0", "log", - "lru 0.7.6", + "lru 0.7.8", "nanoid", - "num_enum 0.5.7", + "num_enum 0.5.11", "once_cell", "rand 0.8.5", "redis-kiss", "regex", - "reqwest 0.11.10", + "reqwest 0.11.27", "revolt-config", "revolt-database", "revolt-models", @@ -5708,7 +6154,7 @@ dependencies = [ "serde_json", "ulid 0.4.1", "url", - "validator 0.16.0", + "validator 0.16.1", "vergen", ] @@ -5747,7 +6193,7 @@ dependencies = [ "mime", "moka", "regex", - "reqwest 0.12.4", + "reqwest 0.12.12", "revolt-config", "revolt-files", "revolt-models", @@ -5756,7 +6202,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "tokio 1.40.0", + "tokio 1.42.0", "tracing", "tracing-subscriber", "utoipa", @@ -5767,8 +6213,10 @@ dependencies = [ name = "revolt-models" version = "0.8.4" dependencies = [ + "fancy-regex", "indexmap 1.9.3", - "iso8601-timestamp 0.2.11", + "iso8601-timestamp 0.2.17", + "num_enum 0.6.1", "once_cell", "regex", "revolt-config", @@ -5778,7 +6226,7 @@ dependencies = [ "schemars", "serde", "utoipa", - "validator 0.16.0", + "validator 0.16.1", ] [[package]] @@ -5830,16 +6278,18 @@ dependencies = [ "base64 0.22.1", "fcm_v1", "isahc", - "iso8601-timestamp 0.2.11", + "iso8601-timestamp 0.2.17", "log", + "pretty_env_logger", "revolt-config", "revolt-database", "revolt-models", + "revolt-presence", "revolt_a2", "revolt_optional_struct", "serde", "serde_json", - "tokio 1.40.0", + "tokio 1.42.0", "ulid 1.1.3", "web-push", ] @@ -5864,22 +6314,22 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edbe1f79cb41271d3cd8f932d75dddeba963c19dc93d1ee6cbe0391b495ab2f5" dependencies = [ - "base64 0.21.3", + "base64 0.21.7", "erased-serde", - "http 1.1.0", + "http 1.2.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.5.2", "hyper-rustls 0.26.0", "hyper-util", "parking_lot", "pem 3.0.4", - "ring 0.17.8", + "ring", "rustls 0.22.4", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.2.0", "serde", "serde_json", - "thiserror", - "tokio 1.40.0", + "thiserror 1.0.69", + "tokio 1.42.0", ] [[package]] @@ -5934,9 +6384,9 @@ checksum = "cc6620569d8ac8f0a1690fcca13f488503807a60e96ebf729749b59aca1dbef9" dependencies = [ "darling 0.13.4", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "rocket_http", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -5950,6 +6400,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rgb" version = "0.8.50" @@ -5959,21 +6419,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -5984,16 +6429,16 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -6002,9 +6447,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25786b0d276110195fa3d6f3f31299900cf71dfbd6c28450f3f58a0e7f7a347e" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" dependencies = [ "byteorder", "rmp", @@ -6019,19 +6464,19 @@ checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" dependencies = [ "async-stream", "async-trait", - "atomic", + "atomic 0.5.3", "binascii", - "bytes 1.5.0", + "bytes 1.9.0", "either", "figment", "futures", - "indexmap 2.0.1", + "indexmap 2.7.0", "log", "memchr", "multer", "num_cpus", "parking_lot", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "rand 0.8.5", "ref-cast", "rocket_codegen", @@ -6041,7 +6486,7 @@ dependencies = [ "state", "tempfile", "time", - "tokio 1.40.0", + "tokio 1.42.0", "tokio-stream", "tokio-util", "ubyte", @@ -6051,12 +6496,12 @@ dependencies = [ [[package]] name = "rocket_authifier" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810753b79106c44a4e76247fc7576b660663133a9e8f4b0afeb303589ec51d59" +checksum = "c2aa1bfaee106d088b78de7c3cc2a8ab2c9e05a0286b6b912f0b18ea656b329e" dependencies = [ "authifier", - "iso8601-timestamp 0.1.10", + "iso8601-timestamp 0.1.11", "revolt_okapi", "revolt_rocket_okapi", "rocket", @@ -6073,12 +6518,12 @@ checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" dependencies = [ "devise", "glob", - "indexmap 2.0.1", + "indexmap 2.7.0", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "rocket_http", - "syn 2.0.76", - "unicode-xid 0.2.3", + "syn 2.0.94", + "unicode-xid 0.2.6", "version_check", ] @@ -6119,28 +6564,28 @@ dependencies = [ "either", "futures", "http 0.2.12", - "hyper 0.14.30", - "indexmap 2.0.1", + "hyper 0.14.32", + "indexmap 2.7.0", "log", "memchr", "pear", "percent-encoding", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "ref-cast", "serde", "smallvec", "stable-pattern", "state", "time", - "tokio 1.40.0", + "tokio 1.42.0", "uncased", ] [[package]] name = "rocket_prometheus" -version = "0.10.0-rc.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e70efcf6b0234723d0d295b95d64283ed02bb98a8a3f0c8c7ebb5b8da69165" +checksum = "76f429d654a6854abef0a5361235e847b6552d5d989c2fc8a312ba4aebd8837f" dependencies = [ "prometheus", "rocket", @@ -6152,7 +6597,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bitflags 1.3.2", "serde", ] @@ -6170,15 +6615,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" dependencies = [ "byteorder", - "digest 0.10.7", + "digest", "num-bigint-dig", "num-integer", "num-iter", "num-traits", "pkcs1", - "pkcs8", + "pkcs8 0.9.0", "rand_core 0.6.4", - "signature", + "signature 1.6.4", "smallvec", "subtle", "zeroize", @@ -6186,11 +6631,11 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" +checksum = "a5885493fdf0be6cdff808d1533ce878d21cfa49c7086fa00c66355cd9141bfc" dependencies = [ - "base64 0.13.0", + "base64 0.21.7", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -6208,61 +6653,40 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.23", + "semver", ] [[package]] name = "rustc_version_runtime" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d31b7153270ebf48bf91c65ae5b0c00e749c4cfad505f66530ac74950249582f" +checksum = "2dd18cd2bae1820af0b6ad5e54f4a51d0f3fcc53b05f845675074efcc7af071d" dependencies = [ - "rustc_version 0.2.3", - "semver 0.9.0", + "rustc_version", + "semver", ] [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.20.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", + "windows-sys 0.59.0", ] [[package]] @@ -6272,7 +6696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki 0.101.7", "sct", ] @@ -6284,9 +6708,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -6303,39 +6740,29 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" -dependencies = [ - "base64 0.13.0", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.3", + "base64 0.21.7", ] [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -6343,26 +6770,26 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "rustybuzz" @@ -6384,25 +6811,24 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.59.0", ] [[package]] name = "schemars" -version = "0.8.10" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -6413,27 +6839,27 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.10" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "serde_derive_internals", - "syn 1.0.107", + "syn 2.0.94", ] [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scraper" @@ -6453,12 +6879,12 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring", + "untrusted", ] [[package]] @@ -6473,10 +6899,24 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ - "base16ct", + "base16ct 0.1.1", "der 0.6.1", - "generic-array 0.14.5", - "pkcs8", + "generic-array 0.14.7", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.9", + "generic-array 0.14.7", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -6489,16 +6929,16 @@ checksum = "b6326ddc956378a0739200b2c30892dccaf198992dfd7323274690b9e188af23" dependencies = [ "der 0.4.5", "pem 0.8.3", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "security-framework" -version = "2.6.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -6507,9 +6947,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -6536,24 +6976,9 @@ dependencies = [ [[package]] name = "semver" -version = "0.9.0" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "send_wrapper" @@ -6563,28 +6988,28 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "sentry" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b0ad16faa5d12372f914ed40d00bda21a6d1bdcc99264c5e5e1c9495cf3654" +checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5" dependencies = [ "httpdate", "native-tls", - "reqwest 0.11.10", + "reqwest 0.11.27", "sentry-backtrace", "sentry-contexts", "sentry-core", "sentry-debug-images", "sentry-panic", "sentry-tracing", - "tokio 1.40.0", + "tokio 1.42.0", "ureq", ] [[package]] name = "sentry-backtrace" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f2ee8f147bb5f22ac59b5c35754a759b9a6f6722402e2a14750b2a63fc59bd" +checksum = "58cc8d4e04a73de8f718dc703943666d03f25d3e9e4d0fb271ca0b8c76dfa00e" dependencies = [ "backtrace", "once_cell", @@ -6594,23 +7019,23 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcd133362c745151eeba0ac61e3ba8350f034e9fe7509877d08059fe1d7720c6" +checksum = "6436c1bad22cdeb02179ea8ef116ffc217797c028927def303bc593d9320c0d1" dependencies = [ "hostname", "libc", "os_info", - "rustc_version 0.4.0", + "rustc_version", "sentry-core", "uname", ] [[package]] name = "sentry-core" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7163491708804a74446642ff2c80b3acd668d4b9e9f497f85621f3d250fd012b" +checksum = "901f761681f97db3db836ef9e094acdd8756c40215326c194201941947164ef1" dependencies = [ "once_cell", "rand 0.8.5", @@ -6621,9 +7046,9 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5003d7ff08aa3b2b76994080b183e8cfa06c083e280737c9cee02ca1c70f5e" +checksum = "afdb263e73d22f39946f6022ed455b7561b22ff5553aca9be3c6a047fa39c328" dependencies = [ "findshlibs", "once_cell", @@ -6632,9 +7057,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4dfe8371c9b2e126a8b64f6fefa54cef716ff2a50e63b5558a48b899265bccd" +checksum = "74fbf1c163f8b6a9d05912e1b272afa27c652e8b47ea60cb9a57ad5e481eea99" dependencies = [ "sentry-backtrace", "sentry-core", @@ -6642,9 +7067,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca8b88978677a27ee1a91beafe4052306c474c06f582321fde72d2e2cc2f7f" +checksum = "82eabcab0a047040befd44599a1da73d3adb228ff53b5ed9795ae04535577704" dependencies = [ "sentry-backtrace", "sentry-core", @@ -6654,35 +7079,35 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.31.5" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7a88e0c1922d19b3efee12a8215f6a8a806e442e665ada71cc222cab72985f" +checksum = "da956cca56e0101998c8688bc65ce1a96f00673a0e58e663664023d4c7911e82" dependencies = [ "debugid", - "getrandom", "hex", + "rand 0.8.5", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "time", "url", - "uuid 1.4.1", + "uuid", ] [[package]] name = "serde" -version = "1.0.209" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.6" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -6698,34 +7123,35 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ - "indexmap 1.9.3", + "indexmap 2.7.0", "itoa", + "memchr", "ryu", "serde", ] @@ -6742,9 +7168,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -6763,24 +7189,32 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.0", "serde", + "serde_derive", + "serde_json", "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ - "darling 0.13.4", + "darling 0.20.10", "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -6794,25 +7228,13 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.8.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -6823,14 +7245,14 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -6840,14 +7262,14 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -6858,21 +7280,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -6883,7 +7295,17 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest 0.10.7", + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", "rand_core 0.6.4", ] @@ -6899,14 +7321,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" dependencies = [ - "quote 1.0.37", + "quote 1.0.38", ] [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "simplecss" @@ -6931,9 +7353,12 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg 1.4.0", +] [[package]] name = "slotmap" @@ -6950,7 +7375,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" dependencies = [ - "async-channel 1.6.1", + "async-channel 1.9.0", "futures-core", "futures-io", ] @@ -6963,9 +7388,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -6973,28 +7398,19 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] [[package]] name = "spki" @@ -7006,6 +7422,16 @@ dependencies = [ "der 0.6.1", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.9", +] + [[package]] name = "stable-pattern" version = "0.1.0" @@ -7027,7 +7453,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" dependencies = [ - "loom", + "loom 0.5.6", ] [[package]] @@ -7062,17 +7488,18 @@ dependencies = [ "phf_generator 0.10.0", "phf_shared 0.10.0", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", ] [[package]] name = "stringprep" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -7093,11 +7520,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "rustversion", - "syn 2.0.76", + "syn 2.0.94", ] [[package]] @@ -7129,23 +7556,23 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.76" +version = "2.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "unicode-ident", ] @@ -7156,8 +7583,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] @@ -7168,9 +7595,12 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] [[package]] name = "synom" @@ -7188,16 +7618,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", - "unicode-xid 0.2.3", + "quote 1.0.38", + "syn 1.0.109", + "unicode-xid 0.2.6", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "sysinfo" -version = "0.27.6" +version = "0.27.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c215311383d25d03753375c53ab9fad8fc0cf46953c409211e065edeabf577ee" +checksum = "a902e9050fca0a5d6877550b769abd2bd1ce8c04634b941dbe2809735e1a1e33" dependencies = [ "cfg-if", "core-foundation-sys", @@ -7215,7 +7656,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -7228,6 +7680,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -7235,7 +7697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ "cfg-expr", - "heck 0.5.0", + "heck", "pkg-config", "toml 0.8.19", "version-compare", @@ -7253,6 +7715,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.16" @@ -7261,12 +7729,13 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", - "fastrand 2.1.1", + "fastrand 2.3.0", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -7285,39 +7754,60 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ + "cfg-if", "once_cell", ] @@ -7334,13 +7824,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.17" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ + "deranged", "itoa", "libc", + "num-conv", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -7348,16 +7841,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.6" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ + "num-conv", "time-core", ] @@ -7388,19 +7882,29 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" @@ -7415,18 +7919,18 @@ dependencies = [ [[package]] name = "tokio" -version = "1.40.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", - "bytes 1.5.0", + "bytes 1.9.0", "libc", "mio", "parking_lot", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.5.8", "tokio-macros", "windows-sys 0.52.0", ] @@ -7438,29 +7942,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.40.0", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.6", - "tokio 1.40.0", - "webpki", + "tokio 1.42.0", ] [[package]] @@ -7470,7 +7963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls 0.21.12", - "tokio 1.40.0", + "tokio 1.42.0", ] [[package]] @@ -7481,40 +7974,49 @@ checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ "rustls 0.22.4", "rustls-pki-types", - "tokio 1.40.0", + "tokio 1.42.0", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.20", + "tokio 1.42.0", ] [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", - "pin-project-lite 0.2.13", - "tokio 1.40.0", + "pin-project-lite 0.2.15", + "tokio 1.42.0", ] [[package]] name = "tokio-util" -version = "0.7.2" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ - "bytes 1.5.0", + "bytes 1.9.0", "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.13", - "tokio 1.40.0", - "tracing", + "pin-project-lite 0.2.15", + "tokio 1.42.0", ] [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -7528,7 +8030,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.22", ] [[package]] @@ -7542,40 +8044,51 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.1", + "indexmap 2.7.0", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.21", ] [[package]] name = "totp-lite" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc496875d9c8fe9a0ce19e3ee8e8808c60376831a439543f0aac71c9dd129fa" +checksum = "f8e43134db17199f7f721803383ac5854edd0d3d523cc34dba321d6acfbe76c3" dependencies = [ - "digest 0.10.7", + "digest", "hmac", - "sha-1 0.10.0", + "sha1", "sha2", ] [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", - "pin-project-lite 0.2.13", - "tokio 1.40.0", + "pin-project-lite 0.2.15", + "sync_wrapper 1.0.2", + "tokio 1.42.0", "tower-layer", "tower-service", "tracing", @@ -7588,55 +8101,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.6.0", - "bytes 1.5.0", - "http 1.1.0", - "http-body 1.0.0", + "bytes 1.9.0", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", - "pin-project-lite 0.2.13", + "pin-project-lite 0.2.15", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -7654,24 +8167,24 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.11" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ - "ansi_term", - "lazy_static", "matchers", + "nu-ansi-term", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -7681,62 +8194,11 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "triomphe" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" - -[[package]] -name = "trust-dns-proto" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c31f240f59877c3d4bb3b3ea0ec5a6a0cff07323580ff8c7a605cd7d08b255d" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.2.3", - "ipnet", - "lazy_static", - "log", - "rand 0.8.5", - "smallvec", - "thiserror", - "tinyvec", - "tokio 1.40.0", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ba72c2ea84515690c9fcef4c6c660bb9df3036ed1051686de84605b74fd558" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lazy_static", - "log", - "lru-cache", - "parking_lot", - "resolv-conf", - "smallvec", - "thiserror", - "tokio 1.40.0", - "trust-dns-proto", -] - [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" @@ -7749,19 +8211,19 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.17.2" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "byteorder", - "bytes 1.5.0", + "bytes 1.9.0", "http 0.2.12", "httparse", "log", "rand 0.8.5", - "sha-1 0.10.0", - "thiserror", + "sha-1", + "thiserror 1.0.69", "url", "utf-8", ] @@ -7773,8 +8235,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 1.0.107", + "quote 1.0.38", + "syn 1.0.109", ] [[package]] @@ -7794,9 +8256,9 @@ dependencies = [ [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "ulid" @@ -7841,9 +8303,9 @@ dependencies = [ [[package]] name = "uncased" -version = "0.9.7" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "serde", "version_check", @@ -7851,12 +8313,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicase_serde" @@ -7870,9 +8329,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-bidi-mirroring" @@ -7888,15 +8347,15 @@ checksum = "260bc6647b3893a9a90668360803a15f96b85a5257b1c3a0c3daf6ae2496de42" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -7915,9 +8374,9 @@ checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-vo" @@ -7939,9 +8398,9 @@ checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -7953,12 +8412,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -7967,11 +8420,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.7.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ - "base64 0.21.3", + "base64 0.22.1", "log", "native-tls", "once_cell", @@ -7980,12 +8433,12 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", "serde", ] @@ -8038,13 +8491,25 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utoipa" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" dependencies = [ - "indexmap 2.0.1", + "indexmap 2.7.0", "serde", "serde_json", "utoipa-gen", @@ -8052,15 +8517,15 @@ dependencies = [ [[package]] name = "utoipa-gen" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be" +checksum = "20c24e8ab68ff9ee746aad22d39b5535601e6416d1b0feeabf78be986a5c4392" dependencies = [ "proc-macro-error", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "regex", - "syn 2.0.76", + "syn 2.0.94", "ulid 1.1.3", ] @@ -8078,19 +8543,9 @@ dependencies = [ [[package]] name = "uuid" -version = "0.8.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "uuid" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", @@ -8124,11 +8579,11 @@ dependencies = [ [[package]] name = "validator" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ad5bf234c7d3ad1042e5252b7eddb2c4669ee23f32c7dd0e9b7705f07ef591" +checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd" dependencies = [ - "idna 0.2.3", + "idna 0.4.0", "lazy_static", "regex", "serde", @@ -8148,9 +8603,9 @@ dependencies = [ "lazy_static", "proc-macro-error", "proc-macro2", - "quote 1.0.37", + "quote 1.0.38", "regex", - "syn 1.0.107", + "syn 1.0.109", "validator_types", ] @@ -8161,7 +8616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3" dependencies = [ "proc-macro2", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -8172,9 +8627,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "vcpkg" @@ -8184,19 +8639,19 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "7.5.0" +version = "7.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" +checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" dependencies = [ "anyhow", "cfg-if", "enum-iterator", "getset", "git2", - "rustc_version 0.4.0", + "rustc_version", "rustversion", "sysinfo", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -8208,9 +8663,9 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vsimd" @@ -8220,17 +8675,16 @@ checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -8241,10 +8695,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.93" +name = "wasix" +version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -8253,71 +8716,71 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ - "quote 1.0.37", + "quote 1.0.38", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-push" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdf799b4be6f04bfee94807548718de568834c9ea020e73b59af3dac66d72c" +checksum = "49214685777c429ac44a92780983f4fadeecddd8c08c463d8196521e17e974bd" dependencies = [ "async-trait", - "base64 0.13.0", + "base64 0.13.1", "chrono", "ece", - "futures-lite", + "futures-lite 1.13.0", "http 0.2.12", "isahc", "jwt-simple", @@ -8331,9 +8794,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -8360,29 +8823,16 @@ dependencies = [ ] [[package]] -name = "webpki" -version = "0.22.0" +name = "webpki-roots" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.22.3" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -8393,20 +8843,11 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "widestring" -version = "0.5.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -8426,11 +8867,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -8439,6 +8880,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -8449,16 +8909,68 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.36.1" +name = "windows-core" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -8531,12 +9043,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -8549,12 +9055,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -8573,12 +9073,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -8591,12 +9085,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -8621,12 +9109,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -8641,41 +9123,53 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.7.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi", -] - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "xmlparser" version = "0.13.6" @@ -8706,6 +9200,30 @@ dependencies = [ "is-terminal", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", + "synstructure 0.13.1", +] + [[package]] name = "yup-oauth2" version = "8.3.2" @@ -8714,10 +9232,10 @@ checksum = "b61da40aeb0907a65f7fb5c1de83c5a224d6a9ebb83bf918588a2bb744d636b8" dependencies = [ "anyhow", "async-trait", - "base64 0.21.3", + "base64 0.21.7", "futures", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "hyper-rustls 0.24.2", "itertools", "log", @@ -8728,7 +9246,7 @@ dependencies = [ "serde", "serde_json", "time", - "tokio 1.40.0", + "tokio 1.42.0", "tower-service", "url", ] @@ -8739,6 +9257,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -8749,15 +9268,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", - "quote 1.0.37", - "syn 2.0.76", + "quote 1.0.38", + "syn 2.0.94", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", + "synstructure 0.13.1", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote 1.0.38", + "syn 2.0.94", +] [[package]] name = "zune-core" @@ -8776,14 +9338,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" dependencies = [ "zune-core", ] - -[[patch.unused]] -name = "redis" -version = "0.23.1" -source = "git+https://github.com/revoltchat/redis-rs?rev=f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9#f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9" diff --git a/Cargo.toml b/Cargo.toml index ff9bec11..6c69df09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,7 @@ members = [ ] [patch.crates-io] -redis22 = { package = "redis", version = "0.22.3", git = "https://github.com/revoltchat/redis-rs", rev = "1a41faf356fd21aebba71cea7eb7eb2653e5f0ef" } -redis23 = { package = "redis", version = "0.23.1", git = "https://github.com/revoltchat/redis-rs", rev = "f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9" } -# authifier = { package = "authifier", version = "1.0.8", path = "../authifier/crates/authifier" } -# rocket_authifier = { package = "rocket_authifier", version = "1.0.8", path = "../authifier/crates/rocket_authifier" } +redis23 = { package = "redis", version = "0.23.3", git = "https://github.com/revoltchat/redis-rs", rev = "523b2937367e17bd0073722bf6e23d06042cb4e4" } # I'm 99% sure this is overloading the GitHub worker # hence builds have been failing since, let's just diff --git a/crates/bonfire/Cargo.toml b/crates/bonfire/Cargo.toml index 30b69507..be3f6edc 100644 --- a/crates/bonfire/Cargo.toml +++ b/crates/bonfire/Cargo.toml @@ -36,7 +36,7 @@ async-std = { version = "1.8.0", features = [ ] } # core -authifier = { version = "1.0.9" } +authifier = { version = "1.0.10" } revolt-result = { path = "../core/result" } revolt-models = { path = "../core/models" } revolt-config = { path = "../core/config" } diff --git a/crates/core/config/Revolt.toml b/crates/core/config/Revolt.toml index df434065..8db462af 100644 --- a/crates/core/config/Revolt.toml +++ b/crates/core/config/Revolt.toml @@ -70,13 +70,19 @@ max_concurrent_connections = 50 # Usually they have to be, so that messages sent from one or the other get sent to everyone production = true +# Changes how many users are processed in each chunk when resolving role/everyone mentions. +# Increasing this will resolve mentions faster, but will consume more memory while resolving. +mass_mention_chunk_size = 200 + # none of these should need changing exchange = "revolt.notifications" message_queue = "notifications.origin.message" -fr_accepted_queue = "notifications.ingest.fr_accepted" # friend request accepted -fr_received_queue = "notifications.ingest.fr_received" # friend request received -generic_queue = "notifications.ingest.generic" # generic messages (title + body) -ack_queue = "notifications.process.ack" # updates badges for apple devices +mass_mention_queue = "notifications.origin.mass_mention" # handles messages that contain role or everyone mentions +fr_accepted_queue = "notifications.ingest.fr_accepted" # friend request accepted +fr_received_queue = "notifications.ingest.fr_received" # friend request received +generic_queue = "notifications.ingest.generic" # generic messages (title + body) +ack_queue = "notifications.process.ack" # updates badges for apple devices + [pushd.vapid] queue = "notifications.outbound.vapid" @@ -175,6 +181,11 @@ default_bucket = "revolt-uploads" [features] # Feature gate options webhooks_enabled = false +# Enable push notifications for mass pings (everyone, online, roles) +# When false this will still ping in-client but will not send notifications from pushd +mass_mentions_send_notifications = true +# Can role/everyone pings be used at all +mass_mentions_enabled = true [features.limits] diff --git a/crates/core/config/src/lib.rs b/crates/core/config/src/lib.rs index c2e35bd7..445fc597 100644 --- a/crates/core/config/src/lib.rs +++ b/crates/core/config/src/lib.rs @@ -187,7 +187,11 @@ pub struct Api { pub struct Pushd { pub production: bool, pub exchange: String, + pub mass_mention_chunk_size: usize, + + // Queues pub message_queue: String, + pub mass_mention_queue: String, pub fr_accepted_queue: String, pub fr_received_queue: String, pub generic_queue: String, @@ -214,6 +218,10 @@ impl Pushd { self.get_routing_key(self.message_queue.clone()) } + pub fn get_mass_mention_routing_key(&self) -> String { + self.get_routing_key(self.mass_mention_queue.clone()) + } + pub fn get_fr_accepted_routing_key(&self) -> String { self.get_routing_key(self.fr_accepted_queue.clone()) } @@ -314,6 +322,9 @@ impl Default for FeaturesAdvanced { pub struct Features { pub limits: FeaturesLimitsCollection, pub webhooks_enabled: bool, + pub mass_mentions_send_notifications: bool, + pub mass_mentions_enabled: bool, + #[serde(default)] pub advanced: FeaturesAdvanced, } diff --git a/crates/core/database/Cargo.toml b/crates/core/database/Cargo.toml index 60dca8c1..ebb38c6b 100644 --- a/crates/core/database/Cargo.toml +++ b/crates/core/database/Cargo.toml @@ -64,7 +64,7 @@ redis-kiss = { version = "0.1.4" } # Database bson = { optional = true, version = "2.1.0" } -mongodb = { optional = true, version = "2.1.0", default-features = false } +mongodb = { optional = true, version = "3.1.0" } # Database Migration unicode-segmentation = "1.10.1" @@ -96,7 +96,7 @@ web-push = "0.10.0" revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] } # Authifier -authifier = { version = "1.0.9", features = ["rocket_impl"] } +authifier = { version = "1.0.10", features = ["rocket_impl"] } # RabbitMQ amqprs = { version = "1.7.0" } diff --git a/crates/core/database/src/amqp/amqp.rs b/crates/core/database/src/amqp/amqp.rs index 39b4820e..b567c7f7 100644 --- a/crates/core/database/src/amqp/amqp.rs +++ b/crates/core/database/src/amqp/amqp.rs @@ -170,6 +170,38 @@ impl AMQP { .await } + pub async fn mass_mention_message_sent( + &self, + server_id: String, + payload: Vec, + ) -> Result<(), AMQPError> { + let config = revolt_config::config().await; + + let payload = MassMessageSentPayload { + notifications: payload, + server_id, + }; + let payload = to_string(&payload).unwrap(); + + let routing_key = config.pushd.get_mass_mention_routing_key(); + + debug!( + "Sending mass mention payload on channel {}: {}", + routing_key, payload + ); + + self.channel + .basic_publish( + BasicProperties::default() + .with_content_type("application/json") + .with_persistence(true) + .finish(), + payload.into(), + BasicPublishArguments::new(&config.pushd.exchange, routing_key.as_str()), + ) + .await + } + pub async fn ack_message( &self, user_id: String, diff --git a/crates/core/database/src/drivers/mongodb.rs b/crates/core/database/src/drivers/mongodb.rs index a4bbe56b..64a2250b 100644 --- a/crates/core/database/src/drivers/mongodb.rs +++ b/crates/core/database/src/drivers/mongodb.rs @@ -31,17 +31,17 @@ impl MongoDb { } /// Get a collection by its name - pub fn col(&self, collection: &str) -> mongodb::Collection { + pub fn col(&self, collection: &str) -> mongodb::Collection { self.db().collection(collection) } /// Insert one document into a collection - pub async fn insert_one( + pub async fn insert_one( &self, collection: &'static str, document: T, ) -> Result { - self.col::(collection).insert_one(document, None).await + self.col::(collection).insert_one(document).await } /// Count documents by projection @@ -51,7 +51,7 @@ impl MongoDb { projection: Document, ) -> Result { self.col::(collection) - .count_documents(projection, None) + .count_documents(projection) .await } @@ -67,7 +67,8 @@ impl MongoDb { { Ok(self .col::(collection) - .find(projection, options) + .find(projection) + .with_options(options) .await? .filter_map(|s| async { if cfg!(debug_assertions) { @@ -101,7 +102,8 @@ impl MongoDb { O: Into>, { self.col::(collection) - .find_one(projection, options) + .find_one(projection) + .with_options(options) .await } @@ -165,7 +167,7 @@ impl MongoDb { }; self.col::(collection) - .update_one(projection, query, None) + .update_one(projection, query) .await } @@ -200,7 +202,7 @@ impl MongoDb { projection: Document, ) -> Result { self.col::(collection) - .delete_one(projection, None) + .delete_one(projection) .await } diff --git a/crates/core/database/src/events/rabbit.rs b/crates/core/database/src/events/rabbit.rs index 61304752..0ae91be1 100644 --- a/crates/core/database/src/events/rabbit.rs +++ b/crates/core/database/src/events/rabbit.rs @@ -11,6 +11,12 @@ pub struct MessageSentPayload { pub users: Vec, } +#[derive(Serialize, Deserialize)] +pub struct MassMessageSentPayload { + pub notifications: Vec, + pub server_id: String, +} + #[derive(Serialize, Deserialize, Clone)] pub struct FRAcceptedPayload { pub accepted_user: User, diff --git a/crates/core/database/src/models/admin_migrations/ops/mongodb.rs b/crates/core/database/src/models/admin_migrations/ops/mongodb.rs index cdc684e9..703e378a 100644 --- a/crates/core/database/src/models/admin_migrations/ops/mongodb.rs +++ b/crates/core/database/src/models/admin_migrations/ops/mongodb.rs @@ -10,7 +10,7 @@ impl AbstractMigrations for MongoDb { #[cfg(test)] /// Drop the database async fn drop_database(&self) { - self.db().drop(None).await.ok(); + self.db().drop().await.ok(); } /// Migrate the database @@ -18,7 +18,7 @@ impl AbstractMigrations for MongoDb { info!("Migrating the database."); let list = self - .list_database_names(None, None) + .list_database_names() .await .expect("Failed to fetch database names."); diff --git a/crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs b/crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs index ab25819b..00fe26b8 100644 --- a/crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs +++ b/crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs @@ -8,278 +8,254 @@ pub async fn create_database(db: &MongoDb) { info!("Creating database."); let db = db.db(); - db.create_collection("accounts", None) + db.create_collection("accounts") .await .expect("Failed to create accounts collection."); - db.create_collection("users", None) + db.create_collection("users") .await .expect("Failed to create users collection."); - db.create_collection("channels", None) + db.create_collection("channels") .await .expect("Failed to create channels collection."); - db.create_collection("messages", None) + db.create_collection("messages") .await .expect("Failed to create messages collection."); - db.create_collection("servers", None) + db.create_collection("servers") .await .expect("Failed to create servers collection."); - db.create_collection("server_members", None) + db.create_collection("server_members") .await .expect("Failed to create server_members collection."); - db.create_collection("server_bans", None) + db.create_collection("server_bans") .await .expect("Failed to create server_bans collection."); - db.create_collection("channel_invites", None) + db.create_collection("channel_invites") .await .expect("Failed to create channel_invites collection."); - db.create_collection("channel_unreads", None) + db.create_collection("channel_unreads") .await .expect("Failed to create channel_unreads collection."); - db.create_collection("channel_webhooks", None) + db.create_collection("channel_webhooks") .await .expect("Failed to create channel_webhooks collection."); - db.create_collection("migrations", None) + db.create_collection("migrations") .await .expect("Failed to create migrations collection."); - db.create_collection("attachments", None) + db.create_collection("attachments") .await .expect("Failed to create attachments collection."); - db.create_collection("attachment_hashes", None) + db.create_collection("attachment_hashes") .await .expect("Failed to create attachment_hashes collection."); - db.create_collection("user_settings", None) + db.create_collection("user_settings") .await .expect("Failed to create user_settings collection."); - db.create_collection("safety_reports", None) + db.create_collection("safety_reports") .await .expect("Failed to create safety_reports collection."); - db.create_collection("safety_snapshots", None) + db.create_collection("safety_snapshots") .await .expect("Failed to create safety_snapshots collection."); - db.create_collection("safety_strikes", None) + db.create_collection("safety_strikes") .await .expect("Failed to create safety_strikes collection."); - db.create_collection("bots", None) + db.create_collection("bots") .await .expect("Failed to create bots collection."); - db.create_collection("ratelimit_events", None) + db.create_collection("ratelimit_events") .await .expect("Failed to create ratelimit_events collection."); - db.create_collection( - "pubsub", - CreateCollectionOptions::builder() - .capped(true) - .size(1_000_000) - .build(), - ) - .await - .expect("Failed to create pubsub collection."); + db.create_collection("pubsub") + .with_options( + CreateCollectionOptions::builder() + .capped(true) + .size(1_000_000) + .build(), + ) + .await + .expect("Failed to create pubsub collection."); - db.run_command( - doc! { - "createIndexes": "users", - "indexes": [ - { - "key": { - "username": 1_i32 - }, - "name": "username", - "unique": false, - "collation": { - "locale": "en", - "strength": 2_i32 - } + db.run_command(doc! { + "createIndexes": "users", + "indexes": [ + { + "key": { + "username": 1_i32 }, - { - "key": { - "username": 1_i32, - "discriminator": 1_i32 - }, - "name": "username_discriminator", - "unique": true, - "collation": { - "locale": "en", - "strength": 2_i32 - } + "name": "username", + "unique": false, + "collation": { + "locale": "en", + "strength": 2_i32 } - ] - }, - None, - ) + }, + { + "key": { + "username": 1_i32, + "discriminator": 1_i32 + }, + "name": "username_discriminator", + "unique": true, + "collation": { + "locale": "en", + "strength": 2_i32 + } + } + ] + }) .await .expect("Failed to create username index."); - db.run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "content": "text" - }, - "name": "content" + db.run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "content": "text" }, - { - "key": { - "channel": 1_i32, - "_id": 1_i32 - }, - "name": "channel_id_compound" + "name": "content" + }, + { + "key": { + "channel": 1_i32, + "_id": 1_i32 }, - { - "key": { - "author": 1_i32 - }, - "name": "author" + "name": "channel_id_compound" + }, + { + "key": { + "author": 1_i32 }, - { - "key": { - "channel": 1_i32, - "pinned": 1_i32 - }, - "name": "channel_pinned_compound" + "name": "author" + }, + { + "key": { + "channel": 1_i32, + "pinned": 1_i32 }, - ] - }, - None, - ) + "name": "channel_pinned_compound" + }, + ] + }) .await .expect("Failed to create message index."); - db.run_command( - doc! { - "createIndexes": "channel_unreads", - "indexes": [ - { - "key": { - "_id.channel": 1_i32, - "_id.user": 1_i32, - }, - "name": "compound_id" + db.run_command(doc! { + "createIndexes": "channel_unreads", + "indexes": [ + { + "key": { + "_id.channel": 1_i32, + "_id.user": 1_i32, }, - { - "key": { - "_id.user": 1_i32, - }, - "name": "user_id" - } - ] - }, - None, - ) + "name": "compound_id" + }, + { + "key": { + "_id.user": 1_i32, + }, + "name": "user_id" + } + ] + }) .await .expect("Failed to create channel_unreads index."); - db.run_command( - doc! { - "createIndexes": "server_members", - "indexes": [ - { - "key": { - "_id.server": 1_i32, - "_id.user": 1_i32, - }, - "name": "compound_id" + db.run_command(doc! { + "createIndexes": "server_members", + "indexes": [ + { + "key": { + "_id.server": 1_i32, + "_id.user": 1_i32, }, - { - "key": { - "_id.user": 1_i32, - }, - "name": "user_id" - } - ] - }, - None, - ) + "name": "compound_id" + }, + { + "key": { + "_id.user": 1_i32, + }, + "name": "user_id" + } + ] + }) .await .expect("Failed to create server_members index."); - db.run_command( - doc! { - "createIndexes": "attachments", - "indexes": [ - { - "key": { - "hash": 1_i32 - }, - "name": "hash" + db.run_command(doc! { + "createIndexes": "attachments", + "indexes": [ + { + "key": { + "hash": 1_i32 }, - { - "key": { - "used_for.id": 1_i32 - }, - "name": "used_for_id" - } - ] - }, - None, - ) + "name": "hash" + }, + { + "key": { + "used_for.id": 1_i32 + }, + "name": "used_for_id" + } + ] + }) .await .expect("Failed to create attachments index."); - db.run_command( - doc! { - "createIndexes": "attachment_hashes", - "indexes": [ - { - "key": { - "processed_hash": 1_i32 - }, - "name": "processed_hash" - } - ] - }, - None, - ) + db.run_command(doc! { + "createIndexes": "attachment_hashes", + "indexes": [ + { + "key": { + "processed_hash": 1_i32 + }, + "name": "processed_hash" + } + ] + }) .await .expect("Failed to create attachment_hashes index."); db.collection("migrations") - .insert_one( - doc! { - "_id": 0_i32, - "revision": LATEST_REVISION - }, - None, - ) + .insert_one(doc! { + "_id": 0_i32, + "revision": LATEST_REVISION + }) .await .expect("Failed to save migration info."); - db.run_command( - doc! { - "createIndexes": "ratelimit_events", - "indexes": [ - { - "key": { - "_id": 1_i32, - "target_id": 1_i32, - "event_type": 1_i32, - }, - "name": "compound_key" - } - ] - }, - None, - ) + db.run_command(doc! { + "createIndexes": "ratelimit_events", + "indexes": [ + { + "key": { + "_id": 1_i32, + "target_id": 1_i32, + "event_type": 1_i32, + }, + "name": "compound_key" + } + ] + }) .await .expect("Failed to create ratelimit_events index."); diff --git a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs index 7780037e..16618ea9 100644 --- a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs +++ b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs @@ -26,7 +26,7 @@ pub const LATEST_REVISION: i32 = 31; pub async fn migrate_database(db: &MongoDb) { let migrations = db.col::("migrations"); let data = migrations - .find_one(None, None) + .find_one(doc! {}) .await .expect("Failed to fetch migration data."); @@ -46,7 +46,6 @@ pub async fn migrate_database(db: &MongoDb) { "revision": revision } }, - None, ) .await .expect("Failed to commit migration information."); @@ -74,7 +73,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .update_many( doc! { "attachment": { "$exists": 1_i32 } }, doc! { "$set": { "attachment.tag": "attachments", "attachment.size": 0_i32 } }, - None, ) .await .expect("Failed to update messages."); @@ -83,7 +81,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .update_many( doc! {}, doc! { "$set": { "tag": "attachments", "size": 0_i32 } }, - None, ) .await .expect("Failed to update attachments."); @@ -93,7 +90,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 2 / 2021-05-08]: Add servers collection."); db.db() - .create_collection("servers", None) + .create_collection("servers") .await .expect("Failed to create servers collection."); } @@ -103,12 +100,12 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { let messages = db.col::("messages"); let mut cursor = messages - .find( - doc! { - "attachment": { - "$exists": 1_i32 - } - }, + .find(doc! { + "attachment": { + "$exists": 1_i32 + } + }) + .with_options( FindOptions::builder() .projection(doc! { "_id": 1_i32, @@ -128,19 +125,18 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .update_one( doc! { "_id": id }, doc! { "$unset": { "attachment": 1_i32 }, "$set": { "attachments": attachments } }, - None, ) .await .unwrap(); } db.db() - .create_collection("channel_unreads", None) + .create_collection("channel_unreads") .await .expect("Failed to create channel_unreads collection."); db.db() - .create_collection("user_settings", None) + .create_collection("user_settings") .await .expect("Failed to create user_settings collection."); } @@ -149,17 +145,17 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 4 / 2021-06-01]: Add more server collections."); db.db() - .create_collection("server_members", None) + .create_collection("server_members") .await .expect("Failed to create server_members collection."); db.db() - .create_collection("server_bans", None) + .create_collection("server_bans") .await .expect("Failed to create server_bans collection."); db.db() - .create_collection("channel_invites", None) + .create_collection("channel_invites") .await .expect("Failed to create channel_invites collection."); } @@ -182,7 +178,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { doc! { "$set": to_document(&server).unwrap() }, - None, ) .await .expect("Failed to migrate servers."); @@ -192,20 +187,17 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 6 / 2021-07-09]: Add message text index."); db.db() - .run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "content": "text" - }, - "name": "content" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "content": "text" + }, + "name": "content" + } + ] + }) .await .expect("Failed to create message index."); } @@ -214,7 +206,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 7 / 2021-08-11]: Add message text index."); db.db() - .create_collection("bots", None) + .create_collection("bots") .await .expect("Failed to create bots collection."); } @@ -223,22 +215,15 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 8 / 2021-09-10]: Update to Authifier version 1."); db.db() - .run_command( - doc! { - "dropIndexes": "accounts", - "index": ["email", "email_normalised"] - }, - None, - ) + .run_command(doc! { + "dropIndexes": "accounts", + "index": ["email", "email_normalised"] + }) .await .expect("Failed to delete legacy account indexes."); let col = db.col::("sessions"); - let mut cursor = db - .col::("accounts") - .find(doc! {}, None) - .await - .unwrap(); + let mut cursor = db.col::("accounts").find(doc! {}).await.unwrap(); while let Some(doc) = cursor.next().await { if let Ok(account) = doc { @@ -267,7 +252,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { doc.insert("subscription", sub); } - col.insert_one(doc, None).await.ok(); + col.insert_one(doc).await.ok(); } } else { info!("Account doesn't have any sessions!"); @@ -288,7 +273,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { } } }, - None, ) .await .unwrap(); @@ -297,11 +281,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if revision <= 9 { info!("Running migration [revision 9 / 2021-09-14]: Switch from last_message to last_message_id."); - let mut cursor = db - .col::("channels") - .find(doc! {}, None) - .await - .unwrap(); + let mut cursor = db.col::("channels").find(doc! {}).await.unwrap(); while let Some(doc) = cursor.next().await { if let Ok(channel) = doc { @@ -340,7 +320,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "last_message": 1_i32, } }, - None, ) .await .unwrap(); @@ -362,7 +341,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "nonce": 1_i32, } }, - None, ) .await .unwrap(); @@ -375,7 +353,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "nonce": 1_i32, } }, - None, ) .await .unwrap(); @@ -385,70 +362,61 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 11 / 2021-11-14]: Add indexes to database."); db.db() - .run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "channel": 1_i32 - }, - "name": "channel" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "channel": 1_i32 + }, + "name": "channel" + } + ] + }) .await .expect("Failed to create message index."); db.db() - .run_command( - doc! { - "createIndexes": "channel_unreads", - "indexes": [ - { - "key": { - "_id.channel": 1_i32, - "_id.user": 1_i32, - }, - "name": "compound_id" + .run_command(doc! { + "createIndexes": "channel_unreads", + "indexes": [ + { + "key": { + "_id.channel": 1_i32, + "_id.user": 1_i32, }, - { - "key": { - "_id.user": 1_i32, - }, - "name": "user_id" - } - ] - }, - None, - ) + "name": "compound_id" + }, + { + "key": { + "_id.user": 1_i32, + }, + "name": "user_id" + } + ] + }) .await .expect("Failed to create channel_unreads index."); db.db() - .run_command( - doc! { - "createIndexes": "server_members", - "indexes": [ - { - "key": { - "_id.server": 1_i32, - "_id.user": 1_i32, - }, - "name": "compound_id" + .run_command(doc! { + "createIndexes": "server_members", + "indexes": [ + { + "key": { + "_id.server": 1_i32, + "_id.user": 1_i32, }, - { - "key": { - "_id.user": 1_i32, - }, - "name": "user_id" - } - ] - }, - None, - ) + "name": "compound_id" + }, + { + "key": { + "_id.user": 1_i32, + }, + "name": "user_id" + } + ] + }) .await .expect("Failed to create server_members index."); } @@ -457,21 +425,18 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 12 / 2021-11-21]: Add indexes to database."); db.db() - .run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "channel": 1_i32, - "_id": 1_i32 - }, - "name": "channel_id_compound" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "channel": 1_i32, + "_id": 1_i32 + }, + "name": "channel_id_compound" + } + ] + }) .await .expect("Failed to create message index."); } @@ -485,7 +450,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { async_std::task::sleep(Duration::from_secs(10)).await; let servers = db.col::("servers"); - let mut cursor = servers.find(doc! {}, None).await.unwrap(); + let mut cursor = servers.find(doc! {}).await.unwrap(); while let Some(Ok(mut document)) = cursor.next().await { let id = document.get_str("_id").unwrap().to_string(); @@ -529,13 +494,13 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { } servers - .update_one(doc! { "_id": id }, doc! { "$set": update }, None) + .update_one(doc! { "_id": id }, doc! { "$set": update }) .await .unwrap(); } let channels = db.col::("channels"); - let mut cursor = channels.find(doc! {}, None).await.unwrap(); + let mut cursor = channels.find(doc! {}).await.unwrap(); while let Some(Ok(document)) = cursor.next().await { let id = document.get_str("_id").unwrap().to_string(); @@ -575,7 +540,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { } channels - .update_one(doc! { "_id": id }, update, None) + .update_one(doc! { "_id": id }, update) .await .unwrap(); } @@ -596,7 +561,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "content": "system" } }, - None, ) .await .unwrap(); @@ -621,25 +585,22 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .unwrap(); db.db() - .create_collection("emojis", None) + .create_collection("emojis") .await .expect("Failed to create emojis collection."); db.db() - .run_command( - doc! { - "createIndexes": "emojis", - "indexes": [ - { - "key": { - "parent.id": 1_i32, - }, - "name": "parent_id" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "emojis", + "indexes": [ + { + "key": { + "parent.id": 1_i32, + }, + "name": "parent_id" + } + ] + }) .await .expect("Failed to create emoji parent index."); } @@ -652,10 +613,9 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { doc! {}, doc! { "$set": { - "joined_at": DateTime::now().to_rfc3339_string() + "joined_at": DateTime::now().try_to_rfc3339_string().expect("Failed to convert the date to rfc3339") } }, - None, ) .await .expect("Failed to update server members."); @@ -666,13 +626,10 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if db .db() - .run_command( - doc! { - "dropIndexes": "messages", - "index": ["channel"] - }, - None, - ) + .run_command(doc! { + "dropIndexes": "messages", + "index": ["channel"] + }) .await .is_err() { @@ -680,20 +637,17 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { } db.db() - .run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "author": 1_i32, - }, - "name": "author" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "author": 1_i32, + }, + "name": "author" + } + ] + }) .await .expect("Failed to create messages author index."); } @@ -703,35 +657,26 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "Running migration [revision 19 / 27-02-2023]: Create report / snapshot collections." ); - db.db() - .create_collection("safety_reports", None) - .await - .unwrap(); + db.db().create_collection("safety_reports").await.unwrap(); - db.db() - .create_collection("safety_snapshots", None) - .await - .unwrap(); + db.db().create_collection("safety_snapshots").await.unwrap(); } if revision <= 20 { info!("Running migration [revision 20 / 28-02-2023]: Add index `snapshot.report_id`."); db.db() - .run_command( - doc! { - "createIndexes": "safety_snapshots", - "indexes": [ - { - "key": { - "report_id": 1_i32 - }, - "name": "report_id" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "safety_snapshots", + "indexes": [ + { + "key": { + "report_id": 1_i32 + }, + "name": "report_id" + } + ] + }) .await .expect("Failed to create safety snapshot index."); } @@ -739,10 +684,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if revision <= 21 { info!("Running migration [revision 21 / 31-05-2023]: Add collection `safety_strikes`."); - db.db() - .create_collection("safety_strikes", None) - .await - .unwrap(); + db.db().create_collection("safety_strikes").await.unwrap(); } if revision <= 22 { @@ -756,7 +698,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "moderator_id": "01EX2NCWQ0CHS3QJF0FEQS1GR4" } }, - None, ) .await .expect("Failed to update server members."); @@ -766,13 +707,10 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 23 / 10-06-2023]: Generate discriminators for users."); db.db() - .run_command( - doc! { - "dropIndexes": "users", - "index": "username" - }, - None, - ) + .run_command(doc! { + "dropIndexes": "users", + "index": "username" + }) .await .expect("Failed to drop existing username index."); @@ -787,7 +725,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { let users: Vec = db .col::("users") - .find(doc! {}, None) + .find(doc! {}) .await .unwrap() .map(|doc| doc.expect("id and username")) @@ -839,7 +777,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "discriminator": discriminator } }, - None, ) .await .unwrap(); @@ -887,7 +824,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "display_name": &info.username } }, - None, ) .await .unwrap(); @@ -898,43 +834,37 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if revision <= 24 { info!("Running migration [revision 24 / 09-06-2023]: Add collection `channel_webhooks` if not exists, update users index."); - db.db() - .create_collection("channel_webhooks", None) - .await - .ok(); + db.db().create_collection("channel_webhooks").await.ok(); db.db() - .run_command( - doc! { - "createIndexes": "users", - "indexes": [ - { - "key": { - "username": 1_i32 - }, - "name": "username", - "unique": false, - "collation": { - "locale": "en", - "strength": 2_i32 - } + .run_command(doc! { + "createIndexes": "users", + "indexes": [ + { + "key": { + "username": 1_i32 }, - { - "key": { - "username": 1_i32, - "discriminator": 1_i32 - }, - "name": "username_discriminator", - "unique": true, - "collation": { - "locale": "en", - "strength": 2_i32 - } + "name": "username", + "unique": false, + "collation": { + "locale": "en", + "strength": 2_i32 } - ] - }, - None, - ) + }, + { + "key": { + "username": 1_i32, + "discriminator": 1_i32 + }, + "name": "username_discriminator", + "unique": true, + "collation": { + "locale": "en", + "strength": 2_i32 + } + } + ] + }) .await .expect("Failed to create username index."); }; @@ -950,7 +880,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "permissions": *DEFAULT_WEBHOOK_PERMISSIONS as i64 } }, - None, ) .await .expect("Failed to update webhooks."); @@ -959,28 +888,22 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if revision <= 25 { info!("Running migration [revision 25 / 15-06-2023]: Add collection `ratelimit_events` with index."); - db.db() - .create_collection("ratelimit_events", None) - .await - .ok(); + db.db().create_collection("ratelimit_events").await.ok(); db.db() - .run_command( - doc! { - "createIndexes": "ratelimit_events", - "indexes": [ - { - "key": { - "_id": 1_i32, - "target_id": 1_i32, - "event_type": 1_i32, - }, - "name": "compound_key" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "ratelimit_events", + "indexes": [ + { + "key": { + "_id": 1_i32, + "target_id": 1_i32, + "event_type": 1_i32, + }, + "name": "compound_key" + } + ] + }) .await .expect("Failed to create ratelimit_events index."); } @@ -1016,12 +939,9 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { let invites = db .db() .collection::("channel_invites") - .find( - doc! { - "type": { "$exists": false } - }, - None, - ) + .find(doc! { + "type": { "$exists": false } + }) .await .expect("failed to find invites") .filter_map(|s| async { s.ok() }) @@ -1055,18 +975,15 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if !invites.is_empty() { db.db() .collection("channel_invites") - .insert_many(invites, None) + .insert_many(invites) .await .expect("failed to insert corrected invite"); db.db() .collection::("channel_invites") - .delete_many( - doc! { - "type": { "$exists": false } - }, - None, - ) + .delete_many(doc! { + "type": { "$exists": false } + }) .await .expect("failed to find invites"); } @@ -1076,21 +993,18 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 27 / 21-07-2024]: create message pinned index."); db.db() - .run_command( - doc! { - "createIndexes": "messages", - "indexes": [ - { - "key": { - "channel": 1_i32, - "pinned": 1_i32 - }, - "name": "channel_pinned_compound" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "messages", + "indexes": [ + { + "key": { + "channel": 1_i32, + "pinned": 1_i32 + }, + "name": "channel_pinned_compound" + } + ] + }) .await .expect("Failed to create message index."); } @@ -1098,44 +1012,35 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { if revision <= 28 { info!("Running migration [revision 28 / 10-09-2024]: Add support for new Autumn."); - db.db() - .create_collection("attachment_hashes", None) - .await - .ok(); + db.db().create_collection("attachment_hashes").await.ok(); db.db() - .run_command( - doc! { - "createIndexes": "attachments", - "indexes": [ - { - "key": { - "hash": 1_i32 - }, - "name": "hash" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "attachments", + "indexes": [ + { + "key": { + "hash": 1_i32 + }, + "name": "hash" + } + ] + }) .await .expect("Failed to create attachments index."); db.db() - .run_command( - doc! { - "createIndexes": "attachment_hashes", - "indexes": [ - { - "key": { - "processed_hash": 1_i32 - }, - "name": "processed_hash" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "attachment_hashes", + "indexes": [ + { + "key": { + "processed_hash": 1_i32 + }, + "name": "processed_hash" + } + ] + }) .await .expect("Failed to create attachment_hashes index."); } @@ -1146,20 +1051,17 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { info!("Running migration [revision 30 / 29-09-2024]: Add index for used_for.id to attachments."); db.db() - .run_command( - doc! { - "createIndexes": "attachments", - "indexes": [ - { - "key": { - "used_for.id": 1_i32 - }, - "name": "used_for_id" - } - ] - }, - None, - ) + .run_command(doc! { + "createIndexes": "attachments", + "indexes": [ + { + "key": { + "used_for.id": 1_i32 + }, + "name": "used_for_id" + } + ] + }) .await .expect("Failed to create attachments index."); } @@ -1176,7 +1078,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { let webhooks = db .db() .collection::("channel_webhooks") - .find(doc! {}, None) + .find(doc! {}) .await .expect("webhooks") .filter_map(|s| async { s.ok() }) @@ -1207,7 +1109,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { "creator_id": creator_id } }, - None, ) .await .expect("update webhook"); @@ -1218,7 +1119,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { }) => { db.db() .collection::("channel_webhooks") - .delete_one(doc! { "_id": webhook._id }, None) + .delete_one(doc! { "_id": webhook._id }) .await .expect("failed to delete invalid webhook"); } diff --git a/crates/core/database/src/models/channel_invites/ops/mongodb.rs b/crates/core/database/src/models/channel_invites/ops/mongodb.rs index f6d55fff..d628be8e 100644 --- a/crates/core/database/src/models/channel_invites/ops/mongodb.rs +++ b/crates/core/database/src/models/channel_invites/ops/mongodb.rs @@ -24,12 +24,9 @@ impl AbstractChannelInvites for MongoDb { async fn fetch_invites_for_server(&self, server_id: &str) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "server": server_id, - }, - None, - ) + .find(doc! { + "server": server_id, + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { diff --git a/crates/core/database/src/models/channel_unreads/ops.rs b/crates/core/database/src/models/channel_unreads/ops.rs index 6a6e98af..6c91bf64 100644 --- a/crates/core/database/src/models/channel_unreads/ops.rs +++ b/crates/core/database/src/models/channel_unreads/ops.rs @@ -26,6 +26,14 @@ pub trait AbstractChannelUnreads: Sync + Send { message_ids: &[String], ) -> Result<()>; + /// Add a mention. + async fn add_mention_to_many_unreads<'a>( + &self, + channel_id: &str, + user_ids: &[String], + message_ids: &[String], + ) -> Result<()>; + /// Fetch all unreads with mentions for a user. async fn fetch_unread_mentions(&self, user_id: &str) -> Result>; diff --git a/crates/core/database/src/models/channel_unreads/ops/mongodb.rs b/crates/core/database/src/models/channel_unreads/ops/mongodb.rs index 76cead11..7225dc3d 100644 --- a/crates/core/database/src/models/channel_unreads/ops/mongodb.rs +++ b/crates/core/database/src/models/channel_unreads/ops/mongodb.rs @@ -37,6 +37,8 @@ impl AbstractChannelUnreads for MongoDb { "last_id": message_id } }, + ) + .with_options( FindOneAndUpdateOptions::builder() .upsert(true) .return_document(ReturnDocument::After) @@ -51,15 +53,12 @@ impl AbstractChannelUnreads for MongoDb { let current_time = Ulid::new().to_string(); self.col::(COL) - .delete_many( - doc! { - "_id.channel": { - "$in": channel_ids - }, - "_id.user": user_id + .delete_many(doc! { + "_id.channel": { + "$in": channel_ids }, - None, - ) + "_id.user": user_id + }) .await .map_err(|_| create_database_error!("delete_many", COL))?; @@ -77,7 +76,6 @@ impl AbstractChannelUnreads for MongoDb { } }) .collect::>(), - None, ) .await .map(|_| ()) @@ -104,13 +102,42 @@ impl AbstractChannelUnreads for MongoDb { } } }, - UpdateOptions::builder().upsert(true).build(), ) + .with_options(UpdateOptions::builder().upsert(true).build()) .await .map(|_| ()) .map_err(|_| create_database_error!("update_one", COL)) } + /// Add a mention to multiple users. + async fn add_mention_to_many_unreads<'a>( + &self, + channel_id: &str, + user_ids: &[String], + message_ids: &[String], + ) -> Result<()> { + self.col::(COL) + .update_many( + doc! { + "_id.channel": channel_id, + "_id.user": { + "$in": user_ids + }, + }, + doc! { + "$push": { + "mentions": { + "$each": message_ids + } + } + }, + ) + .with_options(UpdateOptions::builder().upsert(true).build()) + .await + .map(|_| ()) + .map_err(|_| create_database_error!("update_many", COL)) + } + /// Fetch all channel unreads for a user. async fn fetch_unreads(&self, user_id: &str) -> Result> { query!( diff --git a/crates/core/database/src/models/channel_unreads/ops/reference.rs b/crates/core/database/src/models/channel_unreads/ops/reference.rs index 914ac95d..36969b8f 100644 --- a/crates/core/database/src/models/channel_unreads/ops/reference.rs +++ b/crates/core/database/src/models/channel_unreads/ops/reference.rs @@ -78,6 +78,38 @@ impl AbstractChannelUnreads for ReferenceDb { Ok(()) } + /// Add a mention to multiple users. + async fn add_mention_to_many_unreads<'a>( + &self, + channel_id: &str, + user_ids: &[String], + message_ids: &[String], + ) -> Result<()> { + let mut unreads = self.channel_unreads.lock().await; + + for user_id in user_ids { + let key = ChannelCompositeKey { + channel: channel_id.to_string(), + user: user_id.to_string(), + }; + + if let Some(unread) = unreads.get_mut(&key) { + unread.mentions.replace(message_ids.to_vec()); + } else { + unreads.insert( + key.clone(), + ChannelUnread { + id: key, + last_id: None, + mentions: Some(message_ids.to_vec()), + }, + ); + } + } + + Ok(()) + } + async fn fetch_unread_mentions(&self, user_id: &str) -> Result> { let unreads = self.channel_unreads.lock().await; Ok(unreads diff --git a/crates/core/database/src/models/channel_webhooks/ops/mongodb.rs b/crates/core/database/src/models/channel_webhooks/ops/mongodb.rs index 457e3b68..9e11d561 100644 --- a/crates/core/database/src/models/channel_webhooks/ops/mongodb.rs +++ b/crates/core/database/src/models/channel_webhooks/ops/mongodb.rs @@ -24,12 +24,9 @@ impl AbstractWebhooks for MongoDb { async fn fetch_webhooks_for_channel(&self, channel_id: &str) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "channel_id": channel_id, - }, - None, - ) + .find(doc! { + "channel_id": channel_id, + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { diff --git a/crates/core/database/src/models/channels/ops/mongodb.rs b/crates/core/database/src/models/channels/ops/mongodb.rs index 51c6b66e..b247a683 100644 --- a/crates/core/database/src/models/channels/ops/mongodb.rs +++ b/crates/core/database/src/models/channels/ops/mongodb.rs @@ -23,14 +23,11 @@ impl AbstractChannels for MongoDb { async fn fetch_channels<'a>(&self, ids: &'a [String]) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id": { - "$in": ids - } - }, - None, - ) + .find(doc! { + "_id": { + "$in": ids + } + }) .await .map_err(|_| create_database_error!("fetch", "channels"))? .filter_map(|s| async { @@ -119,7 +116,6 @@ impl AbstractChannels for MongoDb { "recipients": user } }, - None, ) .await .map(|_| ()) @@ -141,7 +137,6 @@ impl AbstractChannels for MongoDb { "role_permissions.".to_owned() + role: permissions } }, - None, ) .await .map(|_| ()) @@ -179,7 +174,6 @@ impl AbstractChannels for MongoDb { "recipients": user } }, - None, ) .await .map(|_| ()) @@ -253,7 +247,6 @@ impl AbstractChannels for MongoDb { "_id": server.id }, update, - None, ) .await .map_err(|_| create_database_error!("update_one", "servers"))?; @@ -274,23 +267,17 @@ impl MongoDb { pub async fn delete_associated_channel_objects(&self, id: Bson) -> Result<()> { // Delete all invites to these channels. self.col::("channel_invites") - .delete_many( - doc! { - "channel": &id - }, - None, - ) + .delete_many(doc! { + "channel": &id + }) .await .map_err(|_| create_database_error!("delete_many", "channel_invites"))?; // Delete unread message objects on channels. self.col::("channel_unreads") - .delete_many( - doc! { - "_id.channel": &id - }, - None, - ) + .delete_many(doc! { + "_id.channel": &id + }) .await .map_err(|_| create_database_error!("delete_many", "channel_unreads")) .map(|_| ())?; @@ -299,12 +286,9 @@ impl MongoDb { // Delete all webhooks on this channel. self.col::("webhooks") - .delete_many( - doc! { - "channel": &id - }, - None, - ) + .delete_many(doc! { + "channel": &id + }) .await .map_err(|_| create_database_error!("delete_many", "webhooks")) .map(|_| ()) diff --git a/crates/core/database/src/models/emojis/ops/mongodb.rs b/crates/core/database/src/models/emojis/ops/mongodb.rs index 168d3db7..6dd3137b 100644 --- a/crates/core/database/src/models/emojis/ops/mongodb.rs +++ b/crates/core/database/src/models/emojis/ops/mongodb.rs @@ -60,7 +60,6 @@ impl AbstractEmojis for MongoDb { } } }, - None, ) .await .map(|_| ()) diff --git a/crates/core/database/src/models/file_hashes/ops/mongodb.rs b/crates/core/database/src/models/file_hashes/ops/mongodb.rs index 153cb72f..e2f06067 100644 --- a/crates/core/database/src/models/file_hashes/ops/mongodb.rs +++ b/crates/core/database/src/models/file_hashes/ops/mongodb.rs @@ -42,7 +42,6 @@ impl AbstractAttachmentHashes for MongoDb { "iv": nonce } }, - None, ) .await .map(|_| ()) diff --git a/crates/core/database/src/models/files/ops/mongodb.rs b/crates/core/database/src/models/files/ops/mongodb.rs index 43e8e946..cd4241fe 100644 --- a/crates/core/database/src/models/files/ops/mongodb.rs +++ b/crates/core/database/src/models/files/ops/mongodb.rs @@ -110,7 +110,6 @@ impl AbstractAttachments for MongoDb { "uploader_id": uploader_id } }, - None, ) .await .map_err(|_| create_database_error!("update_one", COL))?; @@ -130,7 +129,6 @@ impl AbstractAttachments for MongoDb { "reported": true } }, - None, ) .await .map(|_| ()) @@ -149,7 +147,6 @@ impl AbstractAttachments for MongoDb { "deleted": true } }, - None, ) .await .map(|_| ()) @@ -170,7 +167,6 @@ impl AbstractAttachments for MongoDb { "deleted": true } }, - None, ) .await .map(|_| ()) @@ -193,7 +189,6 @@ impl MongoDb { "deleted": true } }, - None, ) .await .map(|_| ()) diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index 00ec6fb9..fd51d0ae 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -5,9 +5,10 @@ use iso8601_timestamp::Timestamp; use revolt_config::{config, FeaturesLimits}; use revolt_models::v0::{ self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageFlags, MessageSort, - MessageWebhook, PushNotification, ReplyIntent, SendableEmbed, Text, RE_MENTION, + MessageWebhook, PushNotification, ReplyIntent, SendableEmbed, Text, RE_BLOCKS, RE_MENTION, + RE_ROLE_MENTION, }; -use revolt_permissions::{ChannelPermission, PermissionValue}; +use revolt_permissions::{calculate_channel_permissions, ChannelPermission, PermissionValue}; use revolt_result::{ErrorType, Result}; use ulid::Ulid; use validator::Validate; @@ -15,7 +16,10 @@ use validator::Validate; use crate::{ events::client::EventV1, tasks::{self, ack::AckEvent}, - util::{bulk_permissions::BulkDatabasePermissionQuery, idempotency::IdempotencyKey}, + util::{ + bulk_permissions::BulkDatabasePermissionQuery, idempotency::IdempotencyKey, + permissions::DatabasePermissionQuery, + }, Channel, Database, Emoji, File, User, AMQP, }; @@ -53,6 +57,9 @@ auto_derived_partial!( /// Array of user ids mentioned in this message #[serde(skip_serializing_if = "Option::is_none")] pub mentions: Option>, + /// Array of role ids mentioned in this message + #[serde(skip_serializing_if = "Option::is_none")] + pub role_mentions: Option>, /// Array of message ids this message is replying to #[serde(skip_serializing_if = "Option::is_none")] pub replies: Option>, @@ -71,7 +78,7 @@ auto_derived_partial!( /// Bitfield of message flags #[serde(skip_serializing_if = "Option::is_none")] - pub flags: Option, + pub flags: Option, }, "PartialMessage" ); @@ -199,6 +206,30 @@ auto_derived!( } ); +pub struct MessageFlagsValue(pub u32); + +impl MessageFlagsValue { + pub fn has(&self, flag: MessageFlags) -> bool { + self.has_value(flag as u32) + } + pub fn has_value(&self, bit: u32) -> bool { + let mask = 1 << bit; + self.0 & mask == mask + } + + pub fn set(&mut self, flag: MessageFlags, toggle: bool) -> &mut Self { + self.set_value(flag as u32, toggle) + } + pub fn set_value(&mut self, bit: u32, toggle: bool) -> &mut Self { + if toggle { + self.0 |= 1 << bit; + } else { + self.0 &= !(1 << bit); + } + self + } +} + #[allow(clippy::derivable_impls)] impl Default for Message { fn default() -> Self { @@ -214,6 +245,7 @@ impl Default for Message { edited: None, embeds: None, mentions: None, + role_mentions: None, replies: None, reactions: Default::default(), interactions: Default::default(), @@ -262,13 +294,43 @@ impl Message { return Err(create_error!(EmptyMessage)); } - // Ensure flags are either not set or have permissible values - if let Some(flags) = &data.flags { - if flags != &0 && flags != &1 { + let allow_mass_mentions = allow_mentions && config.features.mass_mentions_enabled; + + let mut mentions_everyone = false; + let mut mentions_online = false; + let mut suppress_notifications = false; + + if let Some(raw_flags) = &data.flags { + if raw_flags > &7 { + // quick path to failure: bigger than all the bits combined return Err(create_error!(InvalidProperty)); } + + // First step of mass mention resolution + let flags = MessageFlagsValue(*raw_flags); + suppress_notifications = flags.has(MessageFlags::SuppressNotifications); + mentions_everyone = allow_mentions && flags.has(MessageFlags::MentionsEveryone); + mentions_online = allow_mentions && flags.has(MessageFlags::MentionsOnline); + + // Not a bot, and attempting to set mention flags + if user.as_ref().is_some_and(|u| u.bot.as_ref().is_none()) + && (mentions_everyone || mentions_online) + { + return Err(create_error!(IsNotBot)); + } + + if mentions_everyone && mentions_online { + return Err(create_error!(InvalidFlagValue)); + } } + let server_id = match channel { + Channel::TextChannel { ref server, .. } | Channel::VoiceChannel { ref server, .. } => { + Some(server.clone()) + } + _ => None, + }; + // Ensure restrict_reactions is not specified without reactions list if let Some(interactions) = &data.interactions { if interactions.restrict_reactions { @@ -302,19 +364,99 @@ impl Message { .unwrap_or_default(), author: author_id, webhook: webhook.map(|w| w.into()), - flags: data.flags.map(|v| v as i32), + flags: data.flags, ..Default::default() }; // Parse mentions in message. let mut mentions = HashSet::new(); - if allow_mentions { - if let Some(content) = &data.content { - for capture in RE_MENTION.captures_iter(content) { - if let Some(mention) = capture.get(1) { - mentions.insert(mention.as_str().to_string()); + let mut role_mentions = HashSet::new(); + let mut role_model_mentions = vec![]; + + if let Some(raw_content) = &data.content { + // remove all codeblocks before running the mention regex + let modified_content = RE_BLOCKS.replace_all(raw_content, ""); + + for capture in RE_MENTION.captures_iter(&modified_content).flatten() { + if let Some(mention) = capture.get(1) { + mentions.insert(mention.as_str().to_string()); + } + } + if allow_mass_mentions && server_id.is_some() { + // Second step of mass mention resolution. + for capture in RE_ROLE_MENTION.captures_iter(&modified_content).flatten() { + let raw = capture.get(0).expect("No capture?").as_str(); + if raw == "@everyone" { + mentions_everyone = true; + // Can't break early here since we want to capture any role ids + } else if raw == "@online" { + mentions_online = true; + } else if let Some(role_match) = capture.get(1) { + role_mentions.insert(role_match.as_str().to_string()); } } + + if !role_mentions.is_empty() { + let server_data = db + .fetch_server(server_id.unwrap().as_str()) + .await + .expect("Failed to fetch server"); + + role_mentions = role_mentions + .iter() + .filter(|role_id| server_data.roles.contains_key(*role_id)) + .cloned() + .collect(); + + role_model_mentions.extend( + role_mentions + .iter() + .map(|role_id| server_data.roles.get(role_id).to_owned()), + ); + } + } + } + + // Validate the user can perform a mass mention + if !config.features.mass_mentions_enabled + && (mentions_everyone || mentions_online || !role_mentions.is_empty()) + { + mentions_everyone = false; + mentions_online = false; + role_mentions.clear(); + } else if mentions_everyone || mentions_online || !role_mentions.is_empty() { + debug!( + "Mentioned everyone: {}, mentioned online: {}, mentioned roles: {:?}", + mentions_everyone, mentions_online, &role_mentions + ); + if let Some(user) = match author { + MessageAuthor::User(user) => Some(Ok(user)), + MessageAuthor::System { .. } => Some(Err(())), // DISALLOWED + MessageAuthor::Webhook(..) => None, // Bypass check + } { + if user.is_err() { + return Err(create_error!(InvalidProperty)); + } + let owned_user: User = user.unwrap().to_owned().into(); + + let mut query = DatabasePermissionQuery::new(db, &owned_user).channel(&channel); + let perms = calculate_channel_permissions(&mut query).await; + + if (mentions_everyone || mentions_online) + && !perms.has_channel_permission(ChannelPermission::MentionEveryone) + { + return Err(create_error!(MissingPermission { + permission: ChannelPermission::MentionEveryone.to_string() + })); + } + + if !role_mentions.is_empty() + && !perms.has_channel_permission(ChannelPermission::MentionRoles) + { + return Err(create_error!(MissingPermission { + permission: ChannelPermission::MentionRoles.to_string() + })); + } } } @@ -363,6 +505,7 @@ impl Message { let recipients_hash: HashSet<&String, RandomState> = HashSet::from_iter(recipients); mentions.retain(|m| recipients_hash.contains(m)); + role_mentions.clear(); } Channel::TextChannel { ref server, .. } | Channel::VoiceChannel { ref server, .. } => { @@ -403,12 +546,27 @@ impl Message { message.mentions.replace(mentions.into_iter().collect()); } + if !role_mentions.is_empty() { + message + .role_mentions + .replace(role_mentions.into_iter().collect()); + } + if !replies.is_empty() { message .replies .replace(replies.into_iter().collect::>()); } + // Calculate final message flags + let mut flag_value = MessageFlagsValue(0); + flag_value + .set(MessageFlags::SuppressNotifications, suppress_notifications) + .set(MessageFlags::MentionsEveryone, mentions_everyone) + .set(MessageFlags::MentionsOnline, mentions_online); + + message.flags = Some(flag_value.0); + // Add attachments to message. let mut attachments = vec![]; if data @@ -487,7 +645,12 @@ impl Message { tasks::ack::queue_message( self.channel.to_string(), AckEvent::ProcessMessage { - messages: vec![(None, self.clone(), mentions.clone(), true)], + messages: vec![( + None, + self.clone(), + mentions.clone(), + self.has_suppressed_notifications(), + )], }, ) .await; @@ -531,7 +694,9 @@ impl Message { ) .await?; - if !self.has_suppressed_notifications() { + if !self.has_suppressed_notifications() + && (self.mentions.is_some() || self.contains_mass_push_mention()) + { // send Push notifications tasks::ack::queue_message( self.channel.to_string(), @@ -554,7 +719,7 @@ impl Message { } _ => vec![], }, - self.has_suppressed_notifications(), + false, // branch already dictates this )], }, ) @@ -591,13 +756,24 @@ impl Message { /// Whether this message has suppressed notifications pub fn has_suppressed_notifications(&self) -> bool { if let Some(flags) = self.flags { - flags & MessageFlags::SuppressNotifications as i32 - == MessageFlags::SuppressNotifications as i32 + flags & MessageFlags::SuppressNotifications as u32 + == MessageFlags::SuppressNotifications as u32 } else { false } } + pub fn contains_mass_push_mention(&self) -> bool { + let ping = if let Some(flags) = self.flags { + let flags = MessageFlagsValue(flags); + flags.has(MessageFlags::MentionsEveryone) + } else { + false + }; + + ping || self.role_mentions.is_some() + } + /// Update message data pub async fn update( &mut self, diff --git a/crates/core/database/src/models/messages/ops/mongodb.rs b/crates/core/database/src/models/messages/ops/mongodb.rs index 721a3b7c..449e71ef 100644 --- a/crates/core/database/src/models/messages/ops/mongodb.rs +++ b/crates/core/database/src/models/messages/ops/mongodb.rs @@ -228,7 +228,6 @@ impl AbstractMessages for MongoDb { "_id": id }, query, - None, ) .await .map(|_| ()) @@ -247,7 +246,6 @@ impl AbstractMessages for MongoDb { format!("reactions.{emoji}"): user } }, - None, ) .await .map(|_| ()) @@ -266,7 +264,6 @@ impl AbstractMessages for MongoDb { format!("reactions.{emoji}"): user } }, - None, ) .await .map(|_| ()) @@ -285,7 +282,6 @@ impl AbstractMessages for MongoDb { format!("reactions.{emoji}"): 1 } }, - None, ) .await .map(|_| ()) @@ -300,15 +296,12 @@ impl AbstractMessages for MongoDb { /// Delete messages from a channel by their ids and corresponding channel id async fn delete_messages(&self, channel: &str, ids: &[String]) -> Result<()> { self.col::(COL) - .delete_many( - doc! { - "channel": channel, - "_id": { - "$in": ids - } - }, - None, - ) + .delete_many(doc! { + "channel": channel, + "_id": { + "$in": ids + } + }) .await .map(|_| ()) .map_err(|_| create_database_error!("delete_many", COL)) @@ -362,7 +355,6 @@ impl MongoDb { "deleted": true } }, - None, ) .await .map_err(|_| create_database_error!("update_many", "attachments"))?; @@ -370,7 +362,7 @@ impl MongoDb { // And then delete said messages. self.col::(COL) - .delete_many(projection, None) + .delete_many(projection) .await .map(|_| ()) .map_err(|_| create_database_error!("delete_many", COL)) diff --git a/crates/core/database/src/models/ratelimit_events/ops/mongodb.rs b/crates/core/database/src/models/ratelimit_events/ops/mongodb.rs index ed6f0a1b..29edd64d 100644 --- a/crates/core/database/src/models/ratelimit_events/ops/mongodb.rs +++ b/crates/core/database/src/models/ratelimit_events/ops/mongodb.rs @@ -23,16 +23,13 @@ impl AbstractRatelimitEvents for MongoDb { count: usize, ) -> Result { self.col::(COL) - .count_documents( - doc! { - "_id": { - "$gte": Ulid::from_datetime(SystemTime::now() - period).to_string() - }, - "target_id": target_id, - "event_type": event_type.to_string() + .count_documents(doc! { + "_id": { + "$gte": Ulid::from_datetime(SystemTime::now() - period).to_string() }, - None, - ) + "target_id": target_id, + "event_type": event_type.to_string() + }) .await .map(|c| c as usize >= count) .map_err(|_| create_database_error!("count_documents", COL)) diff --git a/crates/core/database/src/models/server_members/ops.rs b/crates/core/database/src/models/server_members/ops.rs index 369f43e2..1d5a045f 100644 --- a/crates/core/database/src/models/server_members/ops.rs +++ b/crates/core/database/src/models/server_members/ops.rs @@ -1,3 +1,4 @@ +use ::mongodb::SessionCursor; use revolt_result::Result; use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember}; @@ -5,6 +6,66 @@ use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember}; mod mongodb; mod reference; +#[derive(Debug)] +pub enum ChunkedServerMembersGenerator { + #[cfg(feature = "mongodb")] + MongoDb { + session: ::mongodb::ClientSession, + cursor: Option>, + }, + + Reference { + offset: i32, + data: Option>, + }, +} + +impl ChunkedServerMembersGenerator { + #[cfg(feature = "mongodb")] + pub fn new_mongo(session: ::mongodb::ClientSession, cursor: SessionCursor) -> Self { + ChunkedServerMembersGenerator::MongoDb { + session, + cursor: Some(cursor), + } + } + + pub fn new_reference(data: Vec) -> Self { + ChunkedServerMembersGenerator::Reference { + offset: 0, + data: Some(data), + } + } + + pub async fn next(&mut self) -> Option { + match self { + #[cfg(feature = "mongodb")] + ChunkedServerMembersGenerator::MongoDb { session, cursor } => { + if let Some(cursor) = cursor { + let value = cursor.next(session).await; + value.map(|val| val.expect("Failed to fetch the next member")) + } else { + warn!("Attempted to access a (MongoDb) server member generator without first setting a cursor"); + None + } + } + ChunkedServerMembersGenerator::Reference { offset, data } => { + if let Some(data) = data { + if data.len() as i32 >= *offset { + None + } else { + let resp = &data[*offset as usize]; + *offset += 1; + Some(resp.clone()) + } + } else { + warn!("Attempted to access a (Reference) server member generator without first providing data"); + None + } + } + } + } +} + #[async_trait] pub trait AbstractServerMembers: Sync + Send { /// Insert a new server member into the database @@ -16,6 +77,24 @@ pub trait AbstractServerMembers: Sync + Send { /// Fetch all members in a server async fn fetch_all_members<'a>(&self, server_id: &str) -> Result>; + /// Fetch all members in a server as an iterator + async fn fetch_all_members_chunked( + &self, + server_id: &str, + ) -> Result; + + async fn fetch_all_members_with_roles( + &self, + server_id: &str, + roles: &[String], + ) -> Result>; + + async fn fetch_all_members_with_roles_chunked( + &self, + server_id: &str, + roles: &[String], + ) -> Result; + /// Fetch all memberships for a user async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result>; diff --git a/crates/core/database/src/models/server_members/ops/mongodb.rs b/crates/core/database/src/models/server_members/ops/mongodb.rs index 8ab52679..07d8a819 100644 --- a/crates/core/database/src/models/server_members/ops/mongodb.rs +++ b/crates/core/database/src/models/server_members/ops/mongodb.rs @@ -1,10 +1,11 @@ use futures::StreamExt; +use mongodb::options::ReadConcern; use revolt_result::Result; use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember}; use crate::{IntoDocumentPath, MongoDb}; -use super::AbstractServerMembers; +use super::{AbstractServerMembers, ChunkedServerMembersGenerator}; static COL: &str = "server_members"; @@ -33,12 +34,9 @@ impl AbstractServerMembers for MongoDb { async fn fetch_all_members<'a>(&self, server_id: &str) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id.server": server_id - }, - None, - ) + .find(doc! { + "_id.server": server_id + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { @@ -52,16 +50,101 @@ impl AbstractServerMembers for MongoDb { .await) } + /// Fetch all members in a server as a generator. + /// Uses config key pushd.mass_mention_chunk_size as the batch size. + async fn fetch_all_members_chunked( + &self, + server_id: &str, + ) -> Result { + let config = revolt_config::config().await; + + let mut session = self + .start_session() + .await + .map_err(|_| create_database_error!("start_session", COL))?; + + session + .start_transaction() + .read_concern(ReadConcern::snapshot()) + .await + .map_err(|_| create_database_error!("start_transaction", COL))?; + + let cursor = self + .col::(COL) + .find(doc! { + "_id.server": server_id + }) + .session(&mut session) + .batch_size(config.pushd.mass_mention_chunk_size as u32) + .await + .map_err(|_| create_database_error!("find", COL))?; + + Ok(ChunkedServerMembersGenerator::new_mongo(session, cursor)) + } + + async fn fetch_all_members_with_roles( + &self, + server_id: &str, + roles: &[String], + ) -> Result> { + Ok(self + .col::(COL) + .find(doc! { + "_id.server": server_id, + "roles": {"$in": roles} + }) + .await + .map_err(|_| create_database_error!("find", COL))? + .filter_map(|s| async { + if cfg!(debug_assertions) { + Some(s.unwrap()) + } else { + s.ok() + } + }) + .collect() + .await) + } + + async fn fetch_all_members_with_roles_chunked( + &self, + server_id: &str, + roles: &[String], + ) -> Result { + let config = revolt_config::config().await; + + let mut session = self + .start_session() + .await + .map_err(|_| create_database_error!("start_session", COL))?; + + session + .start_transaction() + .read_concern(ReadConcern::snapshot()) + .await + .map_err(|_| create_database_error!("start_transaction", COL))?; + + let cursor = self + .col::(COL) + .find(doc! { + "_id.server": server_id, + "roles": {"$in": roles} + }) + .session(&mut session) + .batch_size(config.pushd.mass_mention_chunk_size as u32) + .await + .map_err(|_| create_database_error!("find", COL))?; + + return Ok(ChunkedServerMembersGenerator::new_mongo(session, cursor)); + } + /// Fetch all memberships for a user async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id.user": user_id - }, - None, - ) + .find(doc! { + "_id.user": user_id + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { @@ -79,15 +162,12 @@ impl AbstractServerMembers for MongoDb { async fn fetch_members<'a>(&self, server_id: &str, ids: &'a [String]) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id.server": server_id, - "_id.user": { - "$in": ids - } - }, - None, - ) + .find(doc! { + "_id.server": server_id, + "_id.user": { + "$in": ids + } + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { @@ -104,12 +184,9 @@ impl AbstractServerMembers for MongoDb { /// Fetch member count of a server async fn fetch_member_count(&self, server_id: &str) -> Result { self.col::(COL) - .count_documents( - doc! { - "_id.server": server_id - }, - None, - ) + .count_documents(doc! { + "_id.server": server_id + }) .await .map(|c| c as usize) .map_err(|_| create_database_error!("count_documents", COL)) @@ -118,12 +195,9 @@ impl AbstractServerMembers for MongoDb { /// Fetch server count of a user async fn fetch_server_count(&self, user_id: &str) -> Result { self.col::(COL) - .count_documents( - doc! { - "_id.user": user_id - }, - None, - ) + .count_documents(doc! { + "_id.user": user_id + }) .await .map(|c| c as usize) .map_err(|_| create_database_error!("count_documents", COL)) diff --git a/crates/core/database/src/models/server_members/ops/reference.rs b/crates/core/database/src/models/server_members/ops/reference.rs index f038477e..ac15d977 100644 --- a/crates/core/database/src/models/server_members/ops/reference.rs +++ b/crates/core/database/src/models/server_members/ops/reference.rs @@ -3,7 +3,7 @@ use revolt_result::Result; use crate::ReferenceDb; use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember}; -use super::AbstractServerMembers; +use super::{AbstractServerMembers, ChunkedServerMembersGenerator}; #[async_trait] impl AbstractServerMembers for ReferenceDb { @@ -40,6 +40,70 @@ impl AbstractServerMembers for ReferenceDb { .collect()) } + /// Fetch all members in a server as an iterator + async fn fetch_all_members_chunked( + &self, + server_id: &str, + ) -> Result { + let server_members = self.server_members.lock().await; + + let members = server_members + .clone() + .into_values() + .filter(move |member| member.id.server == server_id) + .collect(); + + // this is inefficient as shit but its the reference db so its fine + Ok(ChunkedServerMembersGenerator::new_reference(members)) + } + + /// Fetch all members that have any of the roles given + async fn fetch_all_members_with_roles( + &self, + server_id: &str, + roles: &[String], + ) -> Result> { + let server_members = self.server_members.lock().await; + + Ok(server_members + .clone() + .into_values() + .filter(|member| { + member.id.server == server_id + && !member + .roles + .iter() + .filter(|p| roles.contains(*p)) + .collect::>() + .is_empty() + }) + .collect()) + } + + async fn fetch_all_members_with_roles_chunked( + &self, + server_id: &str, + roles: &[String], + ) -> Result { + let server_members = self.server_members.lock().await; + + let resp = server_members + .clone() + .into_values() + .filter(|member| { + member.id.server == server_id + && !member + .roles + .iter() + .filter(|p| roles.contains(*p)) + .collect::>() + .is_empty() + }) + .collect(); + + return Ok(ChunkedServerMembersGenerator::new_reference(resp)); + } + /// Fetch all memberships for a user async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result> { let server_members = self.server_members.lock().await; diff --git a/crates/core/database/src/models/servers/ops/mongodb.rs b/crates/core/database/src/models/servers/ops/mongodb.rs index e6bee03f..958963c9 100644 --- a/crates/core/database/src/models/servers/ops/mongodb.rs +++ b/crates/core/database/src/models/servers/ops/mongodb.rs @@ -25,14 +25,11 @@ impl AbstractServers for MongoDb { async fn fetch_servers<'a>(&self, ids: &'a [String]) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id": { - "$in": ids - } - }, - None, - ) + .find(doc! { + "_id": { + "$in": ids + } + }) .await .map_err(|_| create_database_error!("find", "servers"))? .filter_map(|s| async { @@ -84,7 +81,6 @@ impl AbstractServers for MongoDb { .map_err(|_| create_database_error!("to_document", "role"))? } }, - None, ) .await .map(|_| ()) @@ -125,7 +121,6 @@ impl AbstractServers for MongoDb { "roles": &role_id } }, - None, ) .await .map_err(|_| create_database_error!("update_many", "server_members"))?; @@ -140,7 +135,6 @@ impl AbstractServers for MongoDb { "role_permissions.".to_owned() + role_id: 1_i32 } }, - None, ) .await .map_err(|_| create_database_error!("update_one", "channels"))?; @@ -155,7 +149,6 @@ impl AbstractServers for MongoDb { "roles.".to_owned() + role_id: 1_i32 } }, - None, ) .await .map(|_| ()) @@ -188,12 +181,9 @@ impl MongoDb { // Find all channels let channels: Vec = self .col::("channels") - .find( - doc! { - "server": server_id - }, - None, - ) + .find(doc! { + "server": server_id + }) .await .map_err(|_| create_database_error!("find", "channels"))? .filter_map(|s| async { @@ -225,19 +215,15 @@ impl MongoDb { } } }, - None, ) .await .map_err(|_| create_database_error!("update_many", "emojis"))?; // Delete all channels. self.col::("channels") - .delete_many( - doc! { - "server": &server_id - }, - None, - ) + .delete_many(doc! { + "server": &server_id + }) .await .map_err(|_| create_database_error!("delete_many", "channels"))?; @@ -248,12 +234,9 @@ impl MongoDb { // Delete members and bans. for with in &["server_members", "server_bans"] { self.col::(with) - .delete_many( - doc! { - "_id.server": &server_id - }, - None, - ) + .delete_many(doc! { + "_id.server": &server_id + }) .await .map_err(|_| create_database_error!("delete_many", with))?; } diff --git a/crates/core/database/src/models/user_settings/ops/mongodb.rs b/crates/core/database/src/models/user_settings/ops/mongodb.rs index 5de98832..cf5bd762 100644 --- a/crates/core/database/src/models/user_settings/ops/mongodb.rs +++ b/crates/core/database/src/models/user_settings/ops/mongodb.rs @@ -53,8 +53,8 @@ impl AbstractUserSettings for MongoDb { doc! { "$set": set }, - UpdateOptions::builder().upsert(true).build(), ) + .with_options(UpdateOptions::builder().upsert(true).build()) .await .map(|_| ()) .map_err(|_| create_database_error!("update_one", "user_settings")) diff --git a/crates/core/database/src/models/users/ops/mongodb.rs b/crates/core/database/src/models/users/ops/mongodb.rs index ae61b029..000034c5 100644 --- a/crates/core/database/src/models/users/ops/mongodb.rs +++ b/crates/core/database/src/models/users/ops/mongodb.rs @@ -49,12 +49,9 @@ impl AbstractUsers for MongoDb { /// Fetch a session from the database by token async fn fetch_session_by_token(&self, token: &str) -> Result { self.col::("sessions") - .find_one( - doc! { - "token": token - }, - None, - ) + .find_one(doc! { + "token": token + }) .await .map_err(|_| create_database_error!("find_one", "sessions"))? .ok_or_else(|| create_error!(InvalidSession)) @@ -64,14 +61,11 @@ impl AbstractUsers for MongoDb { async fn fetch_users<'a>(&self, ids: &'a [String]) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "_id": { - "$in": ids - } - }, - None, - ) + .find(doc! { + "_id": { + "$in": ids + } + }) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { @@ -94,10 +88,10 @@ impl AbstractUsers for MongoDb { Ok(self .col::(COL) - .find( - doc! { - "username": username - }, + .find(doc! { + "username": username + }) + .with_options( FindOptions::builder() .collation( Collation::builder() @@ -122,15 +116,13 @@ impl AbstractUsers for MongoDb { async fn fetch_mutual_user_ids(&self, user_a: &str, user_b: &str) -> Result> { Ok(self .col::(COL) - .find( - doc! { - "$and": [ - { "relations": { "$elemMatch": { "_id": &user_a, "status": "Friend" } } }, - { "relations": { "$elemMatch": { "_id": &user_b, "status": "Friend" } } } - ] - }, - FindOptions::builder().projection(doc! { "_id": 1 }).build(), - ) + .find(doc! { + "$and": [ + { "relations": { "$elemMatch": { "_id": &user_a, "status": "Friend" } } }, + { "relations": { "$elemMatch": { "_id": &user_b, "status": "Friend" } } } + ] + }) + .with_options(FindOptions::builder().projection(doc! { "_id": 1 }).build()) .await .map_err(|_| create_database_error!("find", COL))? .filter_map(|s| async { s.ok() }) @@ -143,17 +135,15 @@ impl AbstractUsers for MongoDb { async fn fetch_mutual_channel_ids(&self, user_a: &str, user_b: &str) -> Result> { Ok(self .col::("channels") - .find( - doc! { - "channel_type": { - "$in": ["Group", "DirectMessage"] - }, - "recipients": { - "$all": [ user_a, user_b ] - } + .find(doc! { + "channel_type": { + "$in": ["Group", "DirectMessage"] }, - FindOptions::builder().projection(doc! { "_id": 1 }).build(), - ) + "recipients": { + "$all": [ user_a, user_b ] + } + }) + .with_options(FindOptions::builder().projection(doc! { "_id": 1 }).build()) .await .map_err(|_| create_database_error!("find", "channels"))? .filter_map(|s| async { s.ok() }) @@ -166,49 +156,46 @@ impl AbstractUsers for MongoDb { async fn fetch_mutual_server_ids(&self, user_a: &str, user_b: &str) -> Result> { Ok(self .col::("server_members") - .aggregate( - vec![ - doc! { - "$match": { - "_id.user": user_a - } - }, - doc! { - "$lookup": { - "from": "server_members", - "as": "members", - "let": { - "server": "$_id.server" - }, - "pipeline": [ - { - "$match": { - "$expr": { - "$and": [ - { "$eq": [ "$_id.user", user_b ] }, - { "$eq": [ "$_id.server", "$$server" ] } - ] - } + .aggregate(vec![ + doc! { + "$match": { + "_id.user": user_a + } + }, + doc! { + "$lookup": { + "from": "server_members", + "as": "members", + "let": { + "server": "$_id.server" + }, + "pipeline": [ + { + "$match": { + "$expr": { + "$and": [ + { "$eq": [ "$_id.user", user_b ] }, + { "$eq": [ "$_id.server", "$$server" ] } + ] } } - ] - } - }, - doc! { - "$match": { - "members": { - "$size": 1_i32 } + ] + } + }, + doc! { + "$match": { + "members": { + "$size": 1_i32 } - }, - doc! { - "$project": { - "_id": "$_id.server" - } - }, - ], - None, - ) + } + }, + doc! { + "$project": { + "_id": "$_id.server" + } + }, + ]) .await .map_err(|_| create_database_error!("aggregate", "server_members"))? .filter_map(|s| async { s.ok() }) @@ -284,7 +271,6 @@ impl AbstractUsers for MongoDb { } } }], - None, ) .await .map(|_| ()) @@ -305,7 +291,6 @@ impl AbstractUsers for MongoDb { } } }, - None, ) .await .map(|_| ()) @@ -329,7 +314,6 @@ impl AbstractUsers for MongoDb { "subscription": 1 } }, - None, ) .await .map(|_| ()) diff --git a/crates/core/database/src/tasks/ack.rs b/crates/core/database/src/tasks/ack.rs index 89971f66..1d2aff38 100644 --- a/crates/core/database/src/tasks/ack.rs +++ b/crates/core/database/src/tasks/ack.rs @@ -14,6 +14,7 @@ use validator::HasLen; use revolt_result::Result; use super::DelayedTask; +use crate::Channel::{TextChannel, VoiceChannel}; /// Enumeration of possible events #[derive(Debug, Eq, PartialEq)] @@ -120,17 +121,22 @@ pub async fn handle_ack_event( ); // find all the users we'll be notifying - messages - .iter() - .for_each(|(_, _, recipents, _)| users.extend(recipents.iter())); + messages.iter().for_each(|(_, _, recipents, _)| { + users.extend(recipents.iter()); + }); debug!("Found {} users to notify.", users.len()); for user in users { let message_ids: Vec = messages .iter() - .filter(|(_, _, recipients, _)| recipients.contains(user)) - .map(|(_, message, _, _)| message.id.clone()) + .filter_map(|(_, message, recipients, _)| { + if recipients.contains(user) { + Some(message.id.clone()) + } else { + None + } + }) .collect(); if !message_ids.is_empty() { @@ -140,13 +146,18 @@ pub async fn handle_ack_event( debug!("Added {} mentions for user {}", message_ids.len(), &user); } - for (push, _, recipients, silenced) in messages { - if *silenced || recipients.is_empty() || push.is_none() { + let mut mass_mentions = vec![]; + + for (push, message, recipients, silenced) in messages { + if *silenced + || push.is_none() + || (recipients.is_empty() && !message.contains_mass_push_mention()) + { debug!( "Rejecting push: silenced: {}, recipient count: {}, push exists: {:?}", *silenced, recipients.length(), - push + push.is_some() ); continue; } @@ -162,6 +173,35 @@ pub async fn handle_ack_event( { revolt_config::capture_error(&err); } + + if message.contains_mass_push_mention() { + mass_mentions.push(push.clone().unwrap()); + } + } + + if !mass_mentions.is_empty() { + debug!( + "Sending mass mention push event to AMQP; channel {}", + &mass_mentions[0].message.channel + ); + + let channel = db + .fetch_channel(&mass_mentions[0].message.channel) + .await + .expect("Failed to fetch channel from db"); + + match channel { + TextChannel { server, .. } | VoiceChannel { server, .. } => { + if let Err(err) = + amqp.mass_mention_message_sent(server, mass_mentions).await + { + revolt_config::capture_error(&err); + } + } + _ => { + panic!("Unknown channel type when sending mass mention event"); + } + } } } }; @@ -192,7 +232,7 @@ pub async fn worker(db: Database, amqp: AMQP) { revolt_config::capture_error(&err); error!("{err:?} for {event:?}. ({user:?}, {channel})"); } else { - info!("User {user:?} ack in {channel} with {event:?}"); + debug!("User {user:?} ack in {channel} with {event:?}"); } } } @@ -224,6 +264,12 @@ pub async fn worker(db: Database, amqp: AMQP) { // add the new message to the list of messages to be processed. existing.append(new_data); + // if the message contains a mass mention, do not delay it any further. + if new_data[0].1.contains_mass_push_mention() { + task.run_immediately(); + continue; + } + // put a cap on the amount of messages that can be queued, for particularly active channels if (existing.length() as u16) < revolt_config::config() diff --git a/crates/core/database/src/tasks/mod.rs b/crates/core/database/src/tasks/mod.rs index 81bfd4e1..111d5106 100644 --- a/crates/core/database/src/tasks/mod.rs +++ b/crates/core/database/src/tasks/mod.rs @@ -26,6 +26,7 @@ pub fn start_workers(db: Database, amqp: AMQP) { /// Task with additional information on when it should run pub struct DelayedTask { pub data: T, + run_now: bool, last_updated: Instant, first_seen: Instant, } @@ -41,6 +42,7 @@ impl DelayedTask { pub fn new(data: T) -> Self { DelayedTask { data, + run_now: false, last_updated: Instant::now(), first_seen: Instant::now(), } @@ -51,9 +53,15 @@ impl DelayedTask { self.last_updated = Instant::now() } + /// Flag the task to run right away, regardless of the time + pub fn run_immediately(&mut self) { + self.run_now = true + } + /// Check if a task should run yet pub fn should_run(&self) -> bool { - self.first_seen.elapsed().as_secs() > EXPIRE_CONSTANT + self.run_now + || self.first_seen.elapsed().as_secs() > EXPIRE_CONSTANT || self.last_updated.elapsed().as_secs() > SAVE_CONSTANT } } diff --git a/crates/core/database/src/util/bridge/v0.rs b/crates/core/database/src/util/bridge/v0.rs index f6d96b14..c047b03d 100644 --- a/crates/core/database/src/util/bridge/v0.rs +++ b/crates/core/database/src/util/bridge/v0.rs @@ -483,6 +483,7 @@ impl crate::Message { edited: self.edited, embeds: self.embeds, mentions: self.mentions, + role_mentions: self.role_mentions, replies: self.replies, reactions: self.reactions, interactions: self.interactions.into(), @@ -511,6 +512,7 @@ impl From for PartialMessage { edited: value.edited, embeds: value.embeds, mentions: value.mentions, + role_mentions: value.role_mentions, replies: value.replies, reactions: value.reactions, interactions: value.interactions.map(Into::into), diff --git a/crates/core/database/src/util/bulk_permissions.rs b/crates/core/database/src/util/bulk_permissions.rs index 40035977..928acfce 100644 --- a/crates/core/database/src/util/bulk_permissions.rs +++ b/crates/core/database/src/util/bulk_permissions.rs @@ -94,9 +94,28 @@ impl<'z> BulkDatabasePermissionQuery<'z> { } } + pub async fn from_channel_id(self, channel_id: String) -> BulkDatabasePermissionQuery<'z> { + let channel = self + .database + .fetch_channel(channel_id.as_str()) + .await + .expect("Valid channel id"); + + drop(channel_id); + + BulkDatabasePermissionQuery { + channel: Some(channel), + ..self + } + } + pub fn members(self, members: &'z [Member]) -> BulkDatabasePermissionQuery { BulkDatabasePermissionQuery { members: Some(members.to_owned()), + cached_member_perms: None, + users: None, + cached_members: None, + cached_users: None, ..self } } @@ -104,6 +123,10 @@ impl<'z> BulkDatabasePermissionQuery<'z> { pub fn users(self, users: &'z [User]) -> BulkDatabasePermissionQuery { BulkDatabasePermissionQuery { users: Some(users.to_owned()), + cached_member_perms: None, + members: None, + cached_members: None, + cached_users: None, ..self } } diff --git a/crates/core/models/Cargo.toml b/crates/core/models/Cargo.toml index b3bbd409..1d4c5db0 100644 --- a/crates/core/models/Cargo.toml +++ b/crates/core/models/Cargo.toml @@ -24,9 +24,11 @@ revolt-config = { version = "0.8.4", path = "../config" } revolt-permissions = { version = "0.8.4", path = "../permissions" } # Utility -regex = "1" +regex = "1.11" +fancy-regex = "0.14" indexmap = "1.9.3" once_cell = "1.17.1" +num_enum = "0.6.1" # Rocket rocket = { optional = true, version = "0.5.0-rc.2", default-features = false } diff --git a/crates/core/models/src/v0/messages.rs b/crates/core/models/src/v0/messages.rs index f431f43c..0c02903d 100644 --- a/crates/core/models/src/v0/messages.rs +++ b/crates/core/models/src/v0/messages.rs @@ -1,8 +1,8 @@ use std::time::SystemTime; +use fancy_regex::Regex; use indexmap::{IndexMap, IndexSet}; use once_cell::sync::Lazy; -use regex::Regex; use revolt_config::config; #[cfg(feature = "validator")] @@ -18,6 +18,12 @@ use super::{Channel, Embed, File, Member, MessageWebhook, User, Webhook, RE_COLO pub static RE_MENTION: Lazy = Lazy::new(|| Regex::new(r"<@([0-9A-HJKMNP-TV-Z]{26})>").unwrap()); +pub static RE_ROLE_MENTION: Lazy = + Lazy::new(|| Regex::new(r"<%([0-9A-HJKMNP-TV-Z]{26})>|@online|@everyone").unwrap()); + +pub static RE_BLOCKS: Lazy = + Lazy::new(|| Regex::new(r"(?s)(?>, + /// Array of role ids mentioned in this message + pub role_mentions: Option>, /// Array of message ids this message is replying to #[serde(skip_serializing_if = "Option::is_none")] pub replies: Option>, @@ -371,6 +379,11 @@ auto_derived!( pub enum MessageFlags { /// Message will not send push / desktop notifications SuppressNotifications = 1, + /// Message will mention all users who can see the channel + MentionsEveryone = 2, + /// Message will mention all users who are online and can see the channel. + /// This cannot be true if MentionsEveryone is true + MentionsOnline = 3, } /// Optional fields on message diff --git a/crates/core/permissions/src/models/channel.rs b/crates/core/permissions/src/models/channel.rs index 17762b1e..aca22b5c 100644 --- a/crates/core/permissions/src/models/channel.rs +++ b/crates/core/permissions/src/models/channel.rs @@ -90,8 +90,14 @@ pub enum ChannelPermission { /// Move members between voice channels MoveMembers = 1 << 35, + // * Channel permissions two electric boogaloo + /// Mention everyone and online members + MentionEveryone = 1 << 37, + /// Mention roles + MentionRoles = 1 << 38, + // * Misc. permissions - // % Bits 36 to 52: free area + // % Bits 38 to 52: free area // % Bits 53 to 64: do not use // * Grant all permissions diff --git a/crates/core/result/src/axum.rs b/crates/core/result/src/axum.rs index 8c4c6491..e4caf818 100644 --- a/crates/core/result/src/axum.rs +++ b/crates/core/result/src/axum.rs @@ -1,5 +1,4 @@ use axum::{http::StatusCode, response::IntoResponse, Json}; -use rocket::http::Status; use crate::{Error, ErrorType}; @@ -52,6 +51,7 @@ impl IntoResponse for Error { ErrorType::ReachedMaximumBots => StatusCode::BAD_REQUEST, ErrorType::IsBot => StatusCode::BAD_REQUEST, + ErrorType::IsNotBot => StatusCode::BAD_REQUEST, ErrorType::BotIsPrivate => StatusCode::FORBIDDEN, ErrorType::CannotReportYourself => StatusCode::BAD_REQUEST, @@ -75,6 +75,8 @@ impl IntoResponse for Error { ErrorType::NotFound => StatusCode::NOT_FOUND, ErrorType::NoEffect => StatusCode::OK, ErrorType::FailedValidation { .. } => StatusCode::BAD_REQUEST, + ErrorType::InvalidFlagValue => StatusCode::BAD_REQUEST, + ErrorType::FeatureDisabled { .. } => StatusCode::BAD_REQUEST, ErrorType::ProxyError => StatusCode::BAD_REQUEST, ErrorType::FileTooSmall => StatusCode::UNPROCESSABLE_ENTITY, diff --git a/crates/core/result/src/lib.rs b/crates/core/result/src/lib.rs index 4d5e1c65..10b56d5d 100644 --- a/crates/core/result/src/lib.rs +++ b/crates/core/result/src/lib.rs @@ -121,6 +121,7 @@ pub enum ErrorType { // ? Bot related errors ReachedMaximumBots, IsBot, + IsNotBot, BotIsPrivate, // ? User safety related errors @@ -148,6 +149,7 @@ pub enum ErrorType { InvalidCredentials, InvalidProperty, InvalidSession, + InvalidFlagValue, NotAuthenticated, DuplicateNonce, NotFound, @@ -168,6 +170,11 @@ pub enum ErrorType { // ? Legacy errors VosoUnavailable, + + // ? Feature flag disabled in the config + FeatureDisabled { + feature: String, + }, } #[macro_export] diff --git a/crates/core/result/src/rocket.rs b/crates/core/result/src/rocket.rs index 6b889c58..1d996a17 100644 --- a/crates/core/result/src/rocket.rs +++ b/crates/core/result/src/rocket.rs @@ -42,6 +42,7 @@ impl<'r> Responder<'r, 'static> for Error { ErrorType::NotInGroup => Status::NotFound, ErrorType::AlreadyPinned => Status::BadRequest, ErrorType::NotPinned => Status::BadRequest, + ErrorType::InvalidFlagValue => Status::BadRequest, ErrorType::UnknownServer => Status::NotFound, ErrorType::InvalidRole => Status::NotFound, @@ -57,6 +58,7 @@ impl<'r> Responder<'r, 'static> for Error { ErrorType::ReachedMaximumBots => Status::BadRequest, ErrorType::IsBot => Status::BadRequest, + ErrorType::IsNotBot => Status::BadRequest, ErrorType::BotIsPrivate => Status::Forbidden, ErrorType::CannotReportYourself => Status::BadRequest, @@ -80,6 +82,7 @@ impl<'r> Responder<'r, 'static> for Error { ErrorType::NotFound => Status::NotFound, ErrorType::NoEffect => Status::Ok, ErrorType::FailedValidation { .. } => Status::BadRequest, + ErrorType::FeatureDisabled { .. } => Status::BadRequest, ErrorType::ProxyError => Status::BadRequest, ErrorType::FileTooSmall => Status::UnprocessableEntity, diff --git a/crates/daemons/pushd/Cargo.toml b/crates/daemons/pushd/Cargo.toml index dad79cf3..441fa87f 100644 --- a/crates/daemons/pushd/Cargo.toml +++ b/crates/daemons/pushd/Cargo.toml @@ -10,6 +10,9 @@ revolt-database = { version = "0.8.4", path = "../../core/database" } revolt-models = { version = "0.8.4", path = "../../core/models", features = [ "validator", ] } +revolt-presence = { version = "0.8.1", path = "../../core/presence", features = [ + "redis-is-patched", +] } amqprs = { version = "1.7.0" } fcm_v1 = "0.3.0" @@ -20,9 +23,10 @@ tokio = "1.39.2" async-trait = "0.1.81" ulid = "1.0.0" -authifier = "1.0.8" +authifier = "1.0.10" log = "0.4.11" +pretty_env_logger = "0.4.0" #serialization serde_json = "1" diff --git a/crates/daemons/pushd/Pushd Flowchart.graffle b/crates/daemons/pushd/Pushd Flowchart.graffle index 961d5ff61319007beb4e3d9008c648c11425f422..d15942df129b6560f014c7308ee479f31cbba40e 100644 GIT binary patch literal 52601 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 diff --git a/crates/daemons/pushd/src/consumers/inbound/ack.rs b/crates/daemons/pushd/src/consumers/inbound/ack.rs index b9fe0886..77dd5d44 100644 --- a/crates/daemons/pushd/src/consumers/inbound/ack.rs +++ b/crates/daemons/pushd/src/consumers/inbound/ack.rs @@ -71,8 +71,14 @@ impl AsyncConsumer for AckConsumer { #[allow(clippy::disallowed_methods)] let unreads = self.db.fetch_unread_mentions(&payload.user_id).await; + debug!("Processing unreads for {:}", &payload.user_id); + if let Ok(u) = &unreads { if u.is_empty() { + debug!( + "Discarding unread task (no mentions found) for {:}", + &payload.user_id + ); return; } } else { @@ -95,6 +101,10 @@ impl AsyncConsumer for AckConsumer { .collect(); if apple_sessions.is_empty() { + debug!( + "Discarding unread task (no apn sessions found) for {:}", + &payload.user_id + ); return; } diff --git a/crates/daemons/pushd/src/consumers/inbound/mass_mention.rs b/crates/daemons/pushd/src/consumers/inbound/mass_mention.rs new file mode 100644 index 00000000..a44dcb1e --- /dev/null +++ b/crates/daemons/pushd/src/consumers/inbound/mass_mention.rs @@ -0,0 +1,275 @@ +use std::{ + collections::{HashMap, HashSet}, + hash::RandomState, +}; + +use crate::consumers::inbound::internal::*; +use amqprs::{ + channel::{BasicPublishArguments, Channel}, + connection::Connection, + consumer::AsyncConsumer, + BasicProperties, Deliver, +}; +use async_trait::async_trait; +use revolt_database::{ + events::rabbit::*, util::bulk_permissions::BulkDatabasePermissionQuery, Database, Member, + MessageFlagsValue, +}; +use revolt_models::v0::{MessageFlags, PushNotification}; + +pub struct MassMessageConsumer { + #[allow(dead_code)] + db: Database, + authifier_db: authifier::Database, + conn: Option, + channel: Option, +} + +impl Channeled for MassMessageConsumer { + fn get_connection(&self) -> Option<&Connection> { + if self.conn.is_none() { + None + } else { + Some(self.conn.as_ref().unwrap()) + } + } + + fn get_channel(&self) -> Option<&Channel> { + if self.channel.is_none() { + None + } else { + Some(self.channel.as_ref().unwrap()) + } + } + + fn set_connection(&mut self, conn: Connection) { + self.conn = Some(conn); + } + + fn set_channel(&mut self, channel: Channel) { + self.channel = Some(channel) + } +} + +impl MassMessageConsumer { + pub fn new(db: Database, authifier_db: authifier::Database) -> MassMessageConsumer { + MassMessageConsumer { + db, + authifier_db, + conn: None, + channel: None, + } + } + + async fn fire_notification_for_users(&mut self, push: &PushNotification, users: &[String]) { + if let Ok(sessions) = self + .authifier_db + .find_sessions_with_subscription(users) + .await + { + let config = revolt_config::config().await; + for session in sessions { + if let Some(sub) = session.subscription { + let mut sendable = PayloadToService { + notification: PayloadKind::MessageNotification(push.clone()), + token: sub.auth, + user_id: session.user_id, + session_id: session.id, + extras: HashMap::new(), + }; + + let args: BasicPublishArguments; + + if sub.endpoint == "apn" { + args = BasicPublishArguments::new( + config.pushd.exchange.as_str(), + config.pushd.apn.queue.as_str(), + ) + .finish(); + } else if sub.endpoint == "fcm" { + args = BasicPublishArguments::new( + config.pushd.exchange.as_str(), + config.pushd.fcm.queue.as_str(), + ) + .finish(); + } else { + // web push (vapid) + args = BasicPublishArguments::new( + config.pushd.exchange.as_str(), + config.pushd.vapid.queue.as_str(), + ) + .finish(); + sendable.extras.insert("p265dh".to_string(), sub.p256dh); + sendable + .extras + .insert("endpoint".to_string(), sub.endpoint.clone()); + } + + let payload = serde_json::to_string(&sendable).unwrap(); + + publish_message(self, payload.into(), args).await; + } + } + } + } +} + +#[allow(unused_variables)] +#[async_trait] +impl AsyncConsumer for MassMessageConsumer { + /// This consumer handles adding mentions for all the users affected by a mass mention ping, and then sends out push notifications + async fn consume( + &mut self, + channel: &Channel, + deliver: Deliver, + basic_properties: BasicProperties, + content: Vec, + ) { + let config = revolt_config::config().await; + let content = String::from_utf8(content).unwrap(); + let payload: MassMessageSentPayload = serde_json::from_str(content.as_str()).unwrap(); + + debug!("Received mass message event"); + + // We should only ever receive clumped messages from a single channel, so it's safe to reuse this many times. + let mut query: Option> = None; + let query_db = self.db.clone(); + + for push in payload.notifications { + if query.is_none() { + query = Some( + BulkDatabasePermissionQuery::from_server_id(&query_db, &payload.server_id) + .await + .from_channel_id(push.channel.id().to_string()) // wrong channel model, so fetch the right one + .await, + ); + } + + let existing_mentions: HashSet = + if let Some(ref mentions) = push.message.mentions { + HashSet::from_iter(mentions.iter().cloned()) + } else { + HashSet::new() + }; + + // KNOWN QUIRK: if you mention @online and role(s), the offline members with the role(s) wont get pinged + if let Some(ref query) = query { + let flags = MessageFlagsValue(push.message.flags); + if flags.has(MessageFlags::MentionsEveryone) { + let mut db_query = self + .db + .fetch_all_members_chunked(&payload.server_id) + .await + .expect("Failed to fetch members from database"); + + let mut exhausted = false; + let ack_chnl = vec![push.channel.id().to_string()]; + loop { + let mut chunk: Vec = vec![]; + for _ in 0..config.pushd.mass_mention_chunk_size { + if let Some(member) = db_query.next().await { + chunk.push(member); + } else { + exhausted = true; + break; + } + } + + let userids: Vec = + chunk.iter().map(|member| member.id.user.clone()).collect(); + + debug!("Userids in chunk: {:?}", userids); + + if let Err(err) = self + .db + .add_mention_to_many_unreads(push.channel.id(), &userids, &ack_chnl) + .await + { + revolt_config::capture_error(&err); + } + + // ignore anyone in this list + let online_users = revolt_presence::filter_online(&userids).await; + let target_users: Vec = userids + .iter() + .filter(|id| { + !online_users.contains(*id) && !existing_mentions.contains(*id) + }) + .cloned() + .collect(); + + debug!( + "Userids after filter: {:?} (online: {:?}", + target_users, online_users + ); + + self.fire_notification_for_users(&push, &target_users).await; + + if exhausted { + break; + } + } + } else if let Some(roles) = &push.message.role_mentions { + // role mentions + let _role_members = self + .db + .fetch_all_members_with_roles_chunked(&payload.server_id, roles) + .await; + + debug!("role members: {:?}", _role_members); + + if _role_members.is_err() { + revolt_config::capture_error(&_role_members.err().unwrap()); + return; + } + + let mut role_members = _role_members.unwrap(); + let mut chunk = vec![]; + let mut exhausted = false; + + while !exhausted { + chunk.clear(); + + for _ in 0..config.pushd.mass_mention_chunk_size { + if let Some(member) = role_members.next().await { + chunk.push(member); + } else { + exhausted = true; + break; + } + } + + let mut q = query.clone().members(&chunk); + let viewing_members: Vec = q + .members_can_see_channel() + .await + .iter() + .filter_map(|(uid, viewable)| { + if *viewable && !existing_mentions.contains(uid) { + Some(uid.clone()) + } else { + None + } + }) + .collect(); + + debug!("viewing members: {:?}", viewing_members); + + let online = revolt_presence::filter_online(&viewing_members).await; + debug!("online: {:?}", online); + + let targets: Vec = viewing_members + .iter() + .filter(|m| !online.contains(*m)) + .cloned() + .collect(); + + debug!("targets: {:?}", targets); + + self.fire_notification_for_users(&push, &targets).await; + } + } + } + } + } +} diff --git a/crates/daemons/pushd/src/consumers/inbound/mod.rs b/crates/daemons/pushd/src/consumers/inbound/mod.rs index a340143d..9c359336 100644 --- a/crates/daemons/pushd/src/consumers/inbound/mod.rs +++ b/crates/daemons/pushd/src/consumers/inbound/mod.rs @@ -3,4 +3,5 @@ pub mod fr_accepted; pub mod fr_received; pub mod generic; mod internal; +pub mod mass_mention; pub mod message; diff --git a/crates/daemons/pushd/src/consumers/outbound/apn.rs b/crates/daemons/pushd/src/consumers/outbound/apn.rs index 3b6ac3a7..f9a09cc8 100644 --- a/crates/daemons/pushd/src/consumers/outbound/apn.rs +++ b/crates/daemons/pushd/src/consumers/outbound/apn.rs @@ -81,7 +81,7 @@ impl ApnsOutboundConsumer { } } - println!("Got badge count for APN: {}", mention_count); + debug!("Got badge count for APN: {}", mention_count); return Some(mention_count); } @@ -188,6 +188,10 @@ impl AsyncConsumer for ApnsOutboundConsumer { data: BTreeMap::new(), }; + debug!( + "Sending friend request received for user: {:}", + &payload.user_id + ); resp = self.client.send(apn_payload).await; } @@ -230,6 +234,10 @@ impl AsyncConsumer for ApnsOutboundConsumer { data: BTreeMap::new(), }; + debug!( + "Sending friend request accept for user: {:}", + &payload.user_id + ); resp = self.client.send(apn_payload).await; } PayloadKind::Generic(alert) => { @@ -259,6 +267,10 @@ impl AsyncConsumer for ApnsOutboundConsumer { data: BTreeMap::new(), }; + debug!( + "Sending generic notification for user: {:}", + &payload.user_id + ); resp = self.client.send(apn_payload).await; } @@ -294,6 +306,10 @@ impl AsyncConsumer for ApnsOutboundConsumer { channel_name: alert.channel.name().unwrap_or(&title), }; + debug!( + "Sending message notification for user: {:}", + &payload.user_id + ); resp = self.client.send(apn_payload).await; } PayloadKind::BadgeUpdate(badge) => { @@ -307,6 +323,7 @@ impl AsyncConsumer for ApnsOutboundConsumer { data: BTreeMap::new(), }; + debug!("Sending badge update for user: {:}", &payload.user_id); resp = self.client.send(apn_payload).await; } } @@ -321,6 +338,10 @@ impl AsyncConsumer for ApnsOutboundConsumer { }), .. }) => { + info!( + "Removing APNS subscription id {:} (user: {:}) due to invalid token", + &payload.session_id, &payload.user_id + ); if let Err(err) = self .db .remove_push_subscription_by_session_id(&payload.session_id) diff --git a/crates/daemons/pushd/src/main.rs b/crates/daemons/pushd/src/main.rs index c63b8d9a..1560b049 100644 --- a/crates/daemons/pushd/src/main.rs +++ b/crates/daemons/pushd/src/main.rs @@ -1,3 +1,6 @@ +#[macro_use] +extern crate log; + use amqprs::{ channel::{ BasicConsumeArguments, Channel, ExchangeDeclareArguments, QueueBindArguments, @@ -14,7 +17,7 @@ mod consumers; use consumers::{ inbound::{ ack::AckConsumer, fr_accepted::FRAcceptedConsumer, fr_received::FRReceivedConsumer, - generic::GenericConsumer, message::MessageConsumer, + generic::GenericConsumer, mass_mention::MassMessageConsumer, message::MessageConsumer, }, outbound::{apn::ApnsOutboundConsumer, fcm::FcmOutboundConsumer, vapid::VapidOutboundConsumer}, }; @@ -22,6 +25,7 @@ use consumers::{ #[tokio::main(flavor = "multi_thread", worker_threads = 2)] async fn main() { let config = config().await; + pretty_env_logger::init(); // Setup database let db = revolt_database::DatabaseInfo::Auto.connect().await.unwrap(); @@ -96,6 +100,17 @@ async fn main() { .await, ); + connections.push( + make_queue_and_consume( + &config, + &config.pushd.mass_mention_queue, + config.pushd.get_mass_mention_routing_key().as_str(), + None, + MassMessageConsumer::new(db.clone(), authifier.clone()), + ) + .await, + ); + if !config.pushd.apn.pkcs8.is_empty() { connections.push( make_queue_and_consume( @@ -223,11 +238,10 @@ where .manual_ack(false) .finish(); - channel.basic_consume(consumer, args).await.unwrap(); - log::info!( - "Consuming routing key {} as queue {}", - routing_key, - queue_name + let routing_key = channel.basic_consume(consumer, args).await.unwrap(); + info!( + "Consuming routing key {} as queue {}, tag {}", + routing_key, queue_name, routing_key ); (channel, connection) } diff --git a/crates/delta/Cargo.toml b/crates/delta/Cargo.toml index 0ff6006d..536276aa 100644 --- a/crates/delta/Cargo.toml +++ b/crates/delta/Cargo.toml @@ -55,7 +55,7 @@ lettre = "0.10.0-alpha.4" rocket = { version = "0.5.1", default-features = false, features = ["json"] } rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "072d90359b23e9b291df6b672c07c93de9c46011" } rocket_empty = { version = "0.1.1", features = ["schema"] } -rocket_authifier = { version = "1.0.9" } +rocket_authifier = { version = "1.0.10" } rocket_prometheus = "0.10.0-rc.3" # spec generation @@ -66,7 +66,7 @@ revolt_rocket_okapi = { version = "0.10.0", features = ["swagger"] } amqprs = { version = "1.7.0" } # core -authifier = "1.0.9" +authifier = "1.0.10" revolt-config = { path = "../core/config" } revolt-database = { path = "../core/database", features = [ "rocket-impl", diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index 421175a8..9fd3065c 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -117,10 +117,11 @@ mod test { use crate::{rocket, util::test::TestHarness}; use revolt_database::{ util::{idempotency::IdempotencyKey, reference::Reference}, - Channel, Member, Message, PartialChannel, PartialMember, Role, Server, + Channel, Member, Message, MessageFlagsValue, PartialChannel, PartialMember, Role, Server, }; - use revolt_models::v0::{self, DataCreateServerChannel}; + use revolt_models::v0::{self, DataCreateServerChannel, MessageFlags}; use revolt_permissions::{ChannelPermission, OverrideField}; + use revolt_result::ErrorType; #[rocket::async_test] async fn message_mention_constraints() { @@ -482,4 +483,193 @@ mod test { .await .expect_err("Created message with missing reply and none fail"); } + + #[rocket::async_test] + async fn mass_mentions_test() { + let harness = TestHarness::new().await; + let (_, _, user) = harness.new_user().await; + let (_, _, other_user) = harness.new_user().await; + let (server, _) = harness.new_server(&user).await; + let channel = harness.new_channel(&server).await; + let (role_id, mut role) = harness + .new_role( + &server, + 1, + Some(OverrideField { + a: (ChannelPermission::MentionEveryone as i64) + | (ChannelPermission::MentionRoles as i64), + d: 0, + }), + ) + .await; + let (mut other_member, _) = Member::create(&harness.db, &server, &other_user, None) + .await + .expect("Failed to add test member"); + + // Send a message with an everyone and role mention. + // Should fail + let bad_message_with_mentions = Message::create_from_api( + &harness.db, + Some(&harness.amqp), + channel.clone(), + v0::DataMessageSend { + content: Some(format!("Mentioning @everyone and role <%{}>", &role_id)), + nonce: None, + attachments: None, + replies: None, + embeds: None, + masquerade: None, + interactions: None, + flags: None, + }, + v0::MessageAuthor::User( + &other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some( + other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some(other_member.clone().into()), + other_user.limits().await, + IdempotencyKey::unchecked_from_string("1".to_string()), + false, + true, + ) + .await + .expect_err("Should not have created message with everyone and role pings"); + + assert!( + matches!( + bad_message_with_mentions.error_type, + ErrorType::MissingPermission { .. } + ), + "Intentional permissions error did not return MissingPermission" + ); + + // Send a mass mention inside a codeblock. + // Should be undetected and therefor pass + let message_with_codeblock = Message::create_from_api( + &harness.db, + Some(&harness.amqp), + channel.clone(), + v0::DataMessageSend { + content: Some(format!("Mentioning `@everyone` and role `<%{}>`", &role_id)), + nonce: None, + attachments: None, + replies: None, + embeds: None, + masquerade: None, + interactions: None, + flags: None, + }, + v0::MessageAuthor::User( + &other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some( + other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some(other_member.clone().into()), + other_user.limits().await, + IdempotencyKey::unchecked_from_string("1".to_string()), + false, + true, + ) + .await + .expect("Failed to create message with everyone and role pings in codeblocks"); + + assert!( + message_with_codeblock.flags.is_none() + || !MessageFlagsValue(message_with_codeblock.flags.unwrap()) + .has(MessageFlags::MentionsEveryone), + "Message flags mentions everyone when inside codeblock", + ); + + assert!( + message_with_codeblock.role_mentions.is_none(), + "Role mentions detected when inside codeblock" + ); + + other_member.roles.push(role_id.clone()); + harness + .db + .update_member( + &other_member.id, + &PartialMember { + avatar: None, + id: None, + joined_at: None, + nickname: None, + roles: Some(vec![role_id.clone()]), + timeout: None, + }, + vec![], + ) + .await + .expect("Failed to add role to user"); + + // Send a message with an everyone and role mention. + // Should succeed + let message_with_mentions = Message::create_from_api( + &harness.db, + Some(&harness.amqp), + channel.clone(), + v0::DataMessageSend { + content: Some(format!("Mentioning @everyone and role <%{}>", &role_id)), + nonce: None, + attachments: None, + replies: None, + embeds: None, + masquerade: None, + interactions: None, + flags: None, + }, + v0::MessageAuthor::User( + &other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some( + other_user + .clone() + .into(&harness.db, Some(&other_user)) + .await, + ), + Some(other_member.clone().into()), + other_user.limits().await, + IdempotencyKey::unchecked_from_string("1".to_string()), + false, + true, + ) + .await + .expect("Failed to create message with everyone and role pings"); + + assert!( + message_with_mentions.flags.is_some(), + "Message flags is None", + ); + + assert!( + MessageFlagsValue(message_with_mentions.flags.unwrap()) + .has(MessageFlags::MentionsEveryone), + "Message flags does not mention everyone. Flag value is {}", + message_with_mentions.flags.unwrap() + ); + + assert!( + message_with_mentions.role_mentions.is_some(), + "Message has no role mentions" + ); + } } diff --git a/crates/delta/src/util/test.rs b/crates/delta/src/util/test.rs index 533db2ac..98254e47 100644 --- a/crates/delta/src/util/test.rs +++ b/crates/delta/src/util/test.rs @@ -5,11 +5,12 @@ use authifier::{ use futures::StreamExt; use rand::Rng; use redis_kiss::redis::aio::PubSub; -use revolt_database::util::idempotency::IdempotencyKey; use revolt_database::{ events::client::EventV1, Channel, Database, Member, Message, Server, User, AMQP, }; +use revolt_database::{util::idempotency::IdempotencyKey, Role}; use revolt_models::v0; +use revolt_permissions::OverrideField; use rocket::http::Header; use rocket::local::asynchronous::{Client, LocalRequest, LocalResponse}; @@ -122,6 +123,28 @@ impl TestHarness { .expect("Failed to create test server") } + pub async fn new_role( + &self, + server: &Server, + rank: i64, + overrides: Option, + ) -> (String, Role) { + let role = Role { + name: TestHarness::rand_string(), + permissions: overrides.unwrap_or(OverrideField { a: 0, d: 0 }), + rank, + colour: None, + hoist: false, + }; + + let id = role + .create(&self.db, &server.id) + .await + .expect("Failed to create test role"); + + (id, role) + } + pub async fn new_channel(&self, server: &Server) -> Channel { Channel::create_server_channel( &self.db,