diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index f4969ec59..44b82ff15 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -93,16 +93,16 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest] - node-version: [14.0, 16.0, 18.0, 19.0] + node-version: [16.0, 18.0, 19.0, 20.0] include: - os: ubuntu-latest os-name: 🐧 - os: macos-latest os-name: 🍏 - node-version: 18.0 + node-version: 20.0 - - node-version: 18.0 + - node-version: 20.0 build-doc: true steps: @@ -174,7 +174,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: 18.0 + node-version: 20.0 - name: Install NPM dependencies working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }} diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index b6bad5b95..e85110aa8 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -25,7 +25,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 - name: Load cache uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/release_crypto_js.yml b/.github/workflows/release_crypto_js.yml index 25eed08c6..9dc21348a 100644 --- a/.github/workflows/release_crypto_js.yml +++ b/.github/workflows/release_crypto_js.yml @@ -39,7 +39,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: 18.0 + node-version: 20.0 - name: Install NPM dependencies working-directory: ${{ env.PKG_PATH }} diff --git a/Cargo.lock b/Cargo.lock index f35f240b8..437f13e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,7 +40,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" dependencies = [ "cfg-if", - "cipher 0.4.3", + "cipher 0.4.4", "cpufeatures", ] @@ -50,7 +50,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "once_cell", "version_check", ] @@ -62,16 +62,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", - "getrandom 0.2.8", + "getrandom 0.2.9", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ "memchr", ] @@ -98,10 +98,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] -name = "anyhow" -version = "1.0.69" +name = "anstream" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "anymap2" @@ -111,9 +160,9 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" [[package]] name = "arrayref" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -143,7 +192,7 @@ checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" dependencies = [ "askama_shared", "proc-macro2", - "syn", + "syn 1.0.109", ] [[package]] @@ -165,7 +214,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 1.0.109", "toml 0.5.11", ] @@ -217,9 +266,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" dependencies = [ "async-lock", "async-task", @@ -246,39 +295,38 @@ dependencies = [ [[package]] name = "async-io" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock", "autocfg", + "cfg-if", "concurrent-queue", "futures-lite", - "libc", "log", "parking", "polling", + "rustix", "slab", "socket2", "waker-fn", - "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" dependencies = [ "event-listener", - "futures-lite", ] [[package]] name = "async-process" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" dependencies = [ "async-io", "async-lock", @@ -287,9 +335,9 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "libc", + "rustix", "signal-hook", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -321,40 +369,41 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "async-task" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -368,9 +417,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" [[package]] name = "atty" @@ -391,13 +440,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.6" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e246206a63c9830e118d12c894f56a82033da1a2361f5544deeee3df85c99d9" +checksum = "113713495a32dd0ab52baf5c10044725aa3aec00b31beda84218e469029b72a3" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -415,16 +464,15 @@ dependencies = [ "serde_path_to_error", "sync_wrapper", "tower", - "tower-http", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", "bytes", @@ -444,7 +492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.8", + "getrandom 0.2.9", "instant", "pin-project-lite", "rand 0.8.5", @@ -480,9 +528,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "base64ct" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "benchmarks" @@ -514,6 +562,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" + [[package]] name = "bitmaps" version = "3.2.0" @@ -545,27 +599,27 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "block-padding" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a90ec2df9600c28a01c56c4784c9207a96d2451833aeceb8cc97e4c9548bb78" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ "generic-array", ] [[package]] name = "blocking" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" dependencies = [ "async-channel", "async-lock", @@ -573,6 +627,7 @@ dependencies = [ "atomic-waker", "fastrand", "futures-lite", + "log", ] [[package]] @@ -583,15 +638,15 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" [[package]] name = "bytemuck" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" [[package]] name = "byteorder" @@ -607,15 +662,15 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bytesize" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" +checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5" [[package]] name = "camino" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" dependencies = [ "serde", ] @@ -631,9 +686,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", @@ -655,7 +710,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" dependencies = [ - "cipher 0.4.3", + "cipher 0.4.4", ] [[package]] @@ -703,9 +758,9 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", "js-sys", @@ -754,9 +809,9 @@ dependencies = [ [[package]] name = "cipher" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", @@ -769,7 +824,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive 3.2.18", "clap_lex 0.2.4", "indexmap", @@ -781,17 +836,26 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.8" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62" dependencies = [ - "bitflags", - "clap_derive 4.1.8", - "clap_lex 0.3.1", - "is-terminal", + "clap_builder", + "clap_derive 4.2.0", "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749" +dependencies = [ + "anstream", + "anstyle", + "bitflags 1.3.2", + "clap_lex 0.4.1", "strsim", - "termcolor", ] [[package]] @@ -804,20 +868,19 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "clap_derive" -version = "4.1.8" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -831,18 +894,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" -dependencies = [ - "os_str_bytes", -] +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "cmake" -version = "0.1.49" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" dependencies = [ "cc", ] @@ -864,10 +924,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "concurrent-queue" -version = "2.1.0" +name = "colorchoice" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" dependencies = [ "crossbeam-utils", ] @@ -910,9 +976,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" [[package]] name = "convert_case" @@ -935,24 +1001,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpp_demangle" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442" +checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -1006,9 +1072,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1016,9 +1082,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -1027,9 +1093,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", @@ -1040,9 +1106,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -1064,7 +1130,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "ctor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" +dependencies = [ + "quote", + "syn 2.0.15", ] [[package]] @@ -1073,7 +1149,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher 0.4.3", + "cipher 0.4.4", ] [[package]] @@ -1092,9 +1168,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -1104,9 +1180,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -1114,24 +1190,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 2.0.15", ] [[package]] name = "cxxbridge-flags" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -1232,7 +1308,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.3", + "block-buffer 0.10.4", "crypto-common", "subtle", ] @@ -1265,7 +1341,7 @@ checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1310,13 +1386,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1395,7 +1471,7 @@ name = "example-emoji-verification" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.1.8", + "clap 4.2.4", "futures", "matrix-sdk", "tokio", @@ -1467,7 +1543,7 @@ name = "example-timeline" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.1.8", + "clap 4.2.4", "futures", "matrix-sdk", "tokio", @@ -1477,20 +1553,20 @@ dependencies = [ [[package]] name = "extension-trait" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5129068fe3183546eaa0529af88ab0afbcddec2a373db69e94a20b8d5f6c4d74" +checksum = "dd65f1b59dd22d680c7a626cc4a000c1e03d241c51c3e034d2bc9f1e90734f9b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "eyeball" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7be1d67275032c662cadf525a79aef6909469579c5d81c69c148f7257257af" +checksum = "1015c5225a75e0ab3d325e934456d92fdd57f440e8c81d09018878d4f651cd46" dependencies = [ "futures-core", "readlock", @@ -1539,6 +1615,15 @@ dependencies = [ "instant", ] +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + [[package]] name = "findshlibs" version = "0.10.2" @@ -1631,9 +1716,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -1646,9 +1731,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1656,15 +1741,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1673,15 +1758,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[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", "futures-core", @@ -1694,26 +1779,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" @@ -1723,9 +1808,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1750,9 +1835,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1773,9 +1858,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "js-sys", @@ -1794,6 +1879,16 @@ dependencies = [ "weezl", ] +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.27.2" @@ -1833,9 +1928,9 @@ dependencies = [ [[package]] name = "goblin" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572564d6cba7d09775202c8e7eebc4d534d5ae36578ab402fb21e182a0ac9505" +checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" dependencies = [ "log", "plain", @@ -1844,9 +1939,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -1944,14 +2039,14 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", @@ -1969,12 +2064,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" - [[package]] name = "http-types" version = "2.12.0" @@ -2010,9 +2099,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.24" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -2072,16 +2161,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.53" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "winapi", + "windows", ] [[package]] @@ -2113,7 +2202,7 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", - "gif", + "gif 0.11.4", "jpeg-decoder 0.1.22", "num-iter", "num-rational 0.3.2", @@ -2125,19 +2214,18 @@ dependencies = [ [[package]] name = "image" -version = "0.24.5" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" +checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" dependencies = [ "bytemuck", "byteorder", "color_quant", - "gif", + "gif 0.12.0", "jpeg-decoder 0.3.0", "num-rational 0.4.1", "num-traits", - "png 0.17.7", - "scoped_threadpool", + "png 0.17.8", "tiff 0.8.1", ] @@ -2186,9 +2274,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", @@ -2249,30 +2337,31 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2286,9 +2375,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jpeg-decoder" @@ -2374,9 +2463,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" [[package]] name = "libloading" @@ -2416,9 +2505,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" [[package]] name = "lock_api" @@ -2511,7 +2600,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2527,7 +2616,7 @@ dependencies = [ "bytes", "bytesize", "chrono", - "ctor", + "ctor 0.2.0", "dashmap", "dirs", "event-listener", @@ -2537,11 +2626,11 @@ dependencies = [ "futures", "futures-core", "futures-util", - "getrandom 0.2.8", + "getrandom 0.2.9", "gloo-timers", "http", "hyper", - "image 0.24.5", + "image 0.24.6", "imbl", "indexmap", "matrix-sdk-base", @@ -2606,7 +2695,8 @@ dependencies = [ "assign", "async-stream", "async-trait", - "ctor", + "bitflags 2.2.1", + "ctor 0.2.0", "dashmap", "eyeball", "futures", @@ -2660,7 +2750,7 @@ dependencies = [ "bs58", "byteorder", "cfg-if", - "ctor", + "ctor 0.2.0", "ctr", "dashmap", "event-listener", @@ -2809,7 +2899,7 @@ dependencies = [ "async-trait", "base64 0.21.0", "dashmap", - "getrandom 0.2.8", + "getrandom 0.2.9", "gloo-utils", "indexed_db_futures", "js-sys", @@ -2836,7 +2926,7 @@ version = "0.1.0" dependencies = [ "anyhow", "assign", - "ctor", + "ctor 0.2.0", "matrix-sdk", "once_cell", "tempfile", @@ -2893,7 +2983,7 @@ dependencies = [ "assert_matches", "async-stream", "async-trait", - "ctor", + "ctor 0.2.0", "dashmap", "deadpool-sqlite", "fs_extra", @@ -2927,7 +3017,7 @@ dependencies = [ "blake3", "chacha20poly1305", "displaydoc", - "getrandom 0.2.8", + "getrandom 0.2.9", "hmac", "pbkdf2", "rand 0.8.5", @@ -2959,7 +3049,7 @@ version = "0.3.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2970,27 +3060,27 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" @@ -3036,6 +3126,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "mio" version = "0.8.6" @@ -3056,15 +3156,15 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "napi" -version = "2.11.1" +version = "2.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2412d19892730f62fd592f8af41606ca6717ea1eca026103cd44b447829f00c1" +checksum = "69b29acdc6cc5c918c3eabd51d241b1c6dfa8914f3552fcfd76e1d7536934581" dependencies = [ - "bitflags", - "ctor", + "bitflags 2.2.1", + "ctor 0.2.0", + "napi-derive", "napi-sys", "once_cell", - "thread_local", "tokio", ] @@ -3076,29 +3176,30 @@ checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" [[package]] name = "napi-derive" -version = "2.11.0" +version = "2.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03f15c1ac0eac01eca2a24c27905ab47f7411acefd829d0d01fb131dc39befd7" +checksum = "af2ac63101a19228b0881694cac07468d642fd10e4f943a9c9feebeebf1a4787" dependencies = [ "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "napi-derive-backend" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4930d5fa70f5663b9e7d6b4f0816b70d095574ee7f3c865fdb8c43b0f7e6406d" +checksum = "0e32b5bc4d803e40b783b0aa3fe488eac8711cfaa4c5c9915293dfd3d0b99925" dependencies = [ "convert_case", "once_cell", "proc-macro2", "quote", "regex", - "syn", + "semver", + "syn 1.0.109", ] [[package]] @@ -3136,13 +3237,14 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nix" -version = "0.24.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", + "static_assertions", ] [[package]] @@ -3155,15 +3257,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nom8" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" -dependencies = [ - "memchr", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3262,7 +3355,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6c2c7054110ce4d7b4756d7b7fe507fea9413968ad0ef8f1d043d504aec725" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "olm-sys", "serde", "serde_json", @@ -3299,11 +3392,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.48" +version = "0.10.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" +checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -3314,13 +3407,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", - "syn", + "syn 2.0.15", ] [[package]] @@ -3331,11 +3424,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.83" +version = "0.9.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" +checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", @@ -3439,9 +3531,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.4.1" +version = "6.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" [[package]] name = "overload" @@ -3451,9 +3543,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" [[package]] name = "parking_lot" @@ -3485,7 +3577,7 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "winapi", ] @@ -3498,7 +3590,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] @@ -3516,9 +3608,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" [[package]] name = "pbkdf2" @@ -3607,7 +3699,7 @@ dependencies = [ "phf_shared 0.11.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3645,7 +3737,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3716,7 +3808,7 @@ version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "deflate", "miniz_oxide 0.3.7", @@ -3724,28 +3816,31 @@ dependencies = [ [[package]] name = "png" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", + "fdeflate", "flate2", - "miniz_oxide 0.6.2", + "miniz_oxide 0.7.1", ] [[package]] name = "polling" -version = "2.5.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", + "bitflags 1.3.2", "cfg-if", + "concurrent-queue", "libc", "log", - "wepoll-ffi", - "windows-sys 0.42.0", + "pin-project-lite", + "windows-sys 0.48.0", ] [[package]] @@ -3761,9 +3856,9 @@ dependencies = [ [[package]] name = "pprof" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20150f965e0e4c925982b9356da71c84bcd56cb66ef4e894825837cbcf6613e" +checksum = "196ded5d4be535690899a4631cc9f18cdc41b7ebf24a79400f46f48e49a11059" dependencies = [ "backtrace", "cfg-if", @@ -3795,22 +3890,22 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.1.23" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ "proc-macro2", - "syn", + "syn 1.0.109", ] [[package]] name = "proc-macro-crate" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.18.1", + "toml_edit", ] [[package]] @@ -3822,7 +3917,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -3839,9 +3934,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -3852,7 +3947,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -3860,15 +3955,15 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.6.29", "unarray", ] [[package]] name = "prost" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", "prost-derive", @@ -3876,9 +3971,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck", @@ -3891,31 +3986,30 @@ dependencies = [ "prost", "prost-types", "regex", - "syn", + "syn 1.0.109", "tempfile", "which", ] [[package]] name = "prost-derive" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "prost-types" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ - "bytes", "prost", ] @@ -3925,7 +4019,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" dependencies = [ - "bitflags", + "bitflags 1.3.2", "memchr", "unicase", ] @@ -3957,9 +4051,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -4023,7 +4117,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", ] [[package]] @@ -4055,9 +4149,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -4065,9 +4159,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -4077,9 +4171,9 @@ dependencies = [ [[package]] name = "readlock" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c8a22130504d1f661d1bc373b424f2d45910fa5319132d903a4074e1527b2e" +checksum = "ed5b7f359207e69e1395440120fa3b07c59bb92c4ec077804cd10d7ebbe4c01a" [[package]] name = "redox_syscall" @@ -4087,7 +4181,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", ] [[package]] @@ -4096,20 +4199,20 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.8", - "redox_syscall", + "getrandom 0.2.9", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.7.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.1", ] [[package]] @@ -4118,29 +4221,26 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "reqwest" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ "async-compression", "base64 0.21.0", @@ -4189,9 +4289,9 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.35" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7495acf66551cdb696b7711408144bcd3194fc78e32f3a09e809bfe7dd4a7ce3" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" dependencies = [ "bytemuck", ] @@ -4236,7 +4336,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.8.2" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "assign", "js_int", @@ -4251,7 +4351,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.8.1" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "js_int", "ruma-common", @@ -4262,7 +4362,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.16.2" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "assign", "bytes", @@ -4279,12 +4379,12 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "base64 0.21.0", "bytes", "form_urlencoded", - "getrandom 0.2.8", + "getrandom 0.2.9", "html5ever", "http", "indexmap", @@ -4312,7 +4412,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "js_int", "ruma-common", @@ -4323,7 +4423,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.1" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "js_int", "thiserror", @@ -4332,7 +4432,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "once_cell", "proc-macro-crate", @@ -4340,14 +4440,14 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn", - "toml 0.7.2", + "syn 1.0.109", + "toml 0.7.3", ] [[package]] name = "ruma-push-gateway-api" version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=89e398fd062b4e763a3341fc7067428285d51d09#89e398fd062b4e763a3341fc7067428285d51d09" +source = "git+https://github.com/ruma/ruma?rev=0143bd9b9f5dcfcaa835afb76f342c12f014f945#0143bd9b9f5dcfcaa835afb76f342c12f014f945" dependencies = [ "js_int", "ruma-common", @@ -4361,7 +4461,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -4371,22 +4471,22 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.36.8" +version = "0.37.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -4412,15 +4512,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -4469,9 +4569,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "scroll" @@ -4490,7 +4590,7 @@ checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4509,7 +4609,7 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -4528,18 +4628,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.152" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] @@ -4555,13 +4655,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -4579,9 +4679,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -4590,9 +4690,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341" +checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0" dependencies = [ "serde", ] @@ -4631,9 +4731,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.17" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" +checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" dependencies = [ "indexmap", "itoa", @@ -4700,6 +4800,12 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + [[package]] name = "siphasher" version = "0.3.10" @@ -4708,9 +4814,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -4754,9 +4860,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", @@ -4797,9 +4903,9 @@ checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" [[package]] name = "string_cache" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d69e88b23f23030bf4d0e9ca7b07434f70e1c1f4d3ca7e93ce958b373654d9f" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", @@ -4858,9 +4964,20 @@ 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", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", @@ -4873,30 +4990,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "tempfile" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", ] [[package]] @@ -4927,22 +5031,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -4990,9 +5094,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "itoa", "serde", @@ -5008,9 +5112,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" dependencies = [ "time-core", ] @@ -5042,14 +5146,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.26.0" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "pin-project-lite", @@ -5070,13 +5173,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -5149,22 +5252,16 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", "serde_spanned", - "toml_datetime 0.6.1", - "toml_edit 0.19.3", + "toml_datetime", + "toml_edit", ] -[[package]] -name = "toml_datetime" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" - [[package]] name = "toml_datetime" version = "0.6.1" @@ -5176,26 +5273,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.18.1" +version = "0.19.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" dependencies = [ "indexmap", - "nom8", - "toml_datetime 0.5.1", -] - -[[package]] -name = "toml_edit" -version = "0.19.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a7712b49e1775fb9a7b998de6635b299237f48b404dde71704f2e0e7f37e5" -dependencies = [ - "indexmap", - "nom8", "serde", "serde_spanned", - "toml_datetime 0.6.1", + "toml_datetime", + "winnow", ] [[package]] @@ -5240,7 +5326,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -5263,25 +5349,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "tower-layer" version = "0.3.2" @@ -5326,7 +5393,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -5376,9 +5443,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -5387,7 +5454,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "time 0.3.19", + "time 0.3.20", "tracing", "tracing-core", "tracing-log", @@ -5422,15 +5489,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -5518,7 +5585,7 @@ version = "0.23.0" source = "git+https://github.com/mozilla/uniffi-rs?rev=aa91307b6ac27aae6d5c7ad971b762df952d2745#aa91307b6ac27aae6d5c7ad971b762df952d2745" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -5548,7 +5615,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 1.0.109", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -5593,9 +5660,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" +checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" [[package]] name = "untrusted" @@ -5622,12 +5689,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] -name = "uuid" -version = "1.3.0" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "wasm-bindgen", ] @@ -5643,7 +5716,7 @@ version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" dependencies = [ - "ctor", + "ctor 0.1.26", "version_check", ] @@ -5692,12 +5765,11 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -5750,7 +5822,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -5784,7 +5856,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5875,15 +5947,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "which" version = "4.4.0" @@ -5932,19 +5995,28 @@ 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.0", +] + [[package]] name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -5953,65 +6025,140 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", ] [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -6024,13 +6171,13 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12316b50eb725e22b2f6b9c4cbede5b7b89984274d113a7440c86e5c3fc6f99b" +checksum = "bd7b0b5b253ebc0240d6aac6dd671c495c467420577bf634d3064ae7e6fa2b4c" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.13.1", + "base64 0.21.0", "deadpool", "futures", "futures-timer", @@ -6076,7 +6223,7 @@ name = "xtask" version = "0.1.0" dependencies = [ "camino", - "clap 4.1.8", + "clap 4.2.4", "fs_extra", "serde", "serde_json", @@ -6096,12 +6243,11 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.15", ] diff --git a/Cargo.toml b/Cargo.toml index 71f2407c8..d9d522acb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,14 +26,14 @@ async-stream = "0.3.3" async-trait = "0.1.60" base64 = "0.21.0" byteorder = "1.4.3" -ctor = "0.1.26" +ctor = "0.2.0" dashmap = "5.2.0" -eyeball = "0.4.0" +eyeball = "0.6.0" eyeball-im = "0.2.0" futures-util = { version = "0.3.26", default-features = false, features = ["alloc"] } http = "0.2.6" -ruma = { git = "https://github.com/ruma/ruma", rev = "89e398fd062b4e763a3341fc7067428285d51d09", features = ["client-api-c"] } -ruma-common = { git = "https://github.com/ruma/ruma", rev = "89e398fd062b4e763a3341fc7067428285d51d09" } +ruma = { git = "https://github.com/ruma/ruma", rev = "0143bd9b9f5dcfcaa835afb76f342c12f014f945", features = ["client-api-c", "compat-user-id"] } +ruma-common = { git = "https://github.com/ruma/ruma", rev = "0143bd9b9f5dcfcaa835afb76f342c12f014f945" } once_cell = "1.16.0" serde = "1.0.151" serde_html_form = "0.2.0" diff --git a/bindings/matrix-sdk-crypto-ffi/src/backup_recovery_key.rs b/bindings/matrix-sdk-crypto-ffi/src/backup_recovery_key.rs index 110406fb2..5cf6e3974 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/backup_recovery_key.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/backup_recovery_key.rs @@ -27,7 +27,8 @@ pub enum PkDecryptionError { } /// Error type for the decoding and storing of the backup key. -#[derive(Debug, Error)] +#[derive(Debug, Error, uniffi::Error)] +#[uniffi(flat_error)] pub enum DecodeError { /// An error happened while decoding the recovery key. #[error(transparent)] @@ -40,7 +41,7 @@ pub enum DecodeError { /// Struct containing info about the way the backup key got derived from a /// passphrase. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, uniffi::Record)] pub struct PassphraseInfo { /// The salt that was used during key derivation. pub private_key_salt: String, diff --git a/bindings/matrix-sdk-crypto-ffi/src/device.rs b/bindings/matrix-sdk-crypto-ffi/src/device.rs index ed8ae0e3a..a2a0b708b 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/device.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/device.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use matrix_sdk_crypto::Device as InnerDevice; /// An E2EE capable Matrix device. +#[derive(uniffi::Record)] pub struct Device { /// The device owner. pub user_id: String, diff --git a/bindings/matrix-sdk-crypto-ffi/src/error.rs b/bindings/matrix-sdk-crypto-ffi/src/error.rs index d4215fa03..04bcc9e55 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/error.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/error.rs @@ -7,7 +7,8 @@ use matrix_sdk_crypto::{ use matrix_sdk_sqlite::OpenStoreError; use ruma::{IdParseError, OwnedUserId}; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, uniffi::Error)] +#[uniffi(flat_error)] pub enum KeyImportError { #[error(transparent)] Export(#[from] KeyExportError), @@ -17,7 +18,8 @@ pub enum KeyImportError { Json(#[from] serde_json::Error), } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, uniffi::Error)] +#[uniffi(flat_error)] pub enum SecretImportError { #[error(transparent)] CryptoStore(#[from] InnerStoreError), @@ -25,7 +27,8 @@ pub enum SecretImportError { Import(#[from] RustSecretImportError), } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, uniffi::Error)] +#[uniffi(flat_error)] pub enum SignatureError { #[error(transparent)] Signature(#[from] InnerSignatureError), @@ -55,7 +58,7 @@ pub enum CryptoStoreError { Identifier(#[from] IdParseError), } -#[derive(Debug)] +#[derive(Debug, uniffi::Error)] pub enum DecryptionError { Serialization { error: String }, Identifier { error: String }, diff --git a/bindings/matrix-sdk-crypto-ffi/src/lib.rs b/bindings/matrix-sdk-crypto-ffi/src/lib.rs index f5ecd6013..d26ea8d04 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/lib.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/lib.rs @@ -56,7 +56,7 @@ pub use verification::{ use vodozemac::{Curve25519PublicKey, Ed25519PublicKey}; /// Struct collecting data that is important to migrate to the rust-sdk -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, uniffi::Record)] pub struct MigrationData { /// The pickled version of the Olm Account account: PickledAccount, @@ -79,6 +79,7 @@ pub struct MigrationData { } /// Struct collecting data that is important to migrate sessions to the rust-sdk +#[derive(uniffi::Record)] pub struct SessionMigrationData { /// The user id that the data belongs to. user_id: String, @@ -100,7 +101,7 @@ pub struct SessionMigrationData { /// /// Holds all the information that needs to be stored in a database to restore /// an account. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, uniffi::Record)] pub struct PickledAccount { /// The user id of the account owner. pub user_id: String, @@ -118,7 +119,7 @@ pub struct PickledAccount { /// /// Holds all the information that needs to be stored in a database to restore /// a Session. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, uniffi::Record)] pub struct PickledSession { /// The pickle string holding the Olm Session. pub pickle: String, @@ -136,7 +137,7 @@ pub struct PickledSession { /// /// Holds all the information that needs to be stored in a database to restore /// an InboundGroupSession. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, uniffi::Record)] pub struct PickledInboundGroupSession { /// The pickle string holding the InboundGroupSession. pub pickle: String, @@ -157,7 +158,7 @@ pub struct PickledInboundGroupSession { } /// Error type for the migration process. -#[derive(thiserror::Error, Debug)] +#[derive(Debug, thiserror::Error, uniffi::Error)] pub enum MigrationError { /// Generic catch all error variant. #[error("error migrating database: {error_message}")] @@ -188,15 +189,16 @@ impl From for MigrationError { /// /// * `progress_listener` - A callback that can be used to introspect the /// progress of the migration. +#[uniffi::export] pub fn migrate( data: MigrationData, - path: &str, + path: String, passphrase: Option, progress_listener: Box, ) -> Result<(), MigrationError> { let runtime = Runtime::new().context("initializing tokio runtime")?; runtime.block_on(async move { - migrate_data(data, path, passphrase, progress_listener).await?; + migrate_data(data, &path, passphrase, progress_listener).await?; Ok(()) }) } @@ -350,14 +352,15 @@ async fn save_changes( /// /// * `progress_listener` - A callback that can be used to introspect the /// progress of the migration. +#[uniffi::export] pub fn migrate_sessions( data: SessionMigrationData, - path: &str, + path: String, passphrase: Option, progress_listener: Box, ) -> Result<(), MigrationError> { let runtime = Runtime::new().context("initializing tokio runtime")?; - runtime.block_on(migrate_session_data(data, path, passphrase, progress_listener))?; + runtime.block_on(migrate_session_data(data, &path, passphrase, progress_listener))?; Ok(()) } @@ -497,9 +500,10 @@ fn collect_sessions( /// * `passphrase` - The passphrase that should be used to encrypt the data at /// rest in the Sqlite store. **Warning**, if no passphrase is given, the store /// and all its data will remain unencrypted. +#[uniffi::export] pub fn migrate_room_settings( room_settings: HashMap, - path: &str, + path: String, passphrase: Option, ) -> Result<(), MigrationError> { let runtime = Runtime::new().context("initializing tokio runtime")?; @@ -540,7 +544,7 @@ impl ProgressListener for T { } /// An encryption algorithm to be used to encrypt messages sent to a room. -#[derive(Debug, Deserialize, Serialize, PartialEq)] +#[derive(Debug, Deserialize, Serialize, PartialEq, uniffi::Enum)] pub enum EventEncryptionAlgorithm { /// Olm version 1 using Curve25519, AES-256, and SHA-256. OlmV1Curve25519AesSha2, @@ -572,6 +576,7 @@ impl TryFrom for EventEncryptionAlgorithm { } /// Who can see a room's history. +#[derive(uniffi::Enum)] pub enum HistoryVisibility { /// Previous events are accessible to newly joined members from the point /// they were invited onwards. @@ -717,7 +722,7 @@ pub struct CrossSigningStatus { /// A struct containing private cross signing keys that can be backed up or /// uploaded to the secret store. -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, uniffi::Record)] pub struct CrossSigningKeyExport { /// The seed of the master key encoded as unpadded base64. pub master_key: Option, @@ -810,7 +815,7 @@ impl From for CrossSigningStatus { } /// Room encryption settings which are modified by state events or user options -#[derive(Debug, Deserialize, Serialize, PartialEq)] +#[derive(Debug, PartialEq, Deserialize, Serialize, uniffi::Record)] pub struct RoomSettings { /// The encryption algorithm that should be used in the room. pub algorithm: EventEncryptionAlgorithm, @@ -959,12 +964,15 @@ mod test { let migration_data: MigrationData = serde_json::from_value(data)?; let dir = tempdir()?; - let path = - dir.path().to_str().expect("Creating a string from the tempdir path should not fail"); + let path = dir + .path() + .to_str() + .expect("Creating a string from the tempdir path should not fail") + .to_owned(); - migrate(migration_data, path, None, Box::new(|_, _| {}))?; + migrate(migration_data, path.clone(), None, Box::new(|_, _| {}))?; - let machine = OlmMachine::new("@ganfra146:matrix.org", "DEWRCMENGS", path, None)?; + let machine = OlmMachine::new("@ganfra146:matrix.org", "DEWRCMENGS", &path, None)?; assert_eq!( machine.identity_keys()["ed25519"], diff --git a/bindings/matrix-sdk-crypto-ffi/src/logger.rs b/bindings/matrix-sdk-crypto-ffi/src/logger.rs index c2c991119..5f2a36a0e 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/logger.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/logger.rs @@ -41,6 +41,7 @@ pub struct LoggerWrapper { } /// Set the logger that should be used to forward Rust logs over FFI. +#[uniffi::export] pub fn set_logger(logger: Box) { let logger = LoggerWrapper { inner: Arc::new(Mutex::new(logger)) }; diff --git a/bindings/matrix-sdk-crypto-ffi/src/machine.rs b/bindings/matrix-sdk-crypto-ffi/src/machine.rs index bd9b476ac..e9f267601 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/machine.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/machine.rs @@ -79,6 +79,7 @@ impl Drop for OlmMachine { /// A pair of outgoing room key requests, both of those are sendToDevice /// requests. +#[derive(uniffi::Record)] pub struct KeyRequestPair { /// The optional cancellation, this is None if no previous key request was /// sent out for this key, thus it doesn't need to be cancelled. @@ -88,7 +89,7 @@ pub struct KeyRequestPair { } /// The result of a signature verification of a signed JSON object. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, uniffi::Record)] pub struct SignatureVerification { /// The result of the signature verification using the public key of our own /// device. @@ -127,36 +128,6 @@ impl From for SignatureVerification { } } -#[uniffi::export] -impl OlmMachine { - /// Get the user ID of the owner of this `OlmMachine`. - pub fn user_id(&self) -> String { - self.inner.user_id().to_string() - } - - /// Get the device ID of the device of this `OlmMachine`. - pub fn device_id(&self) -> String { - self.inner.device_id().to_string() - } - - /// Get our own identity keys. - pub fn identity_keys(&self) -> HashMap { - let identity_keys = self.inner.identity_keys(); - let curve_key = identity_keys.curve25519.to_base64(); - let ed25519_key = identity_keys.ed25519.to_base64(); - - HashMap::from([("ed25519".to_owned(), ed25519_key), ("curve25519".to_owned(), curve_key)]) - } - - /// Get the status of the private cross signing keys. - /// - /// This can be used to check which private cross signing keys we have - /// stored locally. - pub fn cross_signing_status(&self) -> CrossSigningStatus { - self.runtime.block_on(self.inner.cross_signing_status()).into() - } -} - impl OlmMachine { /// Create a new `OlmMachine` /// @@ -192,9 +163,63 @@ impl OlmMachine { Ok(OlmMachine { inner: ManuallyDrop::new(inner), runtime }) } - /// Get the display name of our own device. - pub fn display_name(&self) -> Result, CryptoStoreError> { - Ok(self.runtime.block_on(self.inner.display_name())?) + fn import_room_keys_helper( + &self, + keys: Vec, + from_backup: bool, + progress_listener: Box, + ) -> Result { + let listener = |progress: usize, total: usize| { + progress_listener.on_progress(progress as i32, total as i32) + }; + + let result = + self.runtime.block_on(self.inner.import_room_keys(keys, from_backup, listener))?; + + Ok(KeysImportResult { + imported: result.imported_count as i64, + total: result.total_count as i64, + keys: result + .keys + .into_iter() + .map(|(r, m)| { + ( + r.to_string(), + m.into_iter().map(|(s, k)| (s, k.into_iter().collect())).collect(), + ) + }) + .collect(), + }) + } +} + +#[uniffi::export] +impl OlmMachine { + /// Get the user ID of the owner of this `OlmMachine`. + pub fn user_id(&self) -> String { + self.inner.user_id().to_string() + } + + /// Get the device ID of the device of this `OlmMachine`. + pub fn device_id(&self) -> String { + self.inner.device_id().to_string() + } + + /// Get our own identity keys. + pub fn identity_keys(&self) -> HashMap { + let identity_keys = self.inner.identity_keys(); + let curve_key = identity_keys.curve25519.to_base64(); + let ed25519_key = identity_keys.ed25519.to_base64(); + + HashMap::from([("ed25519".to_owned(), ed25519_key), ("curve25519".to_owned(), curve_key)]) + } + + /// Get the status of the private cross signing keys. + /// + /// This can be used to check which private cross signing keys we have + /// stored locally. + pub fn cross_signing_status(&self) -> CrossSigningStatus { + self.runtime.block_on(self.inner.cross_signing_status()).into() } /// Get a cross signing user identity for the given user ID. @@ -211,10 +236,10 @@ impl OlmMachine { /// received. pub fn get_identity( &self, - user_id: &str, + user_id: String, timeout: u32, ) -> Result, CryptoStoreError> { - let user_id = parse_user_id(user_id)?; + let user_id = parse_user_id(&user_id)?; let timeout = if timeout == 0 { None } else { Some(Duration::from_secs(timeout.into())) }; @@ -230,8 +255,8 @@ impl OlmMachine { } /// Check if a user identity is considered to be verified by us. - pub fn is_identity_verified(&self, user_id: &str) -> Result { - let user_id = parse_user_id(user_id)?; + pub fn is_identity_verified(&self, user_id: String) -> Result { + let user_id = parse_user_id(&user_id)?; Ok( if let Some(identity) = @@ -258,7 +283,10 @@ impl OlmMachine { /// /// Returns a request that needs to be sent out for the user identity to be /// marked as verified. - pub fn verify_identity(&self, user_id: &str) -> Result { + pub fn verify_identity( + &self, + user_id: String, + ) -> Result { let user_id = UserId::parse(user_id)?; let user_identity = self.runtime.block_on(self.inner.get_identity(&user_id, None))?; @@ -290,17 +318,17 @@ impl OlmMachine { /// received. pub fn get_device( &self, - user_id: &str, - device_id: &str, + user_id: String, + device_id: String, timeout: u32, ) -> Result, CryptoStoreError> { - let user_id = parse_user_id(user_id)?; + let user_id = parse_user_id(&user_id)?; let timeout = if timeout == 0 { None } else { Some(Duration::from_secs(timeout.into())) }; Ok(self .runtime - .block_on(self.inner.get_device(&user_id, device_id.into(), timeout))? + .block_on(self.inner.get_device(&user_id, device_id.as_str().into(), timeout))? .map(|d| d.into())) } @@ -319,17 +347,20 @@ impl OlmMachine { /// as verified. pub fn verify_device( &self, - user_id: &str, - device_id: &str, + user_id: String, + device_id: String, ) -> Result { let user_id = UserId::parse(user_id)?; - let device = - self.runtime.block_on(self.inner.get_device(&user_id, device_id.into(), None))?; + let device = self.runtime.block_on(self.inner.get_device( + &user_id, + device_id.as_str().into(), + None, + ))?; if let Some(device) = device { Ok(self.runtime.block_on(device.verify())?.into()) } else { - Err(SignatureError::UnknownDevice(user_id, device_id.to_owned())) + Err(SignatureError::UnknownDevice(user_id, device_id)) } } @@ -337,14 +368,17 @@ impl OlmMachine { /// or uploading any signatures if verified pub fn set_local_trust( &self, - user_id: &str, - device_id: &str, + user_id: String, + device_id: String, trust_state: LocalTrust, ) -> Result<(), CryptoStoreError> { - let user_id = parse_user_id(user_id)?; + let user_id = parse_user_id(&user_id)?; - let device = - self.runtime.block_on(self.inner.get_device(&user_id, device_id.into(), None))?; + let device = self.runtime.block_on(self.inner.get_device( + &user_id, + device_id.as_str().into(), + None, + ))?; if let Some(device) = device { self.runtime.block_on(device.set_local_trust(trust_state))?; @@ -367,10 +401,10 @@ impl OlmMachine { /// received. pub fn get_user_devices( &self, - user_id: &str, + user_id: String, timeout: u32, ) -> Result, CryptoStoreError> { - let user_id = parse_user_id(user_id)?; + let user_id = parse_user_id(&user_id)?; let timeout = if timeout == 0 { None } else { Some(Duration::from_secs(timeout.into())) }; Ok(self @@ -410,13 +444,13 @@ impl OlmMachine { /// * `response_body` - The body of the response that was received. pub fn mark_request_as_sent( &self, - request_id: &str, + request_id: String, request_type: RequestType, - response_body: &str, + response_body: String, ) -> Result<(), CryptoStoreError> { let id: OwnedTransactionId = request_id.into(); - let response = response_from_string(response_body); + let response = response_from_string(&response_body); let response: OwnedResponse = match request_type { RequestType::KeysUpload => { @@ -447,10 +481,7 @@ impl OlmMachine { Ok(()) } -} -#[uniffi::export] -impl OlmMachine { /// Let the state machine know about E2EE related sync changes that we /// received from the server. /// @@ -867,37 +898,6 @@ impl OlmMachine { Ok(encrypted) } -} - -impl OlmMachine { - fn import_room_keys_helper( - &self, - keys: Vec, - from_backup: bool, - progress_listener: Box, - ) -> Result { - let listener = |progress: usize, total: usize| { - progress_listener.on_progress(progress as i32, total as i32) - }; - - let result = - self.runtime.block_on(self.inner.import_room_keys(keys, from_backup, listener))?; - - Ok(KeysImportResult { - imported: result.imported_count as i64, - total: result.total_count as i64, - keys: result - .keys - .into_iter() - .map(|(r, m)| { - ( - r.to_string(), - m.into_iter().map(|(s, k)| (s, k.into_iter().collect())).collect(), - ) - }) - .collect(), - }) - } /// Import room keys from the given serialized key export. /// @@ -911,12 +911,12 @@ impl OlmMachine { /// progress of the key import. pub fn import_room_keys( &self, - keys: &str, - passphrase: &str, + keys: String, + passphrase: String, progress_listener: Box, ) -> Result { let keys = Cursor::new(keys); - let keys = decrypt_room_key_export(keys, passphrase)?; + let keys = decrypt_room_key_export(keys, &passphrase)?; self.import_room_keys_helper(keys, false, progress_listener) } @@ -935,19 +935,16 @@ impl OlmMachine { /// progress of the key import. pub fn import_decrypted_room_keys( &self, - keys: &str, + keys: String, progress_listener: Box, ) -> Result { - let keys: Vec = serde_json::from_str(keys)?; + let keys: Vec = serde_json::from_str(&keys)?; let keys = keys.into_iter().map(serde_json::from_value).filter_map(|k| k.ok()).collect(); self.import_room_keys_helper(keys, true, progress_listener) } -} -#[uniffi::export] -impl OlmMachine { /// Discard the currently active room key for the given room if there is /// one. pub fn discard_room_key(&self, room_id: String) -> Result<(), CryptoStoreError> { @@ -1352,14 +1349,12 @@ impl OlmMachine { .ok() .map(Arc::new)) } -} -impl OlmMachine { /// Sign the given message using our device key and if available cross /// signing master key. - pub fn sign(&self, message: &str) -> HashMap> { + pub fn sign(&self, message: String) -> HashMap> { self.runtime - .block_on(self.inner.sign(message)) + .block_on(self.inner.sign(&message)) .into_iter() .map(|(k, v)| { ( @@ -1397,9 +1392,9 @@ impl OlmMachine { /// ``` pub fn verify_backup( &self, - backup_info: &str, + backup_info: String, ) -> Result { - let backup_info = serde_json::from_str(backup_info)?; + let backup_info = serde_json::from_str(&backup_info)?; Ok(self .runtime diff --git a/bindings/matrix-sdk-crypto-ffi/src/olm.udl b/bindings/matrix-sdk-crypto-ffi/src/olm.udl index 59f16950c..b98565243 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/olm.udl +++ b/bindings/matrix-sdk-crypto-ffi/src/olm.udl @@ -1,31 +1,4 @@ -namespace matrix_sdk_crypto_ffi { - void set_logger(Logger logger); - [Throws=MigrationError] - void migrate( - MigrationData data, - [ByRef] string path, - string? passphrase, - ProgressListener progress_listener - ); - [Throws=MigrationError] - void migrate_sessions( - SessionMigrationData data, - [ByRef] string path, - string? passphrase, - ProgressListener progress_listener - ); - [Throws=MigrationError] - void migrate_room_settings( - record room_settings, - [ByRef] string path, - string? passphrase - ); -}; - -[Error] -interface MigrationError { - Generic(string error_message); -}; +namespace matrix_sdk_crypto_ffi {}; callback interface Logger { void log(string log_line); @@ -35,29 +8,6 @@ callback interface ProgressListener { void on_progress(i32 progress, i32 total); }; -[Error] -enum KeyImportError { - "Export", - "CryptoStore", - "Json", -}; - -[Error] -enum SignatureError { - "Signature", - "Identifier", - "CryptoStore", - "UnknownDevice", - "UnknownUserIdentity", -}; - -[Error] -enum SecretImportError { - "Import", - "CryptoStore", -}; - - [Error] enum CryptoStoreError { "OpenStore", @@ -68,96 +18,12 @@ enum CryptoStoreError { "Identifier", }; -[Error] -interface DecryptionError { - Identifier(string error); - Serialization(string error); - Megolm(string error); - MissingRoomKey(string error, string? withheld_code); - Store(string error); -}; - -dictionary KeysImportResult { - i64 imported; - i64 total; - record>> keys; -}; - -dictionary Device { - string user_id; - string device_id; - record keys; - sequence algorithms; - string? display_name; - boolean is_blocked; - boolean locally_trusted; - boolean cross_signing_trusted; -}; - -[Enum] -interface UserIdentity { - Own( - string user_id, - boolean trusts_our_own_device, - string master_key, - string self_signing_key, - string user_signing_key - ); - Other( - string user_id, - string master_key, - string self_signing_key - ); -}; - -dictionary CrossSigningKeyExport { - string? master_key; - string? self_signing_key; - string? user_signing_key; -}; - -dictionary UploadSigningKeysRequest { - string master_key; - string self_signing_key; - string user_signing_key; -}; - -dictionary BootstrapCrossSigningResult { - UploadSigningKeysRequest upload_signing_keys_request; - SignatureUploadRequest signature_request; -}; - dictionary CancelInfo { string cancel_code; string reason; boolean cancelled_by_us; }; -dictionary StartSasResult { - Sas sas; - OutgoingVerificationRequest request; -}; - -interface Sas { - string other_user_id(); - string other_device_id(); - string flow_id(); - string? room_id(); - boolean we_started(); - boolean is_done(); - - OutgoingVerificationRequest? accept(); - [Throws=CryptoStoreError] - ConfirmVerificationResult? confirm(); - OutgoingVerificationRequest? cancel([ByRef] string cancel_code); - - sequence? get_emoji_indices(); - sequence? get_decimals(); - - void set_changes_listener(SasListener listener); - SasState state(); -}; - [Enum] interface SasState { Started(); @@ -172,32 +38,6 @@ callback interface SasListener { void on_change(SasState state); }; -dictionary ScanResult { - QrCode qr; - OutgoingVerificationRequest request; -}; - -interface QrCode { - string other_user_id(); - string other_device_id(); - string flow_id(); - string? room_id(); - boolean we_started(); - boolean is_done(); - boolean is_cancelled(); - CancelInfo? cancel_info(); - - boolean reciprocated(); - boolean has_been_scanned(); - - ConfirmVerificationResult? confirm(); - OutgoingVerificationRequest? cancel([ByRef] string cancel_code); - string? generate_qr_code(); - - void set_changes_listener(QrCodeListener listener); - QrCodeState state(); -}; - [Enum] interface QrCodeState { Started(); @@ -212,36 +52,6 @@ callback interface QrCodeListener { void on_change(QrCodeState state); }; -interface VerificationRequest { - string other_user_id(); - string? other_device_id(); - string flow_id(); - string? room_id(); - boolean we_started(); - boolean is_ready(); - boolean is_done(); - boolean is_passive(); - boolean is_cancelled(); - CancelInfo? cancel_info(); - - sequence? their_supported_methods(); - sequence? our_supported_methods(); - - OutgoingVerificationRequest? accept(sequence methods); - - [Throws=CryptoStoreError] - StartSasResult? start_sas_verification(); - - [Throws=CryptoStoreError] - QrCode? start_qr_verification(); - ScanResult? scan_qr_code([ByRef] string data); - - OutgoingVerificationRequest? cancel(); - - void set_changes_listener(VerificationRequestListener listener); - VerificationRequestState state(); -}; - [Enum] interface VerificationRequestState { Requested(); @@ -254,57 +64,6 @@ callback interface VerificationRequestListener { void on_change(VerificationRequestState state); }; -dictionary RequestVerificationResult { - VerificationRequest verification; - OutgoingVerificationRequest request; -}; - -dictionary ConfirmVerificationResult { - sequence requests; - SignatureUploadRequest? signature_request; -}; - -interface Verification { - QrCode? as_qr(); - Sas? as_sas(); -}; - -dictionary KeyRequestPair { - Request? cancellation; - Request key_request; -}; - -[Enum] -interface OutgoingVerificationRequest { - ToDevice(string request_id, string event_type, string body); - InRoom(string request_id, string room_id, string event_type, string content); -}; - -[Enum] -interface Request { - ToDevice(string request_id, string event_type, string body); - KeysUpload(string request_id, string body); - KeysQuery(string request_id, sequence users); - KeysClaim(string request_id, record> one_time_keys); - KeysBackup(string request_id, string version, string rooms); - RoomMessage(string request_id, string room_id, string event_type, string content); - SignatureUpload(string request_id, string body); -}; - -dictionary SignatureUploadRequest { - string body; -}; - -enum RequestType { - "KeysQuery", - "KeysClaim", - "KeysUpload", - "ToDevice", - "SignatureUpload", - "KeysBackup", - "RoomMessage", -}; - enum LocalTrust { "Verified", "BlackListed", @@ -312,19 +71,6 @@ enum LocalTrust { "Unset", }; - -enum EventEncryptionAlgorithm { - "OlmV1Curve25519AesSha2", - "MegolmV1AesSha2", -}; - -enum HistoryVisibility { - "Invited", - "Joined", - "Shared", - "WorldReadable", -}; - interface OlmMachine { [Throws=CryptoStoreError] constructor( @@ -333,59 +79,6 @@ interface OlmMachine { [ByRef] string path, string? passphrase ); - - [Throws=CryptoStoreError] - sequence outgoing_requests(); - [Throws=CryptoStoreError] - void mark_request_as_sent( - [ByRef] string request_id, - RequestType request_type, - [ByRef] string response - ); - - [Throws=CryptoStoreError] - UserIdentity? get_identity([ByRef] string user_id, u32 timeout); - [Throws=SignatureError] - SignatureUploadRequest verify_identity([ByRef] string user_id); - [Throws=CryptoStoreError] - Device? get_device([ByRef] string user_id, [ByRef] string device_id, u32 timeout); - [Throws=CryptoStoreError] - void set_local_trust([ByRef] string user_id, [ByRef] string device_id, LocalTrust trust_state); - [Throws=SignatureError] - SignatureUploadRequest verify_device([ByRef] string user_id, [ByRef] string device_id); - [Throws=CryptoStoreError] - sequence get_user_devices([ByRef] string user_id, u32 timeout); - - [Throws=KeyImportError] - KeysImportResult import_room_keys( - [ByRef] string keys, - [ByRef] string passphrase, - ProgressListener progress_listener - ); - [Throws=KeyImportError] - KeysImportResult import_decrypted_room_keys( - [ByRef] string keys, - ProgressListener progress_listener - ); - - [Throws=CryptoStoreError] - boolean is_identity_verified([ByRef] string user_id); - - record> sign([ByRef] string message); - [Throws=CryptoStoreError] - SignatureVerification verify_backup([ByRef] string auth_data); -}; - -dictionary PassphraseInfo { - string private_key_salt; - i32 private_key_iterations; -}; - -dictionary SignatureVerification { - SignatureState device_signature; - SignatureState user_identity_signature; - record other_devices_signatures; - boolean trusted; }; enum SignatureState { @@ -395,12 +88,6 @@ enum SignatureState { "ValidAndTrusted", }; -[Error] -enum DecodeError { - "Decode", - "CryptoStore", -}; - interface BackupRecoveryKey { constructor(); [Name=from_passphrase] @@ -412,56 +99,3 @@ interface BackupRecoveryKey { [Name=from_base58, Throws=DecodeError] constructor(string key); }; - -dictionary MigrationData { - PickledAccount account; - sequence sessions; - sequence inbound_group_sessions; - string? backup_version; - string? backup_recovery_key; - sequence pickle_key; - CrossSigningKeyExport cross_signing; - sequence tracked_users; - record room_settings; -}; - -dictionary SessionMigrationData { - string user_id; - string device_id; - string curve25519_key; - string ed25519_key; - sequence sessions; - sequence inbound_group_sessions; - sequence pickle_key; -}; - -dictionary PickledAccount { - string user_id; - string device_id; - string pickle; - boolean shared; - i64 uploaded_signed_key_count; -}; - -dictionary PickledSession { - string pickle; - string sender_key; - boolean created_using_fallback_key; - string creation_time; - string last_use_time; -}; - -dictionary PickledInboundGroupSession { - string pickle; - string sender_key; - record signing_key; - string room_id; - sequence forwarding_chains; - boolean imported; - boolean backed_up; -}; - -dictionary RoomSettings { - EventEncryptionAlgorithm algorithm; - boolean only_allow_trusted_devices; -}; diff --git a/bindings/matrix-sdk-crypto-ffi/src/responses.rs b/bindings/matrix-sdk-crypto-ffi/src/responses.rs index 935c3e2e1..df6fbcdf2 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/responses.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/responses.rs @@ -28,6 +28,7 @@ use ruma::{ }; use serde_json::json; +#[derive(uniffi::Record)] pub struct SignatureUploadRequest { pub body: String, } @@ -41,6 +42,7 @@ impl From for SignatureUploadRequest { } } +#[derive(uniffi::Record)] pub struct UploadSigningKeysRequest { pub master_key: String, pub self_signing_key: String, @@ -66,6 +68,7 @@ impl From for UploadSigningKeysRequest { } } +#[derive(uniffi::Record)] pub struct BootstrapCrossSigningResult { pub upload_signing_keys_request: UploadSigningKeysRequest, pub signature_request: SignatureUploadRequest, @@ -82,6 +85,7 @@ impl From<(RustUploadSigningKeysRequest, RustSignatureUploadRequest)> } } +#[derive(uniffi::Enum)] pub enum OutgoingVerificationRequest { ToDevice { request_id: String, event_type: String, body: String }, InRoom { request_id: String, room_id: String, event_type: String, content: String }, @@ -112,7 +116,7 @@ impl From for OutgoingVerificationRequest { } } -#[derive(Debug)] +#[derive(Debug, uniffi::Enum)] pub enum Request { ToDevice { request_id: String, event_type: String, body: String }, KeysUpload { request_id: String, body: String }, @@ -221,6 +225,7 @@ pub(crate) fn response_from_string(body: &str) -> Response> { .expect("Can't create HTTP response") } +#[derive(uniffi::Enum)] pub enum RequestType { KeysQuery, KeysClaim, @@ -254,6 +259,7 @@ impl From for RumaDeviceLists { } } +#[derive(uniffi::Record)] pub struct KeysImportResult { /// The number of room keys that were imported. pub imported: i64, diff --git a/bindings/matrix-sdk-crypto-ffi/src/users.rs b/bindings/matrix-sdk-crypto-ffi/src/users.rs index 77b59d04c..485d4be7c 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/users.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/users.rs @@ -4,6 +4,7 @@ use crate::CryptoStoreError; /// Enum representing cross signing identities of our own user or some other /// user. +#[derive(uniffi::Enum)] pub enum UserIdentity { /// Our own user identity. Own { diff --git a/bindings/matrix-sdk-crypto-ffi/src/verification.rs b/bindings/matrix-sdk-crypto-ffi/src/verification.rs index fda5a6989..86561706e 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/verification.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/verification.rs @@ -77,11 +77,13 @@ impl From for SasState { } /// Enum representing the different verification flows we support. +#[derive(uniffi::Object)] pub struct Verification { pub(crate) inner: InnerVerification, pub(crate) runtime: Handle, } +#[uniffi::export] impl Verification { /// Try to represent the `Verification` as an `Sas` verification object, /// returns `None` if the verification is not a `Sas` verification. @@ -105,11 +107,13 @@ impl Verification { } /// The `m.sas.v1` verification flow. +#[derive(uniffi::Object)] pub struct Sas { pub(crate) inner: InnerSas, pub(crate) runtime: Handle, } +#[uniffi::export] impl Sas { /// Get the user id of the other side. pub fn other_user_id(&self) -> String { @@ -170,7 +174,7 @@ impl Sas { /// list of cancel codes can be found in the [spec] /// /// [spec]: https://spec.matrix.org/unstable/client-server-api/#mkeyverificationcancel - pub fn cancel(&self, cancel_code: &str) -> Option { + pub fn cancel(&self, cancel_code: String) -> Option { self.inner.cancel_with_code(cancel_code.into()).map(|r| r.into()) } @@ -248,7 +252,9 @@ impl Sas { pub fn state(&self) -> SasState { self.inner.state().into() } +} +impl Sas { async fn changes_listener( mut stream: impl Stream + std::marker::Unpin, listener: Box, @@ -315,11 +321,13 @@ impl From for QrCodeState { /// The `m.qr_code.scan.v1`, `m.qr_code.show.v1`, and `m.reciprocate.v1` /// verification flow. +#[derive(uniffi::Object)] pub struct QrCode { pub(crate) inner: InnerQr, pub(crate) runtime: Handle, } +#[uniffi::export] impl QrCode { /// Get the user id of the other side. pub fn other_user_id(&self) -> String { @@ -386,7 +394,7 @@ impl QrCode { /// list of cancel codes can be found in the [spec] /// /// [spec]: https://spec.matrix.org/unstable/client-server-api/#mkeyverificationcancel - pub fn cancel(&self, cancel_code: &str) -> Option { + pub fn cancel(&self, cancel_code: String) -> Option { self.inner.cancel_with_code(cancel_code.into()).map(|r| r.into()) } @@ -424,7 +432,9 @@ impl QrCode { pub fn state(&self) -> QrCodeState { self.inner.state().into() } +} +impl QrCode { async fn changes_listener( mut stream: impl Stream + std::marker::Unpin, listener: Box, @@ -468,6 +478,7 @@ impl From for CancelInfo { } /// A result type for starting SAS verifications. +#[derive(uniffi::Record)] pub struct StartSasResult { /// The SAS verification object that got created. pub sas: Arc, @@ -477,6 +488,7 @@ pub struct StartSasResult { } /// A result type for scanning QR codes. +#[derive(uniffi::Record)] pub struct ScanResult { /// The QR code verification object that got created. pub qr: Arc, @@ -486,6 +498,7 @@ pub struct ScanResult { } /// A result type for requesting verifications. +#[derive(uniffi::Record)] pub struct RequestVerificationResult { /// The verification request object that got created. pub verification: Arc, @@ -495,6 +508,7 @@ pub struct RequestVerificationResult { } /// A result type for confirming verifications. +#[derive(uniffi::Record)] pub struct ConfirmVerificationResult { /// The requests that needs to be sent out to notify the other side that we /// confirmed the verification. @@ -558,11 +572,13 @@ impl From for VerificationRequestState { /// The verificatoin request object which then can transition into some concrete /// verification method +#[derive(uniffi::Object)] pub struct VerificationRequest { pub(crate) inner: InnerVerificationRequest, pub(crate) runtime: Handle, } +#[uniffi::export] impl VerificationRequest { /// The id of the other user that is participating in this verification /// request. @@ -709,7 +725,7 @@ impl VerificationRequest { /// /// * `data` - The data that was extracted from the scanned QR code as an /// base64 encoded string, without padding. - pub fn scan_qr_code(&self, data: &str) -> Option { + pub fn scan_qr_code(&self, data: String) -> Option { let data = STANDARD_NO_PAD.decode(data).ok()?; let data = QrVerificationData::from_bytes(data).ok()?; @@ -738,7 +754,9 @@ impl VerificationRequest { pub fn state(&self) -> VerificationRequestState { self.inner.state().into() } +} +impl VerificationRequest { async fn changes_listener( mut stream: impl Stream + std::marker::Unpin, listener: Box, diff --git a/bindings/matrix-sdk-crypto-nodejs/README.md b/bindings/matrix-sdk-crypto-nodejs/README.md index 7e7b80ff1..b8fca601e 100644 --- a/bindings/matrix-sdk-crypto-nodejs/README.md +++ b/bindings/matrix-sdk-crypto-nodejs/README.md @@ -96,8 +96,8 @@ according to [the Node.js Releases Page](https://nodejs.org/en/about/releases/), _and_ which are compatible with [NAPI v6 (Node.js API)](https://nodejs.org/api/n-api.html#node-api-version-matrix). It -means that this binding will work with the following versions: 14.0.0, -16.0.0 and 18.0.0. +means that this binding will work with the following versions: 16.0.0, +18.0.0, 19.0.0 and 20.0.0. Once the Rust compiler, Node.js and npm are installed, you can run the following commands: diff --git a/bindings/matrix-sdk-crypto-nodejs/package.json b/bindings/matrix-sdk-crypto-nodejs/package.json index e7e3ed1fe..36de43e42 100644 --- a/bindings/matrix-sdk-crypto-nodejs/package.json +++ b/bindings/matrix-sdk-crypto-nodejs/package.json @@ -20,7 +20,7 @@ "yargs-parser": "~21.0.1" }, "engines": { - "node": ">= 14" + "node": ">= 16" }, "scripts": { "lint": "prettier --check .", diff --git a/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs b/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs index 240a21729..69ce50052 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs @@ -1,7 +1,7 @@ use std::time::Duration; use matrix_sdk_common::deserialized_responses::ShieldState as RustShieldState; -use napi::bindgen_prelude::{BigInt, ToNapiValue}; +use napi::bindgen_prelude::{BigInt, FromNapiValue, ToNapiValue}; use napi_derive::*; use crate::events; diff --git a/bindings/matrix-sdk-crypto-nodejs/src/events.rs b/bindings/matrix-sdk-crypto-nodejs/src/events.rs index ce6916d55..aca9d4da4 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/events.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/events.rs @@ -1,6 +1,6 @@ //! Types related to events. -use napi::bindgen_prelude::ToNapiValue; +use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; use napi_derive::*; use ruma::events::room::history_visibility::HistoryVisibility as RumaHistoryVisibility; diff --git a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs b/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs index f5b6c4b55..c7b8f1025 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs @@ -1,7 +1,7 @@ //! Types for [Matrix](https://matrix.org/) identifiers for devices, //! events, keys, rooms, servers, users and URIs. -use napi::bindgen_prelude::ToNapiValue; +use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; use napi_derive::*; use crate::into_err; diff --git a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs b/bindings/matrix-sdk-crypto-nodejs/src/machine.rs index 52ef0e8d5..a525ec3fb 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/machine.rs @@ -7,7 +7,7 @@ use std::{ sync::Arc, }; -use napi::bindgen_prelude::{within_runtime_if_available, Either7, ToNapiValue}; +use napi::bindgen_prelude::{within_runtime_if_available, Either7, FromNapiValue, ToNapiValue}; use napi_derive::*; use ruma::{serde::Raw, DeviceKeyAlgorithm, OwnedTransactionId, UInt}; use serde_json::{value::RawValue, Value as JsonValue}; diff --git a/bindings/matrix-sdk-crypto-nodejs/src/requests.rs b/bindings/matrix-sdk-crypto-nodejs/src/requests.rs index 03c27cbac..35d16d4f6 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/requests.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/requests.rs @@ -6,7 +6,7 @@ use matrix_sdk_crypto::requests::{ KeysBackupRequest as RumaKeysBackupRequest, KeysQueryRequest as RumaKeysQueryRequest, RoomMessageRequest as RumaRoomMessageRequest, ToDeviceRequest as RumaToDeviceRequest, }; -use napi::bindgen_prelude::{Either7, ToNapiValue}; +use napi::bindgen_prelude::{Either7, FromNapiValue, ToNapiValue}; use napi_derive::*; use ruma::{ api::client::keys::{ diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index 2b7aba8c4..2ec81b96c 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -1,8 +1,5 @@ namespace matrix_sdk_ffi {}; - -interface TaskHandle {}; - [Error] interface ClientError { Generic(string msg); @@ -12,16 +9,6 @@ callback interface ClientDelegate { void did_receive_auth_error(boolean is_soft_logout); }; -dictionary RequiredState { - string key; - string value; -}; - -dictionary RoomSubscription { - sequence? required_state; - u32? timeline_limit; -}; - dictionary UpdateSummary { sequence lists; sequence rooms; @@ -93,59 +80,10 @@ callback interface SlidingSyncListRoomItemsObserver { interface SlidingSyncListBuilder { constructor(); - - [Self=ByArc] - SlidingSyncListBuilder sync_mode(SlidingSyncMode mode); - - [Throws=ClientError, Self=ByArc] - SlidingSyncList build(); -}; - -interface SlidingSyncList { - TaskHandle observe_room_list(SlidingSyncListRoomListObserver observer); - TaskHandle observe_rooms_count(SlidingSyncListRoomsCountObserver observer); - TaskHandle observe_state(SlidingSyncListStateObserver observer); -}; - -interface SlidingSyncRoom { - [Throws=ClientError] - SlidingSyncSubscribeResult subscribe_and_add_timeline_listener(TimelineListener listener, RoomSubscription? settings); - [Throws=ClientError] - SlidingSyncSubscribeResult add_timeline_listener(TimelineListener listener); -}; - -dictionary SlidingSyncSubscribeResult { - sequence items; - TaskHandle task_handle; -}; - -interface SlidingSync { - void set_observer(SlidingSyncObserver? observer); - - [Throws=ClientError] - void subscribe(string room_id, RoomSubscription? settings); - [Throws=ClientError] - void unsubscribe(string room_id); - - [Throws=ClientError] - SlidingSyncRoom? get_room(string room_id); - [Throws=ClientError] - sequence get_rooms(sequence room_ids); }; interface ClientBuilder { constructor(); - - [Throws=ClientError, Self=ByArc] - Client build(); -}; - -interface SlidingSyncBuilder { - [Throws=ClientError, Self=ByArc] - SlidingSyncBuilder homeserver(string url); - - [Throws=ClientError, Self=ByArc] - SlidingSync build(); }; dictionary CreateRoomParameters { @@ -181,107 +119,8 @@ enum RoomPreset { "TrustedPrivateChat", }; -interface Client { - void set_delegate(ClientDelegate? delegate); - - [Throws=ClientError] - void login(string username, string password, string? initial_device_name, string? device_id); - - [Throws=ClientError] - MediaFileHandle get_media_file(MediaSource source, string mime_type); -}; - -interface MediaFileHandle { - string path(); -}; - -enum MembershipState { - /// The user is banned. - "Ban", - /// The user has been invited. - "Invite", - /// The user has joined. - "Join", - /// The user has requested to join. - "Knock", - /// The user has left. - "Leave", -}; - interface RoomMember { }; -interface Room { - [Throws=ClientError] - string display_name(); - - [Throws=ClientError] - boolean is_encrypted(); - - [Throws=ClientError] - sequence members(); - - [Throws=ClientError] - string? member_avatar_url(string user_id); - - [Throws=ClientError] - string? member_display_name(string user_id); - - sequence add_timeline_listener(TimelineListener listener); - - // Loads older messages into the timeline. - // - // Raises an exception if there are no timeline listeners. - [Throws=ClientError] - void paginate_backwards(PaginationOptions opts); - - [Throws=ClientError] - void send_read_receipt(string event_id); - - [Throws=ClientError] - void send_read_marker(string fully_read_event_id, string? read_receipt_event_id); - - void send(RoomMessageEventContent msg, string? txn_id); - - [Throws=ClientError] - void send_reply(string msg, string in_reply_to_event_id, string? txn_id); - - [Throws=ClientError] - void edit(string new_msg, string original_event_id, string? txn_id); - - [Throws=ClientError] - void redact(string event_id, string? reason, string? txn_id); - - [Throws=ClientError] - void report_content(string event_id, i32? score, string? reason); - - [Throws=ClientError] - void ignore_user(string user_id); - - [Throws=ClientError] - void send_reaction(string event_id, string key); - - [Throws=ClientError] - void leave(); - - [Throws=ClientError] - void reject_invitation(); - - [Throws=ClientError] - void accept_invitation(); - - [Throws=ClientError] - void set_topic(string topic); - - [Throws=ClientError] - void upload_avatar(string mime_type, sequence data); - - [Throws=ClientError] - void remove_avatar(); - - [Throws=ClientError] - void invite_user_by_id(string user_id); -}; - callback interface TimelineListener { void on_update(TimelineDiff update); }; @@ -311,19 +150,8 @@ interface AuthenticationService { constructor(string base_path, string? passphrase, string? custom_sliding_sync_proxy); }; -dictionary NotificationItem { - TimelineItem item; - string title; - string? subtitle; - boolean is_noisy; - string? avatar_url; -}; - interface NotificationService { constructor(string base_path, string user_id); - - [Throws=ClientError] - NotificationItem? get_notification_item(string room_id, string event_id); }; interface SessionVerificationEmoji {}; @@ -337,25 +165,6 @@ callback interface SessionVerificationControllerDelegate { void did_finish(); }; -interface SessionVerificationController { - void set_delegate(SessionVerificationControllerDelegate? delegate); - - [Throws=ClientError] - void request_verification(); - - [Throws=ClientError] - void start_sas_verification(); - - [Throws=ClientError] - void approve_verification(); - - [Throws=ClientError] - void decline_verification(); - - [Throws=ClientError] - void cancel_verification(); -}; - interface Span { constructor(string file, u32 line, u32 column, LogLevel level, string target, string name); [Name=current] diff --git a/bindings/matrix-sdk-ffi/src/authentication_service.rs b/bindings/matrix-sdk-ffi/src/authentication_service.rs index 50ed05702..58df9ef2a 100644 --- a/bindings/matrix-sdk-ffi/src/authentication_service.rs +++ b/bindings/matrix-sdk-ffi/src/authentication_service.rs @@ -9,6 +9,7 @@ use url::Url; use zeroize::Zeroize; use super::{client::Client, client_builder::ClientBuilder, RUNTIME}; +use crate::error::ClientError; pub struct AuthenticationService { base_path: String, @@ -144,7 +145,7 @@ impl AuthenticationService { } } - let client = builder.build().or_else(|e| { + let client = builder.build_inner().or_else(|e| { if !server_name_or_homeserver_url.starts_with("http://") && !server_name_or_homeserver_url.starts_with("https://") { @@ -153,7 +154,7 @@ impl AuthenticationService { // When discovery fails, fallback to the homeserver URL if supplied. let mut builder = Arc::new(ClientBuilder::new()).base_path(self.base_path.clone()); builder = builder.homeserver_url(server_name_or_homeserver_url); - builder.build() + builder.build_inner() })?; let details = RUNTIME.block_on(self.details_from_client(&client))?; @@ -186,7 +187,9 @@ impl AuthenticationService { // Login and ask the server for the full user ID as this could be different from // the username that was entered. - client.login(username, password, initial_device_name, device_id)?; + client.login(username, password, initial_device_name, device_id).map_err(|e| match e { + ClientError::Generic { msg } => AuthenticationError::Generic { message: msg }, + })?; let whoami = client.whoami()?; // Create a new client to setup the store path now the user ID is known. @@ -208,7 +211,7 @@ impl AuthenticationService { .homeserver_url(homeserver_url) .sliding_sync_proxy(sliding_sync_proxy) .username(whoami.user_id.to_string()) - .build()?; + .build_inner()?; // Restore the client using the session from the login request. client.restore_session_inner(session)?; @@ -260,7 +263,7 @@ impl AuthenticationService { .passphrase(self.passphrase.clone()) .homeserver_url(homeserver_url) .username(whoami.user_id.to_string()) - .build()?; + .build_inner()?; // Restore the client using the session. client.restore_session_inner(session)?; diff --git a/bindings/matrix-sdk-ffi/src/client.rs b/bindings/matrix-sdk-ffi/src/client.rs index 97db62fa2..bff556779 100644 --- a/bindings/matrix-sdk-ffi/src/client.rs +++ b/bindings/matrix-sdk-ffi/src/client.rs @@ -105,7 +105,7 @@ pub trait ClientDelegate: Sync + Send { fn did_receive_auth_error(&self, is_soft_logout: bool); } -#[derive(Clone)] +#[derive(Clone, uniffi::Object)] pub struct Client { pub(crate) client: MatrixClient, delegate: Arc>>>, @@ -161,7 +161,10 @@ impl Client { client } +} +#[uniffi::export] +impl Client { /// Login using a username and password. pub fn login( &self, @@ -169,7 +172,7 @@ impl Client { password: String, initial_device_name: Option, device_id: Option, - ) -> anyhow::Result<()> { + ) -> Result<(), ClientError> { RUNTIME.block_on(async move { let mut builder = self.client.login_username(&username, &password); if let Some(initial_device_name) = initial_device_name.as_ref() { @@ -187,7 +190,7 @@ impl Client { &self, media_source: Arc, mime_type: String, - ) -> anyhow::Result> { + ) -> Result, ClientError> { let client = self.client.clone(); let source = (*media_source).clone(); let mime_type: mime::Mime = mime_type.parse()?; @@ -205,10 +208,7 @@ impl Client { Ok(Arc::new(MediaFileHandle { inner: handle })) }) } -} -#[uniffi::export] -impl Client { /// Restores the client from a `Session`. pub fn restore_session(&self, session: Session) -> Result<(), ClientError> { let Session { @@ -241,17 +241,13 @@ impl Client { }) } - pub fn set_delegate(&self, delegate: Option>) { - *self.delegate.write().unwrap() = delegate; - } - - pub async fn async_homeserver(&self) -> String { + pub(crate) async fn async_homeserver(&self) -> String { self.client.homeserver().await.to_string() } /// The OIDC Provider that is trusted by the homeserver. `None` when /// not configured. - pub async fn authentication_issuer(&self) -> Option { + pub(crate) async fn authentication_issuer(&self) -> Option { self.client.authentication_issuer().await } @@ -268,7 +264,7 @@ impl Client { } /// Whether or not the client's homeserver supports the password login flow. - pub async fn supports_password_login(&self) -> anyhow::Result { + pub(crate) async fn supports_password_login(&self) -> anyhow::Result { let login_types = self.client.get_login_types().await?; let supports_password = login_types .flows @@ -278,7 +274,7 @@ impl Client { } /// Gets information about the owner of a given access token. - pub fn whoami(&self) -> anyhow::Result { + pub(crate) fn whoami(&self) -> anyhow::Result { RUNTIME .block_on(async move { self.client.whoami().await.map_err(|e| anyhow!(e.to_string())) }) } @@ -286,6 +282,10 @@ impl Client { #[uniffi::export] impl Client { + pub fn set_delegate(&self, delegate: Option>) { + *self.delegate.write().unwrap() = delegate; + } + pub fn session(&self) -> Result { RUNTIME.block_on(async move { let matrix_sdk::Session { access_token, refresh_token, user_id, device_id } = @@ -722,10 +722,12 @@ fn gen_transaction_id() -> String { /// A file handle that takes ownership of a media file on disk. When the handle /// is dropped, the file will be removed from the disk. +#[derive(uniffi::Object)] pub struct MediaFileHandle { inner: SdkMediaFileHandle, } +#[uniffi::export] impl MediaFileHandle { /// Get the media file's path. pub fn path(&self) -> String { diff --git a/bindings/matrix-sdk-ffi/src/client_builder.rs b/bindings/matrix-sdk-ffi/src/client_builder.rs index ca77642a6..539b4e6b8 100644 --- a/bindings/matrix-sdk-ffi/src/client_builder.rs +++ b/bindings/matrix-sdk-ffi/src/client_builder.rs @@ -13,7 +13,7 @@ use sanitize_filename_reader_friendly::sanitize; use zeroize::Zeroizing; use super::{client::Client, RUNTIME}; -use crate::helpers::unwrap_or_clone_arc; +use crate::{error::ClientError, helpers::unwrap_or_clone_arc}; #[derive(Clone)] pub struct ClientBuilder { @@ -28,6 +28,22 @@ pub struct ClientBuilder { inner: MatrixClientBuilder, } +impl ClientBuilder { + pub fn new() -> Self { + Self { + base_path: None, + username: None, + server_name: None, + homeserver_url: None, + server_versions: None, + passphrase: Zeroizing::new(None), + user_agent: None, + sliding_sync_proxy: None, + inner: MatrixClient::builder(), + } + } +} + #[uniffi::export] impl ClientBuilder { pub fn base_path(self: Arc, path: String) -> Arc { @@ -77,24 +93,14 @@ impl ClientBuilder { builder.sliding_sync_proxy = sliding_sync_proxy; Arc::new(builder) } + + pub fn build(self: Arc) -> Result, ClientError> { + Ok(self.build_inner()?) + } } impl ClientBuilder { - pub fn new() -> Self { - Self { - base_path: None, - username: None, - server_name: None, - homeserver_url: None, - server_versions: None, - passphrase: Zeroizing::new(None), - user_agent: None, - sliding_sync_proxy: None, - inner: MatrixClient::builder(), - } - } - - pub fn build(self: Arc) -> anyhow::Result> { + pub(crate) fn build_inner(self: Arc) -> anyhow::Result> { let builder = unwrap_or_clone_arc(self); let mut inner_builder = builder.inner; diff --git a/bindings/matrix-sdk-ffi/src/error.rs b/bindings/matrix-sdk-ffi/src/error.rs index 5209d06db..fe809fa71 100644 --- a/bindings/matrix-sdk-ffi/src/error.rs +++ b/bindings/matrix-sdk-ffi/src/error.rs @@ -1,4 +1,4 @@ -use matrix_sdk::{self, encryption::CryptoStoreError, HttpError, IdParseError}; +use matrix_sdk::{self, encryption::CryptoStoreError, HttpError, IdParseError, StoreError}; #[derive(thiserror::Error, Debug)] pub enum ClientError { @@ -18,6 +18,12 @@ impl From for ClientError { } } +impl From for ClientError { + fn from(e: StoreError) -> Self { + anyhow::Error::from(e).into() + } +} + impl From for ClientError { fn from(e: CryptoStoreError) -> Self { anyhow::Error::from(e).into() @@ -41,3 +47,15 @@ impl From for ClientError { anyhow::Error::from(e).into() } } + +impl From for ClientError { + fn from(e: url::ParseError) -> Self { + anyhow::Error::from(e).into() + } +} + +impl From for ClientError { + fn from(e: mime::FromStrError) -> Self { + anyhow::Error::from(e).into() + } +} diff --git a/bindings/matrix-sdk-ffi/src/notification_service.rs b/bindings/matrix-sdk-ffi/src/notification_service.rs index eb935e098..941af436d 100644 --- a/bindings/matrix-sdk-ffi/src/notification_service.rs +++ b/bindings/matrix-sdk-ffi/src/notification_service.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::TimelineItem; +use crate::{error::ClientError, TimelineItem}; #[allow(dead_code)] pub struct NotificationService { @@ -9,6 +9,7 @@ pub struct NotificationService { } /// Notification item struct. +#[derive(uniffi::Record)] pub struct NotificationItem { /// Actual timeline item for the event sent. pub item: Arc, @@ -32,7 +33,10 @@ impl NotificationService { pub fn new(base_path: String, user_id: String) -> Self { Self { base_path, user_id } } +} +#[uniffi::export] +impl NotificationService { /// Get notification item for a given `room_id `and `event_id`. /// /// Returns `None` if this notification should not be displayed to the user. @@ -40,7 +44,7 @@ impl NotificationService { &self, _room_id: String, _event_id: String, - ) -> anyhow::Result> { + ) -> Result, ClientError> { // TODO: Implement Ok(None) } diff --git a/bindings/matrix-sdk-ffi/src/platform.rs b/bindings/matrix-sdk-ffi/src/platform.rs index cc1fe8324..035062c9b 100644 --- a/bindings/matrix-sdk-ffi/src/platform.rs +++ b/bindings/matrix-sdk-ffi/src/platform.rs @@ -98,7 +98,13 @@ pub fn create_otlp_tracer( fn setup_tracing_helper(configuration: String, colors: bool) { tracing_subscriber::registry() .with(EnvFilter::new(configuration)) - .with(fmt::layer().with_ansi(colors).with_writer(io::stderr)) + .with( + fmt::layer() + .with_file(true) + .with_line_number(true) + .with_ansi(colors) + .with_writer(io::stderr), + ) .init(); } @@ -116,7 +122,13 @@ fn setup_otlp_tracing_helper( tracing_subscriber::registry() .with(EnvFilter::new(configuration)) - .with(fmt::layer().with_ansi(colors).with_writer(io::stderr)) + .with( + fmt::layer() + .with_file(true) + .with_line_number(true) + .with_ansi(colors) + .with_writer(io::stderr), + ) .with(otlp_layer) .init(); diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 71667dc09..1b412cc11 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, RwLock}, }; -use anyhow::{bail, Context, Result}; +use anyhow::{anyhow, bail, Context, Result}; use futures_util::StreamExt; use matrix_sdk::{ room::{timeline::Timeline, Receipts, Room as SdkRoom}, @@ -19,12 +19,13 @@ use matrix_sdk::{ }, EventId, UserId, }, + RoomMemberships, }; use mime::Mime; use tracing::error; use super::RUNTIME; -use crate::{RoomMember, TimelineDiff, TimelineItem, TimelineListener}; +use crate::{error::ClientError, RoomMember, TimelineDiff, TimelineItem, TimelineListener}; #[derive(uniffi::Enum)] pub enum Membership { @@ -35,11 +36,22 @@ pub enum Membership { pub(crate) type TimelineLock = Arc>>>; +#[derive(uniffi::Object)] pub struct Room { room: SdkRoom, timeline: TimelineLock, } +impl Room { + pub(crate) fn new(room: SdkRoom) -> Self { + Room { room, timeline: Default::default() } + } + + pub(crate) fn with_timeline(room: SdkRoom, timeline: TimelineLock) -> Self { + Room { room, timeline } + } +} + #[uniffi::export] impl Room { pub fn id(&self) -> String { @@ -139,22 +151,13 @@ impl Room { timeline.fetch_members().await; }); } -} -impl Room { - pub fn new(room: SdkRoom) -> Self { - Room { room, timeline: Default::default() } - } - pub fn with_timeline(room: SdkRoom, timeline: TimelineLock) -> Self { - Room { room, timeline } - } - - pub fn display_name(&self) -> Result { + pub fn display_name(&self) -> Result { let r = self.room.clone(); RUNTIME.block_on(async move { Ok(r.display_name().await?.to_string()) }) } - pub fn is_encrypted(&self) -> Result { + pub fn is_encrypted(&self) -> Result { let room = self.room.clone(); RUNTIME.block_on(async move { let is_encrypted = room.is_encrypted().await?; @@ -162,11 +165,11 @@ impl Room { }) } - pub fn members(&self) -> Result>> { + pub fn members(&self) -> Result>, ClientError> { let room = self.room.clone(); RUNTIME.block_on(async move { let members = room - .members() + .members(RoomMemberships::empty()) .await? .iter() .map(|m| Arc::new(RoomMember::new(m.clone()))) @@ -175,7 +178,7 @@ impl Room { }) } - pub fn member_avatar_url(&self, user_id: String) -> Result> { + pub fn member_avatar_url(&self, user_id: String) -> Result, ClientError> { let room = self.room.clone(); let user_id = user_id; RUNTIME.block_on(async move { @@ -186,7 +189,7 @@ impl Room { }) } - pub fn member_display_name(&self, user_id: String) -> Result> { + pub fn member_display_name(&self, user_id: String) -> Result, ClientError> { let room = self.room.clone(); let user_id = user_id; RUNTIME.block_on(async move { @@ -233,18 +236,25 @@ impl Room { }) } - pub fn paginate_backwards(&self, opts: PaginationOptions) -> Result<()> { + /// Loads older messages into the timeline. + /// + /// Raises an exception if there are no timeline listeners. + pub fn paginate_backwards(&self, opts: PaginationOptions) -> Result<(), ClientError> { if let Some(timeline) = &*self.timeline.read().unwrap() { RUNTIME.block_on(async move { Ok(timeline.paginate_backwards(opts.into()).await?) }) } else { - bail!("No timeline listeners registered, can't paginate"); + Err(anyhow!("No timeline listeners registered, can't paginate").into()) } } - pub fn send_read_receipt(&self, event_id: String) -> Result<()> { + pub fn send_read_receipt(&self, event_id: String) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't send read receipts to room that isn't in joined state"), + _ => { + return Err( + anyhow!("Can't send read receipts to room that isn't in joined state").into() + ) + } }; let event_id = EventId::parse(event_id)?; @@ -260,10 +270,14 @@ impl Room { &self, fully_read_event_id: String, read_receipt_event_id: Option, - ) -> Result<()> { + ) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't send read markers to room that isn't in joined state"), + _ => { + return Err( + anyhow!("Can't send read markers to room that isn't in joined state").into() + ) + } }; let fully_read = @@ -300,15 +314,15 @@ impl Room { msg: String, in_reply_to_event_id: String, txn_id: Option, - ) -> Result<()> { + ) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't send to a room that isn't in joined state"), + _ => return Err(anyhow!("Can't send to a room that isn't in joined state").into()), }; let timeline = match &*self.timeline.read().unwrap() { Some(t) => Arc::clone(t), - None => bail!("Timeline not set up, can't send message"), + None => return Err(anyhow!("Timeline not set up, can't send message").into()), }; let event_id: &EventId = @@ -342,15 +356,15 @@ impl Room { new_msg: String, original_event_id: String, txn_id: Option, - ) -> Result<()> { + ) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't send to a room that isn't in joined state"), + _ => return Err(anyhow!("Can't send to a room that isn't in joined state").into()), }; let timeline = match &*self.timeline.read().unwrap() { Some(t) => Arc::clone(t), - None => bail!("Timeline not set up, can't send message"), + None => return Err(anyhow!("Timeline not set up, can't send message").into()), }; let event_id: &EventId = @@ -365,7 +379,7 @@ impl Room { .context("Couldn't deserialise event")?; if self.own_user_id() != event_content.sender() { - bail!("Can't edit an event not sent by own user") + bail!("Can't edit an event not sent by own user"); } let replacement = Replacement::new( @@ -399,10 +413,10 @@ impl Room { event_id: String, reason: Option, txn_id: Option, - ) -> Result<()> { + ) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't redact in a room that isn't in joined state"), + _ => return Err(anyhow!("Can't redact in a room that isn't in joined state").into()), }; RUNTIME.block_on(async move { @@ -412,10 +426,14 @@ impl Room { }) } - pub fn send_reaction(&self, event_id: String, key: String) -> Result<()> { + pub fn send_reaction(&self, event_id: String, key: String) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't send reaction in a room that isn't in joined state"), + _ => { + return Err( + anyhow!("Can't send reaction in a room that isn't in joined state").into() + ) + } }; RUNTIME.block_on(async move { @@ -440,7 +458,7 @@ impl Room { event_id: String, score: Option, reason: Option, - ) -> Result<()> { + ) -> Result<(), ClientError> { let int_score = score.map(|value| value.into()); RUNTIME.block_on(async move { let event_id = EventId::parse(event_id)?; @@ -465,7 +483,7 @@ impl Room { /// # Arguments /// /// * `event_id` - The ID of the user to ignore. - pub fn ignore_user(&self, user_id: String) -> Result<()> { + pub fn ignore_user(&self, user_id: String) -> Result<(), ClientError> { RUNTIME.block_on(async move { let user_id = UserId::parse(user_id)?; self.client().account().ignore_user(&user_id).await?; @@ -476,10 +494,10 @@ impl Room { /// Leaves the joined room. /// /// Will throw an error if used on an room that isn't in a joined state - pub fn leave(&self) -> Result<()> { + pub fn leave(&self) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't leave a room that isn't in joined state"), + _ => return Err(anyhow!("Can't leave a room that isn't in joined state").into()), }; RUNTIME.block_on(async move { @@ -491,10 +509,15 @@ impl Room { /// Rejects the invitation for the invited room. /// /// Will throw an error if used on an room that isn't in an invited state - pub fn reject_invitation(&self) -> Result<()> { + pub fn reject_invitation(&self) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Invited(i) => i.clone(), - _ => bail!("Can't reject an invite for a room that isn't in invited state"), + _ => { + return Err(anyhow!( + "Can't reject an invite for a room that isn't in invited state" + ) + .into()) + } }; RUNTIME.block_on(async move { @@ -506,10 +529,15 @@ impl Room { /// Accepts the invitation for the invited room. /// /// Will throw an error if used on an room that isn't in an invited state - pub fn accept_invitation(&self) -> Result<()> { + pub fn accept_invitation(&self) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Invited(i) => i.clone(), - _ => bail!("Can't accept an invite for a room that isn't in invited state"), + _ => { + return Err(anyhow!( + "Can't accept an invite for a room that isn't in invited state" + ) + .into()) + } }; RUNTIME.block_on(async move { @@ -519,10 +547,12 @@ impl Room { } /// Sets a new topic in the room. - pub fn set_topic(&self, topic: String) -> Result<()> { + pub fn set_topic(&self, topic: String) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't set a topic in a room that isn't in joined state"), + _ => { + return Err(anyhow!("Can't set a topic in a room that isn't in joined state").into()) + } }; RUNTIME.block_on(async move { @@ -543,10 +573,14 @@ impl Room { /// image/jpeg /// * `data` - The raw data that will be uploaded to the homeserver's /// content repository - pub fn upload_avatar(&self, mime_type: String, data: Vec) -> Result<()> { + pub fn upload_avatar(&self, mime_type: String, data: Vec) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't set a avatar in a room that isn't in joined state"), + _ => { + return Err( + anyhow!("Can't set a avatar in a room that isn't in joined state").into() + ) + } }; RUNTIME.block_on(async move { @@ -558,10 +592,14 @@ impl Room { } /// Removes the current room avatar - pub fn remove_avatar(&self) -> Result<()> { + pub fn remove_avatar(&self) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(j) => j.clone(), - _ => bail!("Can't remove a avatar in a room that isn't in joined state"), + _ => { + return Err( + anyhow!("Can't remove a avatar in a room that isn't in joined state").into() + ) + } }; RUNTIME.block_on(async move { @@ -570,10 +608,10 @@ impl Room { }) } - pub fn invite_user_by_id(&self, user_id: String) -> Result<()> { + pub fn invite_user_by_id(&self, user_id: String) -> Result<(), ClientError> { let room = match &self.room { SdkRoom::Joined(joined_room) => joined_room.clone(), - _ => bail!("Can't invite user to room that isn't in joined state"), + _ => return Err(anyhow!("Can't invite user to room that isn't in joined state").into()), }; RUNTIME.block_on(async move { @@ -583,6 +621,22 @@ impl Room { Ok(()) }) } + + pub fn fetch_event_details(&self, event_id: String) -> Result<(), ClientError> { + let timeline = self + .timeline + .read() + .unwrap() + .as_ref() + .context("Timeline not set up, can't fetch event details")? + .clone(); + + RUNTIME.block_on(async move { + let event_id = <&EventId>::try_from(event_id.as_str())?; + timeline.fetch_event_details(event_id).await.context("Fetching event details")?; + Ok(()) + }) + } } impl std::ops::Deref for Room { diff --git a/bindings/matrix-sdk-ffi/src/room_member.rs b/bindings/matrix-sdk-ffi/src/room_member.rs index 4b4a1dfd4..fe3957115 100644 --- a/bindings/matrix-sdk-ffi/src/room_member.rs +++ b/bindings/matrix-sdk-ffi/src/room_member.rs @@ -3,7 +3,7 @@ use matrix_sdk::room::RoomMember as SdkRoomMember; use super::RUNTIME; use crate::ClientError; -#[derive(Clone)] +#[derive(Clone, uniffi::Enum)] pub enum MembershipState { /// The user is banned. Ban, diff --git a/bindings/matrix-sdk-ffi/src/session_verification.rs b/bindings/matrix-sdk-ffi/src/session_verification.rs index 0ab4f89bd..eceba4699 100644 --- a/bindings/matrix-sdk-ffi/src/session_verification.rs +++ b/bindings/matrix-sdk-ffi/src/session_verification.rs @@ -7,13 +7,11 @@ use matrix_sdk::{ verification::{SasState, SasVerification, VerificationRequest}, Encryption, }, - ruma::{ - events::{key::verification::VerificationMethod, AnyToDeviceEvent}, - serde::Raw, - }, + ruma::events::{key::verification::VerificationMethod, AnyToDeviceEvent}, }; use super::RUNTIME; +use crate::error::ClientError; pub struct SessionVerificationEmoji { symbol: String, @@ -42,7 +40,7 @@ pub trait SessionVerificationControllerDelegate: Sync + Send { pub type Delegate = Arc>>>; -#[derive(Clone)] +#[derive(Clone, uniffi::Object)] pub struct SessionVerificationController { encryption: Encryption, user_identity: UserIdentity, @@ -56,35 +54,26 @@ impl SessionVerificationController { pub fn is_verified(&self) -> bool { self.user_identity.is_verified() } -} - -impl SessionVerificationController { - pub fn new(encryption: Encryption, user_identity: UserIdentity) -> Self { - SessionVerificationController { - encryption, - user_identity, - delegate: Arc::new(RwLock::new(None)), - verification_request: Arc::new(RwLock::new(None)), - sas_verification: Arc::new(RwLock::new(None)), - } - } pub fn set_delegate(&self, delegate: Option>) { *self.delegate.write().unwrap() = delegate; } - pub fn request_verification(&self) -> anyhow::Result<()> { + pub fn request_verification(&self) -> Result<(), ClientError> { RUNTIME.block_on(async move { let methods = vec![VerificationMethod::SasV1]; - let verification_request = - self.user_identity.request_verification_with_methods(methods).await?; + let verification_request = self + .user_identity + .request_verification_with_methods(methods) + .await + .map_err(anyhow::Error::from)?; *self.verification_request.write().unwrap() = Some(verification_request); Ok(()) }) } - pub fn start_sas_verification(&self) -> anyhow::Result<()> { + pub fn start_sas_verification(&self) -> Result<(), ClientError> { RUNTIME.block_on(async move { let verification_request = self.verification_request.read().unwrap().clone(); @@ -112,7 +101,7 @@ impl SessionVerificationController { }) } - pub fn approve_verification(&self) -> anyhow::Result<()> { + pub fn approve_verification(&self) -> Result<(), ClientError> { RUNTIME.block_on(async move { let sas_verification = self.sas_verification.read().unwrap().clone(); if let Some(sas_verification) = sas_verification { @@ -123,7 +112,7 @@ impl SessionVerificationController { }) } - pub fn decline_verification(&self) -> anyhow::Result<()> { + pub fn decline_verification(&self) -> Result<(), ClientError> { RUNTIME.block_on(async move { let sas_verification = self.sas_verification.read().unwrap().clone(); if let Some(sas_verification) = sas_verification { @@ -134,7 +123,7 @@ impl SessionVerificationController { }) } - pub fn cancel_verification(&self) -> anyhow::Result<()> { + pub fn cancel_verification(&self) -> Result<(), ClientError> { RUNTIME.block_on(async move { let verification_request = self.verification_request.read().unwrap().clone(); if let Some(verification) = verification_request { @@ -144,8 +133,20 @@ impl SessionVerificationController { Ok(()) }) } +} - pub async fn process_to_device_message(&self, event: AnyToDeviceEvent) { +impl SessionVerificationController { + pub(crate) fn new(encryption: Encryption, user_identity: UserIdentity) -> Self { + SessionVerificationController { + encryption, + user_identity, + delegate: Arc::new(RwLock::new(None)), + verification_request: Arc::new(RwLock::new(None)), + sas_verification: Arc::new(RwLock::new(None)), + } + } + + pub(crate) async fn process_to_device_message(&self, event: AnyToDeviceEvent) { match event { // TODO: Use the changes stream for this as well once we expose // VerificationRequest::changes() in the main crate. @@ -190,12 +191,6 @@ impl SessionVerificationController { } } - pub async fn process_to_device_messages(&self, to_device_events: Vec>) { - for event in to_device_events.into_iter().filter_map(|e| e.deserialize().ok()) { - self.process_to_device_message(event).await; - } - } - fn is_transaction_id_valid(&self, transaction_id: String) -> bool { match &*self.verification_request.read().unwrap() { Some(verification) => verification.flow_id() == transaction_id, diff --git a/bindings/matrix-sdk-ffi/src/sliding_sync.rs b/bindings/matrix-sdk-ffi/src/sliding_sync.rs index f2ce6db48..67c391a25 100644 --- a/bindings/matrix-sdk-ffi/src/sliding_sync.rs +++ b/bindings/matrix-sdk-ffi/src/sliding_sync.rs @@ -20,12 +20,13 @@ use tracing::{debug, error, warn}; use url::Url; use crate::{ - helpers::unwrap_or_clone_arc, room::TimelineLock, Client, EventTimelineItem, Room, - TimelineDiff, TimelineItem, TimelineListener, RUNTIME, + error::ClientError, helpers::unwrap_or_clone_arc, room::TimelineLock, Client, + EventTimelineItem, Room, TimelineDiff, TimelineItem, TimelineListener, RUNTIME, }; type TaskHandleFinalizer = Box; +#[derive(uniffi::Object)] pub struct TaskHandle { handle: JoinHandle<()>, finalizer: RwLock>, @@ -154,6 +155,7 @@ impl From for SlidingSyncError { } } +#[derive(uniffi::Object)] pub struct SlidingSyncRoom { inner: matrix_sdk::SlidingSyncRoom, timeline: TimelineLock, @@ -206,13 +208,11 @@ impl SlidingSyncRoom { let item = RUNTIME.block_on(self.inner.latest_event())?; Some(Arc::new(EventTimelineItem(item))) } -} -impl SlidingSyncRoom { pub fn add_timeline_listener( &self, listener: Box, - ) -> anyhow::Result { + ) -> Result { let (items, stoppable_spawn) = self.add_timeline_listener_inner(listener)?; Ok(SlidingSyncSubscribeResult { items, task_handle: Arc::new(stoppable_spawn) }) @@ -222,7 +222,7 @@ impl SlidingSyncRoom { &self, listener: Box, settings: Option, - ) -> anyhow::Result { + ) -> Result { let (items, mut stoppable_spawn) = self.add_timeline_listener_inner(listener)?; let room_id = self.inner.room_id().clone(); @@ -233,7 +233,9 @@ impl SlidingSyncRoom { Ok(SlidingSyncSubscribeResult { items, task_handle: Arc::new(stoppable_spawn) }) } +} +impl SlidingSyncRoom { fn add_timeline_listener_inner( &self, listener: Box, @@ -312,6 +314,7 @@ impl SlidingSyncRoom { } } +#[derive(uniffi::Record)] pub struct SlidingSyncSubscribeResult { pub items: Vec>, pub task_handle: Arc, @@ -323,11 +326,13 @@ pub struct UpdateSummary { pub rooms: Vec, } +#[derive(uniffi::Record)] pub struct RequiredState { pub key: String, pub value: String, } +#[derive(uniffi::Record)] pub struct RoomSubscription { pub required_state: Option>, pub timeline_limit: Option, @@ -470,27 +475,21 @@ impl SlidingSyncListBuilder { pub fn new() -> Self { Self { inner: matrix_sdk::SlidingSyncList::builder() } } +} +#[uniffi::export] +impl SlidingSyncListBuilder { pub fn sync_mode(self: Arc, mode: SlidingSyncMode) -> Arc { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.sync_mode(mode); Arc::new(builder) } - pub fn ranges(self: Arc, ranges: Vec<(u32, u32)>) -> Arc { - let mut builder = unwrap_or_clone_arc(self); - builder.inner = builder.inner.ranges(ranges); - Arc::new(builder) - } - - pub fn build(self: Arc) -> anyhow::Result> { + pub fn build(self: Arc) -> Result, ClientError> { let builder = unwrap_or_clone_arc(self); Ok(Arc::new(builder.inner.build()?.into())) } -} -#[uniffi::export] -impl SlidingSyncListBuilder { pub fn sort(self: Arc, sort: Vec) -> Arc { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.sort(sort); @@ -566,7 +565,7 @@ impl SlidingSyncListBuilder { } } -#[derive(Clone)] +#[derive(Clone, uniffi::Object)] pub struct SlidingSyncList { inner: matrix_sdk::SlidingSyncList, } @@ -577,6 +576,7 @@ impl From for SlidingSyncList { } } +#[uniffi::export] impl SlidingSyncList { pub fn observe_state( &self, @@ -622,10 +622,7 @@ impl SlidingSyncList { } }))) } -} -#[uniffi::export] -impl SlidingSyncList { /// Get the current list of rooms pub fn current_room_list(&self) -> Vec { self.inner.room_list() @@ -677,6 +674,7 @@ pub trait SlidingSyncObserver: Sync + Send { fn did_receive_sync_update(&self, summary: UpdateSummary); } +#[derive(uniffi::Object)] pub struct SlidingSync { inner: matrix_sdk::SlidingSync, client: Client, @@ -687,7 +685,10 @@ impl SlidingSync { fn new(inner: matrix_sdk::SlidingSync, client: Client) -> Self { Self { inner, client, observer: Default::default() } } +} +#[uniffi::export] +impl SlidingSync { pub fn set_observer(&self, observer: Option>) { *self.observer.write().unwrap() = observer; } @@ -696,17 +697,17 @@ impl SlidingSync { &self, room_id: String, settings: Option, - ) -> anyhow::Result<()> { + ) -> Result<(), ClientError> { self.inner.subscribe(room_id.try_into()?, settings.map(Into::into)); Ok(()) } - pub fn unsubscribe(&self, room_id: String) -> anyhow::Result<()> { + pub fn unsubscribe(&self, room_id: String) -> Result<(), ClientError> { self.inner.unsubscribe(room_id.try_into()?); Ok(()) } - pub fn get_room(&self, room_id: String) -> anyhow::Result>> { + pub fn get_room(&self, room_id: String) -> Result>, ClientError> { let runner = self.inner.clone(); Ok(self.inner.get_room(<&RoomId>::try_from(room_id.as_str())?).map(|inner| { @@ -722,7 +723,7 @@ impl SlidingSync { pub fn get_rooms( &self, room_ids: Vec, - ) -> anyhow::Result>>> { + ) -> Result>>, ClientError> { let actual_ids = room_ids .into_iter() .map(OwnedRoomId::try_from) @@ -743,10 +744,7 @@ impl SlidingSync { }) .collect()) } -} -#[uniffi::export] -impl SlidingSync { #[allow(clippy::significant_drop_in_scrutinee)] pub fn get_list(&self, name: String) -> Option> { self.inner.list(&name).map(|inner| Arc::new(SlidingSyncList { inner })) @@ -800,29 +798,20 @@ impl SlidingSync { } } -#[derive(Clone)] +#[derive(Clone, uniffi::Object)] pub struct SlidingSyncBuilder { inner: MatrixSlidingSyncBuilder, client: Client, } +#[uniffi::export] impl SlidingSyncBuilder { - pub fn homeserver(self: Arc, url: String) -> anyhow::Result> { + pub fn homeserver(self: Arc, url: String) -> Result, ClientError> { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.homeserver(url.parse()?); Ok(Arc::new(builder)) } - pub fn build(self: Arc) -> anyhow::Result> { - let builder = unwrap_or_clone_arc(self); - RUNTIME.block_on(async move { - Ok(Arc::new(SlidingSync::new(builder.inner.build().await?, builder.client))) - }) - } -} - -#[uniffi::export] -impl SlidingSyncBuilder { pub fn storage_key(self: Arc, name: Option) -> Arc { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.storage_key(name); @@ -877,6 +866,21 @@ impl SlidingSyncBuilder { builder.inner = builder.inner.with_all_extensions(); Arc::new(builder) } + + pub fn bump_event_types(self: Arc, bump_event_types: Vec) -> Arc { + let mut builder = unwrap_or_clone_arc(self); + builder.inner = builder.inner.bump_event_types( + bump_event_types.into_iter().map(Into::into).collect::>().as_slice(), + ); + Arc::new(builder) + } + + pub fn build(self: Arc) -> Result, ClientError> { + let builder = unwrap_or_clone_arc(self); + RUNTIME.block_on(async move { + Ok(Arc::new(SlidingSync::new(builder.inner.build().await?, builder.client))) + }) + } } #[uniffi::export] diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index 1af38e122..145c28bd4 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -550,7 +550,7 @@ mod tests { use matrix_sdk::{ config::RequestConfig, ruma::{api::appservice::Registration, events::room::member::OriginalSyncRoomMemberEvent}, - Client, + Client, RoomMemberships, }; use matrix_sdk_test::{appservice::TransactionBuilder, async_test, TimelineTestEvent}; use ruma::{ @@ -888,7 +888,7 @@ mod tests { .await? .get_room(room_id) .expect("Expected room to be available") - .members_no_sync() + .members_no_sync(RoomMemberships::empty()) .await?; assert_eq!(members[0].display_name().unwrap(), "changed"); diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index 688577bf2..3530eb570 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -30,6 +30,7 @@ testing = ["dep:http", "dep:matrix-sdk-test", "dep:assert_matches"] assert_matches = { workspace = true, optional = true } async-stream = { workspace = true } async-trait = { workspace = true } +bitflags = "2.1.0" dashmap = { workspace = true } eyeball = { workspace = true } futures-core = "0.3.21" diff --git a/crates/matrix-sdk-base/Changelog.md b/crates/matrix-sdk-base/Changelog.md index 99964cb77..fff8ad6e1 100644 --- a/crates/matrix-sdk-base/Changelog.md +++ b/crates/matrix-sdk-base/Changelog.md @@ -6,6 +6,12 @@ - Add `RoomInfo::state` accessor - Remove `members` and `stripped_members` fields in `StateChanges`. Room member events are now with other state events in `state` and `stripped_state`. +- `StateStore::get_user_ids` takes a `RoomMemberships` to be able to filter the results by any + membership state. + - `StateStore::get_joined_user_ids` and `StateStore::get_invited_user_ids` are deprecated. +- `Room::members` takes a `RoomMemberships` to be able to filter the results by any membership + state. + - `Room::active_members` and `Room::joined_members` are deprecated. ## 0.5.1 diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index e17f8dfd3..43ce5a473 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -56,8 +56,6 @@ use ruma::{ use tokio::sync::RwLock; use tracing::{debug, info, trace, warn}; -#[cfg(feature = "e2e-encryption")] -use crate::error::Error; use crate::{ deserialized_responses::{AmbiguityChanges, MembersResponse, SyncTimelineEvent}, error::Result, @@ -69,6 +67,8 @@ use crate::{ sync::{JoinedRoom, LeftRoom, Rooms, SyncResponse, Timeline}, Session, SessionMeta, SessionTokens, }; +#[cfg(feature = "e2e-encryption")] +use crate::{error::Error, RoomMemberships}; /// A no IO Client implementation. /// @@ -757,12 +757,9 @@ impl BaseClient { // The room turned on encryption in this sync, we need // to also get all the existing users and mark them for // tracking. - let joined = self.store.get_joined_user_ids(&room_id).await?; - let invited = self.store.get_invited_user_ids(&room_id).await?; - - let user_ids: Vec<&UserId> = - joined.iter().chain(&invited).map(Deref::deref).collect(); - o.update_tracked_users(user_ids).await? + let user_ids = + self.store.get_user_ids(&room_id, RoomMemberships::ACTIVE).await?; + o.update_tracked_users(user_ids.iter().map(Deref::deref)).await? } o.update_tracked_users(user_ids.iter().map(Deref::deref)).await?; @@ -1058,21 +1055,20 @@ impl BaseClient { .map(|r| (r.history_visibility(), r.encryption_settings())) .unwrap_or((HistoryVisibility::Joined, None)); - let joined = self.store.get_joined_user_ids(room_id).await?; - let invited = self.store.get_invited_user_ids(room_id).await?; - // Don't share the group session with members that are invited // if the history visibility is set to `Joined` - let members = if history_visibility == HistoryVisibility::Joined { - joined.iter().chain(&[]) + let filter = if history_visibility == HistoryVisibility::Joined { + RoomMemberships::JOIN } else { - joined.iter().chain(&invited) + RoomMemberships::ACTIVE }; + let members = self.store.get_user_ids(room_id, filter).await?; + let settings = settings.ok_or(Error::EncryptionNotEnabled)?; let settings = EncryptionSettings::new(settings, history_visibility, false); - Ok(o.share_room_key(room_id, members.map(Deref::deref), settings).await?) + Ok(o.share_room_key(room_id, members.iter().map(Deref::deref), settings).await?) } None => panic!("Olm machine wasn't started"), } diff --git a/crates/matrix-sdk-base/src/lib.rs b/crates/matrix-sdk-base/src/lib.rs index c69e4867f..9712a87bc 100644 --- a/crates/matrix-sdk-base/src/lib.rs +++ b/crates/matrix-sdk-base/src/lib.rs @@ -42,7 +42,7 @@ pub use http; #[cfg(feature = "e2e-encryption")] pub use matrix_sdk_crypto as crypto; pub use once_cell; -pub use rooms::{DisplayName, Room, RoomInfo, RoomMember, RoomState}; +pub use rooms::{DisplayName, Room, RoomInfo, RoomMember, RoomMemberships, RoomState}; pub use store::{StateChanges, StateStore, StateStoreDataKey, StateStoreDataValue, StoreError}; pub use utils::{ MinimalRoomMemberEvent, MinimalStateEvent, OriginalMinimalStateEvent, RedactedMinimalStateEvent, diff --git a/crates/matrix-sdk-base/src/rooms/mod.rs b/crates/matrix-sdk-base/src/rooms/mod.rs index f414fd20e..b3081473f 100644 --- a/crates/matrix-sdk-base/src/rooms/mod.rs +++ b/crates/matrix-sdk-base/src/rooms/mod.rs @@ -3,6 +3,7 @@ mod normal; use std::{collections::HashSet, fmt}; +use bitflags::bitflags; pub use members::RoomMember; pub use normal::{Room, RoomInfo, RoomState}; use ruma::{ @@ -13,9 +14,9 @@ use ruma::{ create::RoomCreateEventContent, encryption::RoomEncryptionEventContent, guest_access::RoomGuestAccessEventContent, history_visibility::RoomHistoryVisibilityEventContent, - join_rules::RoomJoinRulesEventContent, name::RoomNameEventContent, - redaction::OriginalSyncRoomRedactionEvent, tombstone::RoomTombstoneEventContent, - topic::RoomTopicEventContent, + join_rules::RoomJoinRulesEventContent, member::MembershipState, + name::RoomNameEventContent, redaction::OriginalSyncRoomRedactionEvent, + tombstone::RoomTombstoneEventContent, topic::RoomTopicEventContent, }, AnyStrippedStateEvent, AnySyncStateEvent, RedactContent, RedactedStateEventContent, StaticStateEventContent, SyncStateEvent, @@ -307,6 +308,49 @@ fn calculate_room_name( } } +bitflags! { + /// Room membership filter as a bitset. + /// + /// Note that [`RoomMemberships::empty()`] doesn't filter the results and + /// [`RoomMemberships::all()`] filters out unknown memberships. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + pub struct RoomMemberships: u16 { + /// The member joined the room. + const JOIN = 0b00000001; + /// The member was invited to the room. + const INVITE = 0b00000010; + /// The member requested to join the room. + const KNOCK = 0b00000100; + /// The member left the room. + const LEAVE = 0b00001000; + /// The member was banned. + const BAN = 0b00010000; + + /// The member is active in the room (i.e. joined or invited). + const ACTIVE = Self::JOIN.bits() | Self::INVITE.bits(); + } +} + +impl RoomMemberships { + /// Whether the given membership matches this `RoomMemberships`. + pub fn matches(&self, membership: &MembershipState) -> bool { + if self.is_empty() { + return true; + } + + let membership = match membership { + MembershipState::Ban => Self::BAN, + MembershipState::Invite => Self::INVITE, + MembershipState::Join => Self::JOIN, + MembershipState::Knock => Self::KNOCK, + MembershipState::Leave => Self::LEAVE, + _ => return false, + }; + + self.contains(membership) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs index 2b8a38dff..4106d6e4e 100644 --- a/crates/matrix-sdk-base/src/rooms/normal.rs +++ b/crates/matrix-sdk-base/src/rooms/normal.rs @@ -44,7 +44,7 @@ use crate::{ deserialized_responses::MemberEvent, store::{DynStateStore, Result as StoreResult, StateStoreExt}, sync::UnreadNotificationsCount, - MinimalStateEvent, + MinimalStateEvent, RoomMemberships, }; /// The underlying room data structure collecting state for joined, left and @@ -318,12 +318,13 @@ impl Room { /// Get the list of users ids that are considered to be joined members of /// this room. pub async fn joined_user_ids(&self) -> StoreResult> { - self.store.get_joined_user_ids(self.room_id()).await + self.store.get_user_ids(self.room_id(), RoomMemberships::JOIN).await } - /// Get the all `RoomMember`s of this room that are known to the store. - pub async fn members(&self) -> StoreResult> { - let user_ids = self.store.get_user_ids(self.room_id()).await?; + /// Get the `RoomMember`s of this room that are known to the store, with the + /// given memberships. + pub async fn members(&self, memberships: RoomMemberships) -> StoreResult> { + let user_ids = self.store.get_user_ids(self.room_id(), memberships).await?; let mut members = Vec::new(); for u in user_ids { @@ -339,38 +340,16 @@ impl Room { /// Get the list of `RoomMember`s that are considered to be joined members /// of this room. + #[deprecated = "Use members with RoomMemberships::JOIN instead"] pub async fn joined_members(&self) -> StoreResult> { - let joined = self.store.get_joined_user_ids(self.room_id()).await?; - let mut members = Vec::new(); - - for u in joined { - let m = self.get_member(&u).await?; - - if let Some(member) = m { - members.push(member); - } - } - - Ok(members) + self.members(RoomMemberships::JOIN).await } /// Get the list of `RoomMember`s that are considered to be joined or /// invited members of this room. + #[deprecated = "Use members with RoomMemberships::ACTIVE instead"] pub async fn active_members(&self) -> StoreResult> { - let joined = self.store.get_joined_user_ids(self.room_id()).await?; - let invited = self.store.get_invited_user_ids(self.room_id()).await?; - - let mut members = Vec::new(); - - for u in joined.iter().chain(&invited) { - let m = self.get_member(u).await?; - - if let Some(member) = m { - members.push(member); - } - } - - Ok(members) + self.members(RoomMemberships::ACTIVE).await } async fn calculate_name(&self) -> StoreResult { @@ -391,7 +370,12 @@ impl Room { let is_own_user_id = |u: &str| u == self.own_user_id().as_str(); let members: Vec = if summary.heroes.is_empty() { - self.active_members().await?.into_iter().filter(|u| !is_own_member(u)).take(5).collect() + self.members(RoomMemberships::ACTIVE) + .await? + .into_iter() + .filter(|u| !is_own_member(u)) + .take(5) + .collect() } else { let members: Vec<_> = stream::iter(summary.heroes.iter().filter(|u| !is_own_user_id(u))) diff --git a/crates/matrix-sdk-base/src/sliding_sync.rs b/crates/matrix-sdk-base/src/sliding_sync.rs index 0b1cd6847..60951eaa7 100644 --- a/crates/matrix-sdk-base/src/sliding_sync.rs +++ b/crates/matrix-sdk-base/src/sliding_sync.rs @@ -2,8 +2,6 @@ use std::collections::BTreeMap; #[cfg(feature = "e2e-encryption")] use std::ops::Deref; -#[cfg(feature = "e2e-encryption")] -use ruma::UserId; use ruma::{ api::client::sync::sync_events::{ v3::{self, Ephemeral}, @@ -14,6 +12,8 @@ use ruma::{ use tracing::{debug, info, instrument}; use super::BaseClient; +#[cfg(feature = "e2e-encryption")] +use crate::RoomMemberships; use crate::{ deserialized_responses::AmbiguityChanges, error::Result, @@ -196,12 +196,9 @@ impl BaseClient { // The room turned on encryption in this sync, we need // to also get all the existing users and mark them for // tracking. - let joined = store.get_joined_user_ids(room_id).await?; - let invited = store.get_invited_user_ids(room_id).await?; - - let user_ids: Vec<&UserId> = - joined.iter().chain(&invited).map(Deref::deref).collect(); - o.update_tracked_users(user_ids).await? + let user_ids = + store.get_user_ids(room_id, RoomMemberships::ACTIVE).await?; + o.update_tracked_users(user_ids.iter().map(Deref::deref)).await? } if !user_ids.is_empty() { diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index 8cd37af4c..b54ebbb2f 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -35,7 +35,7 @@ use crate::{ deserialized_responses::MemberEvent, media::{MediaFormat, MediaRequest, MediaThumbnailSize}, store::{Result, StateStoreExt}, - RoomInfo, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue, + RoomInfo, RoomMemberships, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue, }; /// `StateStore` integration tests. @@ -330,17 +330,17 @@ impl StateStoreIntegrationTests for DynStateStore { assert!(self.get_profile(room_id, user_id).await?.is_some()); assert!(self.get_member_event(room_id, user_id).await?.is_some()); assert_eq!( - self.get_user_ids(room_id).await?.len(), + self.get_user_ids(room_id, RoomMemberships::empty()).await?.len(), 2, "Expected to find 2 members for room" ); assert_eq!( - self.get_invited_user_ids(room_id).await?.len(), + self.get_user_ids(room_id, RoomMemberships::INVITE).await?.len(), 1, "Expected to find 1 invited user ids" ); assert_eq!( - self.get_joined_user_ids(room_id).await?.len(), + self.get_user_ids(room_id, RoomMemberships::JOIN).await?.len(), 1, "Expected to find 1 joined user ids" ); @@ -394,7 +394,7 @@ impl StateStoreIntegrationTests for DynStateStore { self.save_changes(&changes).await.unwrap(); assert!(self.get_member_event(room_id, user_id).await.unwrap().is_some()); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert!(!members.is_empty(), "We expected to find members for the room") } @@ -466,7 +466,7 @@ impl StateStoreIntegrationTests for DynStateStore { self.save_changes(&changes).await.unwrap(); assert!(self.get_member_event(room_id, user_id).await.unwrap().is_some()); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert!(!members.is_empty(), "We expected to find members for the room") } @@ -774,7 +774,7 @@ impl StateStoreIntegrationTests for DynStateStore { assert_eq!(self.get_room_infos().await.unwrap().len(), 1); assert_eq!(self.get_stripped_room_infos().await.unwrap().len(), 0); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert_eq!(members, vec![user_id.to_owned()]); let mut changes = StateChanges::default(); @@ -788,7 +788,7 @@ impl StateStoreIntegrationTests for DynStateStore { assert_eq!(self.get_room_infos().await.unwrap().len(), 0); assert_eq!(self.get_stripped_room_infos().await.unwrap().len(), 1); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert_eq!(members, vec![user_id.to_owned()]); Ok(()) @@ -813,12 +813,18 @@ impl StateStoreIntegrationTests for DynStateStore { ); assert!(self.get_profile(room_id, user_id).await?.is_none()); assert!(self.get_member_event(room_id, user_id).await?.is_none()); - assert!(self.get_user_ids(room_id).await?.is_empty(), "still user ids found"); assert!( - self.get_invited_user_ids(room_id).await?.is_empty(), + self.get_user_ids(room_id, RoomMemberships::empty()).await?.is_empty(), + "still user ids found" + ); + assert!( + self.get_user_ids(room_id, RoomMemberships::INVITE).await?.is_empty(), "still invited user ids found" ); - assert!(self.get_joined_user_ids(room_id).await?.is_empty(), "still joined users found"); + assert!( + self.get_user_ids(room_id, RoomMemberships::JOIN).await?.is_empty(), + "still joined users found" + ); assert!( self.get_users_with_display_name(room_id, "example").await?.is_empty(), "still display names found" diff --git a/crates/matrix-sdk-base/src/store/memory_store.rs b/crates/matrix-sdk-base/src/store/memory_store.rs index cd571c771..02d99e41b 100644 --- a/crates/matrix-sdk-base/src/store/memory_store.rs +++ b/crates/matrix-sdk-base/src/store/memory_store.rs @@ -18,7 +18,7 @@ use std::{ }; use async_trait::async_trait; -use dashmap::{DashMap, DashSet}; +use dashmap::DashMap; use matrix_sdk_common::instant::Instant; use ruma::{ canonical_json::redact, @@ -38,7 +38,7 @@ use tracing::{debug, warn}; use super::{Result, RoomInfo, StateChanges, StateStore, StoreError}; use crate::{ deserialized_responses::RawMemberEvent, media::MediaRequest, MinimalRoomMemberEvent, - StateStoreDataKey, StateStoreDataValue, + RoomMemberships, StateStoreDataKey, StateStoreDataValue, }; /// In-Memory, non-persistent implementation of the `StateStore` @@ -51,11 +51,9 @@ pub struct MemoryStore { sync_token: Arc>>, filters: Arc>, account_data: Arc>>, - members: Arc>>, profiles: Arc>>, display_names: Arc>>>, - joined_user_ids: Arc>>, - invited_user_ids: Arc>>, + members: Arc>>, room_info: Arc>, room_state: Arc>>>>, @@ -65,9 +63,7 @@ pub struct MemoryStore { stripped_room_state: Arc< DashMap>>>, >, - stripped_members: Arc>>, - stripped_joined_user_ids: Arc>>, - stripped_invited_user_ids: Arc>>, + stripped_members: Arc>>, presence: Arc>>, room_user_receipts: Arc< DashMap< @@ -99,19 +95,15 @@ impl MemoryStore { sync_token: Default::default(), filters: Default::default(), account_data: Default::default(), - members: Default::default(), profiles: Default::default(), display_names: Default::default(), - joined_user_ids: Default::default(), - invited_user_ids: Default::default(), + members: Default::default(), room_info: Default::default(), room_state: Default::default(), room_account_data: Default::default(), stripped_room_infos: Default::default(), stripped_room_state: Default::default(), stripped_members: Default::default(), - stripped_joined_user_ids: Default::default(), - stripped_invited_user_ids: Default::default(), presence: Default::default(), room_user_receipts: Default::default(), room_event_receipts: Default::default(), @@ -240,47 +232,12 @@ impl MemoryStore { } }; - self.stripped_joined_user_ids.remove(room); - self.stripped_invited_user_ids.remove(room); - - match event.membership() { - MembershipState::Join => { - self.joined_user_ids - .entry(room.clone()) - .or_default() - .insert(event.state_key().to_owned()); - self.invited_user_ids - .entry(room.clone()) - .or_default() - .remove(event.state_key()); - } - MembershipState::Invite => { - self.invited_user_ids - .entry(room.clone()) - .or_default() - .insert(event.state_key().to_owned()); - self.joined_user_ids - .entry(room.clone()) - .or_default() - .remove(event.state_key()); - } - _ => { - self.joined_user_ids - .entry(room.clone()) - .or_default() - .remove(event.state_key()); - self.invited_user_ids - .entry(room.clone()) - .or_default() - .remove(event.state_key()); - } - } + self.stripped_members.remove(room); self.members .entry(room.clone()) .or_default() - .insert(event.state_key().to_owned()); - self.stripped_members.remove(room); + .insert(event.state_key().to_owned(), event.membership().clone()); } } } @@ -324,43 +281,10 @@ impl MemoryStore { } }; - match event.content.membership { - MembershipState::Join => { - self.stripped_joined_user_ids - .entry(room.clone()) - .or_default() - .insert(event.state_key.clone()); - self.stripped_invited_user_ids - .entry(room.clone()) - .or_default() - .remove(&event.state_key); - } - MembershipState::Invite => { - self.stripped_invited_user_ids - .entry(room.clone()) - .or_default() - .insert(event.state_key.clone()); - self.stripped_joined_user_ids - .entry(room.clone()) - .or_default() - .remove(&event.state_key); - } - _ => { - self.stripped_joined_user_ids - .entry(room.clone()) - .or_default() - .remove(&event.state_key); - self.stripped_invited_user_ids - .entry(room.clone()) - .or_default() - .remove(&event.state_key); - } - } - self.stripped_members .entry(room.clone()) .or_default() - .insert(event.state_key.clone()); + .insert(event.state_key, event.content.membership.clone()); } } } @@ -507,42 +431,25 @@ impl MemoryStore { } } - fn get_user_ids(&self, room_id: &RoomId) -> Vec { - if let Some(u) = self.stripped_members.get(room_id) { - u.iter().map(|u| u.key().clone()).collect() - } else { - self.members - .get(room_id) - .map(|u| u.iter().map(|u| u.key().clone()).collect()) - .unwrap_or_default() - } - } + /// Get the user IDs for the given room with the given memberships and + /// stripped state. + /// + /// If `memberships` is empty, returns all user IDs in the room with the + /// given stripped state. + fn get_user_ids_inner( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + stripped: bool, + ) -> Vec { + let map = if stripped { &self.stripped_members } else { &self.members }; - fn get_invited_user_ids(&self, room_id: &RoomId) -> Vec { - self.invited_user_ids - .get(room_id) - .map(|u| u.iter().map(|u| u.clone()).collect()) - .unwrap_or_default() - } - - fn get_joined_user_ids(&self, room_id: &RoomId) -> Vec { - self.joined_user_ids - .get(room_id) - .map(|u| u.iter().map(|u| u.clone()).collect()) - .unwrap_or_default() - } - - fn get_stripped_invited_user_ids(&self, room_id: &RoomId) -> Vec { - self.stripped_invited_user_ids - .get(room_id) - .map(|u| u.iter().map(|u| u.clone()).collect()) - .unwrap_or_default() - } - - fn get_stripped_joined_user_ids(&self, room_id: &RoomId) -> Vec { - self.stripped_joined_user_ids - .get(room_id) - .map(|u| u.iter().map(|u| u.clone()).collect()) + map.get(room_id) + .map(|u| { + u.iter() + .filter_map(|u| memberships.matches(u.value()).then(|| u.key().clone())) + .collect() + }) .unwrap_or_default() } @@ -631,11 +538,9 @@ impl MemoryStore { } async fn remove_room(&self, room_id: &RoomId) -> Result<()> { - self.members.remove(room_id); self.profiles.remove(room_id); self.display_names.remove(room_id); - self.joined_user_ids.remove(room_id); - self.invited_user_ids.remove(room_id); + self.members.remove(room_id); self.room_info.remove(room_id); self.room_state.remove(room_id); self.room_account_data.remove(room_id); @@ -711,24 +616,24 @@ impl StateStore for MemoryStore { self.get_member_event(room_id, state_key).await } - async fn get_user_ids(&self, room_id: &RoomId) -> Result> { - Ok(self.get_user_ids(room_id)) + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result> { + let v = self.get_user_ids_inner(room_id, memberships, true); + if !v.is_empty() { + return Ok(v); + } + Ok(self.get_user_ids_inner(room_id, memberships, false)) } async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result> { - let v = self.get_stripped_invited_user_ids(room_id); - if !v.is_empty() { - return Ok(v); - } - Ok(self.get_invited_user_ids(room_id)) + StateStore::get_user_ids(self, room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result> { - let v = self.get_stripped_joined_user_ids(room_id); - if !v.is_empty() { - return Ok(v); - } - Ok(self.get_joined_user_ids(room_id)) + StateStore::get_user_ids(self, room_id, RoomMemberships::JOIN).await } async fn get_room_infos(&self) -> Result> { diff --git a/crates/matrix-sdk-base/src/store/traits.rs b/crates/matrix-sdk-base/src/store/traits.rs index 972dc0e2b..668b1fc88 100644 --- a/crates/matrix-sdk-base/src/store/traits.rs +++ b/crates/matrix-sdk-base/src/store/traits.rs @@ -33,6 +33,7 @@ use ruma::{ use super::{StateChanges, StoreError}; use crate::{ deserialized_responses::RawMemberEvent, media::MediaRequest, MinimalRoomMemberEvent, RoomInfo, + RoomMemberships, }; /// An abstract state store trait that can be used to implement different stores @@ -142,17 +143,23 @@ pub trait StateStore: AsyncTraitDeps { state_key: &UserId, ) -> Result, Self::Error>; - /// Get all the user ids of members for a given room, for stripped and - /// regular rooms alike. - async fn get_user_ids(&self, room_id: &RoomId) -> Result, Self::Error>; + /// Get the user ids of members for a given room with the given memberships, + /// for stripped and regular rooms alike. + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result, Self::Error>; /// Get all the user ids of members that are in the invited state for a /// given room, for stripped and regular rooms alike. + #[deprecated = "Use get_user_ids with RoomMemberships::INVITE instead."] async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result, Self::Error>; /// Get all the user ids of members that are in the joined state for a /// given room, for stripped and regular rooms alike. + #[deprecated = "Use get_user_ids with RoomMemberships::JOIN instead."] async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result, Self::Error>; /// Get all the pure `RoomInfo`s the store knows about. @@ -391,19 +398,23 @@ impl StateStore for EraseStateStoreError { self.0.get_member_event(room_id, state_key).await.map_err(Into::into) } - async fn get_user_ids(&self, room_id: &RoomId) -> Result, Self::Error> { - self.0.get_user_ids(room_id).await.map_err(Into::into) + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result, Self::Error> { + self.0.get_user_ids(room_id, memberships).await.map_err(Into::into) } async fn get_invited_user_ids( &self, room_id: &RoomId, ) -> Result, Self::Error> { - self.0.get_invited_user_ids(room_id).await.map_err(Into::into) + self.0.get_user_ids(room_id, RoomMemberships::INVITE).await.map_err(Into::into) } async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result, Self::Error> { - self.0.get_joined_user_ids(room_id).await.map_err(Into::into) + self.0.get_user_ids(room_id, RoomMemberships::JOIN).await.map_err(Into::into) } async fn get_room_infos(&self) -> Result, Self::Error> { diff --git a/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs b/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs index d72605132..49b7a2ee8 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs @@ -35,11 +35,12 @@ use wasm_bindgen::JsValue; use web_sys::IdbTransactionMode; use super::{ - deserialize_event, encode_key, encode_to_range, keys, serialize_event, Result, ALL_STORES, + deserialize_event, encode_key, encode_to_range, keys, serialize_event, Result, RoomMember, + ALL_STORES, }; use crate::IndexeddbStateStoreError; -const CURRENT_DB_VERSION: u32 = 5; +const CURRENT_DB_VERSION: u32 = 6; const CURRENT_META_DB_VERSION: u32 = 2; /// Sometimes Migrations can't proceed without having to drop existing @@ -65,6 +66,10 @@ mod old_keys { pub const SYNC_TOKEN: &str = "sync_token"; pub const MEMBERS: &str = "members"; pub const STRIPPED_MEMBERS: &str = "stripped_members"; + pub const JOINED_USER_IDS: &str = "joined_user_ids"; + pub const INVITED_USER_IDS: &str = "invited_user_ids"; + pub const STRIPPED_JOINED_USER_IDS: &str = "stripped_joined_user_ids"; + pub const STRIPPED_INVITED_USER_IDS: &str = "stripped_invited_user_ids"; } pub async fn upgrade_meta_db( @@ -211,6 +216,9 @@ pub async fn upgrade_inner_db( if old_version < 5 { migration.merge(migrate_to_v5(&pre_db, store_cipher).await?); } + if old_version < 6 { + migration.merge(migrate_to_v6(&pre_db, store_cipher).await?); + } } pre_db.close(); @@ -255,8 +263,8 @@ pub const V1_STORES: &[&str] = &[ old_keys::MEMBERS, keys::PROFILES, keys::DISPLAY_NAMES, - keys::JOINED_USER_IDS, - keys::INVITED_USER_IDS, + old_keys::JOINED_USER_IDS, + old_keys::INVITED_USER_IDS, keys::ROOM_STATE, keys::ROOM_INFOS, keys::PRESENCE, @@ -264,8 +272,8 @@ pub const V1_STORES: &[&str] = &[ keys::STRIPPED_ROOM_INFOS, old_keys::STRIPPED_MEMBERS, keys::STRIPPED_ROOM_STATE, - keys::STRIPPED_JOINED_USER_IDS, - keys::STRIPPED_INVITED_USER_IDS, + old_keys::STRIPPED_JOINED_USER_IDS, + old_keys::STRIPPED_INVITED_USER_IDS, keys::ROOM_USER_RECEIPTS, keys::ROOM_EVENT_RECEIPTS, keys::MEDIA, @@ -499,6 +507,97 @@ async fn migrate_to_v5( }) } +/// Remove the old user IDs stores and populate the new ones. +async fn migrate_to_v6( + db: &IdbDatabase, + store_cipher: Option<&StoreCipher>, +) -> Result { + // We only have joined and invited user IDs in the old store, so instead we will + // use the room member events to populate the new store. + let tx = db.transaction_on_multi_with_mode( + &[keys::ROOM_STATE, keys::ROOM_INFOS, keys::STRIPPED_ROOM_STATE, keys::STRIPPED_ROOM_INFOS], + IdbTransactionMode::Readonly, + )?; + + let state_store = tx.object_store(keys::ROOM_STATE)?; + let room_infos = tx + .object_store(keys::ROOM_INFOS)? + .get_all()? + .await? + .iter() + .filter_map(|f| deserialize_event::(store_cipher, f).ok()) + .collect::>(); + let mut values = Vec::new(); + + for room_info in room_infos { + let room_id = room_info.room_id(); + let range = + encode_to_range(store_cipher, keys::ROOM_STATE, (room_id, StateEventType::RoomMember))?; + for value in state_store.get_all_with_key(&range)?.await?.iter() { + let member_event = + deserialize_event::>(store_cipher, value.clone())? + .deserialize()?; + let key = encode_key(store_cipher, keys::USER_IDS, (room_id, member_event.state_key())); + let value = serialize_event(store_cipher, &RoomMember::from(&member_event))?; + + values.push((key, value)); + } + } + + let stripped_state_store = tx.object_store(keys::STRIPPED_ROOM_STATE)?; + let stripped_room_infos = tx + .object_store(keys::STRIPPED_ROOM_INFOS)? + .get_all()? + .await? + .iter() + .filter_map(|f| deserialize_event::(store_cipher, f).ok()) + .collect::>(); + let mut stripped_values = Vec::new(); + + for room_info in stripped_room_infos { + let room_id = room_info.room_id(); + let range = encode_to_range( + store_cipher, + keys::STRIPPED_ROOM_STATE, + (room_id, StateEventType::RoomMember), + )?; + for value in stripped_state_store.get_all_with_key(&range)?.await?.iter() { + let stripped_member_event = + deserialize_event::>(store_cipher, value.clone())? + .deserialize()?; + let key = encode_key( + store_cipher, + keys::STRIPPED_USER_IDS, + (room_id, &stripped_member_event.state_key), + ); + let value = serialize_event(store_cipher, &RoomMember::from(&stripped_member_event))?; + + stripped_values.push((key, value)); + } + } + + tx.await.into_result()?; + + let mut data = HashMap::new(); + if !values.is_empty() { + data.insert(keys::USER_IDS, values); + } + if !stripped_values.is_empty() { + data.insert(keys::STRIPPED_USER_IDS, stripped_values); + } + + Ok(OngoingMigration { + drop_stores: HashSet::from_iter([ + old_keys::JOINED_USER_IDS, + old_keys::INVITED_USER_IDS, + old_keys::STRIPPED_JOINED_USER_IDS, + old_keys::STRIPPED_INVITED_USER_IDS, + ]), + create_stores: HashSet::from_iter([keys::USER_IDS, keys::STRIPPED_USER_IDS]), + data, + }) +} + #[cfg(all(test, target_arch = "wasm32"))] mod tests { wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -506,8 +605,8 @@ mod tests { use assert_matches::assert_matches; use indexed_db_futures::prelude::*; use matrix_sdk_base::{ - deserialized_responses::RawMemberEvent, RoomInfo, RoomState, StateStore, StateStoreDataKey, - StoreError, + deserialized_responses::RawMemberEvent, RoomInfo, RoomMemberships, RoomState, StateStore, + StateStoreDataKey, StoreError, }; use matrix_sdk_test::{async_test, test_json}; use ruma::{ @@ -523,12 +622,10 @@ mod tests { use uuid::Uuid; use wasm_bindgen::JsValue; - use super::{ - old_keys, MigrationConflictStrategy, CURRENT_DB_VERSION, CURRENT_META_DB_VERSION, V1_STORES, - }; + use super::{old_keys, MigrationConflictStrategy, CURRENT_DB_VERSION, CURRENT_META_DB_VERSION}; use crate::{ safe_encode::SafeEncode, - state_store::{encode_key, keys, serialize_event, Result, ALL_STORES}, + state_store::{encode_key, keys, serialize_event, Result}, IndexeddbStateStore, IndexeddbStateStoreError, }; @@ -541,20 +638,53 @@ mod tests { move |evt: &IdbVersionChangeEvent| -> Result<(), JsValue> { let db = evt.db(); - // Initialize stores. - if version < 4 { - for name in V1_STORES { - db.create_object_store(name)?; - } - } else { - for name in ALL_STORES { - db.create_object_store(name)?; - } + // Stores common to all versions. + let common_stores = &[ + keys::ACCOUNT_DATA, + keys::PROFILES, + keys::DISPLAY_NAMES, + keys::ROOM_STATE, + keys::ROOM_INFOS, + keys::PRESENCE, + keys::ROOM_ACCOUNT_DATA, + keys::STRIPPED_ROOM_INFOS, + keys::STRIPPED_ROOM_STATE, + keys::ROOM_USER_RECEIPTS, + keys::ROOM_EVENT_RECEIPTS, + keys::MEDIA, + keys::CUSTOM, + ]; - if version < 5 { - for name in [old_keys::MEMBERS, old_keys::STRIPPED_MEMBERS] { - db.create_object_store(name)?; - } + for name in common_stores { + db.create_object_store(name)?; + } + + if version < 4 { + for name in [old_keys::SYNC_TOKEN, old_keys::SESSION] { + db.create_object_store(name)?; + } + } + if version >= 4 { + db.create_object_store(keys::KV)?; + } + if version < 5 { + for name in [old_keys::MEMBERS, old_keys::STRIPPED_MEMBERS] { + db.create_object_store(name)?; + } + } + if version < 6 { + for name in [ + old_keys::INVITED_USER_IDS, + old_keys::JOINED_USER_IDS, + old_keys::STRIPPED_INVITED_USER_IDS, + old_keys::STRIPPED_JOINED_USER_IDS, + ] { + db.create_object_store(name)?; + } + } + if version >= 6 { + for name in [keys::USER_IDS, keys::STRIPPED_USER_IDS] { + db.create_object_store(name)?; } } @@ -924,4 +1054,145 @@ mod tests { Ok(()) } + + #[async_test] + pub async fn test_migrating_to_v6() -> Result<()> { + let name = format!("migrating-v6-{}", Uuid::new_v4().as_hyphenated().to_string()); + + let room_id = room_id!("!room:localhost"); + let invite_member_event = + Raw::new(&*test_json::MEMBER_INVITE).unwrap().cast::(); + let invite_user_id = user_id!("@invited:localhost"); + let ban_member_event = + Raw::new(&*test_json::MEMBER_BAN).unwrap().cast::(); + let ban_user_id = user_id!("@banned:localhost"); + + let stripped_room_id = room_id!("!stripped_room:localhost"); + let stripped_member_event = + Raw::new(&*test_json::MEMBER_STRIPPED).unwrap().cast::(); + let stripped_user_id = user_id!("@example:localhost"); + + // Populate DB with old table. + { + let db = create_fake_db(&name, 5).await?; + let tx = db.transaction_on_multi_with_mode( + &[ + keys::ROOM_STATE, + keys::ROOM_INFOS, + keys::STRIPPED_ROOM_STATE, + keys::STRIPPED_ROOM_INFOS, + old_keys::INVITED_USER_IDS, + old_keys::JOINED_USER_IDS, + old_keys::STRIPPED_INVITED_USER_IDS, + old_keys::STRIPPED_JOINED_USER_IDS, + ], + IdbTransactionMode::Readwrite, + )?; + + let state_store = tx.object_store(keys::ROOM_STATE)?; + state_store.put_key_val( + &encode_key( + None, + keys::ROOM_STATE, + (room_id, StateEventType::RoomMember, invite_user_id), + ), + &serialize_event(None, &invite_member_event)?, + )?; + state_store.put_key_val( + &encode_key( + None, + keys::ROOM_STATE, + (room_id, StateEventType::RoomMember, ban_user_id), + ), + &serialize_event(None, &ban_member_event)?, + )?; + let room_infos_store = tx.object_store(keys::ROOM_INFOS)?; + let room_info = RoomInfo::new(room_id, RoomState::Joined); + room_infos_store.put_key_val( + &encode_key(None, keys::ROOM_INFOS, room_id), + &serialize_event(None, &room_info)?, + )?; + + let stripped_state_store = tx.object_store(keys::STRIPPED_ROOM_STATE)?; + stripped_state_store.put_key_val( + &encode_key( + None, + keys::STRIPPED_ROOM_STATE, + (stripped_room_id, StateEventType::RoomMember, stripped_user_id), + ), + &serialize_event(None, &stripped_member_event)?, + )?; + let stripped_room_infos_store = tx.object_store(keys::STRIPPED_ROOM_INFOS)?; + let stripped_room_info = RoomInfo::new(stripped_room_id, RoomState::Invited); + stripped_room_infos_store.put_key_val( + &encode_key(None, keys::STRIPPED_ROOM_INFOS, stripped_room_id), + &serialize_event(None, &stripped_room_info)?, + )?; + + // Populate the old user IDs stores to check the data is not reused. + let joined_user_id = user_id!("@joined_user:localhost"); + tx.object_store(old_keys::JOINED_USER_IDS)?.put_key_val( + &encode_key(None, old_keys::JOINED_USER_IDS, (room_id, joined_user_id)), + &serialize_event(None, &joined_user_id)?, + )?; + let invited_user_id = user_id!("@invited_user:localhost"); + tx.object_store(old_keys::INVITED_USER_IDS)?.put_key_val( + &encode_key(None, old_keys::INVITED_USER_IDS, (room_id, invited_user_id)), + &serialize_event(None, &invited_user_id)?, + )?; + let stripped_joined_user_id = user_id!("@stripped_joined_user:localhost"); + tx.object_store(old_keys::STRIPPED_JOINED_USER_IDS)?.put_key_val( + &encode_key( + None, + old_keys::STRIPPED_JOINED_USER_IDS, + (room_id, stripped_joined_user_id), + ), + &serialize_event(None, &stripped_joined_user_id)?, + )?; + let stripped_invited_user_id = user_id!("@stripped_invited_user:localhost"); + tx.object_store(old_keys::STRIPPED_INVITED_USER_IDS)?.put_key_val( + &encode_key( + None, + old_keys::STRIPPED_INVITED_USER_IDS, + (room_id, stripped_invited_user_id), + ), + &serialize_event(None, &stripped_invited_user_id)?, + )?; + + tx.await.into_result()?; + db.close(); + } + + // this transparently migrates to the latest version + let store = IndexeddbStateStore::builder().name(name).build().await?; + + assert_eq!(store.get_user_ids(room_id, RoomMemberships::JOIN).await.unwrap().len(), 0); + assert_eq!( + store.get_user_ids(room_id, RoomMemberships::INVITE).await.unwrap().as_slice(), + [invite_user_id.to_owned()] + ); + let user_ids = store.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); + assert_eq!(user_ids.len(), 2); + assert!(user_ids.contains(&invite_user_id.to_owned())); + assert!(user_ids.contains(&ban_user_id.to_owned())); + + assert_eq!( + store.get_user_ids(stripped_room_id, RoomMemberships::JOIN).await.unwrap().as_slice(), + [stripped_user_id.to_owned()] + ); + assert_eq!( + store.get_user_ids(stripped_room_id, RoomMemberships::INVITE).await.unwrap().len(), + 0 + ); + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::empty()) + .await + .unwrap() + .as_slice(), + [stripped_user_id.to_owned()] + ); + + Ok(()) + } } diff --git a/crates/matrix-sdk-indexeddb/src/state_store/mod.rs b/crates/matrix-sdk-indexeddb/src/state_store/mod.rs index fe6aeed6f..586f58744 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store/mod.rs @@ -25,7 +25,7 @@ use matrix_sdk_base::{ deserialized_responses::RawMemberEvent, media::{MediaRequest, UniqueKey}, store::{StateChanges, StateStore, StoreError}, - MinimalStateEvent, RoomInfo, StateStoreDataKey, StateStoreDataValue, + MinimalStateEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue, }; use matrix_sdk_store_encryption::{Error as EncryptionError, StoreCipher}; use ruma::{ @@ -37,12 +37,12 @@ use ruma::{ MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent, SyncRoomMemberEvent, }, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncStateEvent, - GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, + GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, SyncStateEvent, }, serde::Raw, CanonicalJsonObject, EventId, MxcUri, OwnedEventId, OwnedUserId, RoomId, RoomVersionId, UserId, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use tracing::{debug, warn}; use wasm_bindgen::JsValue; use web_sys::IdbKeyRange; @@ -96,8 +96,7 @@ mod keys { pub const PROFILES: &str = "profiles"; pub const DISPLAY_NAMES: &str = "display_names"; - pub const JOINED_USER_IDS: &str = "joined_user_ids"; - pub const INVITED_USER_IDS: &str = "invited_user_ids"; + pub const USER_IDS: &str = "user_ids"; pub const ROOM_STATE: &str = "room_state"; pub const ROOM_INFOS: &str = "room_infos"; @@ -106,8 +105,7 @@ mod keys { pub const STRIPPED_ROOM_INFOS: &str = "stripped_room_infos"; pub const STRIPPED_ROOM_STATE: &str = "stripped_room_state"; - pub const STRIPPED_JOINED_USER_IDS: &str = "stripped_joined_user_ids"; - pub const STRIPPED_INVITED_USER_IDS: &str = "stripped_invited_user_ids"; + pub const STRIPPED_USER_IDS: &str = "stripped_user_ids"; pub const ROOM_USER_RECEIPTS: &str = "room_user_receipts"; pub const ROOM_EVENT_RECEIPTS: &str = "room_event_receipts"; @@ -122,16 +120,14 @@ mod keys { ACCOUNT_DATA, PROFILES, DISPLAY_NAMES, - JOINED_USER_IDS, - INVITED_USER_IDS, + USER_IDS, ROOM_STATE, ROOM_INFOS, PRESENCE, ROOM_ACCOUNT_DATA, STRIPPED_ROOM_INFOS, STRIPPED_ROOM_STATE, - STRIPPED_JOINED_USER_IDS, - STRIPPED_INVITED_USER_IDS, + STRIPPED_USER_IDS, ROOM_USER_RECEIPTS, ROOM_EVENT_RECEIPTS, MEDIA, @@ -316,85 +312,52 @@ impl IndexeddbStateStore { encode_to_range(self.store_cipher.as_deref(), table_name, key) } - pub async fn get_user_ids_stream(&self, room_id: &RoomId) -> Result> { - Ok([ - self.get_invited_user_ids_inner(room_id).await?, - self.get_joined_user_ids_inner(room_id).await?, - ] - .concat()) - } - - pub async fn get_invited_user_ids_inner(&self, room_id: &RoomId) -> Result> { - let range = self.encode_to_range(keys::INVITED_USER_IDS, room_id)?; - let entries = self - .inner - .transaction_on_one_with_mode(keys::INVITED_USER_IDS, IdbTransactionMode::Readonly)? - .object_store(keys::INVITED_USER_IDS)? - .get_all_with_key(&range)? - .await? - .iter() - .filter_map(|f| self.deserialize_event::(f).ok()) - .collect::>(); - - Ok(entries) - } - - pub async fn get_joined_user_ids_inner(&self, room_id: &RoomId) -> Result> { - let range = self.encode_to_range(keys::JOINED_USER_IDS, room_id)?; - Ok(self - .inner - .transaction_on_one_with_mode(keys::JOINED_USER_IDS, IdbTransactionMode::Readonly)? - .object_store(keys::JOINED_USER_IDS)? - .get_all_with_key(&range)? - .await? - .iter() - .filter_map(|f| self.deserialize_event::(f).ok()) - .collect::>()) - } - - pub async fn get_stripped_user_ids_stream(&self, room_id: &RoomId) -> Result> { - Ok([ - self.get_stripped_invited_user_ids(room_id).await?, - self.get_stripped_joined_user_ids(room_id).await?, - ] - .concat()) - } - - pub async fn get_stripped_invited_user_ids( + /// Get user IDs for the given room with the given memberships and stripped + /// state. + pub async fn get_user_ids_inner( &self, room_id: &RoomId, + memberships: RoomMemberships, + stripped: bool, ) -> Result> { - let range = self.encode_to_range(keys::STRIPPED_INVITED_USER_IDS, room_id)?; - let entries = self - .inner - .transaction_on_one_with_mode( - keys::STRIPPED_INVITED_USER_IDS, - IdbTransactionMode::Readonly, - )? - .object_store(keys::STRIPPED_INVITED_USER_IDS)? - .get_all_with_key(&range)? - .await? - .iter() - .filter_map(|f| self.deserialize_event::(f).ok()) - .collect::>(); + let store_name = if stripped { keys::STRIPPED_USER_IDS } else { keys::USER_IDS }; - Ok(entries) - } + let tx = + self.inner.transaction_on_one_with_mode(store_name, IdbTransactionMode::Readonly)?; + let store = tx.object_store(store_name)?; + let range = self.encode_to_range(store_name, room_id)?; - pub async fn get_stripped_joined_user_ids(&self, room_id: &RoomId) -> Result> { - let range = self.encode_to_range(keys::STRIPPED_JOINED_USER_IDS, room_id)?; - Ok(self - .inner - .transaction_on_one_with_mode( - keys::STRIPPED_JOINED_USER_IDS, - IdbTransactionMode::Readonly, - )? - .object_store(keys::STRIPPED_JOINED_USER_IDS)? - .get_all_with_key(&range)? - .await? - .iter() - .filter_map(|f| self.deserialize_event::(f).ok()) - .collect::>()) + let user_ids = if memberships.is_empty() { + // It should be faster to just get all user IDs in this case. + store + .get_all_with_key(&range)? + .await? + .iter() + .filter_map(|f| self.deserialize_event::(f).ok().map(|m| m.user_id)) + .collect::>() + } else { + let mut user_ids = Vec::new(); + let cursor = store.open_cursor_with_range(&range)?.await?; + + if let Some(cursor) = cursor { + loop { + let value = cursor.value(); + let member = self.deserialize_event::(value)?; + + if memberships.matches(&member.membership) { + user_ids.push(member.user_id); + } + + if !cursor.continue_cursor()?.await? { + break; + } + } + } + + user_ids + }; + + Ok(user_ids) } async fn get_custom_value_for_js(&self, jskey: &JsValue) -> Result>> { @@ -543,10 +506,8 @@ impl_state_store! { if !changes.state.is_empty() { stores.extend([ keys::ROOM_STATE, - keys::INVITED_USER_IDS, - keys::JOINED_USER_IDS, - keys::STRIPPED_INVITED_USER_IDS, - keys::STRIPPED_JOINED_USER_IDS, + keys::USER_IDS, + keys::STRIPPED_USER_IDS, keys::STRIPPED_ROOM_STATE, keys::PROFILES, ]); @@ -563,8 +524,7 @@ impl_state_store! { if !changes.stripped_state.is_empty() { stores.extend([ keys::STRIPPED_ROOM_STATE, - keys::STRIPPED_INVITED_USER_IDS, - keys::STRIPPED_JOINED_USER_IDS, + keys::STRIPPED_USER_IDS, ]); } @@ -622,11 +582,9 @@ impl_state_store! { if !changes.state.is_empty() { let state = tx.object_store(keys::ROOM_STATE)?; let profiles = tx.object_store(keys::PROFILES)?; - let joined = tx.object_store(keys::JOINED_USER_IDS)?; - let invited = tx.object_store(keys::INVITED_USER_IDS)?; + let user_ids = tx.object_store(keys::USER_IDS)?; let stripped_state = tx.object_store(keys::STRIPPED_ROOM_STATE)?; - let stripped_joined = tx.object_store(keys::STRIPPED_JOINED_USER_IDS)?; - let stripped_invited = tx.object_store(keys::STRIPPED_INVITED_USER_IDS)?; + let stripped_user_ids = tx.object_store(keys::STRIPPED_USER_IDS)?; for (room, event_types) in &changes.state { let profile_changes = changes.profiles.get(room); @@ -650,31 +608,13 @@ impl_state_store! { let key = (room, state_key); - stripped_joined - .delete(&self.encode_key(keys::STRIPPED_JOINED_USER_IDS, key))?; - stripped_invited - .delete(&self.encode_key(keys::STRIPPED_INVITED_USER_IDS, key))?; + stripped_user_ids + .delete(&self.encode_key(keys::STRIPPED_USER_IDS, key))?; - match event.membership() { - MembershipState::Join => { - joined.put_key_val_owned( - &self.encode_key(keys::JOINED_USER_IDS, key), - &self.serialize_event(state_key)?, + user_ids.put_key_val_owned( + &self.encode_key(keys::USER_IDS, key), + &self.serialize_event(&RoomMember::from(&event))?, )?; - invited.delete(&self.encode_key(keys::INVITED_USER_IDS, key))?; - } - MembershipState::Invite => { - invited.put_key_val_owned( - &self.encode_key(keys::INVITED_USER_IDS, key), - &self.serialize_event(state_key)?, - )?; - joined.delete(&self.encode_key(keys::JOINED_USER_IDS, key))?; - } - _ => { - joined.delete(&self.encode_key(keys::JOINED_USER_IDS, key))?; - invited.delete(&self.encode_key(keys::INVITED_USER_IDS, key))?; - } - } if let Some(profile) = profile_changes.and_then(|p| p.get(event.state_key())) { profiles.put_key_val_owned( @@ -724,8 +664,7 @@ impl_state_store! { if !changes.stripped_state.is_empty() { let store = tx.object_store(keys::STRIPPED_ROOM_STATE)?; - let joined = tx.object_store(keys::STRIPPED_JOINED_USER_IDS)?; - let invited = tx.object_store(keys::STRIPPED_INVITED_USER_IDS)?; + let user_ids = tx.object_store(keys::STRIPPED_USER_IDS)?; for (room, event_types) in &changes.stripped_state { for (event_type, events) in event_types { @@ -735,42 +674,24 @@ impl_state_store! { store.put_key_val(&key, &self.serialize_event(&raw_event)?)?; if *event_type == StateEventType::RoomMember { - let event = match raw_event.deserialize_as::() { - Ok(ev) => ev, - Err(e) => { - let event_id: Option = - raw_event.get_field("event_id").ok().flatten(); - debug!(event_id, "Failed to deserialize stripped member event: {e}"); - continue; - } - }; + let event = match raw_event.deserialize_as::() { + Ok(ev) => ev, + Err(e) => { + let event_id: Option = + raw_event.get_field("event_id").ok().flatten(); + debug!(event_id, "Failed to deserialize stripped member event: {e}"); + continue; + } + }; - let key = (room, state_key); + let key = (room, state_key); - match event.content.membership { - MembershipState::Join => { - joined.put_key_val_owned( - &self.encode_key(keys::STRIPPED_JOINED_USER_IDS, key), - &self.serialize_event(state_key)?, - )?; - invited - .delete(&self.encode_key(keys::STRIPPED_INVITED_USER_IDS, key))?; - } - MembershipState::Invite => { - invited.put_key_val_owned( - &self.encode_key(keys::STRIPPED_INVITED_USER_IDS, key), - &self.serialize_event(state_key)?, - )?; - joined.delete(&self.encode_key(keys::STRIPPED_JOINED_USER_IDS, key))?; - } - _ => { - joined.delete(&self.encode_key(keys::STRIPPED_JOINED_USER_IDS, key))?; - invited - .delete(&self.encode_key(keys::STRIPPED_INVITED_USER_IDS, key))?; - } + user_ids.put_key_val_owned( + &self.encode_key(keys::STRIPPED_USER_IDS, key), + &self.serialize_event(&RoomMember::from(&event))?, + )?; } } - } } } } @@ -1176,13 +1097,13 @@ impl_state_store! { let prefixed_stores = [ keys::PROFILES, keys::DISPLAY_NAMES, - keys::INVITED_USER_IDS, - keys::JOINED_USER_IDS, + keys::USER_IDS, keys::ROOM_STATE, keys::ROOM_ACCOUNT_DATA, keys::ROOM_EVENT_RECEIPTS, keys::ROOM_USER_RECEIPTS, keys::STRIPPED_ROOM_STATE, + keys::STRIPPED_USER_IDS, ]; let all_stores = { @@ -1210,28 +1131,39 @@ impl_state_store! { tx.await.into_result().map_err(|e| e.into()) } - async fn get_user_ids(&self, room_id: &RoomId) -> Result> { - let ids: Vec = self.get_stripped_user_ids_stream(room_id).await?; + async fn get_user_ids(&self, room_id: &RoomId, memberships: RoomMemberships) -> Result> { + let ids = self.get_user_ids_inner(room_id, memberships, true).await?; if !ids.is_empty() { return Ok(ids); } - self.get_user_ids_stream(room_id).await + self.get_user_ids_inner(room_id, memberships, false).await } async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result> { - let ids: Vec = self.get_stripped_invited_user_ids(room_id).await?; - if !ids.is_empty() { - return Ok(ids); - } - self.get_invited_user_ids_inner(room_id).await + self.get_user_ids(room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result> { - let ids: Vec = self.get_stripped_joined_user_ids(room_id).await?; - if !ids.is_empty() { - return Ok(ids); - } - self.get_joined_user_ids_inner(room_id).await + self.get_user_ids(room_id, RoomMemberships::JOIN).await + } +} + +/// A room member. +#[derive(Debug, Serialize, Deserialize)] +struct RoomMember { + user_id: OwnedUserId, + membership: MembershipState, +} + +impl From<&SyncStateEvent> for RoomMember { + fn from(event: &SyncStateEvent) -> Self { + Self { user_id: event.state_key().clone(), membership: event.membership().clone() } + } +} + +impl From<&StrippedRoomMemberEvent> for RoomMember { + fn from(event: &StrippedRoomMemberEvent) -> Self { + Self { user_id: event.state_key.clone(), membership: event.content.membership.clone() } } } diff --git a/crates/matrix-sdk-sled/src/state_store/migrations.rs b/crates/matrix-sdk-sled/src/state_store/migrations.rs index 4aaceefa2..e9a99e485 100644 --- a/crates/matrix-sdk-sled/src/state_store/migrations.rs +++ b/crates/matrix-sdk-sled/src/state_store/migrations.rs @@ -27,10 +27,10 @@ use serde_json::value::{RawValue as RawJsonValue, Value as JsonValue}; use sled::{transaction::TransactionError, Batch, Transactional, Tree}; use tracing::debug; -use super::{keys, Result, SledStateStore, SledStoreError}; +use super::{keys, Result, RoomMember, SledStateStore, SledStoreError}; use crate::encode_key::EncodeKey; -const DATABASE_VERSION: u8 = 5; +const DATABASE_VERSION: u8 = 7; const VERSION_KEY: &str = "state-store-version"; @@ -87,6 +87,13 @@ impl SledStateStore { return Ok(()); } + // Version 6 was dropped and migration is similar to v7. + + if old_version < 7 { + self.migrate_to_v7()?; + return Ok(()); + } + // FUTURE UPGRADE CODE GOES HERE // can't upgrade from that version to the new one @@ -270,6 +277,82 @@ impl SledStateStore { self.set_db_version(5) } + + /// Remove the old user IDs stores and populate the new ones. + fn migrate_to_v7(&self) -> Result<()> { + { + // Reset v6 stores. + self.user_ids.clear()?; + self.stripped_user_ids.clear()?; + + // We only have joined and invited user IDs in the old stores, so instead we + // use the room member events to populate the new stores. + let state = &self.inner.open_tree(keys::ROOM_STATE)?; + let mut user_ids_batch = sled::Batch::default(); + + for room_info in + self.room_info.iter().map(|r| self.deserialize_value::(&r?.1)) + { + let room_info = room_info?; + let room_id = room_info.room_id(); + let prefix = + self.encode_key(keys::ROOM_STATE, (room_id, StateEventType::RoomMember)); + + for entry in state.scan_prefix(prefix) { + let (_, value) = entry?; + let member_event = self + .deserialize_value::>(&value)? + .deserialize()?; + let key = self.encode_key(keys::USER_ID, (room_id, member_event.state_key())); + let value = self.serialize_value(&RoomMember::from(&member_event))?; + user_ids_batch.insert(key, value); + } + } + + let stripped_state = &self.inner.open_tree(keys::STRIPPED_ROOM_STATE)?; + let mut stripped_user_ids_batch = sled::Batch::default(); + + for room_info in + self.stripped_room_infos.iter().map(|r| self.deserialize_value::(&r?.1)) + { + let room_info = room_info?; + let room_id = room_info.room_id(); + let prefix = self + .encode_key(keys::STRIPPED_ROOM_STATE, (room_id, StateEventType::RoomMember)); + + for entry in stripped_state.scan_prefix(prefix) { + let (_, value) = entry?; + let stripped_member_event = self + .deserialize_value::>(&value)? + .deserialize()?; + let key = self.encode_key( + keys::STRIPPED_USER_ID, + (room_id, &stripped_member_event.state_key), + ); + let value = self.serialize_value(&RoomMember::from(&stripped_member_event))?; + stripped_user_ids_batch.insert(key, value); + } + } + + let ret: Result<(), TransactionError> = + (&self.user_ids, &self.stripped_user_ids).transaction( + |(user_ids, stripped_user_ids)| { + user_ids.apply_batch(&user_ids_batch)?; + stripped_user_ids.apply_batch(&stripped_user_ids_batch)?; + + Ok(()) + }, + ); + ret?; + } + + self.inner.drop_tree(old_keys::JOINED_USER_ID)?; + self.inner.drop_tree(old_keys::INVITED_USER_ID)?; + self.inner.drop_tree(old_keys::STRIPPED_JOINED_USER_ID)?; + self.inner.drop_tree(old_keys::STRIPPED_INVITED_USER_ID)?; + + self.set_db_version(7) + } } mod old_keys { @@ -278,14 +361,18 @@ mod old_keys { pub const SESSION: &str = "session"; pub const MEMBER: &str = "member"; pub const STRIPPED_ROOM_MEMBER: &str = "stripped-room-member"; + pub const INVITED_USER_ID: &str = "invited-user-id"; + pub const JOINED_USER_ID: &str = "joined-user-id"; + pub const STRIPPED_INVITED_USER_ID: &str = "stripped-invited-user-id"; + pub const STRIPPED_JOINED_USER_ID: &str = "stripped-joined-user-id"; } pub const V1_DB_STORES: &[&str] = &[ keys::ACCOUNT_DATA, old_keys::SYNC_TOKEN, keys::DISPLAY_NAME, - keys::INVITED_USER_ID, - keys::JOINED_USER_ID, + old_keys::INVITED_USER_ID, + old_keys::JOINED_USER_ID, keys::MEDIA, old_keys::MEMBER, keys::PRESENCE, @@ -297,8 +384,8 @@ pub const V1_DB_STORES: &[&str] = &[ keys::ROOM_USER_RECEIPT, keys::ROOM, old_keys::SESSION, - keys::STRIPPED_INVITED_USER_ID, - keys::STRIPPED_JOINED_USER_ID, + old_keys::STRIPPED_INVITED_USER_ID, + old_keys::STRIPPED_JOINED_USER_ID, keys::STRIPPED_ROOM_INFO, old_keys::STRIPPED_ROOM_MEMBER, keys::STRIPPED_ROOM_STATE, @@ -309,7 +396,8 @@ pub const V1_DB_STORES: &[&str] = &[ mod test { use assert_matches::assert_matches; use matrix_sdk_base::{ - deserialized_responses::RawMemberEvent, RoomInfo, RoomState, StateStoreDataKey, + deserialized_responses::RawMemberEvent, RoomInfo, RoomMemberships, RoomState, + StateStoreDataKey, }; use matrix_sdk_test::{async_test, test_json}; use ruma::{ @@ -613,4 +701,122 @@ mod test { ); assert_eq!(stored_stripped_member_event.json().get(), stripped_member_event.json().get()); } + + #[async_test] + pub async fn migrating_v5_to_v7() { + let room_id = room_id!("!room:localhost"); + let invite_member_event = + Raw::new(&*test_json::MEMBER_INVITE).unwrap().cast::(); + let invite_user_id = user_id!("@invited:localhost"); + let ban_member_event = + Raw::new(&*test_json::MEMBER_BAN).unwrap().cast::(); + let ban_user_id = user_id!("@banned:localhost"); + + let stripped_room_id = room_id!("!stripped_room:localhost"); + let stripped_member_event = + Raw::new(&*test_json::MEMBER_STRIPPED).unwrap().cast::(); + let stripped_user_id = user_id!("@example:localhost"); + + let folder = TempDir::new().unwrap(); + { + let store = SledStateStore::builder() + .path(folder.path().to_path_buf()) + .passphrase("secret".to_owned()) + .build() + .unwrap(); + + let state = store.inner.open_tree(keys::ROOM_STATE).unwrap(); + state + .insert( + store.encode_key( + keys::ROOM_STATE, + (room_id, StateEventType::RoomMember, invite_user_id), + ), + store.serialize_value(&invite_member_event).unwrap(), + ) + .unwrap(); + state + .insert( + store.encode_key( + keys::ROOM_STATE, + (room_id, StateEventType::RoomMember, ban_user_id), + ), + store.serialize_value(&ban_member_event).unwrap(), + ) + .unwrap(); + let room_infos = store.inner.open_tree(keys::ROOM_INFO).unwrap(); + let room_info = RoomInfo::new(room_id, RoomState::Joined); + room_infos + .insert( + store.encode_key(keys::ROOM_INFO, room_id), + store.serialize_value(&room_info).unwrap(), + ) + .unwrap(); + + let stripped_state = store.inner.open_tree(keys::STRIPPED_ROOM_STATE).unwrap(); + stripped_state + .insert( + store.encode_key( + keys::STRIPPED_ROOM_STATE, + (stripped_room_id, StateEventType::RoomMember, stripped_user_id), + ), + store.serialize_value(&stripped_member_event).unwrap(), + ) + .unwrap(); + let stripped_room_infos = store.inner.open_tree(keys::STRIPPED_ROOM_INFO).unwrap(); + let stripped_room_info = RoomInfo::new(stripped_room_id, RoomState::Invited); + stripped_room_infos + .insert( + store.encode_key(keys::STRIPPED_ROOM_INFO, stripped_room_id), + store.serialize_value(&stripped_room_info).unwrap(), + ) + .unwrap(); + + store.set_db_version(5).unwrap(); + } + + let store = SledStateStore::builder() + .path(folder.path().to_path_buf()) + .passphrase("secret".to_owned()) + .build() + .unwrap(); + + assert_eq!( + store.get_user_ids(room_id, RoomMemberships::JOIN, false).await.unwrap().len(), + 0 + ); + assert_eq!( + store.get_user_ids(room_id, RoomMemberships::INVITE, false).await.unwrap().as_slice(), + [invite_user_id.to_owned()] + ); + let user_ids = store.get_user_ids(room_id, RoomMemberships::empty(), false).await.unwrap(); + assert_eq!(user_ids.len(), 2); + assert!(user_ids.contains(&invite_user_id.to_owned())); + assert!(user_ids.contains(&ban_user_id.to_owned())); + + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::JOIN, true) + .await + .unwrap() + .as_slice(), + [stripped_user_id.to_owned()] + ); + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::INVITE, true) + .await + .unwrap() + .len(), + 0 + ); + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::empty(), true) + .await + .unwrap() + .as_slice(), + [stripped_user_id.to_owned()] + ); + } } diff --git a/crates/matrix-sdk-sled/src/state_store/mod.rs b/crates/matrix-sdk-sled/src/state_store/mod.rs index f3c254c6c..8cb72ee5c 100644 --- a/crates/matrix-sdk-sled/src/state_store/mod.rs +++ b/crates/matrix-sdk-sled/src/state_store/mod.rs @@ -21,12 +21,12 @@ use std::{ use async_trait::async_trait; use futures_core::stream::Stream; -use futures_util::stream::{self, StreamExt, TryStreamExt}; +use futures_util::stream::{self, TryStreamExt}; use matrix_sdk_base::{ deserialized_responses::RawMemberEvent, media::{MediaRequest, UniqueKey}, store::{Result as StoreResult, StateChanges, StateStore, StoreError}, - MinimalStateEvent, RoomInfo, StateStoreDataKey, StateStoreDataValue, + MinimalStateEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue, }; use matrix_sdk_store_encryption::{Error as KeyEncryptionError, StoreCipher}; use ruma::{ @@ -38,13 +38,13 @@ use ruma::{ MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent, SyncRoomMemberEvent, }, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncStateEvent, - GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, + GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, SyncStateEvent, }, serde::Raw, CanonicalJsonObject, EventId, IdParseError, MxcUri, OwnedEventId, OwnedUserId, RoomId, RoomVersionId, UserId, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sled::{ transaction::{ConflictableTransactionError, TransactionError}, Config, Db, Transactional, Tree, @@ -112,8 +112,7 @@ mod keys { pub const ACCOUNT_DATA: &str = "account-data"; pub const CUSTOM: &str = "custom"; pub const DISPLAY_NAME: &str = "display-name"; - pub const INVITED_USER_ID: &str = "invited-user-id"; - pub const JOINED_USER_ID: &str = "joined-user-id"; + pub const USER_ID: &str = "user-ids"; pub const MEDIA: &str = "media"; pub const PRESENCE: &str = "presence"; pub const PROFILE: &str = "profile"; @@ -123,8 +122,7 @@ mod keys { pub const ROOM_STATE: &str = "room-state"; pub const ROOM_USER_RECEIPT: &str = "room-user-receipt"; pub const ROOM: &str = "room"; - pub const STRIPPED_INVITED_USER_ID: &str = "stripped-invited-user-id"; - pub const STRIPPED_JOINED_USER_ID: &str = "stripped-joined-user-id"; + pub const STRIPPED_USER_ID: &str = "stripped-user-ids"; pub const STRIPPED_ROOM_INFO: &str = "stripped-room-info"; pub const STRIPPED_ROOM_STATE: &str = "stripped-room-state"; pub const KV: &str = "kv"; @@ -282,13 +280,11 @@ pub struct SledStateStore { account_data: Tree, profiles: Tree, display_names: Tree, - joined_user_ids: Tree, - invited_user_ids: Tree, + user_ids: Tree, room_info: Tree, room_state: Tree, room_account_data: Tree, - stripped_joined_user_ids: Tree, - stripped_invited_user_ids: Tree, + stripped_user_ids: Tree, stripped_room_infos: Tree, stripped_room_state: Tree, presence: Tree, @@ -319,16 +315,14 @@ impl SledStateStore { let profiles = db.open_tree(keys::PROFILE)?; let display_names = db.open_tree(keys::DISPLAY_NAME)?; - let joined_user_ids = db.open_tree(keys::JOINED_USER_ID)?; - let invited_user_ids = db.open_tree(keys::INVITED_USER_ID)?; + let user_ids = db.open_tree(keys::USER_ID)?; let room_state = db.open_tree(keys::ROOM_STATE)?; let room_info = db.open_tree(keys::ROOM_INFO)?; let presence = db.open_tree(keys::PRESENCE)?; let room_account_data = db.open_tree(keys::ROOM_ACCOUNT_DATA)?; - let stripped_joined_user_ids = db.open_tree(keys::STRIPPED_JOINED_USER_ID)?; - let stripped_invited_user_ids = db.open_tree(keys::STRIPPED_INVITED_USER_ID)?; + let stripped_user_ids = db.open_tree(keys::STRIPPED_USER_ID)?; let stripped_room_infos = db.open_tree(keys::STRIPPED_ROOM_INFO)?; let stripped_room_state = db.open_tree(keys::STRIPPED_ROOM_STATE)?; @@ -347,14 +341,12 @@ impl SledStateStore { account_data, profiles, display_names, - joined_user_ids, - invited_user_ids, + user_ids, room_account_data, presence, room_state, room_info, - stripped_joined_user_ids, - stripped_invited_user_ids, + stripped_user_ids, stripped_room_infos, stripped_room_state, room_user_receipts, @@ -467,13 +459,11 @@ impl SledStateStore { let ret: Result<(), TransactionError> = ( &self.profiles, &self.display_names, - &self.joined_user_ids, - &self.invited_user_ids, + &self.user_ids, &self.room_info, &self.room_state, &self.room_account_data, - &self.stripped_joined_user_ids, - &self.stripped_invited_user_ids, + &self.stripped_user_ids, &self.stripped_room_infos, &self.stripped_room_state, ) @@ -481,13 +471,11 @@ impl SledStateStore { |( profiles, display_names, - joined, - invited, + user_ids, rooms, state, room_account_data, - stripped_joined, - stripped_invited, + stripped_user_ids, stripped_rooms, stripped_state, )| { @@ -546,43 +534,14 @@ impl SledStateStore { let key = (room, state_key); - stripped_joined.remove( - self.encode_key(keys::STRIPPED_JOINED_USER_ID, key), - )?; - stripped_invited.remove( - self.encode_key(keys::STRIPPED_INVITED_USER_ID, key), - )?; + stripped_user_ids + .remove(self.encode_key(keys::STRIPPED_USER_ID, key))?; - match event.membership() { - MembershipState::Join => { - joined.insert( - self.encode_key(keys::JOINED_USER_ID, key), - self.serialize_value(state_key) - .map_err(ConflictableTransactionError::Abort)?, - )?; - invited.remove( - self.encode_key(keys::INVITED_USER_ID, key), - )?; - } - MembershipState::Invite => { - invited.insert( - self.encode_key(keys::INVITED_USER_ID, key), - self.serialize_value(state_key) - .map_err(ConflictableTransactionError::Abort)?, - )?; - joined.remove( - self.encode_key(keys::JOINED_USER_ID, key), - )?; - } - _ => { - joined.remove( - self.encode_key(keys::JOINED_USER_ID, key), - )?; - invited.remove( - self.encode_key(keys::INVITED_USER_ID, key), - )?; - } - } + user_ids.insert( + self.encode_key(keys::USER_ID, key), + self.serialize_value(&RoomMember::from(&event)) + .map_err(ConflictableTransactionError::Abort)?, + )?; if let Some(profile) = profile_changes.and_then(|p| p.get(event.state_key())) @@ -646,46 +605,11 @@ impl SledStateStore { }; let key = (room, state_key); - - match event.content.membership { - MembershipState::Join => { - stripped_joined.insert( - self.encode_key(keys::STRIPPED_JOINED_USER_ID, key), - self.serialize_value(state_key) - .map_err(ConflictableTransactionError::Abort)?, - )?; - stripped_invited.remove( - self.encode_key( - keys::STRIPPED_INVITED_USER_ID, - key, - ), - )?; - } - MembershipState::Invite => { - stripped_invited.insert( - self.encode_key( - keys::STRIPPED_INVITED_USER_ID, - key, - ), - self.serialize_value(state_key) - .map_err(ConflictableTransactionError::Abort)?, - )?; - stripped_joined.remove( - self.encode_key(keys::STRIPPED_JOINED_USER_ID, key), - )?; - } - _ => { - stripped_joined.remove( - self.encode_key(keys::STRIPPED_JOINED_USER_ID, key), - )?; - stripped_invited.remove( - self.encode_key( - keys::STRIPPED_INVITED_USER_ID, - key, - ), - )?; - } - } + stripped_user_ids.insert( + self.encode_key(keys::STRIPPED_USER_ID, key), + self.serialize_value(&RoomMember::from(&event)) + .map_err(ConflictableTransactionError::Abort)?, + )?; } } } @@ -930,87 +854,34 @@ impl SledStateStore { .await? } - pub async fn get_user_ids_stream( + /// Get the user IDs for the given room with the given memberships and + /// stripped state. + pub async fn get_user_ids( &self, room_id: &RoomId, - ) -> StoreResult>> { - Ok(self - .get_joined_user_ids(room_id) - .await? - .chain(self.get_invited_user_ids(room_id).await?)) - } - pub async fn get_stripped_user_ids_stream( - &self, - room_id: &RoomId, - ) -> StoreResult>> { - Ok(self - .get_stripped_joined_user_ids(room_id) - .await? - .chain(self.get_stripped_invited_user_ids(room_id).await?)) - } - - pub async fn get_invited_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult>> { + memberships: RoomMemberships, + stripped: bool, + ) -> StoreResult> { let db = self.clone(); - let key = self.encode_key(keys::INVITED_USER_ID, room_id); + let store_name = if stripped { keys::STRIPPED_USER_ID } else { keys::USER_ID }; + let key = self.encode_key(store_name, room_id); + spawn_blocking(move || { - stream::iter(db.invited_user_ids.scan_prefix(key).map(move |u| { - db.deserialize_value(&u.map_err(StoreError::backend)?.1) - .map_err(StoreError::backend) - })) + let tree = if stripped { &db.stripped_user_ids } else { &db.user_ids }; + + tree.scan_prefix(key) + .map(move |u| { + let member = db + .deserialize_value::(&u.map_err(StoreError::backend)?.1) + .map_err(StoreError::backend)?; + + Ok(memberships.matches(&member.membership).then_some(member.user_id)) + }) + .filter_map(|u| u.transpose()) + .collect::>>() }) .await - .map_err(StoreError::backend) - } - - pub async fn get_joined_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult>> { - let db = self.clone(); - let key = self.encode_key(keys::JOINED_USER_ID, room_id); - spawn_blocking(move || { - stream::iter(db.joined_user_ids.scan_prefix(key).map(move |u| { - db.deserialize_value(&u.map_err(StoreError::backend)?.1) - .map_err(StoreError::backend) - })) - }) - .await - .map_err(StoreError::backend) - } - - pub async fn get_stripped_invited_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult>> { - let db = self.clone(); - let key = self.encode_key(keys::STRIPPED_INVITED_USER_ID, room_id); - spawn_blocking(move || { - stream::iter(db.stripped_invited_user_ids.scan_prefix(key).map(move |u| { - db.deserialize_value(&u.map_err(StoreError::backend)?.1) - .map_err(StoreError::backend) - })) - }) - .await - .map_err(StoreError::backend) - } - - pub async fn get_stripped_joined_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult>> { - let db = self.clone(); - let key = self.encode_key(keys::STRIPPED_JOINED_USER_ID, room_id); - spawn_blocking(move || { - stream::iter(db.stripped_joined_user_ids.scan_prefix(key).map(move |u| { - db.deserialize_value(&u.map_err(StoreError::backend)?.1) - .map_err(StoreError::backend) - })) - }) - .await - .map_err(StoreError::backend) + .map_err(StoreError::backend)? } pub async fn get_room_infos(&self) -> Result>> { @@ -1210,38 +1081,18 @@ impl SledStateStore { display_names_batch.remove(key?); } - let mut joined_user_ids_batch = sled::Batch::default(); - for key in - self.joined_user_ids.scan_prefix(self.encode_key(keys::JOINED_USER_ID, room_id)).keys() - { - joined_user_ids_batch.remove(key?); + let mut user_ids_batch = sled::Batch::default(); + for key in self.user_ids.scan_prefix(self.encode_key(keys::USER_ID, room_id)).keys() { + user_ids_batch.remove(key?); } - let mut stripped_joined_user_ids_batch = sled::Batch::default(); + let mut stripped_user_ids_batch = sled::Batch::default(); for key in self - .stripped_joined_user_ids - .scan_prefix(self.encode_key(keys::STRIPPED_JOINED_USER_ID, room_id)) + .stripped_user_ids + .scan_prefix(self.encode_key(keys::STRIPPED_USER_ID, room_id)) .keys() { - stripped_joined_user_ids_batch.remove(key?); - } - - let mut invited_user_ids_batch = sled::Batch::default(); - for key in self - .invited_user_ids - .scan_prefix(self.encode_key(keys::INVITED_USER_ID, room_id)) - .keys() - { - invited_user_ids_batch.remove(key?); - } - - let mut stripped_invited_user_ids_batch = sled::Batch::default(); - for key in self - .stripped_invited_user_ids - .scan_prefix(self.encode_key(keys::STRIPPED_INVITED_USER_ID, room_id)) - .keys() - { - stripped_invited_user_ids_batch.remove(key?); + stripped_user_ids_batch.remove(key?); } let mut room_state_batch = sled::Batch::default(); @@ -1270,10 +1121,8 @@ impl SledStateStore { let ret: Result<(), TransactionError> = ( &self.profiles, &self.display_names, - &self.joined_user_ids, - &self.stripped_joined_user_ids, - &self.invited_user_ids, - &self.stripped_invited_user_ids, + &self.user_ids, + &self.stripped_user_ids, &self.room_info, &self.stripped_room_infos, &self.room_state, @@ -1284,10 +1133,8 @@ impl SledStateStore { |( profiles, display_names, - joined, - stripped_joined, - invited, - stripped_invited, + user_ids, + stripped_user_ids, rooms, stripped_rooms, state, @@ -1299,10 +1146,8 @@ impl SledStateStore { profiles.apply_batch(&profiles_batch)?; display_names.apply_batch(&display_names_batch)?; - joined.apply_batch(&joined_user_ids_batch)?; - stripped_joined.apply_batch(&stripped_joined_user_ids_batch)?; - invited.apply_batch(&invited_user_ids_batch)?; - stripped_invited.apply_batch(&stripped_invited_user_ids_batch)?; + user_ids.apply_batch(&user_ids_batch)?; + stripped_user_ids.apply_batch(&stripped_user_ids_batch)?; state.apply_batch(&room_state_batch)?; stripped_state.apply_batch(&stripped_room_state_batch)?; room_account_data.apply_batch(&room_account_data_batch)?; @@ -1413,31 +1258,24 @@ impl StateStore for SledStateStore { self.get_member_event(room_id, state_key).await.map_err(Into::into) } - async fn get_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v: Vec = - self.get_stripped_user_ids_stream(room_id).await?.try_collect().await?; + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> StoreResult> { + let v = self.get_user_ids(room_id, memberships, true).await?; if !v.is_empty() { return Ok(v); } - self.get_user_ids_stream(room_id).await?.try_collect().await + self.get_user_ids(room_id, memberships, false).await } async fn get_invited_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v: Vec = - self.get_stripped_invited_user_ids(room_id).await?.try_collect().await?; - if !v.is_empty() { - return Ok(v); - } - self.get_invited_user_ids(room_id).await?.try_collect().await + StateStore::get_user_ids(self, room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v: Vec = - self.get_stripped_joined_user_ids(room_id).await?.try_collect().await?; - if !v.is_empty() { - return Ok(v); - } - self.get_joined_user_ids(room_id).await?.try_collect().await + StateStore::get_user_ids(self, room_id, RoomMemberships::JOIN).await } async fn get_room_infos(&self) -> StoreResult> { @@ -1538,6 +1376,25 @@ impl StateStore for SledStateStore { } } +/// A room member. +#[derive(Debug, Serialize, Deserialize)] +struct RoomMember { + user_id: OwnedUserId, + membership: MembershipState, +} + +impl From<&SyncStateEvent> for RoomMember { + fn from(event: &SyncStateEvent) -> Self { + Self { user_id: event.state_key().clone(), membership: event.membership().clone() } + } +} + +impl From<&StrippedRoomMemberEvent> for RoomMember { + fn from(event: &StrippedRoomMemberEvent) -> Self { + Self { user_id: event.state_key.clone(), membership: event.content.membership.clone() } + } +} + #[cfg(test)] mod tests { use matrix_sdk_base::statestore_integration_tests; diff --git a/crates/matrix-sdk/CHANGELOG.md b/crates/matrix-sdk/CHANGELOG.md index 35c8a151f..9950ba377 100644 --- a/crates/matrix-sdk/CHANGELOG.md +++ b/crates/matrix-sdk/CHANGELOG.md @@ -1,3 +1,9 @@ +# unreleased + +- `Common::members` and `Common::members_no_sync` take a `RoomMemberships` to be able to filter the + results by any membership state. + - `Common::active_members(_no_sync)` and `Common::joined_members(_no_sync)` are deprecated. + # 0.6.2 - Fix the access token being printed in tracing span fields. diff --git a/crates/matrix-sdk/src/encryption/identities/users.rs b/crates/matrix-sdk/src/encryption/identities/users.rs index dd7c7043a..3c6f05419 100644 --- a/crates/matrix-sdk/src/encryption/identities/users.rs +++ b/crates/matrix-sdk/src/encryption/identities/users.rs @@ -14,8 +14,12 @@ use std::sync::Arc; -use matrix_sdk_base::crypto::{ - types::MasterPubkey, OwnUserIdentity as InnerOwnUserIdentity, UserIdentity as InnerUserIdentity, +use matrix_sdk_base::{ + crypto::{ + types::MasterPubkey, OwnUserIdentity as InnerOwnUserIdentity, + UserIdentity as InnerUserIdentity, + }, + RoomMemberships, }; use ruma::{ events::{ @@ -465,7 +469,7 @@ impl OtherUserIdentity { let room = if let Some(room) = self.direct_message_room.read().await.as_ref() { // Make sure that the user, to be verified, is still in the room if !room - .active_members() + .members(RoomMemberships::ACTIVE) .await? .iter() .any(|member| member.user_id() == self.inner.user_id()) diff --git a/crates/matrix-sdk/src/lib.rs b/crates/matrix-sdk/src/lib.rs index d5bcafee3..14b91484f 100644 --- a/crates/matrix-sdk/src/lib.rs +++ b/crates/matrix-sdk/src/lib.rs @@ -20,7 +20,7 @@ pub use async_trait::async_trait; pub use bytes; pub use matrix_sdk_base::{ deserialized_responses, DisplayName, Room as BaseRoom, RoomInfo, RoomMember as BaseRoomMember, - RoomState, Session, StateChanges, StoreError, + RoomMemberships, RoomState, Session, StateChanges, StoreError, }; pub use matrix_sdk_common::*; pub use reqwest; diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index bbd10b19d..63c88026c 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -3,7 +3,7 @@ use std::{borrow::Borrow, collections::BTreeMap, ops::Deref, sync::Arc}; use matrix_sdk_base::{ deserialized_responses::{MembersResponse, TimelineEvent}, store::StateStoreExt, - StateChanges, + RoomMemberships, StateChanges, }; #[cfg(feature = "e2e-encryption")] use ruma::events::{ @@ -431,9 +431,10 @@ impl Common { /// /// Use [active_members_no_sync()](#method.active_members_no_sync) if you /// want a method that doesn't do any requests. + #[deprecated = "Use members with RoomMemberships::ACTIVE instead"] pub async fn active_members(&self) -> Result> { self.ensure_members().await?; - self.active_members_no_sync().await + self.members_no_sync(RoomMemberships::ACTIVE).await } /// Get active members for this room, includes invited, joined members. @@ -444,14 +445,9 @@ impl Common { /// /// Use [active_members()](#method.active_members) if you want to ensure to /// always get the full member list. + #[deprecated = "Use members_no_sync with RoomMemberships::ACTIVE instead"] pub async fn active_members_no_sync(&self) -> Result> { - Ok(self - .inner - .active_members() - .await? - .into_iter() - .map(|member| RoomMember::new(self.client.clone(), member)) - .collect()) + self.members_no_sync(RoomMemberships::ACTIVE).await } /// Get all the joined members of this room. @@ -462,9 +458,10 @@ impl Common { /// /// Use [joined_members_no_sync()](#method.joined_members_no_sync) if you /// want a method that doesn't do any requests. + #[deprecated = "Use members with RoomMemberships::JOIN instead"] pub async fn joined_members(&self) -> Result> { self.ensure_members().await?; - self.joined_members_no_sync().await + self.members_no_sync(RoomMemberships::JOIN).await } /// Get all the joined members of this room. @@ -475,14 +472,9 @@ impl Common { /// /// Use [joined_members()](#method.joined_members) if you want to ensure to /// always get the full member list. + #[deprecated = "Use members_no_sync with RoomMemberships::JOIN instead"] pub async fn joined_members_no_sync(&self) -> Result> { - Ok(self - .inner - .joined_members() - .await? - .into_iter() - .map(|member| RoomMember::new(self.client.clone(), member)) - .collect()) + self.members_no_sync(RoomMemberships::JOIN).await } /// Get a specific member of this room. @@ -524,8 +516,7 @@ impl Common { .map(|member| RoomMember::new(self.client.clone(), member))) } - /// Get all members for this room, includes invited, joined and left - /// members. + /// Get members for this room, with the given memberships. /// /// *Note*: This method will fetch the members from the homeserver if the /// member list isn't synchronized due to member lazy loading. Because of @@ -533,13 +524,12 @@ impl Common { /// /// Use [members_no_sync()](#method.members_no_sync) if you want a /// method that doesn't do any requests. - pub async fn members(&self) -> Result> { + pub async fn members(&self, memberships: RoomMemberships) -> Result> { self.ensure_members().await?; - self.members_no_sync().await + self.members_no_sync(memberships).await } - /// Get all members for this room, includes invited, joined and left - /// members. + /// Get members for this room, with the given memberships. /// /// *Note*: This method will not fetch the members from the homeserver if /// the member list isn't synchronized due to member lazy loading. Thus, @@ -547,10 +537,10 @@ impl Common { /// /// Use [members()](#method.members) if you want to ensure to always get /// the full member list. - pub async fn members_no_sync(&self) -> Result> { + pub async fn members_no_sync(&self, memberships: RoomMemberships) -> Result> { Ok(self .inner - .members() + .members(memberships) .await? .into_iter() .map(|member| RoomMember::new(self.client.clone(), member)) @@ -701,7 +691,8 @@ impl Common { /// Returns true if all devices in the room are verified, otherwise false. #[cfg(feature = "e2e-encryption")] pub async fn contains_only_verified_devices(&self) -> Result { - let user_ids = self.client.store().get_user_ids(self.room_id()).await?; + let user_ids = + self.client.store().get_user_ids(self.room_id(), RoomMemberships::empty()).await?; for user_id in user_ids { let devices = self.client.encryption().get_user_devices(&user_id).await?; @@ -800,7 +791,7 @@ impl Common { let this_room_id = self.inner.room_id(); if is_direct { - let mut room_members = self.active_members().await?; + let mut room_members = self.members(RoomMemberships::ACTIVE).await?; room_members.retain(|member| member.user_id() != self.own_user_id()); for member in room_members { @@ -866,7 +857,7 @@ impl Common { // - Are blocked due to server ACLs // - Are IP addresses let members: Vec<_> = self - .joined_members_no_sync() + .members_no_sync(RoomMemberships::JOIN) .await? .into_iter() .filter(|member| { diff --git a/crates/matrix-sdk/src/room/joined.rs b/crates/matrix-sdk/src/room/joined.rs index 52ae2c130..9ead0a5ec 100644 --- a/crates/matrix-sdk/src/room/joined.rs +++ b/crates/matrix-sdk/src/room/joined.rs @@ -4,6 +4,8 @@ use std::io::Cursor; use std::sync::Arc; use std::{borrow::Borrow, ops::Deref}; +#[cfg(feature = "e2e-encryption")] +use matrix_sdk_base::RoomMemberships; use matrix_sdk_common::instant::{Duration, Instant}; use mime::{self, Mime}; use ruma::{ @@ -385,11 +387,12 @@ impl Joined { let _guard = mutex.lock().await; { - let joined = self.client.store().get_joined_user_ids(self.inner.room_id()).await?; - let invited = - self.client.store().get_invited_user_ids(self.inner.room_id()).await?; - let members = joined.iter().chain(&invited).map(Deref::deref); - self.client.claim_one_time_keys(members).await?; + let members = self + .client + .store() + .get_user_ids(self.inner.room_id(), RoomMemberships::ACTIVE) + .await?; + self.client.claim_one_time_keys(members.iter().map(Deref::deref)).await?; }; let response = self.share_room_key().await; diff --git a/crates/matrix-sdk/src/room/member.rs b/crates/matrix-sdk/src/room/member.rs index 69d04499c..fa0507a2a 100644 --- a/crates/matrix-sdk/src/room/member.rs +++ b/crates/matrix-sdk/src/room/member.rs @@ -41,9 +41,10 @@ impl RoomMember { /// /// ```no_run /// # use futures::executor::block_on; - /// # use matrix_sdk::{ - /// # media::MediaFormat, room::RoomMember, ruma::room_id, Client, - /// # }; + /// use matrix_sdk::{ + /// media::MediaFormat, room::RoomMember, ruma::room_id, Client, + /// RoomMemberships, + /// }; /// # use url::Url; /// # let homeserver = Url::parse("http://example.com").unwrap(); /// # block_on(async { @@ -52,7 +53,7 @@ impl RoomMember { /// client.login_username(user, "password").send().await.unwrap(); /// let room_id = room_id!("!roomid:example.com"); /// let room = client.get_joined_room(&room_id).unwrap(); - /// let members = room.members().await.unwrap(); + /// let members = room.members(RoomMemberships::empty()).await.unwrap(); /// let member = members.first().unwrap(); /// if let Some(avatar) = member.avatar(MediaFormat::File).await.unwrap() { /// std::fs::write("avatar.png", avatar); diff --git a/crates/matrix-sdk/src/room/timeline/event_handler.rs b/crates/matrix-sdk/src/room/timeline/event_handler.rs index c4908c8e5..6f10c9f56 100644 --- a/crates/matrix-sdk/src/room/timeline/event_handler.rs +++ b/crates/matrix-sdk/src/room/timeline/event_handler.rs @@ -177,7 +177,10 @@ impl From for TimelineEventKind { #[derive(Debug)] pub(super) enum TimelineItemPosition { Start, - End, + End { + /// Whether this event is coming from a local cache. + from_cache: bool, + }, #[cfg(feature = "e2e-encryption")] Update(usize), } @@ -569,7 +572,8 @@ impl<'a> TimelineEventHandler<'a> { let origin = match position { TimelineItemPosition::Start => RemoteEventOrigin::Pagination, // We only paginate backwards for now, so End only happens for syncs - TimelineItemPosition::End => RemoteEventOrigin::Sync, + TimelineItemPosition::End { from_cache: true } => RemoteEventOrigin::Cache, + TimelineItemPosition::End { from_cache: false } => RemoteEventOrigin::Sync, #[cfg(feature = "e2e-encryption")] TimelineItemPosition::Update(idx) => self.items[*idx] .as_event() @@ -670,7 +674,9 @@ impl<'a> TimelineEventHandler<'a> { self.items.insert(offset + 1, Arc::new(item.into())); } - Flow::Remote { position: TimelineItemPosition::End, txn_id, event_id, .. } => { + Flow::Remote { + position: TimelineItemPosition::End { .. }, txn_id, event_id, .. + } => { let result = rfind_event_item(self.items, |it| { txn_id.is_some() && it.transaction_id() == txn_id.as_deref() || it.event_id() == Some(event_id) diff --git a/crates/matrix-sdk/src/room/timeline/event_item/remote.rs b/crates/matrix-sdk/src/room/timeline/event_item/remote.rs index a91cdf05c..137c2ff50 100644 --- a/crates/matrix-sdk/src/room/timeline/event_item/remote.rs +++ b/crates/matrix-sdk/src/room/timeline/event_item/remote.rs @@ -68,6 +68,8 @@ impl RemoteEventTimelineItem { /// Where we got an event from. #[derive(Clone, Copy, Debug)] pub(in crate::room::timeline) enum RemoteEventOrigin { + /// The event came from a cache. + Cache, /// The event came from a sync response. Sync, /// The event came from pagination. diff --git a/crates/matrix-sdk/src/room/timeline/inner.rs b/crates/matrix-sdk/src/room/timeline/inner.rs index 3e4cfdc95..257bad98c 100644 --- a/crates/matrix-sdk/src/room/timeline/inner.rs +++ b/crates/matrix-sdk/src/room/timeline/inner.rs @@ -150,7 +150,7 @@ impl TimelineInner

{ event.event, event.encryption_info, event.push_actions, - TimelineItemPosition::End, + TimelineItemPosition::End { from_cache: true }, state, &self.room_data_provider, self.track_read_receipts, @@ -182,7 +182,7 @@ impl TimelineInner

{ raw, encryption_info, push_actions, - TimelineItemPosition::End, + TimelineItemPosition::End { from_cache: false }, &mut state, &self.room_data_provider, self.track_read_receipts, diff --git a/crates/matrix-sdk/src/sliding_sync/builder.rs b/crates/matrix-sdk/src/sliding_sync/builder.rs index e7e1e5c1f..559bfa2b4 100644 --- a/crates/matrix-sdk/src/sliding_sync/builder.rs +++ b/crates/matrix-sdk/src/sliding_sync/builder.rs @@ -10,7 +10,9 @@ use ruma::{ self, AccountDataConfig, E2EEConfig, ExtensionsConfig, ReceiptsConfig, ToDeviceConfig, TypingConfig, }, - assign, OwnedRoomId, + assign, + events::TimelineEventType, + OwnedRoomId, }; use tokio::sync::{ mpsc::{channel, Receiver, Sender}, @@ -35,6 +37,7 @@ pub struct SlidingSyncBuilder { homeserver: Option, client: Option, lists: BTreeMap, + bump_event_types: Vec, extensions: Option, subscriptions: BTreeMap, internal_channel: (Sender, Receiver), @@ -47,6 +50,7 @@ impl SlidingSyncBuilder { homeserver: None, client: None, lists: BTreeMap::new(), + bump_event_types: Vec::new(), extensions: None, subscriptions: BTreeMap::new(), internal_channel: channel(8), @@ -198,6 +202,17 @@ impl SlidingSyncBuilder { self } + /// Allowlist of event types which should be considered recent activity + /// when sorting `by_recency`. By omitting event types, clients can ensure + /// that uninteresting events (e.g. a profile rename) do not cause a + /// room to jump to the top of its list(s). Empty or + /// omitted `bump_event_types` have no effect: all events in a room will + /// be considered recent activity. + pub fn bump_event_types(mut self, bump_event_types: &[TimelineEventType]) -> Self { + self.bump_event_types = bump_event_types.to_vec(); + self + } + /// Build the Sliding Sync. /// /// If `self.storage_key` is `Some(_)`, load the cached data from cold @@ -231,6 +246,7 @@ impl SlidingSyncBuilder { lists, rooms, + bump_event_types: self.bump_event_types, extensions: Mutex::new(self.extensions), reset_counter: Default::default(), diff --git a/crates/matrix-sdk/src/sliding_sync/list/mod.rs b/crates/matrix-sdk/src/sliding_sync/list/mod.rs index 0c226410f..52fc10521 100644 --- a/crates/matrix-sdk/src/sliding_sync/list/mod.rs +++ b/crates/matrix-sdk/src/sliding_sync/list/mod.rs @@ -562,9 +562,10 @@ impl SlidingSyncListInner { self.set_ranges(&[(0, range_end)]); // Finally, let's update the list' state. - Observable::update_eq(&mut self.state.write().unwrap(), |state| { - *state = SlidingSyncState::PartiallyLoaded; - }); + Observable::set_if_not_eq( + &mut self.state.write().unwrap(), + SlidingSyncState::PartiallyLoaded, + ); } // Otherwise the current range has reached its maximum, we switched to `FullyLoaded` // mode. @@ -579,17 +580,19 @@ impl SlidingSyncListInner { self.set_ranges(&[(0, range_maximum)]); // Finally, let's update the list' state. - Observable::update_eq(&mut self.state.write().unwrap(), |state| { - *state = SlidingSyncState::FullyLoaded; - }); + Observable::set_if_not_eq( + &mut self.state.write().unwrap(), + SlidingSyncState::FullyLoaded, + ); } } SlidingSyncListRequestGeneratorKind::Selective => { // Selective mode always loads everything. - Observable::update_eq(&mut self.state.write().unwrap(), |state| { - *state = SlidingSyncState::FullyLoaded; - }); + Observable::set_if_not_eq( + &mut self.state.write().unwrap(), + SlidingSyncState::FullyLoaded, + ); } } diff --git a/crates/matrix-sdk/src/sliding_sync/mod.rs b/crates/matrix-sdk/src/sliding_sync/mod.rs index 939e19d3a..504a87cc7 100644 --- a/crates/matrix-sdk/src/sliding_sync/mod.rs +++ b/crates/matrix-sdk/src/sliding_sync/mod.rs @@ -49,7 +49,9 @@ use ruma::{ self, AccountDataConfig, E2EEConfig, ExtensionsConfig, ToDeviceConfig, }, }, - assign, OwnedRoomId, RoomId, + assign, + events::TimelineEventType, + OwnedRoomId, RoomId, }; use serde::{Deserialize, Serialize}; use tokio::{ @@ -106,13 +108,17 @@ pub(super) struct SlidingSyncInner { /// The rooms details rooms: StdRwLock>, + /// The `bump_event_types` field. See + /// [`SlidingSyncBuilder::bump_event_types`] to learn more. + bump_event_types: Vec, + subscriptions: StdRwLock>, unsubscribe: StdRwLock>, /// Number of times a Sliding Session session has been reset. reset_counter: AtomicU8, - /// the intended state of the extensions being supplied to sliding /sync + /// The intended state of the extensions being supplied to sliding /sync /// calls. May contain the latest next_batch for to_devices, etc. extensions: Mutex>, @@ -406,6 +412,7 @@ impl SlidingSync { txn_id: Some(stream_id.to_owned()), timeout: Some(timeout), lists: requests_lists, + bump_event_types: self.inner.bump_event_types.clone(), room_subscriptions, unsubscribe_rooms, extensions, diff --git a/crates/matrix-sdk/tests/integration/room/common.rs b/crates/matrix-sdk/tests/integration/room/common.rs index 750436b69..450aaaeb9 100644 --- a/crates/matrix-sdk/tests/integration/room/common.rs +++ b/crates/matrix-sdk/tests/integration/room/common.rs @@ -1,7 +1,7 @@ use std::time::Duration; use assert_matches::assert_matches; -use matrix_sdk::{config::SyncSettings, room::RoomMember, DisplayName}; +use matrix_sdk::{config::SyncSettings, room::RoomMember, DisplayName, RoomMemberships}; use matrix_sdk_test::{ async_test, bulk_room_members, test_json, EventBuilder, JoinedRoomBuilder, StateTestEvent, TimelineTestEvent, @@ -40,7 +40,7 @@ async fn user_presence() { let _response = client.sync_once(sync_settings).await.unwrap(); let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); - let members: Vec = room.active_members().await.unwrap(); + let members: Vec = room.members(RoomMemberships::ACTIVE).await.unwrap(); assert_eq!(2, members.len()); // assert!(room.power_levels.is_some()) diff --git a/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs b/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs index 0ea46b04e..37cb92aa8 100644 --- a/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs +++ b/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs @@ -9,7 +9,7 @@ use matrix_sdk::{ api::client::room::create_room::v3::Request as CreateRoomRequest, events::room::member::{MembershipState, StrippedRoomMemberEvent}, }, - Client, RoomState, + Client, RoomMemberships, RoomState, }; use tokio::sync::Notify; @@ -105,11 +105,11 @@ async fn test_repeated_join_leave() -> Result<()> { // Now check the underlying state store that it also has the correct information // (for when the client restarts). - let invited = karl.store().get_invited_user_ids(room_id).await?; + let invited = karl.store().get_user_ids(room_id, RoomMemberships::INVITE).await?; assert_eq!(invited.len(), 1); assert_eq!(invited[0], karl_id); - let joined = karl.store().get_joined_user_ids(room_id).await?; + let joined = karl.store().get_user_ids(room_id, RoomMemberships::JOIN).await?; assert!(!joined.contains(&karl_id)); let event = karl diff --git a/testing/matrix-sdk-test/src/event_builder/test_event.rs b/testing/matrix-sdk-test/src/event_builder/test_event.rs index 2470b2634..eccc6db43 100644 --- a/testing/matrix-sdk-test/src/event_builder/test_event.rs +++ b/testing/matrix-sdk-test/src/event_builder/test_event.rs @@ -18,6 +18,7 @@ pub enum TimelineTestEvent { HistoryVisibility, JoinRules, Member, + MemberBan, MemberInvite, MemberNameChange, MessageEdit, @@ -47,6 +48,7 @@ impl TimelineTestEvent { Self::HistoryVisibility => test_json::sync_events::HISTORY_VISIBILITY.to_owned(), Self::JoinRules => test_json::sync_events::JOIN_RULES.to_owned(), Self::Member => test_json::sync_events::MEMBER.to_owned(), + Self::MemberBan => test_json::sync_events::MEMBER_BAN.to_owned(), Self::MemberInvite => test_json::sync_events::MEMBER_INVITE.to_owned(), Self::MemberNameChange => test_json::sync_events::MEMBER_NAME_CHANGE.to_owned(), Self::MessageEdit => test_json::sync_events::MESSAGE_EDIT.to_owned(), @@ -81,6 +83,7 @@ pub enum StateTestEvent { HistoryVisibility, JoinRules, Member, + MemberBan, MemberInvite, MemberNameChange, PowerLevels, @@ -103,6 +106,7 @@ impl StateTestEvent { Self::HistoryVisibility => test_json::sync_events::HISTORY_VISIBILITY.to_owned(), Self::JoinRules => test_json::sync_events::JOIN_RULES.to_owned(), Self::Member => test_json::sync_events::MEMBER.to_owned(), + Self::MemberBan => test_json::sync_events::MEMBER_BAN.to_owned(), Self::MemberInvite => test_json::sync_events::MEMBER_INVITE.to_owned(), Self::MemberNameChange => test_json::sync_events::MEMBER_NAME_CHANGE.to_owned(), Self::PowerLevels => test_json::sync_events::POWER_LEVELS.to_owned(), diff --git a/testing/matrix-sdk-test/src/test_json/mod.rs b/testing/matrix-sdk-test/src/test_json/mod.rs index 2db16a39d..5af09dca5 100644 --- a/testing/matrix-sdk-test/src/test_json/mod.rs +++ b/testing/matrix-sdk-test/src/test_json/mod.rs @@ -27,10 +27,10 @@ pub use sync::{ MORE_SYNC, MORE_SYNC_2, SYNC, VOIP_SYNC, }; pub use sync_events::{ - ALIAS, ALIASES, ENCRYPTION, MEMBER, MEMBER_INVITE, MEMBER_NAME_CHANGE, MEMBER_STRIPPED, - MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, POWER_LEVELS, PRESENCE, PUSH_RULES, REACTION, - READ_RECEIPT, READ_RECEIPT_OTHER, REDACTED, REDACTED_INVALID, REDACTED_STATE, REDACTION, TAG, - TOPIC, TOPIC_REDACTION, TYPING, + ALIAS, ALIASES, ENCRYPTION, MEMBER, MEMBER_BAN, MEMBER_INVITE, MEMBER_NAME_CHANGE, + MEMBER_STRIPPED, MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, POWER_LEVELS, PRESENCE, + PUSH_RULES, REACTION, READ_RECEIPT, READ_RECEIPT_OTHER, REDACTED, REDACTED_INVALID, + REDACTED_STATE, REDACTION, TAG, TOPIC, TOPIC_REDACTION, TYPING, }; /// An empty response. diff --git a/testing/matrix-sdk-test/src/test_json/sync_events.rs b/testing/matrix-sdk-test/src/test_json/sync_events.rs index 407d4e2fd..ba63c5282 100644 --- a/testing/matrix-sdk-test/src/test_json/sync_events.rs +++ b/testing/matrix-sdk-test/src/test_json/sync_events.rs @@ -146,6 +146,21 @@ pub static MEMBER: Lazy = Lazy::new(|| { }) }); +pub static MEMBER_BAN: Lazy = Lazy::new(|| { + json!({ + "content": { + "avatar_url": null, + "displayname": "example", + "membership": "ban" + }, + "event_id": "$151800140517rfvjc:localhost", + "origin_server_ts": 151800140, + "sender": "@example:localhost", + "state_key": "@banned:localhost", + "type": "m.room.member", + }) +}); + pub static MEMBER_INVITE: Lazy = Lazy::new(|| { json!({ "content": {