diff --git a/Cargo.lock b/Cargo.lock index 9e56ad45..b38a0961 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,9 +52,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -82,35 +82,35 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arbitrary" -version = "1.4.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "arc-swap" @@ -126,7 +126,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -183,7 +183,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -256,13 +256,11 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.29" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bee399cc3a623ec5a2db2c5b90ee0190a2260241fbe0c023ac8f7bab426aaf8" +checksum = "ddb939d66e4ae03cee6091612804ba446b12878410cfa17f785f4dd67d4014e8" dependencies = [ "brotli", - "compression-codecs", - "compression-core", "flate2", "futures-core", "memchr", @@ -291,18 +289,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -342,9 +340,9 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42" dependencies = [ "arrayvec", ] @@ -474,7 +472,7 @@ dependencies = [ "hyper", "hyper-util", "pin-project-lite", - "rustls 0.23.31", + "rustls 0.23.29", "rustls-pemfile 2.2.0", "rustls-pki-types", "tokio", @@ -493,7 +491,7 @@ dependencies = [ "http", "http-body-util", "pin-project", - "rustls 0.23.31", + "rustls 0.23.29", "tokio", "tokio-rustls 0.26.2", "tokio-util", @@ -549,7 +547,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.12.1", @@ -562,7 +560,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.106", + "syn 2.0.104", "which", ] @@ -572,7 +570,7 @@ version = "0.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.13.0", @@ -581,14 +579,14 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "bit_field" -version = "0.10.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" @@ -598,9 +596,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.3" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitstream-io" @@ -637,9 +635,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.2" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -676,9 +674,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] name = "byteorder" @@ -716,19 +714,19 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.22.3" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" dependencies = [ "serde", - "toml 0.9.5", + "toml", ] [[package]] name = "cc" -version = "1.2.34" +version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ "jobserver", "libc", @@ -756,9 +754,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -797,9 +795,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.46" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -816,9 +814,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.46" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -828,14 +826,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -846,9 +844,9 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "clap_mangen" -version = "0.2.29" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b4c3c54b30f0d9adcb47f25f61fcce35c4dd8916638c6b82fbd5f4fb4179e2" +checksum = "e2fb6d3f935bbb9819391528b0e7cf655e78a0bc7a7c3d227211a1d24fc11db1" dependencies = [ "clap", "roff", @@ -875,28 +873,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "compression-codecs" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7eea68f0e02c2b0aa8856e9a9478444206d4b6828728e7b0697c0f8cca265cb" -dependencies = [ - "brotli", - "compression-core", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "zstd", - "zstd-safe", -] - -[[package]] -name = "compression-core" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -919,12 +895,10 @@ dependencies = [ "conduwuit_service", "console-subscriber", "const-str", - "ctor", "hardened_malloc-rs", "log", "opentelemetry", - "opentelemetry-jaeger-propagator", - "opentelemetry-otlp", + "opentelemetry-jaeger", "opentelemetry_sdk", "sentry", "sentry-tower", @@ -949,7 +923,6 @@ dependencies = [ "conduwuit_macros", "conduwuit_service", "const-str", - "ctor", "futures", "log", "ruma", @@ -973,7 +946,6 @@ dependencies = [ "conduwuit_core", "conduwuit_service", "const-str", - "ctor", "futures", "hmac", "http", @@ -1048,13 +1020,13 @@ dependencies = [ "serde_yaml", "smallstr", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.12", "tikv-jemalloc-ctl", "tikv-jemalloc-sys", "tikv-jemallocator", "tokio", "tokio-metrics", - "toml 0.9.5", + "toml", "tracing", "tracing-core", "tracing-subscriber", @@ -1068,7 +1040,6 @@ dependencies = [ "async-channel", "conduwuit_core", "const-str", - "ctor", "futures", "log", "minicbor", @@ -1087,7 +1058,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1105,7 +1076,6 @@ dependencies = [ "conduwuit_service", "conduwuit_web", "const-str", - "ctor", "futures", "http", "http-body-util", @@ -1113,7 +1083,7 @@ dependencies = [ "hyper-util", "log", "ruma", - "rustls 0.23.31", + "rustls 0.23.29", "sd-notify", "sentry", "sentry-tower", @@ -1136,7 +1106,6 @@ dependencies = [ "conduwuit_core", "conduwuit_database", "const-str", - "ctor", "either", "futures", "hickory-resolver 0.25.2", @@ -1175,7 +1144,7 @@ dependencies = [ "conduwuit_service", "futures", "rand 0.8.5", - "thiserror 2.0.16", + "thiserror 2.0.12", "tracing", ] @@ -1188,7 +1157,7 @@ dependencies = [ "futures-core", "prost", "prost-types", - "tonic 0.12.3", + "tonic", "tracing-core", ] @@ -1212,7 +1181,7 @@ dependencies = [ "thread_local", "tokio", "tokio-stream", - "tonic 0.12.3", + "tonic", "tracing", "tracing-core", "tracing-subscriber", @@ -1226,18 +1195,15 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const-str" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451d0640545a0553814b4c646eb549343561618838e9b42495f466131fe3ad49" +checksum = "041fbfcf8e7054df725fb9985297e92422cdc80fcf313665f5ca3d761bb63f4c" [[package]] name = "const_panic" -version = "0.2.14" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8a602185c3c95b52f86dc78e55a6df9a287a7a93ddbcf012509930880cf879" -dependencies = [ - "typewit", -] +checksum = "b98d1483e98c9d67f341ab4b3915cfdc54740bd6f5cccc9226ee0535d86aa8fb" [[package]] name = "convert_case" @@ -1319,9 +1285,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crokey" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51360853ebbeb3df20c76c82aecf43d387a62860f1a59ba65ab51f00eea85aad" +checksum = "5282b45c96c5978c8723ea83385cb9a488b64b7d175733f48d07bf9da514a863" dependencies = [ "crokey-proc_macros", "crossterm", @@ -1332,15 +1298,15 @@ dependencies = [ [[package]] name = "crokey-proc_macros" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf1a727caeb5ee5e0a0826a97f205a9cf84ee964b0b48239fef5214a00ae439" +checksum = "2ea0218d3fedf0797fa55676f1964ef5d27103d41ed0281b4bbd2a6e6c3d8d28" dependencies = [ "crossterm", "proc-macro2", "quote", "strict", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1405,7 +1371,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "crossterm_winapi", "derive_more", "document-features", @@ -1445,20 +1411,14 @@ dependencies = [ [[package]] name = "ctor" -version = "0.5.0" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ - "ctor-proc-macro", - "dtor", + "quote", + "syn 2.0.104", ] -[[package]] -name = "ctor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1483,7 +1443,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1565,7 +1525,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1587,7 +1547,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1599,21 +1559,6 @@ dependencies = [ "litrs", ] -[[package]] -name = "dtor" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - [[package]] name = "dunce" version = "1.0.5" @@ -1663,7 +1608,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1683,7 +1628,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1761,7 +1706,7 @@ dependencies = [ "atomic", "pear", "serde", - "toml 0.8.23", + "toml", "uncased", "version_check", ] @@ -1802,9 +1747,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1901,7 +1846,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -1936,9 +1881,9 @@ dependencies = [ [[package]] name = "generator" -version = "0.8.7" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" dependencies = [ "cc", "cfg-if", @@ -1981,7 +1926,7 @@ dependencies = [ "js-sys", "libc", "r-efi", - "wasi 0.14.3+wasi-0.2.4", + "wasi 0.14.2+wasi-0.2.4", "wasm-bindgen", ] @@ -2003,15 +1948,15 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "h2" -version = "0.4.12" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -2019,7 +1964,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.11.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -2050,9 +1995,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "hdrhistogram" @@ -2152,7 +2097,7 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "serde", - "thiserror 2.0.16", + "thiserror 2.0.12", "tinyvec", "tokio", "tracing", @@ -2197,7 +2142,7 @@ dependencies = [ "resolv-conf", "serde", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.12", "tokio", "tracing", ] @@ -2242,7 +2187,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -2308,14 +2253,13 @@ checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] name = "hyper" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "atomic-waker", "bytes", "futures-channel", - "futures-core", + "futures-util", "h2", "http", "http-body", @@ -2323,7 +2267,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -2338,7 +2281,7 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.31", + "rustls 0.23.29", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -2373,7 +2316,7 @@ dependencies = [ "hyper", "libc", "pin-project-lite", - "socket2 0.5.10", + "socket2", "tokio", "tower-service", "tracing", @@ -2467,9 +2410,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", @@ -2511,9 +2454,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" dependencies = [ "byteorder-lite", "quick-error", @@ -2537,12 +2480,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.15.4", "serde", ] @@ -2552,6 +2495,12 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + [[package]] name = "interpolate_name" version = "0.2.4" @@ -2560,16 +2509,16 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "io-uring" -version = "0.7.10" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "cfg-if", "libc", ] @@ -2594,7 +2543,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.10", + "socket2", "widestring", "windows-sys 0.48.0", "winreg", @@ -2647,9 +2596,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ "getrandom 0.3.3", "libc", @@ -2729,7 +2678,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -2789,9 +2738,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libfuzzer-sys" @@ -2810,7 +2759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-targets 0.53.2", ] [[package]] @@ -2850,9 +2799,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "litrs" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" @@ -3004,29 +2953,29 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minicbor" -version = "2.1.1" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f182275033b808ede9427884caa8e05fa7db930801759524ca7925bd8aa7a82" +checksum = "8a309f581ade7597820083bc275075c4c6986e57e53f8d26f88507cfefc8c987" dependencies = [ "minicbor-derive", ] [[package]] name = "minicbor-derive" -version = "0.18.2" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17290c95158a760027059fe3f511970d6857e47ff5008f9e09bffe3d3e1c6af" +checksum = "a9882ef5c56df184b8ffc107fc6c61e33ee3a654b021961d790a78571bb9d67a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "minicbor-serde" -version = "0.6.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbf243b8cc68a7a76473b14328d3546fb002ae3d069227794520e9181003de9" +checksum = "54e45e8beeefea1b8b6f52fa188a5b6ea3746c2885606af8d4d8bf31cee633fb" dependencies = [ "minicbor", "serde", @@ -3096,11 +3045,11 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.30.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", @@ -3185,7 +3134,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -3280,87 +3229,85 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "opentelemetry" -version = "0.30.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ "futures-core", "futures-sink", + "indexmap 2.10.0", "js-sys", + "once_cell", "pin-project-lite", - "thiserror 2.0.16", - "tracing", + "thiserror 1.0.69", + "urlencoding", ] [[package]] -name = "opentelemetry-http" -version = "0.30.0" +name = "opentelemetry-jaeger" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d" +checksum = "e617c66fd588e40e0dbbd66932fdc87393095b125d4459b1a3a10feb1712f8a1" dependencies = [ "async-trait", - "bytes", - "http", + "futures-core", + "futures-util", "opentelemetry", - "reqwest", -] - -[[package]] -name = "opentelemetry-jaeger-propagator" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090b8ec07bb2e304b529581aa1fe530d7861298c9ef549ebbf44a4a56472c539" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b" -dependencies = [ - "http", - "opentelemetry", - "opentelemetry-http", - "opentelemetry-proto", + "opentelemetry-semantic-conventions", "opentelemetry_sdk", - "prost", - "reqwest", - "thiserror 2.0.16", - "tracing", + "thrift", + "tokio", ] [[package]] -name = "opentelemetry-proto" -version = "0.30.0" +name = "opentelemetry-semantic-conventions" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc" +checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" dependencies = [ "opentelemetry", - "opentelemetry_sdk", - "prost", - "tonic 0.13.1", ] [[package]] name = "opentelemetry_sdk" -version = "0.30.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b" +checksum = "2f16aec8a98a457a52664d69e0091bac3a0abd18ead9b641cb00202ba4e0efe4" dependencies = [ + "async-trait", + "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", + "glob", + "once_cell", "opentelemetry", + "ordered-float 4.6.0", "percent-encoding", - "rand 0.9.2", - "serde_json", - "thiserror 2.0.16", + "rand 0.8.5", + "thiserror 1.0.69", "tokio", "tokio-stream", ] +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "os_info" version = "3.12.0" @@ -3448,14 +3395,14 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "percent-encoding" -version = "2.3.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" @@ -3464,7 +3411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.11.0", + "indexmap 2.10.0", ] [[package]] @@ -3522,7 +3469,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -3560,7 +3507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" dependencies = [ "base64 0.22.1", - "indexmap 2.11.0", + "indexmap 2.10.0", "quick-xml", "serde", "time", @@ -3587,9 +3534,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ "zerovec", ] @@ -3617,12 +3564,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.2.37" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -3636,9 +3583,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -3651,7 +3598,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", "version_check", "yansi", ] @@ -3672,7 +3619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -3695,7 +3642,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -3713,7 +3660,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "memchr", "pulldown-cmark-escape", "unicase", @@ -3742,18 +3689,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.38.3" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", "cfg_aliases", @@ -3761,19 +3708,19 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.31", - "socket2 0.6.0", - "thiserror 2.0.16", + "rustls 0.23.29", + "socket2", + "thiserror 2.0.12", "tokio", "tracing", - "web-time", + "web-time 1.1.0", ] [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", "getrandom 0.3.3", @@ -3781,27 +3728,27 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "rustc-hash 2.1.1", - "rustls 0.23.31", + "rustls 0.23.29", "rustls-pki-types", "slab", - "thiserror 2.0.16", + "thiserror 2.0.12", "tinyvec", "tracing", - "web-time", + "web-time 1.1.0", ] [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.0", + "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3930,9 +3877,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3940,9 +3887,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.13.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3950,9 +3897,9 @@ dependencies = [ [[package]] name = "recaptcha-verify" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d694033c2b0abdbb8893edfb367f16270e790be4a67e618206d811dbe4efee4" +checksum = "71e3be7b2e46e24637ac96b0c9f70070f188652018573f36f4e511dcad09738a" dependencies = [ "reqwest", "serde", @@ -3961,23 +3908,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.10", - "regex-syntax 0.8.6", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -3991,13 +3938,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.6", + "regex-syntax 0.8.5", ] [[package]] @@ -4008,9 +3955,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -4040,7 +3987,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.31", + "rustls 0.23.29", "rustls-native-certs 0.8.1", "rustls-pemfile 2.2.0", "rustls-pki-types", @@ -4111,7 +4058,6 @@ checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" [[package]] name = "ruma" version = "0.10.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "assign", "js_int", @@ -4125,13 +4071,12 @@ dependencies = [ "ruma-identity-service-api", "ruma-push-gateway-api", "ruma-signatures", - "web-time", + "web-time 1.1.0", ] [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4143,7 +4088,6 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", "assign", @@ -4158,15 +4102,14 @@ dependencies = [ "serde", "serde_html_form", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.12", "url", - "web-time", + "web-time 1.1.0", ] [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", "base64 0.22.1", @@ -4174,7 +4117,7 @@ dependencies = [ "form_urlencoded", "getrandom 0.2.16", "http", - "indexmap 2.11.0", + "indexmap 2.10.0", "js_int", "konst", "percent-encoding", @@ -4186,22 +4129,21 @@ dependencies = [ "serde_html_form", "serde_json", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.12", "time", "tracing", "url", "uuid", - "web-time", + "web-time 1.1.0", "wildmatch", ] [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", - "indexmap 2.11.0", + "indexmap 2.10.0", "js_int", "js_option", "percent-encoding", @@ -4213,17 +4155,16 @@ dependencies = [ "serde", "serde_json", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.12", "tracing", "url", - "web-time", + "web-time 1.1.0", "wildmatch", ] [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "bytes", "headers", @@ -4238,23 +4179,21 @@ dependencies = [ "ruma-events", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.12", "tracing", ] [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", - "thiserror 2.0.16", + "thiserror 2.0.12", ] [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4264,7 +4203,6 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "cfg-if", "proc-macro-crate", @@ -4272,14 +4210,13 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn 2.0.106", - "toml 0.8.23", + "syn 2.0.104", + "toml", ] [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4291,7 +4228,6 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -4301,7 +4237,7 @@ dependencies = [ "serde_json", "sha2", "subslice", - "thiserror 2.0.16", + "thiserror 2.0.12", ] [[package]] @@ -4332,9 +4268,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -4372,7 +4308,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -4385,7 +4321,7 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.9.4", @@ -4406,9 +4342,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" dependencies = [ "aws-lc-rs", "log", @@ -4441,7 +4377,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.3.0", + "security-framework 3.2.0", ] [[package]] @@ -4468,7 +4404,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "web-time", + "web-time 1.1.0", "zeroize", ] @@ -4496,9 +4432,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rustyline-async" @@ -4509,7 +4445,7 @@ dependencies = [ "futures-util", "pin-project", "thingbuf", - "thiserror 2.0.16", + "thiserror 2.0.12", "unicode-segmentation", "unicode-width 0.2.1", ] @@ -4575,7 +4511,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -4584,11 +4520,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4613,13 +4549,13 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "sentry" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989425268ab5c011e06400187eed6c298272f8ef913e49fcadc3fda788b45030" +checksum = "255914a8e53822abd946e2ce8baa41d4cded6b8e938913b7f7b9da5b7ab44335" dependencies = [ "httpdate", "reqwest", - "rustls 0.23.31", + "rustls 0.23.29", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4630,24 +4566,26 @@ dependencies = [ "sentry-tracing", "tokio", "ureq", + "webpki-roots 0.26.11", ] [[package]] name = "sentry-backtrace" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e299dd3f7bcf676875eee852c9941e1d08278a743c32ca528e2debf846a653" +checksum = "00293cd332a859961f24fd69258f7e92af736feaeb91020cff84dac4188a4302" dependencies = [ "backtrace", + "once_cell", "regex", "sentry-core", ] [[package]] name = "sentry-contexts" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac0c5d6892cd4c414492fc957477b620026fb3411fca9fa12774831da561c88" +checksum = "961990f9caa76476c481de130ada05614cd7f5aa70fb57c2142f0e09ad3fb2aa" dependencies = [ "hostname", "libc", @@ -4659,32 +4597,33 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa38b94e70820ff3f1f9db3c8b0aef053b667be130f618e615e0ff2492cbcc" +checksum = "1a6409d845707d82415c800290a5d63be5e3df3c2e417b0997c60531dfbd35ef" dependencies = [ - "rand 0.9.2", + "once_cell", + "rand 0.8.5", "sentry-types", "serde", "serde_json", - "url", ] [[package]] name = "sentry-debug-images" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00950648aa0d371c7f57057434ad5671bd4c106390df7e7284739330786a01b6" +checksum = "71ab5df4f3b64760508edfe0ba4290feab5acbbda7566a79d72673065888e5cc" dependencies = [ "findshlibs", + "once_cell", "sentry-core", ] [[package]] name = "sentry-log" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670f08baf70058926b0fa60c8f10218524ef0cb1a1634b0388a4123bdec6288c" +checksum = "693841da8dfb693af29105edfbea1d91348a13d23dd0a5d03761eedb9e450c46" dependencies = [ "log", "sentry-core", @@ -4692,9 +4631,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7a23b13c004873de3ce7db86eb0f59fe4adfc655a31f7bbc17fd10bacc9bfe" +checksum = "609b1a12340495ce17baeec9e08ff8ed423c337c1a84dffae36a178c783623f3" dependencies = [ "sentry-backtrace", "sentry-core", @@ -4702,9 +4641,9 @@ dependencies = [ [[package]] name = "sentry-tower" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a303d0127d95ae928a937dcc0886931d28b4186e7338eea7d5786827b69b002" +checksum = "4b98005537e38ee3bc10e7d36e7febe9b8e573d03f2ddd85fcdf05d21f9abd6d" dependencies = [ "http", "pin-project", @@ -4716,11 +4655,10 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac841c7050aa73fc2bec8f7d8e9cb1159af0b3095757b99820823f3e54e5080" +checksum = "49f4e86402d5c50239dc7d8fd3f6d5e048221d5fcb4e026d8d50ab57fe4644cb" dependencies = [ - "bitflags 2.9.3", "sentry-backtrace", "sentry-core", "tracing-core", @@ -4729,16 +4667,16 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.42.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e477f4d4db08ddb4ab553717a8d3a511bc9e81dde0c808c680feacbb8105c412" +checksum = "3d3f117b8755dbede8260952de2aeb029e20f432e72634e8969af34324591631" dependencies = [ "debugid", "hex", - "rand 0.9.2", + "rand 0.8.5", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 1.0.69", "time", "url", "uuid", @@ -4761,7 +4699,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -4771,7 +4709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4" dependencies = [ "form_urlencoded", - "indexmap 2.11.0", + "indexmap 2.10.0", "itoa", "ryu", "serde", @@ -4779,9 +4717,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -4818,15 +4756,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4845,7 +4774,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.10.0", "itoa", "ryu", "serde", @@ -4912,9 +4841,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -4951,15 +4880,15 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallstr" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862077b1e764f04c251fe82a2ef562fd78d7cadaeb072ca7c2bcaf7217b1ff3b" +checksum = "63b1aefdf380735ff8ded0b15f31aab05daf1f70216c01c02a12926badd1df9d" dependencies = [ "serde", "smallvec", @@ -4984,16 +4913,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "socket2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "spin" version = "0.5.2" @@ -5081,9 +5000,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -5119,7 +5038,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -5131,7 +5050,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 0.8.23", + "toml", "version-compare", ] @@ -5160,9 +5079,9 @@ dependencies = [ [[package]] name = "termimad" -version = "0.34.0" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ff5ca043d65d4ea43b65cdb4e3aba119657d0d12caf44f93212ec3168a8e20" +checksum = "7301d9c2c4939c97f25376b70d3c13311f8fefdee44092fc361d2a98adc2cbb6" dependencies = [ "coolor", "crokey", @@ -5170,7 +5089,7 @@ dependencies = [ "lazy-regex", "minimad", "serde", - "thiserror 2.0.16", + "thiserror 2.0.12", "unicode-width 0.1.14", ] @@ -5195,11 +5114,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.12", ] [[package]] @@ -5210,18 +5129,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -5243,6 +5162,28 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09" +dependencies = [ + "byteorder", + "integer-encoding", + "log", + "ordered-float 2.10.1", + "threadpool", +] + [[package]] name = "tiff" version = "0.9.1" @@ -5325,9 +5266,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -5340,9 +5281,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" dependencies = [ "backtrace", "bytes", @@ -5352,10 +5293,10 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5366,14 +5307,14 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] name = "tokio-metrics" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f960dc1df82e5a0cff5a77e986a10ec7bfabf23ff2377922e012af742878e12" +checksum = "23ff82f660c98e4ff60da5eb8fa864a4130f34b56d92d5cd23d6fdfcc14e95fa" dependencies = [ "futures-util", "pin-project-lite", @@ -5397,7 +5338,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.31", + "rustls 0.23.29", "tokio", ] @@ -5426,9 +5367,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -5444,26 +5385,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", + "serde_spanned", + "toml_datetime", "toml_edit", ] -[[package]] -name = "toml" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" -dependencies = [ - "indexmap 2.11.0", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", - "toml_parser", - "toml_writer", - "winnow", -] - [[package]] name = "toml_datetime" version = "0.6.11" @@ -5473,50 +5399,26 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" -dependencies = [ - "serde", -] - [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.10.0", "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", + "serde_spanned", + "toml_datetime", "toml_write", "winnow", ] -[[package]] -name = "toml_parser" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" -dependencies = [ - "winnow", -] - [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "toml_writer" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" - [[package]] name = "tonic" version = "0.12.3" @@ -5538,7 +5440,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "socket2 0.5.10", + "socket2", "tokio", "tokio-stream", "tower 0.4.13", @@ -5547,27 +5449,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tonic" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" -dependencies = [ - "async-trait", - "base64 0.22.1", - "bytes", - "http", - "http-body", - "http-body-util", - "percent-encoding", - "pin-project", - "prost", - "tokio-stream", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.4.13" @@ -5610,7 +5491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "async-compression", - "bitflags 2.9.3", + "bitflags 2.9.1", "bytes", "futures-core", "futures-util", @@ -5655,7 +5536,7 @@ source = "git+https://forgejo.ellis.link/continuwuation/tracing?rev=1e64095a8051 dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -5701,9 +5582,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.31.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c" +checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" dependencies = [ "js-sys", "once_cell", @@ -5714,7 +5595,7 @@ dependencies = [ "tracing-core", "tracing-log", "tracing-subscriber", - "web-time", + "web-time 0.2.4", ] [[package]] @@ -5748,9 +5629,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "typewit" -version = "1.13.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd91acc53c592cb800c11c83e8e7ee1d48378d05cfa33b5474f5f80c5b236bf" +checksum = "97e72ba082eeb9da9dc68ff5a2bf727ef6ce362556e8d29ec1aed3bd05e7d86a" dependencies = [ "typewit_proc_macros", ] @@ -5835,38 +5716,24 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.1.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00432f493971db5d8e47a65aeb3b02f8226b9b11f1450ff86bb772776ebadd70" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64 0.22.1", "log", - "percent-encoding", - "rustls 0.23.31", - "rustls-pemfile 2.2.0", + "once_cell", + "rustls 0.23.29", "rustls-pki-types", - "ureq-proto", - "utf-8", - "webpki-roots 1.0.2", -] - -[[package]] -name = "ureq-proto" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe120bb823a0061680e66e9075942fcdba06d46551548c2c259766b9558bc9a" -dependencies = [ - "base64 0.22.1", - "http", - "httparse", - "log", + "url", + "webpki-roots 0.26.11", ] [[package]] name = "url" -version = "2.5.7" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -5874,6 +5741,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -5894,9 +5767,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -5956,11 +5829,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.3+wasi-0.2.4" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ - "wit-bindgen", + "wit-bindgen-rt", ] [[package]] @@ -5985,7 +5858,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -6020,7 +5893,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6044,6 +5917,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -6190,7 +6073,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -6201,7 +6084,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -6228,7 +6111,7 @@ checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings 0.3.1", - "windows-targets 0.53.3", + "windows-targets 0.53.2", ] [[package]] @@ -6291,7 +6174,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.2", ] [[package]] @@ -6327,11 +6210,10 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ - "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -6491,9 +6373,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -6509,10 +6391,13 @@ dependencies = [ ] [[package]] -name = "wit-bindgen" -version = "0.45.0" +name = "wit-bindgen-rt" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] [[package]] name = "writeable" @@ -6594,7 +6479,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", "synstructure 0.13.2", ] @@ -6615,7 +6500,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -6635,7 +6520,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", "synstructure 0.13.2", ] @@ -6658,9 +6543,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -6675,7 +6560,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.104", ] [[package]] @@ -6723,9 +6608,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.20" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 12ba6456..158dc23f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -352,7 +352,7 @@ version = "0.1.2" [workspace.dependencies.ruma] git = "https://forgejo.ellis.link/continuwuation/ruwuma" #branch = "conduwuit-changes" -rev = "8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" +rev = "191e5c541e8339080bebb5ac6855a682330bb886" features = [ "compat", "rand", diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 37ab030c..7cfe74f4 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -756,7 +756,7 @@ pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAli .build_and_append_pdu( PduBuilder::state(String::new(), &power_levels_content), &user_id, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -901,7 +901,13 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result { ); let redaction_event_id = { - let state_lock = self.services.rooms.state.mutex.lock(event.room_id()).await; + let state_lock = self + .services + .rooms + .state + .mutex + .lock(&event.room_id_or_hash()) + .await; self.services .rooms @@ -915,7 +921,7 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result { }) }, event.sender(), - event.room_id(), + Some(&event.room_id_or_hash()), &state_lock, ) .await? diff --git a/src/api/client/account.rs b/src/api/client/account.rs index 67268c9f..67dc2a01 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -929,7 +929,7 @@ pub async fn full_user_deactivate( .build_and_append_pdu( PduBuilder::state(String::new(), &power_levels_content), user_id, - room_id, + Some(room_id), &state_lock, ) .await diff --git a/src/api/client/context.rs b/src/api/client/context.rs index 4a7d34d2..9a11bad8 100644 --- a/src/api/client/context.rs +++ b/src/api/client/context.rs @@ -69,7 +69,7 @@ pub(crate) async fn get_context_route( let (base_id, base_pdu, visible) = try_join3(base_id, base_pdu, visible).await?; - if base_pdu.room_id != *room_id || base_pdu.event_id != *event_id { + if base_pdu.room_id_or_hash() != *room_id || base_pdu.event_id != *event_id { return Err!(Request(NotFound("Base event not found."))); } diff --git a/src/api/client/membership/ban.rs b/src/api/client/membership/ban.rs index 339dcf2e..8e46e4a9 100644 --- a/src/api/client/membership/ban.rs +++ b/src/api/client/membership/ban.rs @@ -49,7 +49,7 @@ pub(crate) async fn ban_user_route( ..current_member_content }), sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/client/membership/invite.rs b/src/api/client/membership/invite.rs index 018fb774..dd23e8b6 100644 --- a/src/api/client/membership/invite.rs +++ b/src/api/client/membership/invite.rs @@ -128,12 +128,12 @@ pub(crate) async fn invite_helper( .create_hash_and_sign_event( PduBuilder::state(user_id.to_string(), &content), sender_user, - room_id, + Some(room_id), &state_lock, ) .await?; - let invite_room_state = services.rooms.state.summary_stripped(&pdu).await; + let invite_room_state = services.rooms.state.summary_stripped(&pdu, room_id).await; drop(state_lock); @@ -227,7 +227,7 @@ pub(crate) async fn invite_helper( .build_and_append_pdu( PduBuilder::state(user_id.to_string(), &content), sender_user, - room_id, + Some(room_id), &state_lock, ) .await?; diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index f3434bf5..ef004be1 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -18,7 +18,7 @@ use conduwuit::{ }, warn, }; -use futures::{FutureExt, StreamExt}; +use futures::{FutureExt, StreamExt, TryFutureExt}; use ruma::{ CanonicalJsonObject, CanonicalJsonValue, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, RoomVersionId, UserId, @@ -553,12 +553,20 @@ async fn join_room_by_id_helper_remote( .iter() .stream() .then(|pdu| { + debug!(?pdu, "Validating send_join response room_state event"); services .server_keys .validate_and_add_event_id_no_fetch(pdu, &room_version_id) + .inspect_err(|e| { + debug_warn!( + "Could not validate send_join response room_state event: {e:?}" + ); + }) + .inspect(|_| debug!("Completed validating send_join response room_state event")) }) .ready_filter_map(Result::ok) .fold(HashMap::new(), |mut state, (event_id, value)| async move { + debug!(?event_id, "Processing send_join response room_state event"); let pdu = match PduEvent::from_id_val(&event_id, value.clone()) { | Ok(pdu) => pdu, | Err(e) => { @@ -566,9 +574,10 @@ async fn join_room_by_id_helper_remote( return state; }, }; - + debug!(event_id = ?event_id.clone(), "Adding PDU outlier for send_join response room_state event"); services.rooms.outlier.add_pdu_outlier(&event_id, &value); if let Some(state_key) = &pdu.state_key { + debug!(?state_key, "Creating shortstatekey for state event in send_join response"); let shortstatekey = services .rooms .short @@ -577,7 +586,7 @@ async fn join_room_by_id_helper_remote( state.insert(shortstatekey, pdu.event_id.clone()); } - + debug!("Completed send_join response"); state }) .await; @@ -618,6 +627,9 @@ async fn join_room_by_id_helper_remote( &parsed_join_pdu, None, // TODO: third party invite |k, s| state_fetch(k.clone(), s.into()), + &state_fetch(StateEventType::RoomCreate, "".into()) + .await + .expect("create event is missing from send_join auth"), ) .await .map_err(|e| err!(Request(Forbidden(warn!("Auth check failed: {e:?}")))))?; @@ -665,7 +677,7 @@ async fn join_room_by_id_helper_remote( let statehash_after_join = services .rooms .state - .append_to_state(&parsed_join_pdu) + .append_to_state(&parsed_join_pdu, room_id) .await?; info!("Appending new room join event"); @@ -677,6 +689,7 @@ async fn join_room_by_id_helper_remote( join_event, once(parsed_join_pdu.event_id.borrow()), &state_lock, + room_id, ) .await?; @@ -776,7 +789,7 @@ async fn join_room_by_id_helper_local( .build_and_append_pdu( PduBuilder::state(sender_user.to_string(), &content), sender_user, - room_id, + Some(room_id), &state_lock, ) .await diff --git a/src/api/client/membership/kick.rs b/src/api/client/membership/kick.rs index 5e0e86e2..93438545 100644 --- a/src/api/client/membership/kick.rs +++ b/src/api/client/membership/kick.rs @@ -54,7 +54,7 @@ pub(crate) async fn kick_user_route( ..event }), sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/client/membership/knock.rs b/src/api/client/membership/knock.rs index 79f16631..4cbc6ec1 100644 --- a/src/api/client/membership/knock.rs +++ b/src/api/client/membership/knock.rs @@ -373,7 +373,7 @@ async fn knock_room_helper_local( .build_and_append_pdu( PduBuilder::state(sender_user.to_string(), &content), sender_user, - room_id, + Some(room_id), &state_lock, ) .await @@ -502,6 +502,7 @@ async fn knock_room_helper_local( knock_event, once(parsed_knock_pdu.event_id.borrow()), &state_lock, + room_id, ) .await?; @@ -672,7 +673,7 @@ async fn knock_room_helper_remote( let statehash_after_knock = services .rooms .state - .append_to_state(&parsed_knock_pdu) + .append_to_state(&parsed_knock_pdu, room_id) .await?; info!("Updating membership locally to knock state with provided stripped state events"); @@ -701,6 +702,7 @@ async fn knock_room_helper_remote( knock_event, once(parsed_knock_pdu.event_id.borrow()), &state_lock, + room_id, ) .await?; diff --git a/src/api/client/membership/leave.rs b/src/api/client/membership/leave.rs index 0aadd833..5af9abc2 100644 --- a/src/api/client/membership/leave.rs +++ b/src/api/client/membership/leave.rs @@ -206,7 +206,7 @@ pub async fn leave_room( ..event }), user_id, - room_id, + Some(room_id), &state_lock, ) .await?; diff --git a/src/api/client/membership/mod.rs b/src/api/client/membership/mod.rs index 691419f6..4f3850e3 100644 --- a/src/api/client/membership/mod.rs +++ b/src/api/client/membership/mod.rs @@ -70,9 +70,10 @@ pub(crate) async fn banned_room_check( if let Some(room_id) = room_id { if services.rooms.metadata.is_banned(room_id).await - || services - .moderation - .is_remote_server_forbidden(room_id.server_name().expect("legacy room mxid")) + || (room_id.server_name().is_some() + && services + .moderation + .is_remote_server_forbidden(room_id.server_name().expect("legacy room mxid"))) { warn!( "User {user_id} who is not an admin attempted to send an invite for or \ diff --git a/src/api/client/membership/unban.rs b/src/api/client/membership/unban.rs index 34c5eace..20a28268 100644 --- a/src/api/client/membership/unban.rs +++ b/src/api/client/membership/unban.rs @@ -47,7 +47,7 @@ pub(crate) async fn unban_user_route( ..current_member_content }), sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/client/message.rs b/src/api/client/message.rs index 842036f5..bc7403c1 100644 --- a/src/api/client/message.rs +++ b/src/api/client/message.rs @@ -309,7 +309,7 @@ pub(crate) async fn visibility_filter( services .rooms .state_accessor - .user_can_see_event(user_id, pdu.room_id(), pdu.event_id()) + .user_can_see_event(user_id, &pdu.room_id_or_hash(), pdu.event_id()) .await .then_some(item) } diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index eaa66e70..ab259eee 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -423,7 +423,7 @@ pub async fn update_all_rooms( if let Err(e) = services .rooms .timeline - .build_and_append_pdu(pdu_builder, user_id, room_id, &state_lock) + .build_and_append_pdu(pdu_builder, user_id, Some(room_id), &state_lock) .await { warn!(%user_id, %room_id, "Failed to update/send new profile join membership update in room: {e}"); diff --git a/src/api/client/redact.rs b/src/api/client/redact.rs index 86d871ff..35fd2eec 100644 --- a/src/api/client/redact.rs +++ b/src/api/client/redact.rs @@ -36,7 +36,7 @@ pub(crate) async fn redact_event_route( }) }, sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/client/relations.rs b/src/api/client/relations.rs index 79fa1459..27e779a3 100644 --- a/src/api/client/relations.rs +++ b/src/api/client/relations.rs @@ -222,7 +222,7 @@ async fn visibility_filter( services .rooms .state_accessor - .user_can_see_event(sender_user, pdu.room_id(), pdu.event_id()) + .user_can_see_event(sender_user, &pdu.room_id_or_hash(), pdu.event_id()) .await .then_some(item) } diff --git a/src/api/client/report.rs b/src/api/client/report.rs index 60a16e1a..09da3d5f 100644 --- a/src/api/client/report.rs +++ b/src/api/client/report.rs @@ -2,7 +2,7 @@ use std::{fmt::Write as _, ops::Mul, time::Duration}; use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{Err, Result, debug_info, info, matrix::pdu::PduEvent, utils::ReadyExt}; +use conduwuit::{Err, Event, Result, debug_info, info, matrix::pdu::PduEvent, utils::ReadyExt}; use conduwuit_service::Services; use rand::Rng; use ruma::{ @@ -200,7 +200,7 @@ async fn is_event_report_valid( valid" ); - if room_id != pdu.room_id { + if room_id != &pdu.room_id_or_hash() { return Err!(Request(NotFound("Event ID does not belong to the reported room",))); } diff --git a/src/api/client/room/create.rs b/src/api/client/room/create.rs index 238691d1..0b574864 100644 --- a/src/api/client/room/create.rs +++ b/src/api/client/room/create.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{ - Err, Result, debug_info, debug_warn, err, info, + Err, Result, RoomVersion, debug, debug_info, debug_warn, err, info, matrix::{StateKey, pdu::PduBuilder}, warn, }; @@ -68,51 +68,6 @@ pub(crate) async fn create_room_route( return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } - let room_id: OwnedRoomId = match &body.room_id { - | Some(custom_room_id) => custom_room_id_check(&services, custom_room_id)?, - | _ => RoomId::new(&services.server.name), - }; - - // check if room ID doesn't already exist instead of erroring on auth check - if services.rooms.short.get_shortroomid(&room_id).await.is_ok() { - return Err!(Request(RoomInUse("Room with that custom room ID already exists",))); - } - - if body.visibility == room::Visibility::Public - && services.server.config.lockdown_public_room_directory - && !services.users.is_admin(sender_user).await - && body.appservice_info.is_none() - { - warn!( - "Non-admin user {sender_user} tried to publish {room_id} to the room directory \ - while \"lockdown_public_room_directory\" is enabled" - ); - - if services.server.config.admin_room_notices { - services - .admin - .notice(&format!( - "Non-admin user {sender_user} tried to publish {room_id} to the room \ - directory while \"lockdown_public_room_directory\" is enabled" - )) - .await; - } - - return Err!(Request(Forbidden("Publishing rooms to the room directory is not allowed"))); - } - let _short_id = services - .rooms - .short - .get_or_create_shortroomid(&room_id) - .await; - let state_lock = services.rooms.state.mutex.lock(&room_id).await; - - let alias: Option = match body.room_alias_name.as_ref() { - | Some(alias) => - Some(room_alias_check(&services, alias, body.appservice_info.as_ref()).await?), - | _ => None, - }; - let room_version = match body.room_version.clone() { | Some(room_version) => if services.server.supported_room_version(&room_version) { @@ -124,6 +79,51 @@ pub(crate) async fn create_room_route( }, | None => services.server.config.default_room_version.clone(), }; + let room_features = RoomVersion::new(&room_version)?; + + let room_id: Option = match room_features.room_ids_as_hashes { + | true => None, + | false => match &body.room_id { + | Some(custom_room_id) => Some(custom_room_id_check(&services, custom_room_id)?), + | None => Some(RoomId::new(services.globals.server_name())), + }, + }; + + // check if room ID doesn't already exist instead of erroring on auth check + if let Some(ref room_id) = room_id { + if services.rooms.short.get_shortroomid(&room_id).await.is_ok() { + return Err!(Request(RoomInUse("Room with that custom room ID already exists",))); + } + } + + if body.visibility == room::Visibility::Public + && services.server.config.lockdown_public_room_directory + && !services.users.is_admin(sender_user).await + && body.appservice_info.is_none() + { + warn!( + "Non-admin user {sender_user} tried to publish {room_id:?} to the room directory \ + while \"lockdown_public_room_directory\" is enabled" + ); + + if services.server.config.admin_room_notices { + services + .admin + .notice(&format!( + "Non-admin user {sender_user} tried to publish {room_id:?} to the room \ + directory while \"lockdown_public_room_directory\" is enabled" + )) + .await; + } + + return Err!(Request(Forbidden("Publishing rooms to the room directory is not allowed"))); + } + + let alias: Option = match body.room_alias_name.as_ref() { + | Some(alias) => + Some(room_alias_check(&services, alias, body.appservice_info.as_ref()).await?), + | _ => None, + }; let create_content = match &body.creation_content { | Some(content) => { @@ -156,6 +156,10 @@ pub(crate) async fn create_room_route( .try_into() .map_err(|e| err!(Request(BadJson("Invalid creation content: {e}"))))?, ); + if room_version == V12 { + // TODO(hydra): v12 rooms cannot be federated until they are stable. + content.insert("m.federate".into(), false.into()); + } content }, | None => { @@ -164,18 +168,32 @@ pub(crate) async fn create_room_route( let content = match room_version { | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => RoomCreateEventContent::new_v1(sender_user.to_owned()), - | _ => RoomCreateEventContent::new_v11(), + | V11 => RoomCreateEventContent::new_v11(), + | _ => RoomCreateEventContent::new_v12(), }; let mut content = - serde_json::from_str::(to_raw_value(&content)?.get()) - .unwrap(); + serde_json::from_str::(to_raw_value(&content)?.get())?; content.insert("room_version".into(), json!(room_version.as_str()).try_into()?); + if room_version == V12 { + // TODO(hydra): v12 rooms cannot be federated until they are stable. + content.insert("m.federate".into(), false.into()); + } content }, }; + let state_lock = match room_id.clone() { + | Some(room_id) => services.rooms.state.mutex.lock(&room_id).await, + | None => { + let temp_room_id = RoomId::new(services.globals.server_name()); + debug_info!("Locking temporary room state mutex for {temp_room_id}"); + services.rooms.state.mutex.lock(&temp_room_id).await + }, + }; + // 1. The room create event - services + debug!("Creating room create event for {sender_user} in room {room_id:?}"); + let create_event_id = services .rooms .timeline .build_and_append_pdu( @@ -186,13 +204,26 @@ pub(crate) async fn create_room_route( ..Default::default() }, sender_user, - &room_id, + None, &state_lock, ) .boxed() .await?; + debug!("Created room create event with ID {}", create_event_id); + let room_id = match room_id { + | Some(room_id) => room_id, + | None => { + let as_room_id = create_event_id.as_str().replace('$', "!"); + debug_info!("Creating room with v12 room ID {as_room_id}"); + RoomId::parse(&as_room_id)?.to_owned() + }, + }; + drop(state_lock); + debug!("Room created with ID {room_id}"); + let state_lock = services.rooms.state.mutex.lock(&room_id).await; // 2. Let the room creator join + debug_info!("Joining {sender_user} to room {room_id}"); services .rooms .timeline @@ -205,7 +236,7 @@ pub(crate) async fn create_room_route( ..RoomMemberEventContent::new(MembershipState::Join) }), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -235,10 +266,28 @@ pub(crate) async fn create_room_route( } } + let mut creators: Vec = vec![sender_user.to_owned()]; + if let Some(additional_creators) = create_content.get("additional_creators") { + if let Some(additional_creators) = additional_creators.as_array() { + for creator in additional_creators { + if let Some(creator) = creator.as_str() { + if let Ok(creator) = OwnedUserId::parse(creator) { + creators.push(creator.clone()); + users.insert(creator.clone(), int!(100)); + } + } + } + } + } + if !(RoomVersion::new(&room_version)?).explicitly_privilege_room_creators { + creators.clear(); + } + let power_levels_content = default_power_levels_content( body.power_level_content_override.as_ref(), &body.visibility, users, + creators, )?; services @@ -252,7 +301,7 @@ pub(crate) async fn create_room_route( ..Default::default() }, sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -269,7 +318,7 @@ pub(crate) async fn create_room_route( alt_aliases: vec![], }), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -292,7 +341,7 @@ pub(crate) async fn create_room_route( }), ), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -308,7 +357,7 @@ pub(crate) async fn create_room_route( &RoomHistoryVisibilityEventContent::new(HistoryVisibility::Shared), ), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -327,7 +376,7 @@ pub(crate) async fn create_room_route( }), ), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -363,7 +412,7 @@ pub(crate) async fn create_room_route( services .rooms .timeline - .build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock) + .build_and_append_pdu(pdu_builder, sender_user, Some(&room_id), &state_lock) .boxed() .await?; } @@ -376,7 +425,7 @@ pub(crate) async fn create_room_route( .build_and_append_pdu( PduBuilder::state(String::new(), &RoomNameEventContent::new(name.clone())), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -390,7 +439,7 @@ pub(crate) async fn create_room_route( .build_and_append_pdu( PduBuilder::state(String::new(), &RoomTopicEventContent { topic: topic.clone() }), sender_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -450,6 +499,7 @@ fn default_power_levels_content( power_level_content_override: Option<&Raw>, visibility: &room::Visibility, users: BTreeMap, + creators: Vec, ) -> Result { let mut power_levels_content = serde_json::to_value(RoomPowerLevelsEventContent { users, ..Default::default() }) @@ -499,6 +549,19 @@ fn default_power_levels_content( } } + if !creators.is_empty() { + // Raise the default power level of tombstone to 150 + power_levels_content["events"]["m.room.tombstone"] = + serde_json::to_value(150).expect("150 is valid Value"); + for creator in creators { + // Omit creators from the power level list altogether + power_levels_content["users"] + .as_object_mut() + .expect("users is an object") + .remove(creator.as_str()); + } + } + Ok(power_levels_content) } diff --git a/src/api/client/room/upgrade.rs b/src/api/client/room/upgrade.rs index c2c3aa81..1c75d767 100644 --- a/src/api/client/room/upgrade.rs +++ b/src/api/client/room/upgrade.rs @@ -91,7 +91,7 @@ pub(crate) async fn upgrade_room_route( replacement_room: replacement_room.clone(), }), sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; @@ -173,7 +173,7 @@ pub(crate) async fn upgrade_room_route( timestamp: None, }, sender_user, - &replacement_room, + Some(&replacement_room), &state_lock, ) .boxed() @@ -204,7 +204,7 @@ pub(crate) async fn upgrade_room_route( timestamp: None, }, sender_user, - &replacement_room, + Some(&replacement_room), &state_lock, ) .boxed() @@ -243,7 +243,7 @@ pub(crate) async fn upgrade_room_route( ..Default::default() }, sender_user, - &replacement_room, + Some(&replacement_room), &state_lock, ) .boxed() @@ -302,7 +302,7 @@ pub(crate) async fn upgrade_room_route( ..power_levels_event_content }), sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .boxed() @@ -352,7 +352,7 @@ pub(crate) async fn upgrade_room_route( ..Default::default() }, sender_user, - space_id, + Some(space_id), &state_lock, ) .boxed() @@ -376,7 +376,7 @@ pub(crate) async fn upgrade_room_route( ..Default::default() }, sender_user, - space_id, + Some(space_id), &state_lock, ) .boxed() diff --git a/src/api/client/send.rs b/src/api/client/send.rs index b87d1822..7c5ea0c1 100644 --- a/src/api/client/send.rs +++ b/src/api/client/send.rs @@ -80,7 +80,7 @@ pub(crate) async fn send_message_event_route( ..Default::default() }, sender_user, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/client/state.rs b/src/api/client/state.rs index c0f5fe7c..139d565b 100644 --- a/src/api/client/state.rs +++ b/src/api/client/state.rs @@ -201,7 +201,7 @@ async fn send_state_event_for_key_helper( ..Default::default() }, sender, - room_id, + Some(room_id), &state_lock, ) .await?; diff --git a/src/api/client/sync/v3.rs b/src/api/client/sync/v3.rs index 298a6e4b..bd63e278 100644 --- a/src/api/client/sync/v3.rs +++ b/src/api/client/sync/v3.rs @@ -457,7 +457,7 @@ async fn handle_left_room( state_key: Some(sender_user.as_str().into()), unsigned: None, // The following keys are dropped on conversion - room_id: room_id.clone(), + room_id: Some(room_id.clone()), prev_events: vec![], depth: uint!(1), auth_events: vec![], diff --git a/src/api/server/backfill.rs b/src/api/server/backfill.rs index 3cfbcedc..6b80c098 100644 --- a/src/api/server/backfill.rs +++ b/src/api/server/backfill.rs @@ -2,7 +2,7 @@ use std::cmp; use axum::extract::State; use conduwuit::{ - PduCount, Result, + Event, PduCount, Result, utils::{IterStream, ReadyExt, stream::TryTools}, }; use futures::{FutureExt, StreamExt, TryStreamExt}; @@ -68,7 +68,7 @@ pub(crate) async fn get_backfill_route( Ok(services .rooms .state_accessor - .server_can_see_event(body.origin(), &pdu.room_id, &pdu.event_id) + .server_can_see_event(body.origin(), &pdu.room_id_or_hash(), &pdu.event_id) .await .then_some(pdu)) }) diff --git a/src/api/server/make_join.rs b/src/api/server/make_join.rs index 3204c30c..94af394d 100644 --- a/src/api/server/make_join.rs +++ b/src/api/server/make_join.rs @@ -122,7 +122,7 @@ pub(crate) async fn create_join_event_template_route( ..RoomMemberEventContent::new(MembershipState::Join) }), &body.user_id, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/server/make_knock.rs b/src/api/server/make_knock.rs index 423c8e81..847b99bb 100644 --- a/src/api/server/make_knock.rs +++ b/src/api/server/make_knock.rs @@ -95,7 +95,7 @@ pub(crate) async fn create_knock_event_template_route( &RoomMemberEventContent::new(MembershipState::Knock), ), &body.user_id, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/server/make_leave.rs b/src/api/server/make_leave.rs index cb6bd2fa..6640f8a1 100644 --- a/src/api/server/make_leave.rs +++ b/src/api/server/make_leave.rs @@ -45,7 +45,7 @@ pub(crate) async fn create_leave_event_template_route( &RoomMemberEventContent::new(MembershipState::Leave), ), &body.user_id, - &body.room_id, + Some(&body.room_id), &state_lock, ) .await?; diff --git a/src/api/server/send.rs b/src/api/server/send.rs index 9c5bfd2b..b228fa98 100644 --- a/src/api/server/send.rs +++ b/src/api/server/send.rs @@ -138,6 +138,7 @@ async fn handle( pdus: impl Stream + Send, edus: impl Stream + Send, ) -> Result { + // TODO(hydra): Does having no room ID break this? // group pdus by room let pdus = pdus .collect() @@ -186,6 +187,7 @@ async fn handle_room( .lock(&room_id) .await; + // TODO(hydra): We might be missing a room ID let room_id = &room_id; pdus.try_stream() .and_then(|(_, event_id, value)| async move { diff --git a/src/api/server/send_knock.rs b/src/api/server/send_knock.rs index ffd41ada..52550ced 100644 --- a/src/api/server/send_knock.rs +++ b/src/api/server/send_knock.rs @@ -175,7 +175,11 @@ pub(crate) async fn create_knock_event_v1_route( .send_pdu_room(&body.room_id, &pdu_id) .await?; - let knock_room_state = services.rooms.state.summary_stripped(&pdu).await; + let knock_room_state = services + .rooms + .state + .summary_stripped(&pdu, &body.room_id) + .await; Ok(send_knock::v1::Response { knock_room_state }) } diff --git a/src/core/info/room_version.rs b/src/core/info/room_version.rs index 54ed8fdc..5009e4fe 100644 --- a/src/core/info/room_version.rs +++ b/src/core/info/room_version.rs @@ -17,8 +17,12 @@ pub const STABLE_ROOM_VERSIONS: &[RoomVersionId] = &[ ]; /// Experimental, partially supported room versions -pub const UNSTABLE_ROOM_VERSIONS: &[RoomVersionId] = - &[RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5]; +pub const UNSTABLE_ROOM_VERSIONS: &[RoomVersionId] = &[ + RoomVersionId::V3, + RoomVersionId::V4, + RoomVersionId::V5, + RoomVersionId::V12, +]; type RoomVersion = (RoomVersionId, RoomVersionStability); diff --git a/src/core/matrix/event.rs b/src/core/matrix/event.rs index a1d1339e..b2cd5731 100644 --- a/src/core/matrix/event.rs +++ b/src/core/matrix/event.rs @@ -10,7 +10,7 @@ mod unsigned; use std::fmt::Debug; use ruma::{ - CanonicalJsonObject, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, RoomId, + CanonicalJsonObject, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId, events::TimelineEventType, }; use serde::Deserialize; @@ -168,7 +168,12 @@ pub trait Event: Clone + Debug { fn redacts(&self) -> Option<&EventId>; /// The `RoomId` of this event. - fn room_id(&self) -> &RoomId; + fn room_id(&self) -> Option<&RoomId>; + + /// The `RoomId` or hash of this event. + /// This should only be preferred over room_id() if the event is a v12 + /// create event. + fn room_id_or_hash(&self) -> OwnedRoomId; /// The `UserId` of this event. fn sender(&self) -> &UserId; diff --git a/src/core/matrix/event/filter.rs b/src/core/matrix/event/filter.rs index d3a225b6..e698a90f 100644 --- a/src/core/matrix/event/filter.rs +++ b/src/core/matrix/event/filter.rs @@ -32,12 +32,16 @@ impl Matches for &RoomEventFilter { } fn matches_room(event: &E, filter: &RoomEventFilter) -> bool { - if filter.not_rooms.iter().any(is_equal_to!(event.room_id())) { + if filter + .not_rooms + .iter() + .any(is_equal_to!(event.room_id().unwrap())) + { return false; } if let Some(rooms) = filter.rooms.as_ref() { - if !rooms.iter().any(is_equal_to!(event.room_id())) { + if !rooms.iter().any(is_equal_to!(event.room_id().unwrap())) { return false; } } diff --git a/src/core/matrix/pdu.rs b/src/core/matrix/pdu.rs index bff0c203..3977be7d 100644 --- a/src/core/matrix/pdu.rs +++ b/src/core/matrix/pdu.rs @@ -31,7 +31,7 @@ use crate::Result; pub struct Pdu { pub event_id: OwnedEventId, - pub room_id: OwnedRoomId, + pub room_id: Option, pub sender: OwnedUserId, @@ -110,7 +110,19 @@ impl Event for Pdu { fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() } #[inline] - fn room_id(&self) -> &RoomId { &self.room_id } + fn room_id(&self) -> Option<&RoomId> { self.room_id.as_deref() } + + #[inline] + fn room_id_or_hash(&self) -> OwnedRoomId { + if let Some(room_id) = &self.room_id { + room_id.clone() + } else { + let constructed_hash = "!".to_owned() + &self.event_id.as_str()[1..]; + RoomId::parse(&constructed_hash) + .expect("event ID can be indexed") + .to_owned() + } + } #[inline] fn sender(&self) -> &UserId { &self.sender } @@ -163,7 +175,19 @@ impl Event for &Pdu { fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() } #[inline] - fn room_id(&self) -> &RoomId { &self.room_id } + fn room_id(&self) -> Option<&RoomId> { self.room_id.as_ref().map(AsRef::as_ref) } + + #[inline] + fn room_id_or_hash(&self) -> OwnedRoomId { + if let Some(room_id) = &self.room_id { + room_id.clone() + } else { + let constructed_hash = "!".to_owned() + &self.event_id.as_str()[1..]; + RoomId::parse(&constructed_hash) + .expect("event ID can be indexed") + .to_owned() + } + } #[inline] fn sender(&self) -> &UserId { &self.sender } diff --git a/src/core/matrix/state_res/benches.rs b/src/core/matrix/state_res/benches.rs index 69088369..de62f266 100644 --- a/src/core/matrix/state_res/benches.rs +++ b/src/core/matrix/state_res/benches.rs @@ -406,7 +406,7 @@ where Pdu { event_id: id.try_into().unwrap(), - room_id: room_id().to_owned(), + room_id: Some(room_id().to_owned()), sender: sender.to_owned(), origin_server_ts: ts.try_into().unwrap(), state_key: state_key.map(Into::into), diff --git a/src/core/matrix/state_res/event_auth.rs b/src/core/matrix/state_res/event_auth.rs index 77a4a95c..0550fdc0 100644 --- a/src/core/matrix/state_res/event_auth.rs +++ b/src/core/matrix/state_res/event_auth.rs @@ -2,10 +2,10 @@ use std::{borrow::Borrow, collections::BTreeSet}; use futures::{ Future, - future::{OptionFuture, join3}, + future::{OptionFuture, join, join3}, }; use ruma::{ - Int, OwnedUserId, RoomVersionId, UserId, + Int, OwnedRoomId, OwnedUserId, RoomVersionId, UserId, events::room::{ create::RoomCreateEventContent, join_rules::{JoinRule, RoomJoinRulesEventContent}, @@ -44,6 +44,15 @@ struct RoomMemberContentFields { join_authorised_via_users_server: Option>, } +#[derive(Deserialize)] +struct RoomCreateContentFields { + room_version: Option>, + creator: Option>, + additional_creators: Option>>, + #[serde(rename = "m.federate", default = "ruma::serde::default_true")] + federate: bool, +} + /// For the given event `kind` what are the relevant auth events that are needed /// to authenticate this `content`. /// @@ -56,16 +65,24 @@ pub fn auth_types_for_event( sender: &UserId, state_key: Option<&str>, content: &RawJsonValue, + room_version: &RoomVersion, ) -> serde_json::Result> { if kind == &TimelineEventType::RoomCreate { return Ok(vec![]); } - let mut auth_types = vec![ - (StateEventType::RoomPowerLevels, StateKey::new()), - (StateEventType::RoomMember, sender.as_str().into()), - (StateEventType::RoomCreate, StateKey::new()), - ]; + let mut auth_types = if room_version.room_ids_as_hashes { + vec![ + (StateEventType::RoomPowerLevels, StateKey::new()), + (StateEventType::RoomMember, sender.as_str().into()), + ] + } else { + vec![ + (StateEventType::RoomPowerLevels, StateKey::new()), + (StateEventType::RoomMember, sender.as_str().into()), + (StateEventType::RoomCreate, StateKey::new()), + ] + }; if kind == &TimelineEventType::RoomMember { #[derive(Deserialize)] @@ -141,6 +158,7 @@ pub async fn auth_check( incoming_event: &E, current_third_party_invite: Option<&E>, fetch_state: F, + create_event: &E, ) -> Result where F: Fn(&StateEventType, &str) -> Fut + Send, @@ -169,12 +187,6 @@ where // // 1. If type is m.room.create: if *incoming_event.event_type() == TimelineEventType::RoomCreate { - #[derive(Deserialize)] - struct RoomCreateContentFields { - room_version: Option>, - creator: Option>, - } - debug!("start m.room.create check"); // If it has any previous events, reject @@ -184,14 +196,16 @@ where } // If the domain of the room_id does not match the domain of the sender, reject - let Some(room_id_server_name) = incoming_event.room_id().server_name() else { - warn!("room ID has no servername"); - return Ok(false); - }; - - if room_id_server_name != sender.server_name() { - warn!("servername of room ID does not match servername of sender"); - return Ok(false); + if incoming_event.room_id().is_some() { + let Some(room_id_server_name) = incoming_event.room_id().unwrap().server_name() + else { + warn!("room ID has no servername"); + return Ok(false); + }; + if room_id_server_name != sender.server_name() { + warn!("servername of room ID does not match servername of sender"); + return Ok(false); + } } // If content.room_version is present and is not a recognized version, reject @@ -204,7 +218,15 @@ where return Ok(false); } - if !room_version.use_room_create_sender { + // TODO(hydra): If the create event has a room_id, reject + if room_version.room_ids_as_hashes && incoming_event.room_id().is_some() { + warn!("this room version does not support room IDs in m.room.create"); + return Ok(false); + } + + if !room_version.use_room_create_sender + && !room_version.explicitly_privilege_room_creators + { // If content has no creator field, reject if content.creator.is_none() { warn!("no creator field found in m.room.create content"); @@ -216,6 +238,8 @@ where return Ok(true); } + // NOTE(hydra): We must have an event ID from this point forward. + /* // TODO: In the past this code was commented as it caused problems with Synapse. This is no // longer the case. This needs to be implemented. @@ -242,54 +266,102 @@ where } */ - let (room_create_event, power_levels_event, sender_member_event) = join3( - fetch_state(&StateEventType::RoomCreate, ""), + let (power_levels_event, sender_member_event) = join( + // fetch_state(&StateEventType::RoomCreate, ""), fetch_state(&StateEventType::RoomPowerLevels, ""), fetch_state(&StateEventType::RoomMember, sender.as_str()), ) .await; - let room_create_event = match room_create_event { - | None => { - warn!("no m.room.create event in auth chain"); - return Ok(false); - }, - | Some(e) => e, + // TODO(hydra): Re-enable { + // // Room was either v11 with no create event, or v12+ room + // if incoming_event.room_id().is_some() { + // // invalid v11 + // warn!("no m.room.create event found in claimed state"); + // return Ok(false); + // } + // // v12 room + // debug!("no m.room.create event found, assuming v12 room"); + // create_event.clone() + // }, + // | Some(e) => e, + // }; + let room_create_event = create_event.clone(); + + // Get the content of the room create event, used later. + let room_create_content: RoomCreateContentFields = + from_json_str(room_create_event.content().get())?; + if room_create_content + .room_version + .is_some_and(|v| v.deserialize().is_err()) + { + warn!("invalid room version found in m.room.create event"); + return Ok(false); + } + let expected_room_id = match room_version.room_ids_as_hashes { + // If the room version uses hashes, we replace the create event's event ID leading sigil + // with ! + | true => OwnedRoomId::try_from(room_create_event.event_id().as_str().replace('$', "!")) + .expect("Failed to convert event ID to room ID") + .clone(), + | false => room_create_event.room_id().unwrap().to_owned(), }; - if incoming_event.room_id() != room_create_event.room_id() { - warn!("room_id of incoming event does not match room_id of m.room.create event"); + if incoming_event.room_id().unwrap() != expected_room_id { + warn!( + expected = %expected_room_id, + received = %incoming_event.room_id().unwrap(), + "room_id of incoming event ({}) does not match room_id of m.room.create event ({})", + incoming_event.room_id().unwrap(), + expected_room_id, + ); + return Ok(false); + } + + // If the create event is referenced in the event's auth events, and this is a + // v12 room, reject + let claims_create_event = incoming_event + .auth_events() + .any(|id| id == room_create_event.event_id()); + if room_version.room_ids_as_hashes && claims_create_event { + warn!("m.room.create event incorrectly found in auth events"); + return Ok(false); + } else if !room_version.room_ids_as_hashes && !claims_create_event { + // If the create event is not referenced in the event's auth events, and this is + // a v11 room, reject + warn!("no m.room.create event found in auth events"); return Ok(false); } if let Some(ref pe) = power_levels_event { - if pe.room_id() != room_create_event.room_id() { - warn!("room_id of power levels event does not match room_id of m.room.create event"); + if *pe.room_id().unwrap() != expected_room_id { + warn!( + expected = %expected_room_id, + received = %pe.room_id().unwrap(), + "room_id of power levels event does not match room_id of m.room.create event" + ); return Ok(false); } } // 3. If event does not have m.room.create in auth_events reject - if !incoming_event - .auth_events() - .any(|id| id == room_create_event.event_id()) - { - warn!("no m.room.create event in auth events"); - return Ok(false); - } + // removed as part of Hydra. + // TODO: reintroduce this for { - warn!("no statekey in member event"); + warn!("no state key in member event"); return Ok(false); }, | Some(s) => s, @@ -377,6 +449,7 @@ where &user_for_join_auth_membership, &room_create_event, )? { + warn!("membership change not valid for some reason"); return Ok(false); } @@ -394,8 +467,16 @@ where }, }; - if sender_member_event.room_id() != room_create_event.room_id() { - warn!("room_id of incoming event does not match room_id of m.room.create event"); + if sender_member_event + .room_id() + .expect("we have a room ID for non create events") + != room_create_event.room_id_or_hash() + { + warn!( + "room_id of incoming event ({}) does not match room_id of m.room.create event ({})", + sender_member_event.room_id_or_hash(), + room_create_event.room_id_or_hash() + ); return Ok(false); } @@ -417,7 +498,7 @@ where } // If type is m.room.third_party_invite - let sender_power_level = match &power_levels_event { + let mut sender_power_level = match &power_levels_event { | Some(pl) => { let content = deserialize_power_levels_content_fields(pl.content().get(), room_version)?; @@ -439,6 +520,24 @@ where if is_creator { int!(100) } else { int!(0) } }, }; + if room_version.explicitly_privilege_room_creators { + // If the user sent the create event, or is listed in additional_creators, just + // give them Int::MAX + if sender == room_create_event.sender() + || room_create_content + .additional_creators + .as_ref() + .is_some_and(|creators| { + creators + .iter() + .any(|c| c.deserialize().is_ok_and(|c| c == *sender)) + }) { + trace!("privileging room creator or additional creator"); + // This user is the room creator or an additional creator, give them max power + // level + sender_power_level = Int::MAX; + } + } // Allow if and only if sender's current power level is greater than // or equal to the invite level @@ -554,6 +653,7 @@ where struct GetThirdPartyInvite { third_party_invite: Option>, } + let create_content = from_json_str::(create_room.content().get())?; let content = current_event.content(); let target_membership = from_json_str::(content.get())?.membership; @@ -576,15 +676,36 @@ where | None => RoomPowerLevelsEventContent::default(), }; - let sender_power = power_levels + let mut sender_power = power_levels .users .get(sender) .or_else(|| sender_is_joined.then_some(&power_levels.users_default)); - let target_power = power_levels.users.get(target_user).or_else(|| { + let mut target_power = power_levels.users.get(target_user).or_else(|| { (target_membership == MembershipState::Join).then_some(&power_levels.users_default) }); + let mut creators = BTreeSet::new(); + creators.insert(create_room.sender().to_owned()); + if room_version.explicitly_privilege_room_creators { + // Explicitly privilege room creators + // If the sender sent the create event, or in additional_creators, give them + // Int::MAX. Same case for target. + if let Some(additional_creators) = &create_content.additional_creators { + for c in additional_creators { + if let Ok(c) = c.deserialize() { + creators.insert(c); + } + } + } + if creators.contains(sender) { + sender_power = Some(&Int::MAX); + } + if creators.contains(target_user) { + target_power = Some(&Int::MAX); + } + } + let mut join_rules = JoinRule::Invite; if let Some(jr) = &join_rules_event { join_rules = from_json_str::(jr.content().get())?.join_rule; @@ -597,7 +718,7 @@ where let user_for_join_auth_is_valid = if let Some(user_for_join_auth) = user_for_join_auth { // Is the authorised user allowed to invite users into this room - let (auth_user_pl, invite_level) = if let Some(pl) = &power_levels_event { + let (mut auth_user_pl, invite_level) = if let Some(pl) = &power_levels_event { // TODO Refactor all powerlevel parsing let invite = deserialize_power_levels_content_invite(pl.content().get(), room_version)?.invite; @@ -613,6 +734,9 @@ where } else { (int!(0), int!(0)) }; + if creators.contains(user_for_join_auth) { + auth_user_pl = Int::MAX; + } (user_for_join_auth_membership == &MembershipState::Join) && (auth_user_pl >= invite_level) } else { @@ -622,6 +746,7 @@ where Ok(match target_membership { | MembershipState::Join => { + debug!("starting target_membership=join check"); // 1. If the only previous event is an m.room.create and the state_key is the // creator, // allow @@ -633,7 +758,10 @@ where let no_more_prev_events = prev_events.next().is_none(); if prev_event_is_create_event && no_more_prev_events { - let is_creator = if room_version.use_room_create_sender { + debug!("checking if sender is a room creator for initial membership event"); + let is_creator = if room_version.explicitly_privilege_room_creators { + creators.contains(target_user) && creators.contains(sender) + } else if room_version.use_room_create_sender { let creator = create_room.sender(); creator == sender && creator == target_user @@ -647,10 +775,15 @@ where }; if is_creator { + debug!("sender is room creator, allowing join"); return Ok(true); } + debug!("sender is not room creator, proceeding with normal auth checks"); } - + let membership_allows_join = matches!( + target_user_current_membership, + MembershipState::Join | MembershipState::Invite + ); if sender != target_user { // If the sender does not match state_key, reject. warn!("Can't make other user join"); @@ -659,39 +792,48 @@ where // If the sender is banned, reject. warn!(?target_user_membership_event_id, "Banned user can't join"); false - } else if (join_rules == JoinRule::Invite - || room_version.allow_knocking && (join_rules == JoinRule::Knock || matches!(join_rules, JoinRule::KnockRestricted(_)))) - // If the join_rule is invite then allow if membership state is invite or join - && (target_user_current_membership == MembershipState::Join - || target_user_current_membership == MembershipState::Invite) - { - true - } else if room_version.restricted_join_rules - && matches!(join_rules, JoinRule::Restricted(_)) - || room_version.knock_restricted_join_rule - && matches!(join_rules, JoinRule::KnockRestricted(_)) - { - // If the join_rule is restricted or knock_restricted - if matches!( - target_user_current_membership, - MembershipState::Invite | MembershipState::Join - ) { - // If membership state is join or invite, allow. - true - } else { - // If the join_authorised_via_users_server key in content is not a user with - // sufficient permission to invite other users, reject. - // Otherwise, allow. - user_for_join_auth_is_valid - } } else { - // If the join_rule is public, allow. - // Otherwise, reject. - join_rules == JoinRule::Public + match join_rules { + | JoinRule::Invite if !membership_allows_join => { + warn!("Join rule is invite but membership does not allow join"); + false + }, + | JoinRule::Knock if !room_version.allow_knocking => { + warn!("Join rule is knock but room version does not allow knocking"); + false + }, + | JoinRule::Knock if !membership_allows_join => { + warn!("Join rule is knock but membership does not allow join"); + false + }, + | JoinRule::KnockRestricted(_) if !room_version.knock_restricted_join_rule => + { + warn!( + "Join rule is knock_restricted but room version does not support it" + ); + false + }, + | JoinRule::KnockRestricted(_) if !membership_allows_join => { + warn!("Join rule is knock_restricted but membership does not allow join"); + false + }, + | JoinRule::Restricted(_) | JoinRule::KnockRestricted(_) => + if !user_for_join_auth_is_valid { + warn!( + "Join rule is a restricted one but no valid authorising user \ + was given" + ); + false + } else { + true + }, + | _ => true, + } } }, | MembershipState::Invite => { // If content has third_party_invite key + debug!("starting target_membership=invite check"); match third_party_invite.and_then(|i| i.deserialize().ok()) { | Some(tp_id) => if target_user_current_membership == MembershipState::Ban { @@ -849,6 +991,7 @@ fn can_send_event(event: &impl Event, ple: Option<&impl Event>, user_level: Int) required_level = i64::from(event_type_power_level), user_level = i64::from(user_level), state_key = ?event.state_key(), + power_level_event_id = ?ple.map(|e| e.event_id().as_str()), "permissions factors", ); diff --git a/src/core/matrix/state_res/mod.rs b/src/core/matrix/state_res/mod.rs index ce9d9276..de7a0c3a 100644 --- a/src/core/matrix/state_res/mod.rs +++ b/src/core/matrix/state_res/mod.rs @@ -92,6 +92,11 @@ where Pdu: Event + Clone + Send + Sync, for<'b> &'b Pdu: Event + Send, { + use RoomVersionId::*; + let stateres_version = match room_version { + | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 | V11 => 2.0, + | _ => 2.1, + }; debug!("State resolution starting"); // Split non-conflicting and conflicting state @@ -108,13 +113,27 @@ where debug!(count = conflicting.len(), "conflicting events"); trace!(map = ?conflicting, "conflicting events"); + let conflicted_state_subgraph: HashSet<_> = if stateres_version >= 2.1 { + calculate_conflicted_subgraph(&conflicting, event_fetch) + .await + .ok_or_else(|| { + Error::InvalidPdu("Failed to calculate conflicted subgraph".to_owned()) + })? + } else { + HashSet::new() + }; + debug!(count = conflicted_state_subgraph.len(), "conflicted subgraph"); + trace!(set = ?conflicted_state_subgraph, "conflicted subgraph"); + let conflicting_values = conflicting.into_values().flatten().stream(); // `all_conflicted` contains unique items // synapse says `full_set = {eid for eid in full_conflicted_set if eid in // event_map}` + // Hydra: Also consider the conflicted state subgraph let all_conflicted: HashSet<_> = get_auth_chain_diff(auth_chain_sets) .chain(conflicting_values) + .chain(conflicted_state_subgraph.into_iter().stream()) .broad_filter_map(async |id| event_exists(id.clone()).await.then_some(id)) .collect() .await; @@ -150,6 +169,7 @@ where // Sequentially auth check each control event. let resolved_control = iterative_auth_check( &room_version, + stateres_version, sorted_control_levels.iter().stream().map(AsRef::as_ref), clean.clone(), &event_fetch, @@ -183,10 +203,11 @@ where let sorted_left_events = mainline_sort(&events_to_resolve, power_event.cloned(), &event_fetch).await?; - trace!(list = ?sorted_left_events, "events left, sorted"); + trace!(list = ?sorted_left_events, "events left, sorted, running iterative auth check"); let mut resolved_state = iterative_auth_check( &room_version, + stateres_version, sorted_left_events.iter().stream().map(AsRef::as_ref), resolved_control, // The control events are added to the final resolved state &event_fetch, @@ -198,6 +219,7 @@ where resolved_state.extend(clean); debug!("state resolution finished"); + trace!( map = ?resolved_state, "final resolved state" ); Ok(resolved_state) } @@ -250,6 +272,52 @@ where (unconflicted_state, conflicted_state) } +/// Calculate the conflicted subgraph +async fn calculate_conflicted_subgraph( + conflicted: &StateMap>, + fetch_event: &F, +) -> Option> +where + F: Fn(OwnedEventId) -> Fut + Sync, + Fut: Future> + Send, + E: Event + Send + Sync, +{ + let conflicted_events: HashSet<_> = conflicted.values().flatten().cloned().collect(); + let mut subgraph: HashSet = HashSet::new(); + let mut stack: Vec> = + vec![conflicted_events.iter().cloned().collect::>()]; + let mut path: Vec = Vec::new(); + let mut seen: HashSet = HashSet::new(); + let next_event = |stack: &mut Vec>, path: &mut Vec<_>| { + while stack.last().is_some_and(|s| s.is_empty()) { + stack.pop(); + path.pop(); + } + stack.last_mut().and_then(|s| s.pop()) + }; + while let Some(event_id) = next_event(&mut stack, &mut path) { + path.push(event_id.clone()); + if subgraph.contains(&event_id) { + if path.len() > 1 { + subgraph.extend(path.iter().cloned()); + } + path.pop(); + continue; + } + if conflicted_events.contains(&event_id) && path.len() > 1 { + subgraph.extend(path.iter().cloned()); + } + if seen.contains(&event_id) { + path.pop(); + continue; + } + let evt = fetch_event(event_id.clone()).await?; + stack.push(evt.auth_events().map(ToOwned::to_owned).collect()); + seen.insert(event_id); + } + Some(subgraph) +} + /// Returns a Vec of deduped EventIds that appear in some chains but not others. #[allow(clippy::arithmetic_side_effects)] fn get_auth_chain_diff( @@ -513,8 +581,10 @@ where /// For each `events_to_check` event we gather the events needed to auth it from /// the the `fetch_event` closure and verify each event using the /// `event_auth::auth_check` function. +#[tracing::instrument(level = "trace", skip_all)] async fn iterative_auth_check<'a, E, F, Fut, S>( room_version: &RoomVersion, + stateres_version: f32, events_to_check: S, unconflicted_state: StateMap, fetch_event: &F, @@ -538,12 +608,15 @@ where .try_collect() .boxed() .await?; + trace!(list = ?events_to_check, "events to check"); let auth_event_ids: HashSet = events_to_check .iter() .flat_map(|event: &E| event.auth_events().map(ToOwned::to_owned)) .collect(); + trace!(set = ?auth_event_ids, "auth event IDs to fetch"); + let auth_events: HashMap = auth_event_ids .into_iter() .stream() @@ -553,9 +626,15 @@ where .boxed() .await; + trace!(map = ?auth_events.keys().collect::>(), "fetched auth events"); + let auth_events = &auth_events; - let mut resolved_state = unconflicted_state; + let mut resolved_state = match stateres_version { + | 2.1 => StateMap::new(), + | _ => unconflicted_state, + }; for event in events_to_check { + trace!(event_id = event.event_id().as_str(), "checking event"); let state_key = event .state_key() .ok_or_else(|| Error::InvalidPdu("State event had no state key".to_owned()))?; @@ -565,13 +644,29 @@ where event.sender(), Some(state_key), event.content(), + room_version, )?; + trace!(list = ?auth_types, event_id = event.event_id().as_str(), "auth types for event"); let mut auth_state = StateMap::new(); + if room_version.room_ids_as_hashes { + trace!("room version uses hashed IDs, manually fetching create event"); + let create_event_id_raw = event.room_id_or_hash().as_str().replace('!', "$"); + let create_event_id = EventId::parse(&create_event_id_raw).map_err(|e| { + Error::InvalidPdu(format!( + "Failed to parse create event ID from room ID/hash: {e}" + )) + })?; + let create_event = fetch_event(create_event_id.into()) + .await + .ok_or_else(|| Error::NotFound("Failed to find create event".into()))?; + auth_state.insert(create_event.event_type().with_state_key(""), create_event); + } for aid in event.auth_events() { if let Some(ev) = auth_events.get(aid) { //TODO: synapse checks "rejected_reason" which is most likely related to // soft-failing + trace!(event_id = aid.as_str(), "found auth event"); auth_state.insert( ev.event_type() .with_state_key(ev.state_key().ok_or_else(|| { @@ -600,8 +695,9 @@ where auth_state.insert(key.to_owned(), event); }) .await; + trace!(map = ?auth_state.keys().collect::>(), event_id = event.event_id().as_str(), "auth state for event"); - debug!("event to check {:?}", event.event_id()); + debug!(event_id = event.event_id().as_str(), "Running auth checks"); // The key for this is (eventType + a state_key of the signed token not sender) // so search for it @@ -617,16 +713,29 @@ where ) }; - let auth_result = - auth_check(room_version, &event, current_third_party, fetch_state).await; + let auth_result = auth_check( + room_version, + &event, + current_third_party, + fetch_state, + &fetch_state(&StateEventType::RoomCreate, "") + .await + .expect("create event must exist"), + ) + .await; match auth_result { | Ok(true) => { // add event to resolved state map + trace!( + event_id = event.event_id().as_str(), + "event passed the authentication check, adding to resolved state" + ); resolved_state.insert( event.event_type().with_state_key(state_key), event.event_id().to_owned(), ); + trace!(map = ?resolved_state, "new resolved state"); }, | Ok(false) => { // synapse passes here on AuthError. We do not add this event to resolved_state. @@ -638,7 +747,8 @@ where }, } } - + trace!(map = ?resolved_state, "final resolved state from iterative auth check"); + debug!("iterative auth check finished"); Ok(resolved_state) } @@ -909,6 +1019,7 @@ mod tests { let resolved_power = super::iterative_auth_check( &RoomVersion::V6, + 2.1, sorted_power_events.iter().map(AsRef::as_ref).stream(), HashMap::new(), // unconflicted events &fetcher, diff --git a/src/core/matrix/state_res/room_version.rs b/src/core/matrix/state_res/room_version.rs index 8dfd6cde..7fa219f9 100644 --- a/src/core/matrix/state_res/room_version.rs +++ b/src/core/matrix/state_res/room_version.rs @@ -61,25 +61,34 @@ pub struct RoomVersion { pub extra_redaction_checks: bool, /// Allow knocking in event authentication. /// - /// See [room v7 specification](https://spec.matrix.org/latest/rooms/v7/) for more information. + /// See [room v7 specification](https://spec.matrix.org/latest/rooms/v7/) pub allow_knocking: bool, /// Adds support for the restricted join rule. /// - /// See: [MSC3289](https://github.com/matrix-org/matrix-spec-proposals/pull/3289) for more information. + /// See: [MSC3289](https://github.com/matrix-org/matrix-spec-proposals/pull/3289) pub restricted_join_rules: bool, /// Adds support for the knock_restricted join rule. /// - /// See: [MSC3787](https://github.com/matrix-org/matrix-spec-proposals/pull/3787) for more information. + /// See: [MSC3787](https://github.com/matrix-org/matrix-spec-proposals/pull/3787) pub knock_restricted_join_rule: bool, /// Enforces integer power levels. /// - /// See: [MSC3667](https://github.com/matrix-org/matrix-spec-proposals/pull/3667) for more information. + /// See: [MSC3667](https://github.com/matrix-org/matrix-spec-proposals/pull/3667) pub integer_power_levels: bool, /// Determine the room creator using the `m.room.create` event's `sender`, /// instead of the event content's `creator` field. /// - /// See: [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175) for more information. + /// See: [MSC2175](https://github.com/matrix-org/matrix-spec-proposals/pull/2175) pub use_room_create_sender: bool, + /// Whether the room creators are considered superusers. + /// A superuser will always have infinite power levels in the room. + /// + /// See: [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289) + pub explicitly_privilege_room_creators: bool, + /// Whether the room's m.room.create event ID is itself the room ID. + /// + /// See: [MSC4291](https://github.com/matrix-org/matrix-spec-proposals/pull/4291) + pub room_ids_as_hashes: bool, } impl RoomVersion { @@ -97,6 +106,8 @@ impl RoomVersion { knock_restricted_join_rule: false, integer_power_levels: false, use_room_create_sender: false, + explicitly_privilege_room_creators: false, + room_ids_as_hashes: false, }; pub const V10: Self = Self { knock_restricted_join_rule: true, @@ -107,6 +118,11 @@ impl RoomVersion { use_room_create_sender: true, ..Self::V10 }; + pub const V12: Self = Self { + explicitly_privilege_room_creators: true, + room_ids_as_hashes: true, + ..Self::V11 + }; pub const V2: Self = Self { state_res: StateResolutionVersion::V2, ..Self::V1 @@ -144,6 +160,7 @@ impl RoomVersion { | RoomVersionId::V9 => Self::V9, | RoomVersionId::V10 => Self::V10, | RoomVersionId::V11 => Self::V11, + | RoomVersionId::V12 => Self::V12, | ver => return Err(Error::Unsupported(format!("found version `{ver}`"))), }) } diff --git a/src/core/matrix/state_res/test_utils.rs b/src/core/matrix/state_res/test_utils.rs index 9f24c51b..10b79de1 100644 --- a/src/core/matrix/state_res/test_utils.rs +++ b/src/core/matrix/state_res/test_utils.rs @@ -24,7 +24,7 @@ use serde_json::{ use super::auth_types_for_event; use crate::{ - Result, info, + Result, RoomVersion, info, matrix::{Event, EventTypeExt, Pdu, StateMap, pdu::EventHash}, }; @@ -154,6 +154,7 @@ pub(crate) async fn do_check( fake_event.sender(), fake_event.state_key(), fake_event.content(), + &RoomVersion::V6, ) .unwrap(); @@ -398,7 +399,7 @@ pub(crate) fn to_init_pdu_event( Pdu { event_id: id.try_into().unwrap(), - room_id: room_id().to_owned(), + room_id: Some(room_id().to_owned()), sender: sender.to_owned(), origin_server_ts: ts.try_into().unwrap(), state_key: state_key.map(Into::into), @@ -446,7 +447,7 @@ where Pdu { event_id: id.try_into().unwrap(), - room_id: room_id().to_owned(), + room_id: Some(room_id().to_owned()), sender: sender.to_owned(), origin_server_ts: ts.try_into().unwrap(), state_key: state_key.map(Into::into), diff --git a/src/service/admin/create.rs b/src/service/admin/create.rs index 755673fe..913acc2d 100644 --- a/src/service/admin/create.rs +++ b/src/service/admin/create.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use conduwuit::{Result, pdu::PduBuilder}; +use conduwuit::{Result, info, pdu::PduBuilder}; use futures::FutureExt; use ruma::{ RoomId, RoomVersionId, @@ -26,7 +26,7 @@ use crate::Services; /// used to issue admin commands by talking to the server user inside it. pub async fn create_admin_room(services: &Services) -> Result { let room_id = RoomId::new(services.globals.server_name()); - let room_version = &services.config.default_room_version; + let room_version = &RoomVersionId::V11; let _short_id = services .rooms @@ -45,10 +45,13 @@ pub async fn create_admin_room(services: &Services) -> Result { match room_version { | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => RoomCreateEventContent::new_v1(server_user.into()), - | _ => RoomCreateEventContent::new_v11(), + | V11 => RoomCreateEventContent::new_v11(), + | _ => RoomCreateEventContent::new_v12(), } }; + info!("Creating admin room {} with version {}", room_id, room_version); + // 1. The room create event services .rooms @@ -61,7 +64,7 @@ pub async fn create_admin_room(services: &Services) -> Result { ..create_content }), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -77,7 +80,7 @@ pub async fn create_admin_room(services: &Services) -> Result { &RoomMemberEventContent::new(MembershipState::Join), ), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -95,7 +98,7 @@ pub async fn create_admin_room(services: &Services) -> Result { ..Default::default() }), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -108,7 +111,7 @@ pub async fn create_admin_room(services: &Services) -> Result { .build_and_append_pdu( PduBuilder::state(String::new(), &RoomJoinRulesEventContent::new(JoinRule::Invite)), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -124,7 +127,7 @@ pub async fn create_admin_room(services: &Services) -> Result { &RoomHistoryVisibilityEventContent::new(HistoryVisibility::Shared), ), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -140,7 +143,7 @@ pub async fn create_admin_room(services: &Services) -> Result { &RoomGuestAccessEventContent::new(GuestAccess::Forbidden), ), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -154,7 +157,7 @@ pub async fn create_admin_room(services: &Services) -> Result { .build_and_append_pdu( PduBuilder::state(String::new(), &RoomNameEventContent::new(room_name)), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -168,7 +171,7 @@ pub async fn create_admin_room(services: &Services) -> Result { topic: format!("Manage {} | Run commands prefixed with `!admin` | Run `!admin -h` for help | Documentation: https://continuwuity.org/", services.config.server_name), }), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -186,7 +189,7 @@ pub async fn create_admin_room(services: &Services) -> Result { alt_aliases: Vec::new(), }), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() @@ -204,7 +207,7 @@ pub async fn create_admin_room(services: &Services) -> Result { .build_and_append_pdu( PduBuilder::state(String::new(), &RoomPreviewUrlsEventContent { disabled: true }), server_user, - &room_id, + Some(&room_id), &state_lock, ) .boxed() diff --git a/src/service/admin/grant.rs b/src/service/admin/grant.rs index 172187cb..d3d5d491 100644 --- a/src/service/admin/grant.rs +++ b/src/service/admin/grant.rs @@ -55,7 +55,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result { &RoomMemberEventContent::new(MembershipState::Invite), ), server_user, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -69,7 +69,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result { &RoomMemberEventContent::new(MembershipState::Join), ), user_id, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -83,7 +83,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result { &RoomMemberEventContent::new(MembershipState::Invite), ), server_user, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -111,7 +111,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result { .build_and_append_pdu( PduBuilder::state(String::new(), &room_power_levels), server_user, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -135,7 +135,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result { .build_and_append_pdu( PduBuilder::timeline(&RoomMessageEventContent::text_markdown(welcome_message)), server_user, - &room_id, + Some(&room_id), &state_lock, ) .await?; @@ -218,7 +218,7 @@ pub async fn revoke_admin(&self, user_id: &UserId) -> Result { ..event }), self.services.globals.server_user.as_ref(), - &room_id, + Some(&room_id), &state_lock, ) .await diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index c052198c..7b0fb037 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -393,13 +393,13 @@ impl Service { return Ok(()); }; - let response_sender = if self.is_admin_room(pdu.room_id()).await { + let response_sender = if self.is_admin_room(pdu.room_id().unwrap()).await { &self.services.globals.server_user } else { pdu.sender() }; - self.respond_to_room(content, pdu.room_id(), response_sender) + self.respond_to_room(content, pdu.room_id().unwrap(), response_sender) .boxed() .await } @@ -419,7 +419,7 @@ impl Service { .build_and_append_pdu( PduBuilder::timeline(&self.text_or_file(content).await), user_id, - room_id, + Some(room_id), &state_lock, ) .await @@ -447,7 +447,12 @@ impl Service { self.services .timeline - .build_and_append_pdu(PduBuilder::timeline(&content), user_id, room_id, state_lock) + .build_and_append_pdu( + PduBuilder::timeline(&content), + user_id, + Some(room_id), + state_lock, + ) .await?; Ok(()) @@ -484,7 +489,10 @@ impl Service { } // Prevent unescaped !admin from being used outside of the admin room - if is_public_prefix && !self.is_admin_room(event.room_id()).await { + if event.room_id().is_some() + && is_public_prefix + && !self.is_admin_room(event.room_id().unwrap()).await + { return false; } @@ -497,7 +505,7 @@ impl Service { // the administrator can execute commands as the server user let emergency_password_set = self.services.server.config.emergency_password.is_some(); let from_server = event.sender() == server_user && !emergency_password_set; - if from_server && self.is_admin_room(event.room_id()).await { + if from_server && self.is_admin_room(event.room_id().unwrap()).await { return false; } diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index 071bf822..043c6933 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -287,18 +287,22 @@ impl Service { { let mut notify = None; let mut tweaks = Vec::new(); + if event.room_id().is_none() { + // TODO(hydra): does this matter? + return Ok(()); + } let power_levels: RoomPowerLevelsEventContent = self .services .state_accessor - .room_state_get(event.room_id(), &StateEventType::RoomPowerLevels, "") + .room_state_get(event.room_id().unwrap(), &StateEventType::RoomPowerLevels, "") .await .and_then(|event| event.get_content()) .unwrap_or_default(); let serialized = event.to_format(); for action in self - .get_actions(user, &ruleset, &power_levels, &serialized, event.room_id()) + .get_actions(user, &ruleset, &power_levels, &serialized, event.room_id().unwrap()) .await { let n = match action { @@ -426,7 +430,7 @@ impl Service { let mut notifi = Notification::new(d); notifi.event_id = Some(event.event_id().to_owned()); - notifi.room_id = Some(event.room_id().to_owned()); + notifi.room_id = Some(event.room_id().unwrap().to_owned()); if http .data .get("org.matrix.msc4076.disable_badge_count") @@ -470,14 +474,14 @@ impl Service { notifi.room_name = self .services .state_accessor - .get_name(event.room_id()) + .get_name(event.room_id().unwrap()) .await .ok(); notifi.room_alias = self .services .state_accessor - .get_canonical_alias(event.room_id()) + .get_canonical_alias(event.room_id().unwrap()) .await .ok(); diff --git a/src/service/rooms/auth_chain/mod.rs b/src/service/rooms/auth_chain/mod.rs index 79d4d070..fe15549c 100644 --- a/src/service/rooms/auth_chain/mod.rs +++ b/src/service/rooms/auth_chain/mod.rs @@ -195,11 +195,11 @@ async fn get_auth_chain_inner( debug_error!(?event_id, ?e, "Could not find pdu mentioned in auth events"); }, | Ok(pdu) => { - if pdu.room_id != room_id { + if pdu.room_id.is_some() && pdu.room_id != Some(room_id.to_owned()) { return Err!(Request(Forbidden(error!( ?event_id, ?room_id, - wrong_room_id = ?pdu.room_id, + wrong_room_id = ?pdu.room_id.unwrap(), "auth event for incorrect room" )))); } diff --git a/src/service/rooms/event_handler/handle_incoming_pdu.rs b/src/service/rooms/event_handler/handle_incoming_pdu.rs index 5299e8d4..b3358785 100644 --- a/src/service/rooms/event_handler/handle_incoming_pdu.rs +++ b/src/service/rooms/event_handler/handle_incoming_pdu.rs @@ -58,6 +58,10 @@ pub async fn handle_incoming_pdu<'a>( value: BTreeMap, is_timeline_event: bool, ) -> Result> { + if room_id.is_empty() { + // TODO(hydra): Room IDs should be calculated before this function is called + panic!("room ID cannot be empty"); + } // 1. Skip the PDU if we already have it as a timeline event if let Ok(pdu_id) = self.services.timeline.get_pdu_id(event_id).await { return Ok(Some(pdu_id)); diff --git a/src/service/rooms/event_handler/handle_outlier_pdu.rs b/src/service/rooms/event_handler/handle_outlier_pdu.rs index d79eed77..7c0cfd9f 100644 --- a/src/service/rooms/event_handler/handle_outlier_pdu.rs +++ b/src/service/rooms/event_handler/handle_outlier_pdu.rs @@ -139,6 +139,7 @@ where &pdu_event, None, // TODO: third party invite state_fetch, + create_event.as_pdu(), ) .await .map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?; diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index ef724ab0..c9de1419 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -99,7 +99,10 @@ impl Service { } fn check_room_id(room_id: &RoomId, pdu: &Pdu) -> Result { - if pdu.room_id() != room_id { + if pdu + .room_id() + .is_some_and(|claimed_room_id| claimed_room_id != room_id) + { return Err!(Request(InvalidParam(error!( pdu_event_id = ?pdu.event_id(), pdu_room_id = ?pdu.room_id(), diff --git a/src/service/rooms/event_handler/upgrade_outlier_pdu.rs b/src/service/rooms/event_handler/upgrade_outlier_pdu.rs index d2e0623c..46a63150 100644 --- a/src/service/rooms/event_handler/upgrade_outlier_pdu.rs +++ b/src/service/rooms/event_handler/upgrade_outlier_pdu.rs @@ -102,6 +102,7 @@ where &incoming_pdu, None, // TODO: third party invite |ty, sk| state_fetch(ty.clone(), sk.into()), + create_event.as_pdu(), ) .await .map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?; @@ -123,6 +124,7 @@ where incoming_pdu.sender(), incoming_pdu.state_key(), incoming_pdu.content(), + &room_version, ) .await?; @@ -140,6 +142,7 @@ where &incoming_pdu, None, // third-party invite state_fetch, + create_event.as_pdu(), ) .await .map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?; @@ -156,7 +159,7 @@ where !self .services .state_accessor - .user_can_redact(&redact_id, incoming_pdu.sender(), incoming_pdu.room_id(), true) + .user_can_redact(&redact_id, incoming_pdu.sender(), room_id, true) .await?, }; @@ -313,6 +316,7 @@ where state_ids_compressed, soft_fail, &state_lock, + room_id, ) .await?; @@ -347,6 +351,7 @@ where state_ids_compressed, soft_fail, &state_lock, + room_id, ) .await?; diff --git a/src/service/rooms/search/mod.rs b/src/service/rooms/search/mod.rs index ea2f90af..9bea0264 100644 --- a/src/service/rooms/search/mod.rs +++ b/src/service/rooms/search/mod.rs @@ -124,7 +124,7 @@ pub async fn search_pdus<'a>( .wide_filter_map(move |pdu| async move { self.services .state_accessor - .user_can_see_event(query.user_id?, pdu.room_id(), pdu.event_id()) + .user_can_see_event(query.user_id?, pdu.room_id().unwrap(), pdu.event_id()) .await .then_some(pdu) }) diff --git a/src/service/rooms/state/mod.rs b/src/service/rooms/state/mod.rs index 386adf9d..808d61b4 100644 --- a/src/service/rooms/state/mod.rs +++ b/src/service/rooms/state/mod.rs @@ -1,6 +1,7 @@ use std::{collections::HashMap, fmt::Write, iter::once, sync::Arc}; use async_trait::async_trait; +use conduwuit::{RoomVersion, debug}; use conduwuit_core::{ Event, PduEvent, Result, err, result::FlatOk, @@ -15,6 +16,7 @@ use conduwuit_database::{Deserialized, Ignore, Interfix, Map}; use futures::{ FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt, future::join_all, pin_mut, }; +use log::trace; use ruma::{ EventId, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId, events::{ @@ -148,7 +150,7 @@ impl Service { .roomid_spacehierarchy_cache .lock() .await - .remove(&pdu.room_id); + .remove(room_id); }, | _ => continue, } @@ -239,7 +241,7 @@ impl Service { /// This adds all current state events (not including the incoming event) /// to `stateid_pduid` and adds the incoming event to `eventid_statehash`. #[tracing::instrument(skip(self, new_pdu), level = "debug")] - pub async fn append_to_state(&self, new_pdu: &PduEvent) -> Result { + pub async fn append_to_state(&self, new_pdu: &PduEvent, room_id: &RoomId) -> Result { const BUFSIZE: usize = size_of::(); let shorteventid = self @@ -248,7 +250,7 @@ impl Service { .get_or_create_shorteventid(&new_pdu.event_id) .await; - let previous_shortstatehash = self.get_room_shortstatehash(&new_pdu.room_id).await; + let previous_shortstatehash = self.get_room_shortstatehash(room_id).await; if let Ok(p) = previous_shortstatehash { self.db @@ -319,7 +321,11 @@ impl Service { } #[tracing::instrument(skip_all, level = "debug")] - pub async fn summary_stripped<'a, E>(&self, event: &'a E) -> Vec> + pub async fn summary_stripped<'a, E>( + &self, + event: &'a E, + room_id: &RoomId, + ) -> Vec> where E: Event + Send + Sync, &'a E: Event + Send, @@ -338,7 +344,7 @@ impl Service { let fetches = cells.into_iter().map(|(event_type, state_key)| { self.services .state_accessor - .room_state_get(event.room_id(), event_type, state_key) + .room_state_get(room_id, event_type, state_key) }); join_all(fetches) @@ -421,7 +427,7 @@ impl Service { } /// This fetches auth events from the current state. - #[tracing::instrument(skip(self, content), level = "debug")] + #[tracing::instrument(skip(self, content, room_version), level = "trace")] pub async fn get_auth_events( &self, room_id: &RoomId, @@ -429,13 +435,15 @@ impl Service { sender: &UserId, state_key: Option<&str>, content: &serde_json::value::RawValue, + room_version: &RoomVersion, ) -> Result> { let Ok(shortstatehash) = self.get_room_shortstatehash(room_id).await else { return Ok(HashMap::new()); }; - let auth_types = state_res::auth_types_for_event(kind, sender, state_key, content)?; - + let auth_types = + state_res::auth_types_for_event(kind, sender, state_key, content, room_version)?; + debug!(?auth_types, "Auth types for event"); let sauthevents: HashMap<_, _> = auth_types .iter() .stream() @@ -448,6 +456,7 @@ impl Service { }) .collect() .await; + debug!(?sauthevents, "Auth events to fetch"); let (state_keys, event_ids): (Vec<_>, Vec<_>) = self .services @@ -461,7 +470,7 @@ impl Service { }) .unzip() .await; - + debug!(?state_keys, ?event_ids, "Auth events found in state"); self.services .short .multi_get_eventid_from_short(event_ids.into_iter().stream()) @@ -473,6 +482,7 @@ impl Service { .get_pdu(&event_id) .await .map(move |pdu| (((*ty).clone(), (*sk).clone()), pdu)) + .inspect_err(|e| warn!("Failed to get auth event {event_id}: {e:?}")) .ok() }) .collect() diff --git a/src/service/rooms/state_accessor/user_can.rs b/src/service/rooms/state_accessor/user_can.rs index 221263a8..c6827e09 100644 --- a/src/service/rooms/state_accessor/user_can.rs +++ b/src/service/rooms/state_accessor/user_can.rs @@ -161,7 +161,7 @@ pub async fn user_can_invite( &RoomMemberEventContent::new(MembershipState::Invite), ), sender, - room_id, + Some(room_id), state_lock, ) .await diff --git a/src/service/rooms/timeline/append.rs b/src/service/rooms/timeline/append.rs index 1d404e8a..27fb1d90 100644 --- a/src/service/rooms/timeline/append.rs +++ b/src/service/rooms/timeline/append.rs @@ -42,6 +42,7 @@ pub async fn append_incoming_pdu<'a, Leaves>( state_ids_compressed: Arc, soft_fail: bool, state_lock: &'a RoomMutexGuard, + room_id: &'a ruma::RoomId, ) -> Result> where Leaves: Iterator + Send + 'a, @@ -51,24 +52,24 @@ where // fail. self.services .state - .set_event_state(&pdu.event_id, &pdu.room_id, state_ids_compressed) + .set_event_state(&pdu.event_id, room_id, state_ids_compressed) .await?; if soft_fail { self.services .pdu_metadata - .mark_as_referenced(&pdu.room_id, pdu.prev_events.iter().map(AsRef::as_ref)); + .mark_as_referenced(room_id, pdu.prev_events.iter().map(AsRef::as_ref)); self.services .state - .set_forward_extremities(&pdu.room_id, new_room_leaves, state_lock) + .set_forward_extremities(room_id, new_room_leaves, state_lock) .await; return Ok(None); } let pdu_id = self - .append_pdu(pdu, pdu_json, new_room_leaves, state_lock) + .append_pdu(pdu, pdu_json, new_room_leaves, state_lock, room_id) .await?; Ok(Some(pdu_id)) @@ -88,6 +89,7 @@ pub async fn append_pdu<'a, Leaves>( mut pdu_json: CanonicalJsonObject, leaves: Leaves, state_lock: &'a RoomMutexGuard, + room_id: &'a ruma::RoomId, ) -> Result where Leaves: Iterator + Send + 'a, @@ -98,7 +100,7 @@ where let shortroomid = self .services .short - .get_shortroomid(pdu.room_id()) + .get_shortroomid(room_id) .await .map_err(|_| err!(Database("Room does not exist")))?; @@ -151,14 +153,14 @@ where // We must keep track of all events that have been referenced. self.services .pdu_metadata - .mark_as_referenced(pdu.room_id(), pdu.prev_events().map(AsRef::as_ref)); + .mark_as_referenced(room_id, pdu.prev_events().map(AsRef::as_ref)); self.services .state - .set_forward_extremities(pdu.room_id(), leaves, state_lock) + .set_forward_extremities(room_id, leaves, state_lock) .await; - let insert_lock = self.mutex_insert.lock(pdu.room_id()).await; + let insert_lock = self.mutex_insert.lock(room_id).await; let count1 = self.services.globals.next_count().unwrap(); @@ -166,11 +168,11 @@ where // appending fails self.services .read_receipt - .private_read_set(pdu.room_id(), pdu.sender(), count1); + .private_read_set(room_id, pdu.sender(), count1); self.services .user - .reset_notification_counts(pdu.sender(), pdu.room_id()); + .reset_notification_counts(pdu.sender(), room_id); let count2 = PduCount::Normal(self.services.globals.next_count().unwrap()); let pdu_id: RawPduId = PduId { shortroomid, shorteventid: count2 }.into(); @@ -184,14 +186,14 @@ where let power_levels: RoomPowerLevelsEventContent = self .services .state_accessor - .room_state_get_content(pdu.room_id(), &StateEventType::RoomPowerLevels, "") + .room_state_get_content(room_id, &StateEventType::RoomPowerLevels, "") .await .unwrap_or_default(); let mut push_target: HashSet<_> = self .services .state_cache - .active_local_users_in_room(pdu.room_id()) + .active_local_users_in_room(room_id) .map(ToOwned::to_owned) // Don't notify the sender of their own events, and dont send from ignored users .ready_filter(|user| *user != pdu.sender()) @@ -230,7 +232,7 @@ where for action in self .services .pusher - .get_actions(user, &rules_for_user, &power_levels, &serialized, pdu.room_id()) + .get_actions(user, &rules_for_user, &power_levels, &serialized, room_id) .await { match action { @@ -268,20 +270,20 @@ where } self.db - .increment_notification_counts(pdu.room_id(), notifies, highlights); + .increment_notification_counts(room_id, notifies, highlights); match *pdu.kind() { | TimelineEventType::RoomRedaction => { use RoomVersionId::*; - let room_version_id = self.services.state.get_room_version(pdu.room_id()).await?; + let room_version_id = self.services.state.get_room_version(room_id).await?; match room_version_id { | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => { if let Some(redact_id) = pdu.redacts() { if self .services .state_accessor - .user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false) + .user_can_redact(redact_id, pdu.sender(), room_id, false) .await? { self.redact_pdu(redact_id, pdu, shortroomid).await?; @@ -294,7 +296,7 @@ where if self .services .state_accessor - .user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false) + .user_can_redact(redact_id, pdu.sender(), room_id, false) .await? { self.redact_pdu(redact_id, pdu, shortroomid).await?; @@ -310,7 +312,7 @@ where .roomid_spacehierarchy_cache .lock() .await - .remove(pdu.room_id()); + .remove(room_id); }, | TimelineEventType::RoomMember => { if let Some(state_key) = pdu.state_key() { @@ -320,8 +322,12 @@ where let content: RoomMemberEventContent = pdu.get_content()?; let stripped_state = match content.membership { - | MembershipState::Invite | MembershipState::Knock => - self.services.state.summary_stripped(pdu).await.into(), + | MembershipState::Invite | MembershipState::Knock => self + .services + .state + .summary_stripped(pdu, room_id) + .await + .into(), | _ => None, }; @@ -331,7 +337,7 @@ where self.services .state_cache .update_membership( - pdu.room_id(), + room_id, target_user_id, content, pdu.sender(), @@ -392,7 +398,7 @@ where if self .services .state_cache - .appservice_in_room(pdu.room_id(), appservice) + .appservice_in_room(room_id, appservice) .await { self.services @@ -430,12 +436,12 @@ where let matching_aliases = |aliases: NamespaceRegex| { self.services .alias - .local_aliases_for_room(pdu.room_id()) + .local_aliases_for_room(room_id) .ready_any(move |room_alias| aliases.is_match(room_alias.as_str())) }; if matching_aliases(appservice.aliases.clone()).await - || appservice.rooms.is_match(pdu.room_id().as_str()) + || appservice.rooms.is_match(room_id.as_str()) || matching_users(&appservice.users) { self.services diff --git a/src/service/rooms/timeline/build.rs b/src/service/rooms/timeline/build.rs index a522c531..6bee3769 100644 --- a/src/service/rooms/timeline/build.rs +++ b/src/service/rooms/timeline/build.rs @@ -1,5 +1,6 @@ use std::{collections::HashSet, iter::once}; +use conduwuit::{RoomVersion, debug_warn, trace}; use conduwuit_core::{ Err, Result, implement, matrix::{event::Event, pdu::PduBuilder}, @@ -11,6 +12,7 @@ use ruma::{ events::{ TimelineEventType, room::{ + create::RoomCreateEventContent, member::{MembershipState, RoomMemberEventContent}, redaction::RoomRedactionEventContent, }, @@ -23,32 +25,36 @@ use super::RoomMutexGuard; /// takes a roomid_mutex_state, meaning that only this function is able to /// mutate the room state. #[implement(super::Service)] -#[tracing::instrument(skip(self, state_lock), level = "debug")] +#[tracing::instrument(skip(self, state_lock), level = "trace")] pub async fn build_and_append_pdu( &self, pdu_builder: PduBuilder, sender: &UserId, - room_id: &RoomId, + room_id: Option<&RoomId>, state_lock: &RoomMutexGuard, ) -> Result { let (pdu, pdu_json) = self .create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock) .await?; - if self.services.admin.is_admin_room(pdu.room_id()).await { + let room_id = pdu.room_id_or_hash(); + trace!("Checking if room {room_id} is an admin room"); + if self.services.admin.is_admin_room(&room_id).await { + trace!("Room {room_id} is an admin room, checking PDU for admin room restrictions"); self.check_pdu_for_admin_room(&pdu, sender).boxed().await?; } // If redaction event is not authorized, do not append it to the timeline if *pdu.kind() == TimelineEventType::RoomRedaction { use RoomVersionId::*; - match self.services.state.get_room_version(pdu.room_id()).await? { + trace!("Running redaction checks for room {room_id}"); + match self.services.state.get_room_version(&room_id).await? { | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => { if let Some(redact_id) = pdu.redacts() { if !self .services .state_accessor - .user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false) + .user_can_redact(redact_id, pdu.sender(), &room_id, false) .await? { return Err!(Request(Forbidden("User cannot redact this event."))); @@ -61,7 +67,7 @@ pub async fn build_and_append_pdu( if !self .services .state_accessor - .user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false) + .user_can_redact(redact_id, pdu.sender(), &room_id, false) .await? { return Err!(Request(Forbidden("User cannot redact this event."))); @@ -72,6 +78,7 @@ pub async fn build_and_append_pdu( } if *pdu.kind() == TimelineEventType::RoomMember { + trace!("Running room member checks for room {room_id}"); let content: RoomMemberEventContent = pdu.get_content()?; if content.join_authorized_via_users_server.is_some() @@ -93,12 +100,27 @@ pub async fn build_and_append_pdu( ))); } } + if *pdu.kind() == TimelineEventType::RoomCreate { + trace!("Running room create checks for room {room_id}"); + let content: RoomCreateEventContent = pdu.get_content()?; + let room_features = RoomVersion::new(&content.room_version)?; + if room_features.room_ids_as_hashes { + // bootstrap shortid for room + debug_warn!(%room_id, "Bootstrapping shortid for room"); + self.services + .short + .get_or_create_shortroomid(&room_id) + .await; + } + } // We append to state before appending the pdu, so we don't have a moment in // time with the pdu without it's state. This is okay because append_pdu can't // fail. - let statehashid = self.services.state.append_to_state(&pdu).await?; + trace!("Appending {} state for room {room_id}", pdu.event_id()); + let statehashid = self.services.state.append_to_state(&pdu, &room_id).await?; + trace!("Generating raw ID for PDU {}", pdu.event_id()); let pdu_id = self .append_pdu( &pdu, @@ -107,20 +129,22 @@ pub async fn build_and_append_pdu( // of the room once(pdu.event_id()), state_lock, + &room_id, ) .boxed() .await?; // We set the room state after inserting the pdu, so that we never have a moment // in time where events in the current room state do not exist + trace!("Setting room state for room {room_id}"); self.services .state - .set_room_state(pdu.room_id(), statehashid, state_lock); + .set_room_state(&room_id, statehashid, state_lock); let mut servers: HashSet = self .services .state_cache - .room_servers(pdu.room_id()) + .room_servers(&room_id) .map(ToOwned::to_owned) .collect() .await; @@ -141,11 +165,13 @@ pub async fn build_and_append_pdu( // room_servers() and/or the if statement above servers.remove(self.services.globals.server_name()); + trace!("Sending PDU {} to {} servers", pdu.event_id(), servers.len()); self.services .sending .send_pdu_servers(servers.iter().map(AsRef::as_ref).stream(), &pdu_id) .await?; + trace!("Event {} in room {:?} has been appended", pdu.event_id(), room_id); Ok(pdu.event_id().to_owned()) } @@ -179,7 +205,7 @@ where let count = self .services .state_cache - .room_members(pdu.room_id()) + .room_members(&pdu.room_id_or_hash()) .ready_filter(|user| self.services.globals.user_is_local(user)) .ready_filter(|user| *user != target) .boxed() @@ -203,7 +229,7 @@ where let count = self .services .state_cache - .room_members(pdu.room_id()) + .room_members(&pdu.room_id_or_hash()) .ready_filter(|user| self.services.globals.user_is_local(user)) .ready_filter(|user| *user != target) .boxed() diff --git a/src/service/rooms/timeline/create.rs b/src/service/rooms/timeline/create.rs index 6732cd8e..19c0ce28 100644 --- a/src/service/rooms/timeline/create.rs +++ b/src/service/rooms/timeline/create.rs @@ -1,5 +1,6 @@ -use std::cmp; +use std::{cmp, collections::HashMap}; +use conduwuit::{smallstr::SmallString, trace}; use conduwuit_core::{ Err, Error, Result, err, implement, matrix::{ @@ -11,12 +12,13 @@ use conduwuit_core::{ }; use futures::{StreamExt, TryStreamExt, future, future::ready}; use ruma::{ - CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomId, RoomVersionId, UserId, + CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, + UserId, canonical_json::to_canonical_value, events::{StateEventType, TimelineEventType, room::create::RoomCreateEventContent}, uint, }; -use serde_json::value::to_raw_value; +use serde_json::value::{RawValue, to_raw_value}; use tracing::warn; use super::RoomMutexGuard; @@ -26,10 +28,25 @@ pub async fn create_hash_and_sign_event( &self, pdu_builder: PduBuilder, sender: &UserId, - room_id: &RoomId, + room_id: Option<&RoomId>, _mutex_lock: &RoomMutexGuard, /* Take mutex guard to make sure users get the room * state mutex */ ) -> Result<(PduEvent, CanonicalJsonObject)> { + fn from_evt( + room_id: OwnedRoomId, + event_type: TimelineEventType, + content: Box, + ) -> Result { + if event_type == TimelineEventType::RoomCreate { + let content: RoomCreateEventContent = serde_json::from_str(content.get())?; + Ok(content.room_version) + } else { + Err(Error::InconsistentRoomState( + "non-create event for room of unknown version", + room_id, + )) + } + } let PduBuilder { event_type, content, @@ -38,67 +55,84 @@ pub async fn create_hash_and_sign_event( redacts, timestamp, } = pdu_builder; - - let prev_events: Vec = self - .services - .state - .get_forward_extremities(room_id) - .take(20) - .map(Into::into) - .collect() - .await; - // If there was no create event yet, assume we are creating a room - let room_version_id = self - .services - .state - .get_room_version(room_id) - .await - .or_else(|_| { - if event_type == TimelineEventType::RoomCreate { - let content: RoomCreateEventContent = serde_json::from_str(content.get())?; - Ok(content.room_version) - } else { - Err(Error::InconsistentRoomState( - "non-create event for room of unknown version", - room_id.to_owned(), - )) - } - })?; + let room_version_id = match room_id { + | Some(room_id) => self + .services + .state + .get_room_version(room_id) + .await + .or_else(|_| from_evt(room_id.to_owned(), event_type.clone(), content.clone()))?, + | None => from_evt( + RoomId::new(self.services.globals.server_name()), + event_type.clone(), + content.clone(), + )?, + }; let room_version = RoomVersion::new(&room_version_id).expect("room version is supported"); + // TODO(hydra): Only create events can lack a room ID. - let auth_events = self - .services - .state - .get_auth_events(room_id, &event_type, sender, state_key.as_deref(), &content) - .await?; + let prev_events: Vec = match room_id { + | Some(room_id) => + self.services + .state + .get_forward_extremities(room_id) + .take(20) + .map(Into::into) + .collect() + .await, + | None => Vec::new(), + }; + let auth_events: HashMap<(StateEventType, SmallString<[u8; 48]>), PduEvent> = match room_id { + | Some(room_id) => + self.services + .state + .get_auth_events( + room_id, + &event_type, + sender, + state_key.as_deref(), + &content, + &room_version, + ) + .await?, + | None => HashMap::new(), + }; // Our depth is the maximum depth of prev_events + 1 - let depth = prev_events - .iter() - .stream() - .map(Ok) - .and_then(|event_id| self.get_pdu(event_id)) - .and_then(|pdu| future::ok(pdu.depth)) - .ignore_err() - .ready_fold(uint!(0), cmp::max) - .await - .saturating_add(uint!(1)); + let depth = match room_id { + | Some(_) => prev_events + .iter() + .stream() + .map(Ok) + .and_then(|event_id| self.get_pdu(event_id)) + .and_then(|pdu| future::ok(pdu.depth)) + .ignore_err() + .ready_fold(uint!(0), cmp::max) + .await + .saturating_add(uint!(1)), + | None => uint!(1), + }; let mut unsigned = unsigned.unwrap_or_default(); - if let Some(state_key) = &state_key { - if let Ok(prev_pdu) = self - .services - .state_accessor - .room_state_get(room_id, &event_type.to_string().into(), state_key) - .await - { - unsigned.insert("prev_content".to_owned(), prev_pdu.get_content_as_value()); - unsigned.insert("prev_sender".to_owned(), serde_json::to_value(prev_pdu.sender())?); - unsigned - .insert("replaces_state".to_owned(), serde_json::to_value(prev_pdu.event_id())?); + if let Some(room_id) = room_id { + if let Some(state_key) = &state_key { + if let Ok(prev_pdu) = self + .services + .state_accessor + .room_state_get(room_id, &event_type.clone().to_string().into(), state_key) + .await + { + unsigned.insert("prev_content".to_owned(), prev_pdu.get_content_as_value()); + unsigned + .insert("prev_sender".to_owned(), serde_json::to_value(prev_pdu.sender())?); + unsigned.insert( + "replaces_state".to_owned(), + serde_json::to_value(prev_pdu.event_id())?, + ); + } } } @@ -109,15 +143,15 @@ pub async fn create_hash_and_sign_event( // The first two events in a room are always m.room.create and m.room.member, // so any other events with that same depth are illegal. warn!( - "Had unsafe depth {depth} when creating non-state event in {room_id}. Cowardly \ - aborting" + "Had unsafe depth {depth} when creating non-state event in {}. Cowardly aborting", + room_id.expect("room_id is Some here").as_str() ); return Err!(Request(Unknown("Unsafe depth for non-state event."))); } let mut pdu = PduEvent { event_id: ruma::event_id!("$thiswillbefilledinlater").into(), - room_id: room_id.to_owned(), + room_id: room_id.map(ToOwned::to_owned), sender: sender.to_owned(), origin: None, origin_server_ts: timestamp.map_or_else( @@ -152,11 +186,30 @@ pub async fn create_hash_and_sign_event( ready(auth_events.get(&key).map(ToOwned::to_owned)) }; + let room_id_or_hash = pdu.room_id_or_hash(); + let create_pdu = match &pdu.kind { + | TimelineEventType::RoomCreate => None, + | _ => Some( + self.services + .state_accessor + .room_state_get(&room_id_or_hash, &StateEventType::RoomCreate, "") + .await + .map_err(|e| { + err!(Request(Forbidden(warn!("Failed to fetch room create event: {e}")))) + })?, + ), + }; + let create_event = match &pdu.kind { + | TimelineEventType::RoomCreate => &pdu, + | _ => create_pdu.as_ref().unwrap().as_pdu(), + }; + let auth_check = state_res::auth_check( &room_version, &pdu, None, // TODO: third_party_invite auth_fetch, + create_event, ) .await .map_err(|e| err!(Request(Forbidden(warn!("Auth check failed: {e:?}")))))?; @@ -164,6 +217,11 @@ pub async fn create_hash_and_sign_event( if !auth_check { return Err!(Request(Forbidden("Event is not authorized."))); } + trace!( + "Event {} in room {} is authorized", + pdu.event_id, + pdu.room_id.as_ref().map_or("None", |id| id.as_str()) + ); // Hash and sign let mut pdu_json = utils::to_canonical_object(&pdu).map_err(|e| { @@ -178,13 +236,13 @@ pub async fn create_hash_and_sign_event( }, } - // Add origin because synapse likes that (and it's required in the spec) pdu_json.insert( "origin".to_owned(), to_canonical_value(self.services.globals.server_name()) .expect("server name is a valid CanonicalJsonValue"), ); + trace!("hashing and signing event {}", pdu.event_id); if let Err(e) = self .services .server_keys @@ -204,30 +262,45 @@ pub async fn create_hash_and_sign_event( pdu_json.insert("event_id".into(), CanonicalJsonValue::String(pdu.event_id.clone().into())); // Check with the policy server - match self - .services - .event_handler - .ask_policy_server(&pdu, room_id) - .await - { - | Ok(true) => {}, - | Ok(false) => { - return Err!(Request(Forbidden(debug_warn!( - "Policy server marked this event as spam" - )))); - }, - | Err(e) => { - // fail open - warn!("Failed to check event with policy server: {e}"); - }, + // TODO(hydra): Skip this check for create events (why didnt we do this + // already?) + if room_id.is_some() { + trace!( + "Checking event {} in room {} with policy server", + pdu.event_id, + pdu.room_id.as_ref().map_or("None", |id| id.as_str()) + ); + match self + .services + .event_handler + .ask_policy_server(&pdu, &pdu.room_id_or_hash()) + .await + { + | Ok(true) => {}, + | Ok(false) => { + return Err!(Request(Forbidden(debug_warn!( + "Policy server marked this event as spam" + )))); + }, + | Err(e) => { + // fail open + warn!("Failed to check event with policy server: {e}"); + }, + } } // Generate short event id + trace!( + "Generating short event ID for {} in room {}", + pdu.event_id, + pdu.room_id.as_ref().map_or("None", |id| id.as_str()) + ); let _shorteventid = self .services .short .get_or_create_shorteventid(&pdu.event_id) .await; + trace!("New PDU created: {pdu:?}"); Ok((pdu, pdu_json)) } diff --git a/src/service/rooms/timeline/redact.rs b/src/service/rooms/timeline/redact.rs index d51a8462..9d41e986 100644 --- a/src/service/rooms/timeline/redact.rs +++ b/src/service/rooms/timeline/redact.rs @@ -39,7 +39,11 @@ pub async fn redact_pdu( } } - let room_version_id = self.services.state.get_room_version(pdu.room_id()).await?; + let room_version_id = self + .services + .state + .get_room_version(&pdu.room_id_or_hash()) + .await?; pdu.redact(&room_version_id, reason.to_value())?; diff --git a/src/service/sending/sender.rs b/src/service/sending/sender.rs index a708f746..33b0c1c3 100644 --- a/src/service/sending/sender.rs +++ b/src/service/sending/sender.rs @@ -798,7 +798,7 @@ impl Service { let unread: UInt = self .services .user - .notification_count(&user_id, pdu.room_id()) + .notification_count(&user_id, &pdu.room_id_or_hash()) .await .try_into() .expect("notification count can't go that high"); diff --git a/src/service/server_keys/get.rs b/src/service/server_keys/get.rs index f9c5bdaf..98b3ff35 100644 --- a/src/service/server_keys/get.rs +++ b/src/service/server_keys/get.rs @@ -1,6 +1,6 @@ use std::borrow::Borrow; -use conduwuit::{Err, Result, implement}; +use conduwuit::{Err, Result, debug, debug_error, implement}; use ruma::{ CanonicalJsonObject, RoomVersionId, ServerName, ServerSigningKeyId, api::federation::discovery::VerifyKey, @@ -19,9 +19,11 @@ pub async fn get_event_keys( let required = match required_keys(object, version) { | Ok(required) => required, | Err(e) => { + debug_error!("Failed to determine keys required to verify: {e}"); return Err!(BadServerResponse("Failed to determine keys required to verify: {e}")); }, }; + debug!(?required, "Keys required to verify event"); let batch = required .iter() @@ -61,6 +63,7 @@ where } #[implement(super::Service)] +#[tracing::instrument(skip(self))] pub async fn get_verify_key( &self, origin: &ServerName, @@ -70,6 +73,7 @@ pub async fn get_verify_key( let notary_only = self.services.server.config.only_query_trusted_key_servers; if let Some(result) = self.verify_keys_for(origin).await.remove(key_id) { + debug!("Found key in cache"); return Ok(result); } diff --git a/src/service/server_keys/mod.rs b/src/service/server_keys/mod.rs index bf6799ba..0bc06e8a 100644 --- a/src/service/server_keys/mod.rs +++ b/src/service/server_keys/mod.rs @@ -8,7 +8,7 @@ mod verify; use std::{collections::BTreeMap, sync::Arc, time::Duration}; use conduwuit::{ - Result, Server, implement, + Result, Server, debug, debug_error, debug_warn, implement, utils::{IterStream, timepoint_from_now}, }; use database::{Deserialized, Json, Map}; @@ -112,6 +112,7 @@ async fn add_signing_keys(&self, new_keys: ServerSigningKeys) { } #[implement(Service)] +#[tracing::instrument(skip(self, object))] pub async fn required_keys_exist( &self, object: &CanonicalJsonObject, @@ -119,10 +120,12 @@ pub async fn required_keys_exist( ) -> bool { use ruma::signatures::required_keys; + debug!(?object, "Checking required keys exist"); let Ok(required_keys) = required_keys(object, version) else { + debug_error!("Failed to determine required keys"); return false; }; - + debug!(?required_keys, "Required keys to verify event"); required_keys .iter() .flat_map(|(server, key_ids)| key_ids.iter().map(move |key_id| (server, key_id))) @@ -132,6 +135,7 @@ pub async fn required_keys_exist( } #[implement(Service)] +#[tracing::instrument(skip(self))] pub async fn verify_key_exists(&self, origin: &ServerName, key_id: &ServerSigningKeyId) -> bool { type KeysMap<'a> = BTreeMap<&'a ServerSigningKeyId, &'a RawJsonValue>; @@ -142,6 +146,7 @@ pub async fn verify_key_exists(&self, origin: &ServerName, key_id: &ServerSignin .await .deserialized::>() else { + debug_warn!("No known signing keys found for {origin}"); return false; }; @@ -157,6 +162,7 @@ pub async fn verify_key_exists(&self, origin: &ServerName, key_id: &ServerSignin } } + debug_warn!("Key {key_id} not found for {origin}"); false } diff --git a/src/service/server_keys/verify.rs b/src/service/server_keys/verify.rs index 9cc3655a..f1027e54 100644 --- a/src/service/server_keys/verify.rs +++ b/src/service/server_keys/verify.rs @@ -1,4 +1,6 @@ -use conduwuit::{Err, Result, implement, matrix::event::gen_event_id_canonical_json}; +use conduwuit::{ + Err, Result, debug, debug_warn, implement, matrix::event::gen_event_id_canonical_json, +}; use ruma::{ CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId, signatures::Verified, }; @@ -28,18 +30,25 @@ pub async fn validate_and_add_event_id_no_fetch( pdu: &RawJsonValue, room_version: &RoomVersionId, ) -> Result<(OwnedEventId, CanonicalJsonObject)> { + debug!(?pdu, "Validating PDU without fetching keys"); let (event_id, mut value) = gen_event_id_canonical_json(pdu, room_version)?; + debug!(event_id = event_id.as_str(), "Generated event ID, checking required keys"); if !self.required_keys_exist(&value, room_version).await { + debug_warn!( + "Event {event_id} is missing required keys, cannot verify without fetching keys" + ); return Err!(BadServerResponse(debug_warn!( "Event {event_id} cannot be verified: missing keys." ))); } - + debug!("All required keys exist, verifying event"); if let Err(e) = self.verify_event(&value, Some(room_version)).await { + debug_warn!("Event verification failed"); return Err!(BadServerResponse(debug_error!( "Event {event_id} failed verification: {e:?}" ))); } + debug!("Event verified successfully"); value.insert("event_id".into(), CanonicalJsonValue::String(event_id.as_str().into())); @@ -52,7 +61,7 @@ pub async fn verify_event( event: &CanonicalJsonObject, room_version: Option<&RoomVersionId>, ) -> Result { - let room_version = room_version.unwrap_or(&RoomVersionId::V11); + let room_version = room_version.unwrap_or(&RoomVersionId::V12); let keys = self.get_event_keys(event, room_version).await?; ruma::signatures::verify_event(&keys, event, room_version).map_err(Into::into) } @@ -63,7 +72,7 @@ pub async fn verify_json( event: &CanonicalJsonObject, room_version: Option<&RoomVersionId>, ) -> Result { - let room_version = room_version.unwrap_or(&RoomVersionId::V11); + let room_version = room_version.unwrap_or(&RoomVersionId::V12); let keys = self.get_event_keys(event, room_version).await?; ruma::signatures::verify_json(&keys, event.clone()).map_err(Into::into) }