mirror of
https://github.com/girlbossceo/conduwuit.git
synced 2025-12-10 09:18:50 -05:00
Compare commits
21 commits
5ace30e78e
...
f46bfd1abc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46bfd1abc | ||
|
|
4e5b87d0cd | ||
|
|
00f7745ec4 | ||
|
|
d036394ec7 | ||
|
|
6a073b4fa4 | ||
|
|
b7109131e2 | ||
|
|
94b107b42b | ||
|
|
29d55b8036 | ||
|
|
45fd3875c8 | ||
|
|
f9529937ce | ||
|
|
0b56204f89 | ||
|
|
58adb6fead | ||
|
|
5d1404e9df | ||
|
|
f14756fb76 | ||
|
|
24be579477 | ||
|
|
0e0b8cc403 | ||
|
|
1036f8dfa8 | ||
|
|
74012c5289 | ||
|
|
ea246d91d9 | ||
|
|
1b71b99c51 | ||
|
|
63230501c9 |
41 changed files with 1305 additions and 771 deletions
476
Cargo.lock
generated
476
Cargo.lock
generated
|
|
@ -142,6 +142,17 @@ dependencies = [
|
|||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.6"
|
||||
|
|
@ -221,9 +232,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.12.6"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01"
|
||||
checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"zeroize",
|
||||
|
|
@ -231,9 +242,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f"
|
||||
checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f"
|
||||
dependencies = [
|
||||
"bindgen 0.69.5",
|
||||
"cc",
|
||||
|
|
@ -652,9 +663,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.34"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
|
||||
checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -662,9 +673,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.34"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
|
||||
checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
|
|
@ -731,8 +742,8 @@ dependencies = [
|
|||
"opentelemetry-jaeger",
|
||||
"opentelemetry_sdk",
|
||||
"sentry",
|
||||
"sentry-tower 0.35.0",
|
||||
"sentry-tracing 0.35.0",
|
||||
"sentry-tower",
|
||||
"sentry-tracing",
|
||||
"tokio",
|
||||
"tokio-metrics",
|
||||
"tracing",
|
||||
|
|
@ -905,8 +916,8 @@ dependencies = [
|
|||
"rustls",
|
||||
"sd-notify",
|
||||
"sentry",
|
||||
"sentry-tower 0.35.0",
|
||||
"sentry-tracing 0.35.0",
|
||||
"sentry-tower",
|
||||
"sentry-tracing",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tower 0.5.2",
|
||||
|
|
@ -927,7 +938,7 @@ dependencies = [
|
|||
"const-str",
|
||||
"either",
|
||||
"futures",
|
||||
"hickory-resolver",
|
||||
"hickory-resolver 0.25.1",
|
||||
"http",
|
||||
"image",
|
||||
"ipaddress",
|
||||
|
|
@ -1061,6 +1072,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crokey"
|
||||
version = "1.1.1"
|
||||
|
|
@ -1437,9 +1454,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
|
@ -1584,6 +1601,19 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows 0.58.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
|
|
@ -1769,6 +1799,34 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hickory-proto"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"data-encoding",
|
||||
"enum-as-inner",
|
||||
"futures-channel",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"idna",
|
||||
"ipnet",
|
||||
"once_cell",
|
||||
"rand 0.9.0",
|
||||
"ring",
|
||||
"serde",
|
||||
"thiserror 2.0.12",
|
||||
"tinyvec",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hickory-resolver"
|
||||
version = "0.24.4"
|
||||
|
|
@ -1777,7 +1835,7 @@ checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"hickory-proto",
|
||||
"hickory-proto 0.24.4",
|
||||
"ipconfig",
|
||||
"lru-cache",
|
||||
"once_cell",
|
||||
|
|
@ -1790,6 +1848,28 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hickory-resolver"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a128410b38d6f931fcc6ca5c107a3b02cabd6c05967841269a4ad65d23c44331"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"hickory-proto 0.25.1",
|
||||
"ipconfig",
|
||||
"moka",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rand 0.9.0",
|
||||
"resolv-conf",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
|
|
@ -1816,7 +1896,7 @@ checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows",
|
||||
"windows 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1936,9 +2016,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hyper-timeout"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
|
||||
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
|
||||
dependencies = [
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
|
|
@ -1949,9 +2029,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba"
|
||||
version = "0.1.11"
|
||||
source = "git+https://github.com/girlbossceo/hyper-util?rev=e4ae7628fe4fcdacef9788c4c8415317a4489941#e4ae7628fe4fcdacef9788c4c8415317a4489941"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
|
@ -1959,10 +2038,10 @@ dependencies = [
|
|||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"libc",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tower 0.4.13",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
|
@ -2256,10 +2335,11 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -2439,6 +2519,19 @@ dependencies = [
|
|||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"generator",
|
||||
"scoped-tls",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loop9"
|
||||
version = "0.1.5"
|
||||
|
|
@ -2609,6 +2702,25 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moka"
|
||||
version = "0.12.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"loom",
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"tagptr",
|
||||
"thiserror 1.0.69",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.6"
|
||||
|
|
@ -2773,6 +2885,10 @@ name = "once_cell"
|
|||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
|
|
@ -3052,6 +3168,12 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
|
|
@ -3452,9 +3574,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
|||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.9"
|
||||
version = "0.12.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
|
||||
checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"base64 0.22.1",
|
||||
|
|
@ -3463,7 +3585,7 @@ dependencies = [
|
|||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"hickory-resolver",
|
||||
"hickory-resolver 0.24.4",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
|
|
@ -3490,6 +3612,7 @@ dependencies = [
|
|||
"tokio-rustls",
|
||||
"tokio-socks",
|
||||
"tokio-util",
|
||||
"tower 0.5.2",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
|
|
@ -3531,7 +3654,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.10.1"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
|
|
@ -3551,7 +3674,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.10.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
|
@ -3563,7 +3686,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
|
|
@ -3586,7 +3709,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64 0.22.1",
|
||||
|
|
@ -3618,7 +3741,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.28.1"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap 2.8.0",
|
||||
|
|
@ -3643,7 +3766,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"headers",
|
||||
|
|
@ -3665,7 +3788,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.9.5"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.12",
|
||||
|
|
@ -3674,7 +3797,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identity-service-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
|
@ -3684,7 +3807,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-crate",
|
||||
|
|
@ -3699,7 +3822,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
|
@ -3711,7 +3834,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ed25519-dalek",
|
||||
|
|
@ -3893,6 +4016,12 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
|
|
@ -3939,21 +4068,21 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
|||
|
||||
[[package]]
|
||||
name = "sentry"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a7332159e544e34db06b251b1eda5e546bd90285c3f58d9c8ff8450b484e0da"
|
||||
checksum = "255914a8e53822abd946e2ce8baa41d4cded6b8e938913b7f7b9da5b7ab44335"
|
||||
dependencies = [
|
||||
"httpdate",
|
||||
"reqwest",
|
||||
"rustls",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
"sentry-debug-images",
|
||||
"sentry-log",
|
||||
"sentry-panic",
|
||||
"sentry-tower 0.36.0",
|
||||
"sentry-tracing 0.36.0",
|
||||
"sentry-tower",
|
||||
"sentry-tracing",
|
||||
"tokio",
|
||||
"ureq",
|
||||
"webpki-roots",
|
||||
|
|
@ -3961,107 +4090,83 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sentry-backtrace"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "565ec31ad37bab8e6d9f289f34913ed8768347b133706192f10606dabd5c6bc4"
|
||||
checksum = "00293cd332a859961f24fd69258f7e92af736feaeb91020cff84dac4188a4302"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-contexts"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e860275f25f27e8c0c7726ce116c7d5c928c5bba2ee73306e52b20a752298ea6"
|
||||
checksum = "961990f9caa76476c481de130ada05614cd7f5aa70fb57c2142f0e09ad3fb2aa"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"libc",
|
||||
"os_info",
|
||||
"rustc_version",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
"uname",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-core"
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9f8b6dcd4fbae1e3e22b447f32670360b27e31b62ab040f7fb04e0f80c04d92"
|
||||
checksum = "1a6409d845707d82415c800290a5d63be5e3df3c2e417b0997c60531dfbd35ef"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"sentry-types 0.35.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-core"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "653942e6141f16651273159f4b8b1eaeedf37a7554c00cd798953e64b8a9bf72"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"sentry-types 0.36.0",
|
||||
"sentry-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-debug-images"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60bc2154e6df59beed0ac13d58f8dfaf5ad20a88548a53e29e4d92e8e835c2"
|
||||
checksum = "71ab5df4f3b64760508edfe0ba4290feab5acbbda7566a79d72673065888e5cc"
|
||||
dependencies = [
|
||||
"findshlibs",
|
||||
"once_cell",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-log"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c96d796cba1b3a0793e7f53edc420c61f9419fba8fb34ad5519f5c7d01af6b2"
|
||||
checksum = "693841da8dfb693af29105edfbea1d91348a13d23dd0a5d03761eedb9e450c46"
|
||||
dependencies = [
|
||||
"log",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-panic"
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "105e3a956c8aa9dab1e4087b1657b03271bfc49d838c6ae9bfc7c58c802fd0ef"
|
||||
checksum = "609b1a12340495ce17baeec9e08ff8ed423c337c1a84dffae36a178c783623f3"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tower"
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcdaf9b1939589476bd57751d12a9653bbfe356610fc476d03d7683189183ab7"
|
||||
dependencies = [
|
||||
"sentry-core 0.35.0",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tower"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "082f781dfc504d984e16d99f8dbf94d6ee4762dd0fc28de25713d0f900a8164d"
|
||||
checksum = "4b98005537e38ee3bc10e7d36e7febe9b8e573d03f2ddd85fcdf05d21f9abd6d"
|
||||
dependencies = [
|
||||
"http",
|
||||
"pin-project",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"url",
|
||||
|
|
@ -4069,49 +4174,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sentry-tracing"
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "263f73c757ed7915d3e1e34625eae18cad498a95b4261603d4ce3f87b159a6f0"
|
||||
dependencies = [
|
||||
"sentry-core 0.35.0",
|
||||
"tracing-core",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-tracing"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e75c831b4d8b34a5aec1f65f67c5d46a26c7c5d3c7abd8b5ef430796900cf8"
|
||||
checksum = "49f4e86402d5c50239dc7d8fd3f6d5e048221d5fcb4e026d8d50ab57fe4644cb"
|
||||
dependencies = [
|
||||
"sentry-backtrace",
|
||||
"sentry-core 0.36.0",
|
||||
"sentry-core",
|
||||
"tracing-core",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-types"
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a71ed3a389948a6a6d92b98e997a2723ca22f09660c5a7b7388ecd509a70a527"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"hex",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"time",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-types"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d4203359e60724aa05cf2385aaf5d4f147e837185d7dd2b9ccf1ee77f4420c8"
|
||||
checksum = "3d3f117b8755dbede8260952de2aeb029e20f432e72634e8969af34324591631"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"hex",
|
||||
|
|
@ -4464,6 +4541,12 @@ dependencies = [
|
|||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tagptr"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.16"
|
||||
|
|
@ -5367,7 +5450,17 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-core 0.52.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core 0.58.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
|
|
@ -5381,16 +5474,57 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.2.0"
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings 0.1.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
||||
dependencies = [
|
||||
"windows-result 0.3.2",
|
||||
"windows-strings 0.3.1",
|
||||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
|
|
@ -5400,16 +5534,34 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-result 0.2.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
|
@ -5461,13 +5613,29 @@ dependencies = [
|
|||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_gnullvm 0.52.6",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
"windows_i686_gnullvm 0.53.0",
|
||||
"windows_i686_msvc 0.53.0",
|
||||
"windows_x86_64_gnu 0.53.0",
|
||||
"windows_x86_64_gnullvm 0.53.0",
|
||||
"windows_x86_64_msvc 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5480,6 +5648,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5492,6 +5666,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5504,12 +5684,24 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5522,6 +5714,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5534,6 +5732,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5546,6 +5750,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
|
|
@ -5558,6 +5768,12 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.4"
|
||||
|
|
|
|||
44
Cargo.toml
44
Cargo.toml
|
|
@ -141,12 +141,12 @@ features = [
|
|||
]
|
||||
|
||||
[workspace.dependencies.rustls]
|
||||
version = "0.23.19"
|
||||
version = "0.23.25"
|
||||
default-features = false
|
||||
features = ["aws_lc_rs"]
|
||||
|
||||
[workspace.dependencies.reqwest]
|
||||
version = "0.12.9"
|
||||
version = "0.12.15"
|
||||
default-features = false
|
||||
features = [
|
||||
"rustls-tls-native-roots",
|
||||
|
|
@ -204,7 +204,7 @@ features = [
|
|||
|
||||
# logging
|
||||
[workspace.dependencies.log]
|
||||
version = "0.4.22"
|
||||
version = "0.4.27"
|
||||
default-features = false
|
||||
[workspace.dependencies.tracing]
|
||||
version = "0.1.41"
|
||||
|
|
@ -224,7 +224,7 @@ default-features = false
|
|||
|
||||
# used for conduwuit's CLI and admin room command parsing
|
||||
[workspace.dependencies.clap]
|
||||
version = "4.5.23"
|
||||
version = "4.5.35"
|
||||
default-features = false
|
||||
features = [
|
||||
"derive",
|
||||
|
|
@ -284,8 +284,7 @@ features = [
|
|||
]
|
||||
|
||||
[workspace.dependencies.hyper-util]
|
||||
# hyper-util >=0.1.9 seems to have DNS issues
|
||||
version = "=0.1.8"
|
||||
version = "0.1.11"
|
||||
default-features = false
|
||||
features = [
|
||||
"server-auto",
|
||||
|
|
@ -306,8 +305,13 @@ default-features = false
|
|||
features = ["env", "toml"]
|
||||
|
||||
[workspace.dependencies.hickory-resolver]
|
||||
version = "0.24.2"
|
||||
version = "0.25.1"
|
||||
default-features = false
|
||||
features = [
|
||||
"serde",
|
||||
"system-config",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
# Used for conduwuit::Error type
|
||||
[workspace.dependencies.thiserror]
|
||||
|
|
@ -316,7 +320,7 @@ default-features = false
|
|||
|
||||
# Used when hashing the state
|
||||
[workspace.dependencies.ring]
|
||||
version = "0.17.8"
|
||||
version = "0.17.14"
|
||||
default-features = false
|
||||
|
||||
# Used to make working with iterators easier, was already a transitive depdendency
|
||||
|
|
@ -346,7 +350,7 @@ version = "0.1.2"
|
|||
[workspace.dependencies.ruma]
|
||||
git = "https://github.com/girlbossceo/ruwuma"
|
||||
#branch = "conduwuit-changes"
|
||||
rev = "d197318a2507d38ffe6ee524d0d52728ca72538a"
|
||||
rev = "edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
|
||||
features = [
|
||||
"compat",
|
||||
"rand",
|
||||
|
|
@ -405,7 +409,7 @@ default-features = false
|
|||
|
||||
# optional opentelemetry, performance measurements, flamegraphs, etc for performance measurements and monitoring
|
||||
[workspace.dependencies.opentelemetry]
|
||||
version = "0.21.0"
|
||||
version = "0.29.0"
|
||||
|
||||
[workspace.dependencies.tracing-flame]
|
||||
version = "0.2.0"
|
||||
|
|
@ -414,16 +418,16 @@ version = "0.2.0"
|
|||
version = "0.22.0"
|
||||
|
||||
[workspace.dependencies.opentelemetry_sdk]
|
||||
version = "0.21.2"
|
||||
version = "0.29.0"
|
||||
features = ["rt-tokio"]
|
||||
|
||||
[workspace.dependencies.opentelemetry-jaeger]
|
||||
version = "0.20.0"
|
||||
version = "0.22.0"
|
||||
features = ["rt-tokio"]
|
||||
|
||||
# optional sentry metrics for crash/panic reporting
|
||||
[workspace.dependencies.sentry]
|
||||
version = "0.36.0"
|
||||
version = "0.37.0"
|
||||
default-features = false
|
||||
features = [
|
||||
"backtrace",
|
||||
|
|
@ -439,9 +443,9 @@ features = [
|
|||
]
|
||||
|
||||
[workspace.dependencies.sentry-tracing]
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
[workspace.dependencies.sentry-tower]
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
|
||||
# jemalloc usage
|
||||
[workspace.dependencies.tikv-jemalloc-sys]
|
||||
|
|
@ -475,7 +479,7 @@ default-features = false
|
|||
features = ["resource"]
|
||||
|
||||
[workspace.dependencies.sd-notify]
|
||||
version = "0.4.3"
|
||||
version = "0.4.5"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.hardened_malloc-rs]
|
||||
|
|
@ -492,7 +496,7 @@ version = "0.4.3"
|
|||
default-features = false
|
||||
|
||||
[workspace.dependencies.termimad]
|
||||
version = "0.31.1"
|
||||
version = "0.31.2"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.checked_ops]
|
||||
|
|
@ -566,10 +570,16 @@ rev = "fe4aebeeaae435af60087ddd56b573a2e0be671d"
|
|||
git = "https://github.com/girlbossceo/async-channel"
|
||||
rev = "92e5e74063bf2a3b10414bcc8a0d68b235644280"
|
||||
|
||||
# adds affinity masks for selecting more than one core at a time
|
||||
[patch.crates-io.core_affinity]
|
||||
git = "https://github.com/girlbossceo/core_affinity_rs"
|
||||
rev = "9c8e51510c35077df888ee72a36b4b05637147da"
|
||||
|
||||
# reverts hyperium#148 conflicting with our delicate federation resolver hooks
|
||||
[patch.crates-io.hyper-util]
|
||||
git = "https://github.com/girlbossceo/hyper-util"
|
||||
rev = "e4ae7628fe4fcdacef9788c4c8415317a4489941"
|
||||
|
||||
#
|
||||
# Our crates
|
||||
#
|
||||
|
|
|
|||
|
|
@ -195,14 +195,6 @@
|
|||
#
|
||||
#servernameevent_data_cache_capacity = varies by system
|
||||
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#server_visibility_cache_capacity = varies by system
|
||||
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#user_visibility_cache_capacity = varies by system
|
||||
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#stateinfo_cache_capacity = varies by system
|
||||
|
|
|
|||
|
|
@ -318,14 +318,14 @@ pub(crate) async fn register_route(
|
|||
// Success!
|
||||
},
|
||||
| _ => match body.json_body {
|
||||
| Some(json) => {
|
||||
| Some(ref json) => {
|
||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||
services.uiaa.create(
|
||||
&UserId::parse_with_server_name("", services.globals.server_name())
|
||||
.unwrap(),
|
||||
"".into(),
|
||||
&uiaainfo,
|
||||
&json,
|
||||
json,
|
||||
);
|
||||
return Err(Error::Uiaa(uiaainfo));
|
||||
},
|
||||
|
|
@ -373,8 +373,12 @@ pub(crate) async fn register_route(
|
|||
)
|
||||
.await?;
|
||||
|
||||
// Inhibit login does not work for guests
|
||||
if !is_guest && body.inhibit_login {
|
||||
if (!is_guest && body.inhibit_login)
|
||||
|| body
|
||||
.appservice_info
|
||||
.as_ref()
|
||||
.is_some_and(|appservice| appservice.registration.device_management)
|
||||
{
|
||||
return Ok(register::v3::Response {
|
||||
access_token: None,
|
||||
user_id,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,13 @@ pub(crate) async fn appservice_ping(
|
|||
)));
|
||||
}
|
||||
|
||||
if appservice_info.registration.url.is_none() {
|
||||
if appservice_info.registration.url.is_none()
|
||||
|| appservice_info
|
||||
.registration
|
||||
.url
|
||||
.as_ref()
|
||||
.is_some_and(|url| url.is_empty() || url == "null")
|
||||
{
|
||||
return Err!(Request(UrlNotSet(
|
||||
"Appservice does not have a URL set, there is nothing to ping."
|
||||
)));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use axum::extract::State;
|
||||
use axum_client_ip::InsecureClientIp;
|
||||
use conduwuit::{Err, err};
|
||||
use conduwuit::{Err, debug, err};
|
||||
use futures::StreamExt;
|
||||
use ruma::{
|
||||
MilliSecondsSinceUnixEpoch,
|
||||
MilliSecondsSinceUnixEpoch, OwnedDeviceId,
|
||||
api::client::{
|
||||
device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
|
||||
error::ErrorKind,
|
||||
|
|
@ -12,7 +12,7 @@ use ruma::{
|
|||
};
|
||||
|
||||
use super::SESSION_ID_LENGTH;
|
||||
use crate::{Error, Result, Ruma, utils};
|
||||
use crate::{Error, Result, Ruma, client::DEVICE_ID_LENGTH, utils};
|
||||
|
||||
/// # `GET /_matrix/client/r0/devices`
|
||||
///
|
||||
|
|
@ -59,14 +59,15 @@ pub(crate) async fn update_device_route(
|
|||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<update_device::v3::Request>,
|
||||
) -> Result<update_device::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
let sender_user = body.sender_user();
|
||||
let appservice = body.appservice_info.as_ref();
|
||||
|
||||
let mut device = services
|
||||
match services
|
||||
.users
|
||||
.get_device_metadata(sender_user, &body.device_id)
|
||||
.await
|
||||
.map_err(|_| err!(Request(NotFound("Device not found."))))?;
|
||||
|
||||
{
|
||||
| Ok(mut device) => {
|
||||
device.display_name.clone_from(&body.display_name);
|
||||
device.last_seen_ip.clone_from(&Some(client.to_string()));
|
||||
device
|
||||
|
|
@ -79,6 +80,37 @@ pub(crate) async fn update_device_route(
|
|||
.await?;
|
||||
|
||||
Ok(update_device::v3::Response {})
|
||||
},
|
||||
| Err(_) => {
|
||||
let Some(appservice) = appservice else {
|
||||
return Err!(Request(NotFound("Device not found.")));
|
||||
};
|
||||
if !appservice.registration.device_management {
|
||||
return Err!(Request(NotFound("Device not found.")));
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Creating new device for {sender_user} from appservice {} as MSC4190 is enabled \
|
||||
and device ID does not exist",
|
||||
appservice.registration.id
|
||||
);
|
||||
|
||||
let device_id = OwnedDeviceId::from(utils::random_string(DEVICE_ID_LENGTH));
|
||||
|
||||
services
|
||||
.users
|
||||
.create_device(
|
||||
sender_user,
|
||||
&device_id,
|
||||
&appservice.registration.as_token,
|
||||
None,
|
||||
Some(client.to_string()),
|
||||
)
|
||||
.await?;
|
||||
|
||||
return Ok(update_device::v3::Response {});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// # `DELETE /_matrix/client/r0/devices/{deviceId}`
|
||||
|
|
@ -95,8 +127,21 @@ pub(crate) async fn delete_device_route(
|
|||
State(services): State<crate::State>,
|
||||
body: Ruma<delete_device::v3::Request>,
|
||||
) -> Result<delete_device::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||
let (sender_user, sender_device) = body.sender();
|
||||
let appservice = body.appservice_info.as_ref();
|
||||
|
||||
if appservice.is_some_and(|appservice| appservice.registration.device_management) {
|
||||
debug!(
|
||||
"Skipping UIAA for {sender_user} as this is from an appservice and MSC4190 is \
|
||||
enabled"
|
||||
);
|
||||
services
|
||||
.users
|
||||
.remove_device(sender_user, &body.device_id)
|
||||
.await;
|
||||
|
||||
return Ok(delete_device::v3::Response {});
|
||||
}
|
||||
|
||||
// UIAA
|
||||
let mut uiaainfo = UiaaInfo {
|
||||
|
|
@ -120,11 +165,11 @@ pub(crate) async fn delete_device_route(
|
|||
// Success!
|
||||
},
|
||||
| _ => match body.json_body {
|
||||
| Some(json) => {
|
||||
| Some(ref json) => {
|
||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||
services
|
||||
.uiaa
|
||||
.create(sender_user, sender_device, &uiaainfo, &json);
|
||||
.create(sender_user, sender_device, &uiaainfo, json);
|
||||
|
||||
return Err!(Uiaa(uiaainfo));
|
||||
},
|
||||
|
|
@ -142,11 +187,12 @@ pub(crate) async fn delete_device_route(
|
|||
Ok(delete_device::v3::Response {})
|
||||
}
|
||||
|
||||
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
|
||||
/// # `POST /_matrix/client/v3/delete_devices`
|
||||
///
|
||||
/// Deletes the given device.
|
||||
/// Deletes the given list of devices.
|
||||
///
|
||||
/// - Requires UIAA to verify user password
|
||||
/// - Requires UIAA to verify user password unless from an appservice with
|
||||
/// MSC4190 enabled.
|
||||
///
|
||||
/// For each device:
|
||||
/// - Invalidates access token
|
||||
|
|
@ -158,8 +204,20 @@ pub(crate) async fn delete_devices_route(
|
|||
State(services): State<crate::State>,
|
||||
body: Ruma<delete_devices::v3::Request>,
|
||||
) -> Result<delete_devices::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||
let (sender_user, sender_device) = body.sender();
|
||||
let appservice = body.appservice_info.as_ref();
|
||||
|
||||
if appservice.is_some_and(|appservice| appservice.registration.device_management) {
|
||||
debug!(
|
||||
"Skipping UIAA for {sender_user} as this is from an appservice and MSC4190 is \
|
||||
enabled"
|
||||
);
|
||||
for device_id in &body.devices {
|
||||
services.users.remove_device(sender_user, device_id).await;
|
||||
}
|
||||
|
||||
return Ok(delete_devices::v3::Response {});
|
||||
}
|
||||
|
||||
// UIAA
|
||||
let mut uiaainfo = UiaaInfo {
|
||||
|
|
@ -183,11 +241,11 @@ pub(crate) async fn delete_devices_route(
|
|||
// Success!
|
||||
},
|
||||
| _ => match body.json_body {
|
||||
| Some(json) => {
|
||||
| Some(ref json) => {
|
||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||
services
|
||||
.uiaa
|
||||
.create(sender_user, sender_device, &uiaainfo, &json);
|
||||
.create(sender_user, sender_device, &uiaainfo, json);
|
||||
|
||||
return Err(Error::Uiaa(uiaainfo));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use ruma::{
|
|||
client::{
|
||||
error::ErrorKind,
|
||||
keys::{
|
||||
claim_keys, get_key_changes, get_keys, upload_keys, upload_signatures,
|
||||
claim_keys, get_key_changes, get_keys, upload_keys,
|
||||
upload_signatures::{self, v3::Failure},
|
||||
upload_signing_keys,
|
||||
},
|
||||
uiaa::{AuthFlow, AuthType, UiaaInfo},
|
||||
|
|
@ -308,53 +309,83 @@ async fn check_for_new_keys(
|
|||
/// # `POST /_matrix/client/r0/keys/signatures/upload`
|
||||
///
|
||||
/// Uploads end-to-end key signatures from the sender user.
|
||||
///
|
||||
/// TODO: clean this timo-code up more. tried to improve it a bit to stop
|
||||
/// exploding the entire request on bad sigs, but needs way more work.
|
||||
pub(crate) async fn upload_signatures_route(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<upload_signatures::v3::Request>,
|
||||
) -> Result<upload_signatures::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
use upload_signatures::v3::FailureErrorCode::*;
|
||||
|
||||
if body.signed_keys.is_empty() {
|
||||
debug!("Empty signed_keys sent in key signature upload");
|
||||
return Ok(upload_signatures::v3::Response::new());
|
||||
}
|
||||
|
||||
let sender_user = body.sender_user();
|
||||
let mut failures: BTreeMap<OwnedUserId, BTreeMap<String, Failure>> = BTreeMap::new();
|
||||
let mut failure_reasons: BTreeMap<String, Failure> = BTreeMap::new();
|
||||
let failure = Failure {
|
||||
errcode: InvalidSignature,
|
||||
error: String::new(),
|
||||
};
|
||||
|
||||
for (user_id, keys) in &body.signed_keys {
|
||||
for (key_id, key) in keys {
|
||||
let key = serde_json::to_value(key)
|
||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid key JSON"))?;
|
||||
let Ok(key) = serde_json::to_value(key)
|
||||
.inspect_err(|e| debug_warn!(?key_id, "Invalid \"key\" JSON: {e}"))
|
||||
else {
|
||||
let mut failure = failure.clone();
|
||||
failure.error = String::from("Invalid \"key\" JSON");
|
||||
failure_reasons.insert(key_id.to_owned(), failure);
|
||||
continue;
|
||||
};
|
||||
|
||||
for signature in key
|
||||
.get("signatures")
|
||||
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Missing signatures field."))?
|
||||
.get(sender_user.to_string())
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid user in signatures field.",
|
||||
))?
|
||||
.as_object()
|
||||
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Invalid signature."))?
|
||||
.clone()
|
||||
{
|
||||
// Signature validation?
|
||||
let signature = (
|
||||
signature.0,
|
||||
signature
|
||||
.1
|
||||
.as_str()
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid signature value.",
|
||||
))?
|
||||
.to_owned(),
|
||||
);
|
||||
let Some(signatures) = key.get("signatures") else {
|
||||
let mut failure = failure.clone();
|
||||
failure.error = String::from("Missing \"signatures\" field");
|
||||
failure_reasons.insert(key_id.to_owned(), failure);
|
||||
continue;
|
||||
};
|
||||
|
||||
services
|
||||
let Some(sender_user_val) = signatures.get(sender_user.to_string()) else {
|
||||
let mut failure = failure.clone();
|
||||
failure.error = String::from("Invalid user in signatures field");
|
||||
failure_reasons.insert(key_id.to_owned(), failure);
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(sender_user_object) = sender_user_val.as_object() else {
|
||||
let mut failure = failure.clone();
|
||||
failure.error = String::from("signatures field is not a JSON object");
|
||||
failure_reasons.insert(key_id.to_owned(), failure);
|
||||
continue;
|
||||
};
|
||||
|
||||
for (signature, val) in sender_user_object.clone() {
|
||||
let signature = (signature, val.to_string());
|
||||
|
||||
if let Err(e) = services
|
||||
.users
|
||||
.sign_key(user_id, key_id, signature, sender_user)
|
||||
.await?;
|
||||
.await
|
||||
.inspect_err(|e| debug_warn!("{e}"))
|
||||
{
|
||||
let mut failure = failure.clone();
|
||||
failure.error = format!("Error signing key: {e}");
|
||||
failure_reasons.insert(key_id.to_owned(), failure);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(upload_signatures::v3::Response {
|
||||
failures: BTreeMap::new(), // TODO: integrate
|
||||
})
|
||||
if !failure_reasons.is_empty() {
|
||||
failures.insert(user_id.to_owned(), failure_reasons.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(upload_signatures::v3::Response { failures })
|
||||
}
|
||||
|
||||
/// # `POST /_matrix/client/r0/keys/changes`
|
||||
|
|
|
|||
|
|
@ -475,9 +475,9 @@ pub(crate) async fn leave_room_route(
|
|||
State(services): State<crate::State>,
|
||||
body: Ruma<leave_room::v3::Request>,
|
||||
) -> Result<leave_room::v3::Response> {
|
||||
leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()).await?;
|
||||
|
||||
Ok(leave_room::v3::Response::new())
|
||||
leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone())
|
||||
.await
|
||||
.map(|()| leave_room::v3::Response::new())
|
||||
}
|
||||
|
||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
|
||||
|
|
@ -1763,8 +1763,8 @@ pub(crate) async fn invite_helper(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Make a user leave all their joined rooms, forgets all rooms, and ignores
|
||||
// errors
|
||||
// Make a user leave all their joined rooms, rescinds knocks, forgets all rooms,
|
||||
// and ignores errors
|
||||
pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
||||
let rooms_joined = services
|
||||
.rooms
|
||||
|
|
@ -1778,7 +1778,17 @@ pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
|||
.rooms_invited(user_id)
|
||||
.map(|(r, _)| r);
|
||||
|
||||
let all_rooms: Vec<_> = rooms_joined.chain(rooms_invited).collect().await;
|
||||
let rooms_knocked = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_knocked(user_id)
|
||||
.map(|(r, _)| r);
|
||||
|
||||
let all_rooms: Vec<_> = rooms_joined
|
||||
.chain(rooms_invited)
|
||||
.chain(rooms_knocked)
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
for room_id in all_rooms {
|
||||
// ignore errors
|
||||
|
|
@ -1795,7 +1805,40 @@ pub async fn leave_room(
|
|||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
reason: Option<String>,
|
||||
) -> Result<()> {
|
||||
) -> Result {
|
||||
let default_member_content = RoomMemberEventContent {
|
||||
membership: MembershipState::Leave,
|
||||
reason: reason.clone(),
|
||||
join_authorized_via_users_server: None,
|
||||
is_direct: None,
|
||||
avatar_url: None,
|
||||
displayname: None,
|
||||
third_party_invite: None,
|
||||
blurhash: None,
|
||||
};
|
||||
|
||||
if services.rooms.metadata.is_banned(room_id).await
|
||||
|| services.rooms.metadata.is_disabled(room_id).await
|
||||
{
|
||||
// the room is banned/disabled, the room must be rejected locally since we
|
||||
// cant/dont want to federate with this server
|
||||
services
|
||||
.rooms
|
||||
.state_cache
|
||||
.update_membership(
|
||||
room_id,
|
||||
user_id,
|
||||
default_member_content,
|
||||
user_id,
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Ask a remote server if we don't have this room and are not knocking on it
|
||||
if !services
|
||||
.rooms
|
||||
|
|
@ -1828,7 +1871,7 @@ pub async fn leave_room(
|
|||
.update_membership(
|
||||
room_id,
|
||||
user_id,
|
||||
RoomMemberEventContent::new(MembershipState::Leave),
|
||||
default_member_content,
|
||||
user_id,
|
||||
last_state,
|
||||
None,
|
||||
|
|
@ -1848,26 +1891,23 @@ pub async fn leave_room(
|
|||
)
|
||||
.await
|
||||
else {
|
||||
// Fix for broken rooms
|
||||
warn!(
|
||||
debug_warn!(
|
||||
"Trying to leave a room you are not a member of, marking room as left locally."
|
||||
);
|
||||
|
||||
services
|
||||
return services
|
||||
.rooms
|
||||
.state_cache
|
||||
.update_membership(
|
||||
room_id,
|
||||
user_id,
|
||||
RoomMemberEventContent::new(MembershipState::Leave),
|
||||
default_member_content,
|
||||
user_id,
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
.await;
|
||||
};
|
||||
|
||||
services
|
||||
|
|
@ -1897,7 +1937,7 @@ async fn remote_leave_room(
|
|||
room_id: &RoomId,
|
||||
) -> Result<()> {
|
||||
let mut make_leave_response_and_server =
|
||||
Err!(BadServerResponse("No server available to assist in leaving."));
|
||||
Err!(BadServerResponse("No remote server available to assist in leaving {room_id}."));
|
||||
|
||||
let mut servers: HashSet<OwnedServerName> = services
|
||||
.rooms
|
||||
|
|
@ -1977,20 +2017,25 @@ async fn remote_leave_room(
|
|||
let (make_leave_response, remote_server) = make_leave_response_and_server?;
|
||||
|
||||
let Some(room_version_id) = make_leave_response.room_version else {
|
||||
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
||||
return Err!(BadServerResponse(warn!(
|
||||
"No room version was returned by {remote_server} for {room_id}, room version is \
|
||||
likely not supported by conduwuit"
|
||||
)));
|
||||
};
|
||||
|
||||
if !services.server.supported_room_version(&room_version_id) {
|
||||
return Err!(BadServerResponse(
|
||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
||||
));
|
||||
return Err!(BadServerResponse(warn!(
|
||||
"Remote room version {room_version_id} for {room_id} is not supported by conduwuit",
|
||||
)));
|
||||
}
|
||||
|
||||
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
|
||||
make_leave_response.event.get(),
|
||||
)
|
||||
.map_err(|e| {
|
||||
err!(BadServerResponse("Invalid make_leave event json received from server: {e:?}"))
|
||||
err!(BadServerResponse(warn!(
|
||||
"Invalid make_leave event json received from {remote_server} for {room_id}: {e:?}"
|
||||
)))
|
||||
})?;
|
||||
|
||||
// TODO: Is origin needed?
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@ mod aliases;
|
|||
mod create;
|
||||
mod event;
|
||||
mod initial_sync;
|
||||
mod summary;
|
||||
mod upgrade;
|
||||
|
||||
pub(crate) use self::{
|
||||
aliases::get_room_aliases_route, create::create_room_route, event::get_room_event_route,
|
||||
initial_sync::room_initial_sync_route, upgrade::upgrade_room_route,
|
||||
aliases::get_room_aliases_route,
|
||||
create::create_room_route,
|
||||
event::get_room_event_route,
|
||||
initial_sync::room_initial_sync_route,
|
||||
summary::{get_room_summary, get_room_summary_legacy},
|
||||
upgrade::upgrade_room_route,
|
||||
};
|
||||
|
|
|
|||
308
src/api/client/room/summary.rs
Normal file
308
src/api/client/room/summary.rs
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
use axum::extract::State;
|
||||
use axum_client_ip::InsecureClientIp;
|
||||
use conduwuit::{
|
||||
Err, Result, debug_warn,
|
||||
utils::{IterStream, future::TryExtExt},
|
||||
};
|
||||
use futures::{FutureExt, StreamExt, future::join3, stream::FuturesUnordered};
|
||||
use ruma::{
|
||||
OwnedRoomId, OwnedServerName, RoomId, UserId,
|
||||
api::{
|
||||
client::room::get_summary,
|
||||
federation::space::{SpaceHierarchyParentSummary, get_hierarchy},
|
||||
},
|
||||
events::room::member::MembershipState,
|
||||
space::SpaceRoomJoinRule::{self, *},
|
||||
};
|
||||
use service::Services;
|
||||
|
||||
use crate::{Ruma, RumaResponse};
|
||||
|
||||
/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary`
|
||||
///
|
||||
/// Returns a short description of the state of a room.
|
||||
///
|
||||
/// This is the "wrong" endpoint that some implementations/clients may use
|
||||
/// according to the MSC. Request and response bodies are the same as
|
||||
/// `get_room_summary`.
|
||||
///
|
||||
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
|
||||
pub(crate) async fn get_room_summary_legacy(
|
||||
State(services): State<crate::State>,
|
||||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<get_summary::msc3266::Request>,
|
||||
) -> Result<RumaResponse<get_summary::msc3266::Response>> {
|
||||
get_room_summary(State(services), InsecureClientIp(client), body)
|
||||
.boxed()
|
||||
.await
|
||||
.map(RumaResponse)
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}`
|
||||
///
|
||||
/// Returns a short description of the state of a room.
|
||||
///
|
||||
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
|
||||
#[tracing::instrument(skip_all, fields(%client), name = "room_summary")]
|
||||
pub(crate) async fn get_room_summary(
|
||||
State(services): State<crate::State>,
|
||||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<get_summary::msc3266::Request>,
|
||||
) -> Result<get_summary::msc3266::Response> {
|
||||
let (room_id, servers) = services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_with_servers(&body.room_id_or_alias, Some(body.via.clone()))
|
||||
.await?;
|
||||
|
||||
if services.rooms.metadata.is_banned(&room_id).await {
|
||||
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
|
||||
}
|
||||
|
||||
room_summary_response(&services, &room_id, &servers, body.sender_user.as_deref())
|
||||
.boxed()
|
||||
.await
|
||||
}
|
||||
|
||||
async fn room_summary_response(
|
||||
services: &Services,
|
||||
room_id: &RoomId,
|
||||
servers: &[OwnedServerName],
|
||||
sender_user: Option<&UserId>,
|
||||
) -> Result<get_summary::msc3266::Response> {
|
||||
if services.rooms.metadata.exists(room_id).await {
|
||||
return local_room_summary_response(services, room_id, sender_user)
|
||||
.boxed()
|
||||
.await;
|
||||
}
|
||||
|
||||
let room =
|
||||
remote_room_summary_hierarchy_response(services, room_id, servers, sender_user).await?;
|
||||
|
||||
Ok(get_summary::msc3266::Response {
|
||||
room_id: room_id.to_owned(),
|
||||
canonical_alias: room.canonical_alias,
|
||||
avatar_url: room.avatar_url,
|
||||
guest_can_join: room.guest_can_join,
|
||||
name: room.name,
|
||||
num_joined_members: room.num_joined_members,
|
||||
topic: room.topic,
|
||||
world_readable: room.world_readable,
|
||||
join_rule: room.join_rule,
|
||||
room_type: room.room_type,
|
||||
room_version: room.room_version,
|
||||
membership: if sender_user.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(MembershipState::Leave)
|
||||
},
|
||||
encryption: room.encryption,
|
||||
allowed_room_ids: room.allowed_room_ids,
|
||||
})
|
||||
}
|
||||
|
||||
async fn local_room_summary_response(
|
||||
services: &Services,
|
||||
room_id: &RoomId,
|
||||
sender_user: Option<&UserId>,
|
||||
) -> Result<get_summary::msc3266::Response> {
|
||||
let join_rule = services.rooms.state_accessor.get_space_join_rule(room_id);
|
||||
let world_readable = services.rooms.state_accessor.is_world_readable(room_id);
|
||||
let guest_can_join = services.rooms.state_accessor.guest_can_join(room_id);
|
||||
|
||||
let ((join_rule, allowed_room_ids), world_readable, guest_can_join) =
|
||||
join3(join_rule, world_readable, guest_can_join).await;
|
||||
|
||||
user_can_see_summary(
|
||||
services,
|
||||
room_id,
|
||||
&join_rule,
|
||||
guest_can_join,
|
||||
world_readable,
|
||||
&allowed_room_ids,
|
||||
sender_user,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let canonical_alias = services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_canonical_alias(room_id)
|
||||
.ok();
|
||||
let name = services.rooms.state_accessor.get_name(room_id).ok();
|
||||
let topic = services.rooms.state_accessor.get_room_topic(room_id).ok();
|
||||
let room_type = services.rooms.state_accessor.get_room_type(room_id).ok();
|
||||
let avatar_url = services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_avatar(room_id)
|
||||
.map(|res| res.into_option().unwrap_or_default().url);
|
||||
let room_version = services.rooms.state.get_room_version(room_id).ok();
|
||||
let encryption = services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_encryption(room_id)
|
||||
.ok();
|
||||
let num_joined_members = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_joined_count(room_id)
|
||||
.unwrap_or(0);
|
||||
|
||||
let (
|
||||
canonical_alias,
|
||||
name,
|
||||
num_joined_members,
|
||||
topic,
|
||||
avatar_url,
|
||||
room_type,
|
||||
room_version,
|
||||
encryption,
|
||||
) = futures::join!(
|
||||
canonical_alias,
|
||||
name,
|
||||
num_joined_members,
|
||||
topic,
|
||||
avatar_url,
|
||||
room_type,
|
||||
room_version,
|
||||
encryption,
|
||||
);
|
||||
|
||||
Ok(get_summary::msc3266::Response {
|
||||
room_id: room_id.to_owned(),
|
||||
canonical_alias,
|
||||
avatar_url,
|
||||
guest_can_join,
|
||||
name,
|
||||
num_joined_members: num_joined_members.try_into().unwrap_or_default(),
|
||||
topic,
|
||||
world_readable,
|
||||
join_rule,
|
||||
room_type,
|
||||
room_version,
|
||||
membership: if let Some(sender_user) = sender_user {
|
||||
services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_member(room_id, sender_user)
|
||||
.await
|
||||
.map_or(Some(MembershipState::Leave), |content| Some(content.membership))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
encryption,
|
||||
allowed_room_ids,
|
||||
})
|
||||
}
|
||||
|
||||
/// used by MSC3266 to fetch a room's info if we do not know about it
|
||||
async fn remote_room_summary_hierarchy_response(
|
||||
services: &Services,
|
||||
room_id: &RoomId,
|
||||
servers: &[OwnedServerName],
|
||||
sender_user: Option<&UserId>,
|
||||
) -> Result<SpaceHierarchyParentSummary> {
|
||||
if !services.config.allow_federation {
|
||||
return Err!(Request(Forbidden("Federation is disabled.")));
|
||||
}
|
||||
|
||||
if services.rooms.metadata.is_disabled(room_id).await {
|
||||
return Err!(Request(Forbidden(
|
||||
"Federaton of room {room_id} is currently disabled on this server."
|
||||
)));
|
||||
}
|
||||
|
||||
let request = get_hierarchy::v1::Request::new(room_id.to_owned());
|
||||
|
||||
let mut requests: FuturesUnordered<_> = servers
|
||||
.iter()
|
||||
.map(|server| {
|
||||
services
|
||||
.sending
|
||||
.send_federation_request(server, request.clone())
|
||||
})
|
||||
.collect();
|
||||
|
||||
while let Some(Ok(response)) = requests.next().await {
|
||||
let room = response.room.clone();
|
||||
if room.room_id != room_id {
|
||||
debug_warn!(
|
||||
"Room ID {} returned does not belong to the requested room ID {}",
|
||||
room.room_id,
|
||||
room_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
return user_can_see_summary(
|
||||
services,
|
||||
room_id,
|
||||
&room.join_rule,
|
||||
room.guest_can_join,
|
||||
room.world_readable,
|
||||
&room.allowed_room_ids,
|
||||
sender_user,
|
||||
)
|
||||
.await
|
||||
.map(|()| room);
|
||||
}
|
||||
|
||||
Err!(Request(NotFound(
|
||||
"Room is unknown to this server and was unable to fetch over federation with the \
|
||||
provided servers available"
|
||||
)))
|
||||
}
|
||||
|
||||
async fn user_can_see_summary(
|
||||
services: &Services,
|
||||
room_id: &RoomId,
|
||||
join_rule: &SpaceRoomJoinRule,
|
||||
guest_can_join: bool,
|
||||
world_readable: bool,
|
||||
allowed_room_ids: &[OwnedRoomId],
|
||||
sender_user: Option<&UserId>,
|
||||
) -> Result {
|
||||
match sender_user {
|
||||
| Some(sender_user) => {
|
||||
let user_can_see_state_events = services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.user_can_see_state_events(sender_user, room_id);
|
||||
let is_guest = services.users.is_deactivated(sender_user).unwrap_or(false);
|
||||
let user_in_allowed_restricted_room = allowed_room_ids
|
||||
.iter()
|
||||
.stream()
|
||||
.any(|room| services.rooms.state_cache.is_joined(sender_user, room));
|
||||
|
||||
let (user_can_see_state_events, is_guest, user_in_allowed_restricted_room) =
|
||||
join3(user_can_see_state_events, is_guest, user_in_allowed_restricted_room)
|
||||
.boxed()
|
||||
.await;
|
||||
|
||||
if user_can_see_state_events
|
||||
|| (is_guest && guest_can_join)
|
||||
|| matches!(&join_rule, &Public | &Knock | &KnockRestricted)
|
||||
|| user_in_allowed_restricted_room
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err!(Request(Forbidden(
|
||||
"Room is not world readable, not publicly accessible/joinable, restricted room \
|
||||
conditions not met, and guest access is forbidden. Not allowed to see details \
|
||||
of this room."
|
||||
)))
|
||||
},
|
||||
| None => {
|
||||
if matches!(join_rule, Public | Knock | KnockRestricted) || world_readable {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err!(Request(Forbidden(
|
||||
"Room is not world readable or publicly accessible/joinable, authentication is \
|
||||
required"
|
||||
)))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ pub(crate) async fn upgrade_room_route(
|
|||
// Use the m.room.tombstone event as the predecessor
|
||||
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
||||
body.room_id.clone(),
|
||||
(*tombstone_event_id).to_owned(),
|
||||
Some(tombstone_event_id),
|
||||
));
|
||||
|
||||
// Send a m.room.create event containing a predecessor field and the applicable
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ async fn allowed_to_send_state_event(
|
|||
|
||||
if acl_content.deny.contains(&String::from("*"))
|
||||
&& !acl_content.is_allowed(services.globals.server_name())
|
||||
&& !acl_content
|
||||
.allow
|
||||
.contains(&services.globals.server_name().to_string())
|
||||
{
|
||||
return Err!(Request(BadJson(debug_warn!(
|
||||
?room_id,
|
||||
|
|
@ -240,6 +243,9 @@ async fn allowed_to_send_state_event(
|
|||
|
||||
if !acl_content.allow.contains(&String::from("*"))
|
||||
&& !acl_content.is_allowed(services.globals.server_name())
|
||||
&& !acl_content
|
||||
.allow
|
||||
.contains(&services.globals.server_name().to_string())
|
||||
{
|
||||
return Err!(Request(BadJson(debug_warn!(
|
||||
?room_id,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use conduwuit::{
|
|||
math::ruma_from_u64,
|
||||
stream::{BroadbandExt, Tools, TryExpect, WidebandExt},
|
||||
},
|
||||
warn,
|
||||
};
|
||||
use conduwuit_service::{
|
||||
Services,
|
||||
|
|
@ -428,9 +429,12 @@ async fn handle_left_room(
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
if !services.rooms.metadata.exists(room_id).await {
|
||||
if !services.rooms.metadata.exists(room_id).await
|
||||
|| services.rooms.metadata.is_disabled(room_id).await
|
||||
|| services.rooms.metadata.is_banned(room_id).await
|
||||
{
|
||||
// This is just a rejected invite, not a room we know
|
||||
// Insert a leave event anyways
|
||||
// Insert a leave event anyways for the client
|
||||
let event = PduEvent {
|
||||
event_id: EventId::new(services.globals.server_name()),
|
||||
sender: sender_user.to_owned(),
|
||||
|
|
@ -489,7 +493,7 @@ async fn handle_left_room(
|
|||
.room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str())
|
||||
.await
|
||||
else {
|
||||
error!("Left room but no left state event");
|
||||
warn!("Left {room_id} but no left state event");
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
|
|
@ -499,7 +503,7 @@ async fn handle_left_room(
|
|||
.pdu_shortstatehash(&left_event_id)
|
||||
.await
|
||||
else {
|
||||
error!(event_id = %left_event_id, "Leave event has no state");
|
||||
warn!(event_id = %left_event_id, "Leave event has no state in {room_id}");
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -438,7 +438,10 @@ pub(crate) async fn sync_events_v4_route(
|
|||
|
||||
let mut known_subscription_rooms = BTreeSet::new();
|
||||
for (room_id, room) in &body.room_subscriptions {
|
||||
if !services.rooms.metadata.exists(room_id).await {
|
||||
if !services.rooms.metadata.exists(room_id).await
|
||||
|| services.rooms.metadata.is_disabled(room_id).await
|
||||
|| services.rooms.metadata.is_banned(room_id).await
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let todo_room =
|
||||
|
|
|
|||
|
|
@ -214,7 +214,10 @@ async fn fetch_subscriptions(
|
|||
) {
|
||||
let mut known_subscription_rooms = BTreeSet::new();
|
||||
for (room_id, room) in &body.room_subscriptions {
|
||||
if !services.rooms.metadata.exists(room_id).await {
|
||||
if !services.rooms.metadata.exists(room_id).await
|
||||
|| services.rooms.metadata.is_disabled(room_id).await
|
||||
|| services.rooms.metadata.is_banned(room_id).await
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let todo_room =
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeMap;
|
|||
|
||||
use axum::extract::State;
|
||||
use axum_client_ip::InsecureClientIp;
|
||||
use conduwuit::Err;
|
||||
use conduwuit::{Err, Error, Result};
|
||||
use futures::StreamExt;
|
||||
use ruma::{
|
||||
OwnedRoomId,
|
||||
|
|
@ -14,16 +14,14 @@ use ruma::{
|
|||
delete_profile_key, delete_timezone_key, get_profile_key, get_timezone_key,
|
||||
set_profile_key, set_timezone_key,
|
||||
},
|
||||
room::get_summary,
|
||||
},
|
||||
federation,
|
||||
},
|
||||
events::room::member::MembershipState,
|
||||
presence::PresenceState,
|
||||
};
|
||||
|
||||
use super::{update_avatar_url, update_displayname};
|
||||
use crate::{Error, Result, Ruma, RumaResponse};
|
||||
use crate::Ruma;
|
||||
|
||||
/// # `GET /_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms`
|
||||
///
|
||||
|
|
@ -38,13 +36,10 @@ pub(crate) async fn get_mutual_rooms_route(
|
|||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<mutual_rooms::unstable::Request>,
|
||||
) -> Result<mutual_rooms::unstable::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
let sender_user = body.sender_user();
|
||||
|
||||
if sender_user == &body.user_id {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Unknown,
|
||||
"You cannot request rooms in common with yourself.",
|
||||
));
|
||||
if sender_user == body.user_id {
|
||||
return Err!(Request(Unknown("You cannot request rooms in common with yourself.")));
|
||||
}
|
||||
|
||||
if !services.users.exists(&body.user_id).await {
|
||||
|
|
@ -65,129 +60,6 @@ pub(crate) async fn get_mutual_rooms_route(
|
|||
})
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary`
|
||||
///
|
||||
/// Returns a short description of the state of a room.
|
||||
///
|
||||
/// This is the "wrong" endpoint that some implementations/clients may use
|
||||
/// according to the MSC. Request and response bodies are the same as
|
||||
/// `get_room_summary`.
|
||||
///
|
||||
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
|
||||
pub(crate) async fn get_room_summary_legacy(
|
||||
State(services): State<crate::State>,
|
||||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<get_summary::msc3266::Request>,
|
||||
) -> Result<RumaResponse<get_summary::msc3266::Response>> {
|
||||
get_room_summary(State(services), InsecureClientIp(client), body)
|
||||
.await
|
||||
.map(RumaResponse)
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}`
|
||||
///
|
||||
/// Returns a short description of the state of a room.
|
||||
///
|
||||
/// TODO: support fetching remote room info if we don't know the room
|
||||
///
|
||||
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
|
||||
#[tracing::instrument(skip_all, fields(%client), name = "room_summary")]
|
||||
pub(crate) async fn get_room_summary(
|
||||
State(services): State<crate::State>,
|
||||
InsecureClientIp(client): InsecureClientIp,
|
||||
body: Ruma<get_summary::msc3266::Request>,
|
||||
) -> Result<get_summary::msc3266::Response> {
|
||||
let sender_user = body.sender_user.as_ref();
|
||||
|
||||
let room_id = services.rooms.alias.resolve(&body.room_id_or_alias).await?;
|
||||
|
||||
if !services.rooms.metadata.exists(&room_id).await {
|
||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server"));
|
||||
}
|
||||
|
||||
if sender_user.is_none()
|
||||
&& !services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.is_world_readable(&room_id)
|
||||
.await
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::forbidden(),
|
||||
"Room is not world readable, authentication is required",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(get_summary::msc3266::Response {
|
||||
room_id: room_id.clone(),
|
||||
canonical_alias: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_canonical_alias(&room_id)
|
||||
.await
|
||||
.ok(),
|
||||
avatar_url: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_avatar(&room_id)
|
||||
.await
|
||||
.into_option()
|
||||
.unwrap_or_default()
|
||||
.url,
|
||||
guest_can_join: services.rooms.state_accessor.guest_can_join(&room_id).await,
|
||||
name: services.rooms.state_accessor.get_name(&room_id).await.ok(),
|
||||
num_joined_members: services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_joined_count(&room_id)
|
||||
.await
|
||||
.unwrap_or(0)
|
||||
.try_into()?,
|
||||
topic: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_topic(&room_id)
|
||||
.await
|
||||
.ok(),
|
||||
world_readable: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.is_world_readable(&room_id)
|
||||
.await,
|
||||
join_rule: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_join_rule(&room_id)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.0,
|
||||
room_type: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_type(&room_id)
|
||||
.await
|
||||
.ok(),
|
||||
room_version: services.rooms.state.get_room_version(&room_id).await.ok(),
|
||||
membership: if let Some(sender_user) = sender_user {
|
||||
services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_member(&room_id, sender_user)
|
||||
.await
|
||||
.map_or_else(|_| MembershipState::Leave, |content| content.membership)
|
||||
.into()
|
||||
} else {
|
||||
None
|
||||
},
|
||||
encryption: services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_encryption(&room_id)
|
||||
.await
|
||||
.ok(),
|
||||
})
|
||||
}
|
||||
|
||||
/// # `DELETE /_matrix/client/unstable/uk.tcpip.msc4133/profile/:user_id/us.cloke.msc4175.tz`
|
||||
///
|
||||
/// Deletes the `tz` (timezone) of a user, as per MSC4133 and MSC4175.
|
||||
|
|
|
|||
|
|
@ -6,11 +6,17 @@ use conduwuit::{
|
|||
utils::{IterStream, ReadyExt, stream::TryTools},
|
||||
};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill, uint};
|
||||
use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill};
|
||||
|
||||
use super::AccessCheck;
|
||||
use crate::Ruma;
|
||||
|
||||
/// arbitrary number but synapse's is 100 and we can handle lots of these
|
||||
/// anyways
|
||||
const LIMIT_MAX: usize = 150;
|
||||
/// no spec defined number but we can handle a lot of these
|
||||
const LIMIT_DEFAULT: usize = 50;
|
||||
|
||||
/// # `GET /_matrix/federation/v1/backfill/<room_id>`
|
||||
///
|
||||
/// Retrieves events from before the sender joined the room, if the room's
|
||||
|
|
@ -30,9 +36,9 @@ pub(crate) async fn get_backfill_route(
|
|||
|
||||
let limit = body
|
||||
.limit
|
||||
.min(uint!(100))
|
||||
.try_into()
|
||||
.expect("UInt could not be converted to usize");
|
||||
.unwrap_or(LIMIT_DEFAULT)
|
||||
.min(LIMIT_MAX);
|
||||
|
||||
let from = body
|
||||
.v
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
use axum::extract::State;
|
||||
use conduwuit::{Error, Result};
|
||||
use ruma::{
|
||||
CanonicalJsonValue, EventId, RoomId,
|
||||
api::{client::error::ErrorKind, federation::event::get_missing_events},
|
||||
};
|
||||
use conduwuit::{Result, debug, debug_error, utils::to_canonical_object};
|
||||
use ruma::api::federation::event::get_missing_events;
|
||||
|
||||
use super::AccessCheck;
|
||||
use crate::Ruma;
|
||||
|
||||
/// arbitrary number but synapse's is 20 and we can handle lots of these anyways
|
||||
const LIMIT_MAX: usize = 50;
|
||||
/// spec says default is 10
|
||||
const LIMIT_DEFAULT: usize = 10;
|
||||
|
||||
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
|
||||
///
|
||||
/// Retrieves events that the sender is missing.
|
||||
|
|
@ -24,7 +26,11 @@ pub(crate) async fn get_missing_events_route(
|
|||
.check()
|
||||
.await?;
|
||||
|
||||
let limit = body.limit.try_into()?;
|
||||
let limit = body
|
||||
.limit
|
||||
.try_into()
|
||||
.unwrap_or(LIMIT_DEFAULT)
|
||||
.min(LIMIT_MAX);
|
||||
|
||||
let mut queued_events = body.latest_events.clone();
|
||||
// the vec will never have more entries the limit
|
||||
|
|
@ -32,23 +38,14 @@ pub(crate) async fn get_missing_events_route(
|
|||
|
||||
let mut i: usize = 0;
|
||||
while i < queued_events.len() && events.len() < limit {
|
||||
if let Ok(pdu) = services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&queued_events[i])
|
||||
.await
|
||||
{
|
||||
let room_id_str = pdu
|
||||
.get("room_id")
|
||||
.and_then(|val| val.as_str())
|
||||
.ok_or_else(|| Error::bad_database("Invalid event in database."))?;
|
||||
|
||||
let event_room_id = <&RoomId>::try_from(room_id_str)
|
||||
.map_err(|_| Error::bad_database("Invalid room_id in event in database."))?;
|
||||
|
||||
if event_room_id != body.room_id {
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Event from wrong room."));
|
||||
}
|
||||
let Ok(pdu) = services.rooms.timeline.get_pdu(&queued_events[i]).await else {
|
||||
debug!(
|
||||
?body.origin,
|
||||
"Event {} does not exist locally, skipping", &queued_events[i]
|
||||
);
|
||||
i = i.saturating_add(1);
|
||||
continue;
|
||||
};
|
||||
|
||||
if body.earliest_events.contains(&queued_events[i]) {
|
||||
i = i.saturating_add(1);
|
||||
|
|
@ -61,31 +58,32 @@ pub(crate) async fn get_missing_events_route(
|
|||
.server_can_see_event(body.origin(), &body.room_id, &queued_events[i])
|
||||
.await
|
||||
{
|
||||
debug!(
|
||||
?body.origin,
|
||||
"Server cannot see {:?} in {:?}, skipping", pdu.event_id, pdu.room_id
|
||||
);
|
||||
i = i.saturating_add(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
let prev_events = pdu
|
||||
.get("prev_events")
|
||||
.and_then(CanonicalJsonValue::as_array)
|
||||
.unwrap_or_default();
|
||||
|
||||
queued_events.extend(
|
||||
prev_events
|
||||
.iter()
|
||||
.map(<&EventId>::try_from)
|
||||
.filter_map(Result::ok)
|
||||
.map(ToOwned::to_owned),
|
||||
let Ok(event) = to_canonical_object(&pdu) else {
|
||||
debug_error!(
|
||||
?body.origin,
|
||||
"Failed to convert PDU in database to canonical JSON: {pdu:?}"
|
||||
);
|
||||
|
||||
events.push(
|
||||
services
|
||||
.sending
|
||||
.convert_to_outgoing_federation_event(pdu)
|
||||
.await,
|
||||
);
|
||||
}
|
||||
i = i.saturating_add(1);
|
||||
continue;
|
||||
};
|
||||
|
||||
let prev_events = pdu.prev_events.iter().map(ToOwned::to_owned);
|
||||
|
||||
let event = services
|
||||
.sending
|
||||
.convert_to_outgoing_federation_event(event)
|
||||
.await;
|
||||
|
||||
queued_events.extend(prev_events);
|
||||
events.push(event);
|
||||
}
|
||||
|
||||
Ok(get_missing_events::v1::Response { events })
|
||||
|
|
|
|||
|
|
@ -252,14 +252,6 @@ pub struct Config {
|
|||
#[serde(default = "default_servernameevent_data_cache_capacity")]
|
||||
pub servernameevent_data_cache_capacity: u32,
|
||||
|
||||
/// default: varies by system
|
||||
#[serde(default = "default_server_visibility_cache_capacity")]
|
||||
pub server_visibility_cache_capacity: u32,
|
||||
|
||||
/// default: varies by system
|
||||
#[serde(default = "default_user_visibility_cache_capacity")]
|
||||
pub user_visibility_cache_capacity: u32,
|
||||
|
||||
/// default: varies by system
|
||||
#[serde(default = "default_stateinfo_cache_capacity")]
|
||||
pub stateinfo_cache_capacity: u32,
|
||||
|
|
@ -2035,10 +2027,6 @@ fn default_servernameevent_data_cache_capacity() -> u32 {
|
|||
parallelism_scaled_u32(100_000).saturating_add(500_000)
|
||||
}
|
||||
|
||||
fn default_server_visibility_cache_capacity() -> u32 { parallelism_scaled_u32(500) }
|
||||
|
||||
fn default_user_visibility_cache_capacity() -> u32 { parallelism_scaled_u32(1000) }
|
||||
|
||||
fn default_stateinfo_cache_capacity() -> u32 { parallelism_scaled_u32(100) }
|
||||
|
||||
fn default_roomid_spacehierarchy_cache_capacity() -> u32 { parallelism_scaled_u32(1000) }
|
||||
|
|
|
|||
|
|
@ -69,10 +69,6 @@ impl Server {
|
|||
return Err!("Reloading not enabled");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Reloading])
|
||||
.expect("failed to notify systemd of reloading state");
|
||||
|
||||
if self.reloading.swap(true, Ordering::AcqRel) {
|
||||
return Err!("Reloading already in progress");
|
||||
}
|
||||
|
|
@ -98,10 +94,6 @@ impl Server {
|
|||
}
|
||||
|
||||
pub fn shutdown(&self) -> Result {
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Stopping])
|
||||
.expect("failed to notify systemd of stopping state");
|
||||
|
||||
if self.stopping.swap(true, Ordering::AcqRel) {
|
||||
return Err!("Shutdown already in progress");
|
||||
}
|
||||
|
|
@ -144,7 +136,16 @@ impl Server {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn running(&self) -> bool { !self.stopping.load(Ordering::Acquire) }
|
||||
pub fn running(&self) -> bool { !self.is_stopping() }
|
||||
|
||||
#[inline]
|
||||
pub fn is_stopping(&self) -> bool { self.stopping.load(Ordering::Relaxed) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_reloading(&self) -> bool { self.reloading.load(Ordering::Relaxed) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_restarting(&self) -> bool { self.restarting.load(Ordering::Relaxed) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_ours(&self, name: &str) -> bool { name == self.config.server_name }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use std::{
|
|||
|
||||
use async_channel::{QueueStrategy, Receiver, RecvError, Sender};
|
||||
use conduwuit::{
|
||||
Error, Result, Server, debug, debug_warn, err, error, implement,
|
||||
Error, Result, Server, debug, err, error, implement,
|
||||
result::DebugInspect,
|
||||
smallvec::SmallVec,
|
||||
trace,
|
||||
|
|
@ -245,13 +245,6 @@ async fn execute(&self, queue: &Sender<Cmd>, cmd: Cmd) -> Result {
|
|||
self.queued_max.fetch_max(queue.len(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if queue.is_full() {
|
||||
debug_warn!(
|
||||
capacity = ?queue.capacity(),
|
||||
"pool queue is full"
|
||||
);
|
||||
}
|
||||
|
||||
queue
|
||||
.send(cmd)
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -16,15 +16,14 @@ use server::Server;
|
|||
|
||||
rustc_flags_capture! {}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
fn main() -> Result {
|
||||
let args = clap::parse();
|
||||
let runtime = runtime::new(&args)?;
|
||||
let server = Server::new(&args, Some(runtime.handle()))?;
|
||||
|
||||
runtime.spawn(signal::signal(server.clone()));
|
||||
runtime.block_on(async_main(&server))?;
|
||||
|
||||
// explicit drop here to trace thread and tls dtors
|
||||
drop(runtime);
|
||||
runtime::shutdown(&server, runtime);
|
||||
|
||||
#[cfg(unix)]
|
||||
if server.server.restarting.load(Ordering::Acquire) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{
|
||||
iter::once,
|
||||
sync::{
|
||||
OnceLock,
|
||||
Arc, OnceLock,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
},
|
||||
thread,
|
||||
|
|
@ -11,17 +11,18 @@ use std::{
|
|||
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
|
||||
use conduwuit_core::result::LogDebugErr;
|
||||
use conduwuit_core::{
|
||||
Result, is_true,
|
||||
Result, debug, is_true,
|
||||
utils::sys::compute::{nth_core_available, set_affinity},
|
||||
};
|
||||
use tokio::runtime::Builder;
|
||||
|
||||
use crate::clap::Args;
|
||||
use crate::{clap::Args, server::Server};
|
||||
|
||||
const WORKER_NAME: &str = "conduwuit:worker";
|
||||
const WORKER_MIN: usize = 2;
|
||||
const WORKER_KEEPALIVE: u64 = 36;
|
||||
const MAX_BLOCKING_THREADS: usize = 1024;
|
||||
const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(10000);
|
||||
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
|
||||
const DISABLE_MUZZY_THRESHOLD: usize = 4;
|
||||
|
||||
|
|
@ -83,6 +84,42 @@ fn enable_histogram(builder: &mut Builder, args: &Args) {
|
|||
.metrics_poll_time_histogram_configuration(linear);
|
||||
}
|
||||
|
||||
#[cfg(tokio_unstable)]
|
||||
#[tracing::instrument(name = "stop", level = "info", skip_all)]
|
||||
pub(super) fn shutdown(server: &Arc<Server>, runtime: tokio::runtime::Runtime) {
|
||||
use conduwuit_core::event;
|
||||
use tracing::Level;
|
||||
|
||||
// The final metrics output is promoted to INFO when tokio_unstable is active in
|
||||
// a release/bench mode and DEBUG is likely optimized out
|
||||
const LEVEL: Level = if cfg!(debug_assertions) {
|
||||
Level::DEBUG
|
||||
} else {
|
||||
Level::INFO
|
||||
};
|
||||
|
||||
debug!(
|
||||
timeout = ?SHUTDOWN_TIMEOUT,
|
||||
"Waiting for runtime..."
|
||||
);
|
||||
|
||||
runtime.shutdown_timeout(SHUTDOWN_TIMEOUT);
|
||||
let runtime_metrics = server.server.metrics.runtime_interval().unwrap_or_default();
|
||||
|
||||
event!(LEVEL, ?runtime_metrics, "Final runtime metrics");
|
||||
}
|
||||
|
||||
#[cfg(not(tokio_unstable))]
|
||||
#[tracing::instrument(name = "stop", level = "info", skip_all)]
|
||||
pub(super) fn shutdown(_server: &Arc<Server>, runtime: tokio::runtime::Runtime) {
|
||||
debug!(
|
||||
timeout = ?SHUTDOWN_TIMEOUT,
|
||||
"Waiting for runtime..."
|
||||
);
|
||||
|
||||
runtime.shutdown_timeout(SHUTDOWN_TIMEOUT);
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
name = "fork",
|
||||
level = "debug",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@ pub(crate) async fn start(server: Arc<Server>) -> Result<Arc<Services>> {
|
|||
pub(crate) async fn stop(services: Arc<Services>) -> Result<()> {
|
||||
debug!("Shutting down...");
|
||||
|
||||
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
||||
sd_notify::notify(true, &[sd_notify::NotifyState::Stopping])
|
||||
.expect("failed to notify systemd of stopping state");
|
||||
|
||||
// Wait for all completions before dropping or we'll lose them to the module
|
||||
// unload and explode.
|
||||
services.stop().await;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl crate::Service for Service {
|
|||
.build()?,
|
||||
|
||||
well_known: base(config)?
|
||||
.dns_resolver(resolver.resolver.hooked.clone())
|
||||
.dns_resolver(resolver.resolver.clone())
|
||||
.connect_timeout(Duration::from_secs(config.well_known_conn_timeout))
|
||||
.read_timeout(Duration::from_secs(config.well_known_timeout))
|
||||
.timeout(Duration::from_secs(config.well_known_timeout))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use conduwuit::{Err, Result, debug, debug_info, err, error, trace};
|
||||
use futures::{FutureExt, TryFutureExt};
|
||||
use hickory_resolver::error::ResolveError;
|
||||
use hickory_resolver::ResolveError;
|
||||
use ipaddress::IPAddress;
|
||||
use ruma::ServerName;
|
||||
|
||||
|
|
@ -334,27 +334,30 @@ impl super::Service {
|
|||
}
|
||||
|
||||
fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result<()> {
|
||||
use hickory_resolver::error::ResolveErrorKind;
|
||||
use hickory_resolver::{ResolveErrorKind::Proto, proto::ProtoErrorKind};
|
||||
|
||||
match *e.kind() {
|
||||
| ResolveErrorKind::NoRecordsFound { .. } => {
|
||||
match e.kind() {
|
||||
| Proto(e) => match e.kind() {
|
||||
| ProtoErrorKind::NoRecordsFound { .. } => {
|
||||
// Raise to debug_warn if we can find out the result wasn't from cache
|
||||
debug!(%host, "No DNS records found: {e}");
|
||||
Ok(())
|
||||
},
|
||||
| ResolveErrorKind::Timeout => {
|
||||
| ProtoErrorKind::Timeout => {
|
||||
Err!(warn!(%host, "DNS {e}"))
|
||||
},
|
||||
| ResolveErrorKind::NoConnections => {
|
||||
| ProtoErrorKind::NoConnections => {
|
||||
error!(
|
||||
"Your DNS server is overloaded and has ran out of connections. It is \
|
||||
strongly recommended you remediate this issue to ensure proper federation \
|
||||
connectivity."
|
||||
strongly recommended you remediate this issue to ensure proper \
|
||||
federation connectivity."
|
||||
);
|
||||
|
||||
Err!(error!(%host, "DNS error: {e}"))
|
||||
},
|
||||
| _ => Err!(error!(%host, "DNS error: {e}")),
|
||||
},
|
||||
| _ => Err!(error!(%host, "DNS error: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ use std::{net::SocketAddr, sync::Arc, time::Duration};
|
|||
|
||||
use conduwuit::{Result, Server, err};
|
||||
use futures::FutureExt;
|
||||
use hickory_resolver::{TokioAsyncResolver, lookup_ip::LookupIp};
|
||||
use hickory_resolver::{TokioResolver, lookup_ip::LookupIp};
|
||||
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
|
||||
|
||||
use super::cache::{Cache, CachedOverride};
|
||||
|
||||
pub struct Resolver {
|
||||
pub(crate) resolver: Arc<TokioAsyncResolver>,
|
||||
pub(crate) resolver: Arc<TokioResolver>,
|
||||
pub(crate) hooked: Arc<Hooked>,
|
||||
server: Arc<Server>,
|
||||
}
|
||||
|
||||
pub(crate) struct Hooked {
|
||||
resolver: Arc<TokioAsyncResolver>,
|
||||
resolver: Arc<TokioResolver>,
|
||||
cache: Arc<Cache>,
|
||||
server: Arc<Server>,
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ impl Resolver {
|
|||
let mut ns = sys_conf.clone();
|
||||
|
||||
if config.query_over_tcp_only {
|
||||
ns.protocol = hickory_resolver::config::Protocol::Tcp;
|
||||
ns.protocol = hickory_resolver::proto::xfer::Protocol::Tcp;
|
||||
}
|
||||
|
||||
ns.trust_negative_responses = !config.query_all_nameservers;
|
||||
|
|
@ -51,6 +51,7 @@ impl Resolver {
|
|||
}
|
||||
|
||||
opts.cache_size = config.dns_cache_entries as usize;
|
||||
opts.preserve_intermediates = true;
|
||||
opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain));
|
||||
opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30));
|
||||
opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl));
|
||||
|
|
@ -60,8 +61,7 @@ impl Resolver {
|
|||
opts.try_tcp_on_error = config.dns_tcp_fallback;
|
||||
opts.num_concurrent_reqs = 1;
|
||||
opts.edns0 = true;
|
||||
opts.shuffle_dns_servers = true;
|
||||
opts.rotate = true;
|
||||
opts.case_randomization = true;
|
||||
opts.ip_strategy = match config.ip_lookup_strategy {
|
||||
| 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only,
|
||||
| 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only,
|
||||
|
|
@ -69,9 +69,13 @@ impl Resolver {
|
|||
| 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4,
|
||||
| _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6,
|
||||
};
|
||||
opts.authentic_data = false;
|
||||
|
||||
let resolver = Arc::new(TokioAsyncResolver::tokio(conf, opts));
|
||||
let rt_prov = hickory_resolver::proto::runtime::TokioRuntimeProvider::new();
|
||||
let conn_prov = hickory_resolver::name_server::TokioConnectionProvider::new(rt_prov);
|
||||
let mut builder = TokioResolver::builder_with_config(conf, conn_prov);
|
||||
*builder.options_mut() = opts;
|
||||
let resolver = Arc::new(builder.build());
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
resolver: resolver.clone(),
|
||||
hooked: Arc::new(Hooked { resolver, cache, server: server.clone() }),
|
||||
|
|
@ -105,7 +109,7 @@ impl Resolve for Hooked {
|
|||
async fn hooked_resolve(
|
||||
cache: Arc<Cache>,
|
||||
server: Arc<Server>,
|
||||
resolver: Arc<TokioAsyncResolver>,
|
||||
resolver: Arc<TokioResolver>,
|
||||
name: Name,
|
||||
) -> Result<Addrs, Box<dyn std::error::Error + Send + Sync>> {
|
||||
match cache.get_override(name.as_str()).await {
|
||||
|
|
@ -129,7 +133,7 @@ async fn hooked_resolve(
|
|||
|
||||
async fn resolve_to_reqwest(
|
||||
server: Arc<Server>,
|
||||
resolver: Arc<TokioAsyncResolver>,
|
||||
resolver: Arc<TokioResolver>,
|
||||
name: Name,
|
||||
) -> ResolvingResult {
|
||||
use std::{io, io::ErrorKind::Interrupted};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{
|
||||
collections::{BTreeMap, HashSet, VecDeque, hash_map},
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
|
|
@ -8,7 +7,6 @@ use conduwuit::{
|
|||
PduEvent, debug, debug_error, debug_warn, implement, pdu, trace,
|
||||
utils::continue_exponential_backoff_secs, warn,
|
||||
};
|
||||
use futures::TryFutureExt;
|
||||
use ruma::{
|
||||
CanonicalJsonValue, OwnedEventId, RoomId, ServerName, api::federation::event::get_event,
|
||||
};
|
||||
|
|
@ -31,7 +29,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>(
|
|||
events: &'a [OwnedEventId],
|
||||
create_event: &'a PduEvent,
|
||||
room_id: &'a RoomId,
|
||||
) -> Vec<(Arc<PduEvent>, Option<BTreeMap<String, CanonicalJsonValue>>)> {
|
||||
) -> Vec<(PduEvent, Option<BTreeMap<String, CanonicalJsonValue>>)> {
|
||||
let back_off = |id| match self
|
||||
.services
|
||||
.globals
|
||||
|
|
@ -53,7 +51,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>(
|
|||
// a. Look in the main timeline (pduid_pdu tree)
|
||||
// b. Look at outlier pdu tree
|
||||
// (get_pdu_json checks both)
|
||||
if let Ok(local_pdu) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await {
|
||||
if let Ok(local_pdu) = self.services.timeline.get_pdu(id).await {
|
||||
trace!("Found {id} in db");
|
||||
events_with_auth_events.push((id, Some(local_pdu), vec![]));
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
use std::{
|
||||
collections::{BTreeMap, HashMap, HashSet, VecDeque},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||
|
||||
use conduwuit::{
|
||||
PduEvent, Result, debug_warn, err, implement,
|
||||
|
|
@ -31,7 +28,7 @@ pub(super) async fn fetch_prev(
|
|||
initial_set: Vec<OwnedEventId>,
|
||||
) -> Result<(
|
||||
Vec<OwnedEventId>,
|
||||
HashMap<OwnedEventId, (Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>,
|
||||
HashMap<OwnedEventId, (PduEvent, BTreeMap<String, CanonicalJsonValue>)>,
|
||||
)> {
|
||||
let mut graph: HashMap<OwnedEventId, _> = HashMap::with_capacity(initial_set.len());
|
||||
let mut eventid_info = HashMap::new();
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ use std::{
|
|||
time::Instant,
|
||||
};
|
||||
|
||||
use conduwuit::{Err, Result, debug, debug::INFO_SPAN_LEVEL, err, implement, warn};
|
||||
use conduwuit::{
|
||||
Err, Result, debug, debug::INFO_SPAN_LEVEL, defer, err, implement, utils::stream::IterStream,
|
||||
warn,
|
||||
};
|
||||
use futures::{
|
||||
FutureExt,
|
||||
FutureExt, TryFutureExt, TryStreamExt,
|
||||
future::{OptionFuture, try_join5},
|
||||
};
|
||||
use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UserId, events::StateEventType};
|
||||
|
|
@ -86,7 +89,7 @@ pub async fn handle_incoming_pdu<'a>(
|
|||
.state_accessor
|
||||
.room_state_get(room_id, &StateEventType::RoomCreate, "");
|
||||
|
||||
let (meta_exists, is_disabled, (), (), create_event) = try_join5(
|
||||
let (meta_exists, is_disabled, (), (), ref create_event) = try_join5(
|
||||
meta_exists,
|
||||
is_disabled,
|
||||
origin_acl_check,
|
||||
|
|
@ -104,7 +107,7 @@ pub async fn handle_incoming_pdu<'a>(
|
|||
}
|
||||
|
||||
let (incoming_pdu, val) = self
|
||||
.handle_outlier_pdu(origin, &create_event, event_id, room_id, value, false)
|
||||
.handle_outlier_pdu(origin, create_event, event_id, room_id, value, false)
|
||||
.await?;
|
||||
|
||||
// 8. if not timeline event: stop
|
||||
|
|
@ -129,66 +132,71 @@ pub async fn handle_incoming_pdu<'a>(
|
|||
let (sorted_prev_events, mut eventid_info) = self
|
||||
.fetch_prev(
|
||||
origin,
|
||||
&create_event,
|
||||
create_event,
|
||||
room_id,
|
||||
first_ts_in_room,
|
||||
incoming_pdu.prev_events.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
debug!(events = ?sorted_prev_events, "Got previous events");
|
||||
for prev_id in sorted_prev_events {
|
||||
self.services.server.check_running()?;
|
||||
if let Err(e) = self
|
||||
.handle_prev_pdu(
|
||||
debug!(
|
||||
events = ?sorted_prev_events,
|
||||
"Handling previous events"
|
||||
);
|
||||
|
||||
sorted_prev_events
|
||||
.iter()
|
||||
.try_stream()
|
||||
.map_ok(AsRef::as_ref)
|
||||
.try_for_each(|prev_id| {
|
||||
self.handle_prev_pdu(
|
||||
origin,
|
||||
event_id,
|
||||
room_id,
|
||||
&mut eventid_info,
|
||||
&create_event,
|
||||
eventid_info.remove(prev_id),
|
||||
create_event,
|
||||
first_ts_in_room,
|
||||
&prev_id,
|
||||
prev_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
use hash_map::Entry;
|
||||
|
||||
let now = Instant::now();
|
||||
warn!("Prev event {prev_id} failed: {e}");
|
||||
|
||||
.inspect_err(move |e| {
|
||||
warn!("Prev {prev_id} failed: {e}");
|
||||
match self
|
||||
.services
|
||||
.globals
|
||||
.bad_event_ratelimiter
|
||||
.write()
|
||||
.expect("locked")
|
||||
.entry(prev_id)
|
||||
.entry(prev_id.into())
|
||||
{
|
||||
| Entry::Vacant(e) => {
|
||||
e.insert((now, 1));
|
||||
| hash_map::Entry::Vacant(e) => {
|
||||
e.insert((Instant::now(), 1));
|
||||
},
|
||||
| Entry::Occupied(mut e) => {
|
||||
*e.get_mut() = (now, e.get().1.saturating_add(1));
|
||||
| hash_map::Entry::Occupied(mut e) => {
|
||||
let tries = e.get().1.saturating_add(1);
|
||||
*e.get_mut() = (Instant::now(), tries);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.map(|_| self.services.server.check_running())
|
||||
})
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
// Done with prev events, now handling the incoming event
|
||||
let start_time = Instant::now();
|
||||
self.federation_handletime
|
||||
.write()
|
||||
.expect("locked")
|
||||
.insert(room_id.to_owned(), (event_id.to_owned(), start_time));
|
||||
|
||||
let r = self
|
||||
.upgrade_outlier_to_timeline_pdu(incoming_pdu, val, &create_event, origin, room_id)
|
||||
.await;
|
||||
.insert(room_id.into(), (event_id.to_owned(), start_time));
|
||||
|
||||
defer! {{
|
||||
self.federation_handletime
|
||||
.write()
|
||||
.expect("locked")
|
||||
.remove(&room_id.to_owned());
|
||||
.remove(room_id);
|
||||
}};
|
||||
|
||||
r
|
||||
self.upgrade_outlier_to_timeline_pdu(incoming_pdu, val, create_event, origin, room_id)
|
||||
.boxed()
|
||||
.await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
use std::{
|
||||
collections::{BTreeMap, HashMap, hash_map},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::collections::{BTreeMap, HashMap, hash_map};
|
||||
|
||||
use conduwuit::{
|
||||
Err, Error, PduEvent, Result, debug, debug_info, err, implement, state_res, trace, warn,
|
||||
};
|
||||
use futures::{TryFutureExt, future::ready};
|
||||
use futures::future::ready;
|
||||
use ruma::{
|
||||
CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, ServerName,
|
||||
api::client::error::ErrorKind, events::StateEventType,
|
||||
|
|
@ -24,7 +21,7 @@ pub(super) async fn handle_outlier_pdu<'a>(
|
|||
room_id: &'a RoomId,
|
||||
mut value: CanonicalJsonObject,
|
||||
auth_events_known: bool,
|
||||
) -> Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)> {
|
||||
) -> Result<(PduEvent, BTreeMap<String, CanonicalJsonValue>)> {
|
||||
// 1. Remove unsigned field
|
||||
value.remove("unsigned");
|
||||
|
||||
|
|
@ -95,7 +92,7 @@ pub(super) async fn handle_outlier_pdu<'a>(
|
|||
// Build map of auth events
|
||||
let mut auth_events = HashMap::with_capacity(incoming_pdu.auth_events.len());
|
||||
for id in &incoming_pdu.auth_events {
|
||||
let Ok(auth_event) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await else {
|
||||
let Ok(auth_event) = self.services.timeline.get_pdu(id).await else {
|
||||
warn!("Could not find auth event {id}");
|
||||
continue;
|
||||
};
|
||||
|
|
@ -123,15 +120,10 @@ pub(super) async fn handle_outlier_pdu<'a>(
|
|||
|
||||
// The original create event must be in the auth events
|
||||
if !matches!(
|
||||
auth_events
|
||||
.get(&(StateEventType::RoomCreate, String::new().into()))
|
||||
.map(AsRef::as_ref),
|
||||
auth_events.get(&(StateEventType::RoomCreate, String::new().into())),
|
||||
Some(_) | None
|
||||
) {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Incoming event refers to wrong create event.",
|
||||
));
|
||||
return Err!(Request(InvalidParam("Incoming event refers to wrong create event.")));
|
||||
}
|
||||
|
||||
let state_fetch = |ty: &StateEventType, sk: &str| {
|
||||
|
|
@ -161,5 +153,5 @@ pub(super) async fn handle_outlier_pdu<'a>(
|
|||
|
||||
trace!("Added pdu as outlier.");
|
||||
|
||||
Ok((Arc::new(incoming_pdu), val))
|
||||
Ok((incoming_pdu, val))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
use std::{collections::BTreeMap, time::Instant};
|
||||
|
||||
use conduwuit::{
|
||||
Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, implement,
|
||||
Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, defer, implement,
|
||||
utils::continue_exponential_backoff_secs,
|
||||
};
|
||||
use ruma::{CanonicalJsonValue, EventId, OwnedEventId, RoomId, ServerName, UInt};
|
||||
use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UInt};
|
||||
|
||||
#[implement(super::Service)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
|
@ -24,13 +20,10 @@ pub(super) async fn handle_prev_pdu<'a>(
|
|||
origin: &'a ServerName,
|
||||
event_id: &'a EventId,
|
||||
room_id: &'a RoomId,
|
||||
eventid_info: &mut HashMap<
|
||||
OwnedEventId,
|
||||
(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>),
|
||||
>,
|
||||
create_event: &PduEvent,
|
||||
eventid_info: Option<(PduEvent, BTreeMap<String, CanonicalJsonValue>)>,
|
||||
create_event: &'a PduEvent,
|
||||
first_ts_in_room: UInt,
|
||||
prev_id: &EventId,
|
||||
prev_id: &'a EventId,
|
||||
) -> Result {
|
||||
// Check for disabled again because it might have changed
|
||||
if self.services.metadata.is_disabled(room_id).await {
|
||||
|
|
@ -61,7 +54,10 @@ pub(super) async fn handle_prev_pdu<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((pdu, json)) = eventid_info.remove(prev_id) {
|
||||
let Some((pdu, json)) = eventid_info else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// Skip old events
|
||||
if pdu.origin_server_ts < first_ts_in_room {
|
||||
return Ok(());
|
||||
|
|
@ -71,21 +67,22 @@ pub(super) async fn handle_prev_pdu<'a>(
|
|||
self.federation_handletime
|
||||
.write()
|
||||
.expect("locked")
|
||||
.insert(room_id.to_owned(), ((*prev_id).to_owned(), start_time));
|
||||
|
||||
self.upgrade_outlier_to_timeline_pdu(pdu, json, create_event, origin, room_id)
|
||||
.await?;
|
||||
.insert(room_id.into(), ((*prev_id).to_owned(), start_time));
|
||||
|
||||
defer! {{
|
||||
self.federation_handletime
|
||||
.write()
|
||||
.expect("locked")
|
||||
.remove(&room_id.to_owned());
|
||||
.remove(room_id);
|
||||
}};
|
||||
|
||||
self.upgrade_outlier_to_timeline_pdu(pdu, json, create_event, origin, room_id)
|
||||
.await?;
|
||||
|
||||
debug!(
|
||||
elapsed = ?start_time.elapsed(),
|
||||
"Handled prev_event",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::{
|
|||
borrow::Borrow,
|
||||
collections::{HashMap, HashSet},
|
||||
iter::Iterator,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use conduwuit::{
|
||||
|
|
@ -20,7 +19,7 @@ use crate::rooms::short::ShortStateHash;
|
|||
#[tracing::instrument(name = "state", level = "debug", skip_all)]
|
||||
pub(super) async fn state_at_incoming_degree_one(
|
||||
&self,
|
||||
incoming_pdu: &Arc<PduEvent>,
|
||||
incoming_pdu: &PduEvent,
|
||||
) -> Result<Option<HashMap<u64, OwnedEventId>>> {
|
||||
let prev_event = &incoming_pdu.prev_events[0];
|
||||
let Ok(prev_event_sstatehash) = self
|
||||
|
|
@ -67,7 +66,7 @@ pub(super) async fn state_at_incoming_degree_one(
|
|||
#[tracing::instrument(name = "state", level = "debug", skip_all)]
|
||||
pub(super) async fn state_at_incoming_resolved(
|
||||
&self,
|
||||
incoming_pdu: &Arc<PduEvent>,
|
||||
incoming_pdu: &PduEvent,
|
||||
room_id: &RoomId,
|
||||
room_version_id: &RoomVersionId,
|
||||
) -> Result<Option<HashMap<u64, OwnedEventId>>> {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use crate::rooms::{
|
|||
#[implement(super::Service)]
|
||||
pub(super) async fn upgrade_outlier_to_timeline_pdu(
|
||||
&self,
|
||||
incoming_pdu: Arc<PduEvent>,
|
||||
incoming_pdu: PduEvent,
|
||||
val: BTreeMap<String, CanonicalJsonValue>,
|
||||
create_event: &PduEvent,
|
||||
origin: &ServerName,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ use ruma::{
|
|||
},
|
||||
events::{
|
||||
StateEventType,
|
||||
room::join_rules::{JoinRule, RoomJoinRulesEventContent},
|
||||
space::child::{HierarchySpaceChildEvent, SpaceChildEventContent},
|
||||
},
|
||||
serde::Raw,
|
||||
|
|
@ -306,25 +305,18 @@ async fn get_room_summary(
|
|||
children_state: Vec<Raw<HierarchySpaceChildEvent>>,
|
||||
identifier: &Identifier<'_>,
|
||||
) -> Result<SpaceHierarchyParentSummary, Error> {
|
||||
let join_rule = self
|
||||
let (join_rule, allowed_room_ids) = self
|
||||
.services
|
||||
.state_accessor
|
||||
.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "")
|
||||
.await
|
||||
.map_or(JoinRule::Invite, |c: RoomJoinRulesEventContent| c.join_rule);
|
||||
.get_space_join_rule(room_id)
|
||||
.await;
|
||||
|
||||
let allowed_room_ids = self
|
||||
.services
|
||||
.state_accessor
|
||||
.allowed_room_ids(join_rule.clone());
|
||||
|
||||
let join_rule = join_rule.clone().into();
|
||||
let is_accessible_child = self
|
||||
.is_accessible_child(room_id, &join_rule, identifier, &allowed_room_ids)
|
||||
.await;
|
||||
|
||||
if !is_accessible_child {
|
||||
return Err!(Request(Forbidden("User is not allowed to see the room",)));
|
||||
return Err!(Request(Forbidden("User is not allowed to see the room")));
|
||||
}
|
||||
|
||||
let name = self.services.state_accessor.get_name(room_id).ok();
|
||||
|
|
@ -355,6 +347,14 @@ async fn get_room_summary(
|
|||
.get_avatar(room_id)
|
||||
.map(|res| res.into_option().unwrap_or_default().url);
|
||||
|
||||
let room_version = self.services.state.get_room_version(room_id).ok();
|
||||
|
||||
let encryption = self
|
||||
.services
|
||||
.state_accessor
|
||||
.get_room_encryption(room_id)
|
||||
.ok();
|
||||
|
||||
let (
|
||||
canonical_alias,
|
||||
name,
|
||||
|
|
@ -364,6 +364,8 @@ async fn get_room_summary(
|
|||
guest_can_join,
|
||||
avatar_url,
|
||||
room_type,
|
||||
room_version,
|
||||
encryption,
|
||||
) = futures::join!(
|
||||
canonical_alias,
|
||||
name,
|
||||
|
|
@ -372,7 +374,9 @@ async fn get_room_summary(
|
|||
world_readable,
|
||||
guest_can_join,
|
||||
avatar_url,
|
||||
room_type
|
||||
room_type,
|
||||
room_version,
|
||||
encryption,
|
||||
);
|
||||
|
||||
Ok(SpaceHierarchyParentSummary {
|
||||
|
|
@ -387,9 +391,9 @@ async fn get_room_summary(
|
|||
allowed_room_ids,
|
||||
join_rule,
|
||||
room_id: room_id.to_owned(),
|
||||
num_joined_members: num_joined_members
|
||||
.try_into()
|
||||
.expect("user count should not be that big"),
|
||||
num_joined_members: num_joined_members.try_into().unwrap_or_default(),
|
||||
encryption,
|
||||
room_version,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -487,6 +491,8 @@ async fn cache_insert(
|
|||
join_rule,
|
||||
room_type,
|
||||
allowed_room_ids,
|
||||
encryption,
|
||||
room_version,
|
||||
} = child;
|
||||
|
||||
let summary = SpaceHierarchyParentSummary {
|
||||
|
|
@ -506,6 +512,8 @@ async fn cache_insert(
|
|||
.map(PduEvent::into_stripped_spacechild_state_event)
|
||||
.collect()
|
||||
.await,
|
||||
encryption,
|
||||
room_version,
|
||||
};
|
||||
|
||||
cache.insert(current_room.to_owned(), Some(CachedSpaceHierarchySummary { summary }));
|
||||
|
|
@ -527,7 +535,9 @@ impl From<CachedSpaceHierarchySummary> for SpaceHierarchyRoomsChunk {
|
|||
join_rule,
|
||||
room_type,
|
||||
children_state,
|
||||
..
|
||||
allowed_room_ids,
|
||||
encryption,
|
||||
room_version,
|
||||
} = value.summary;
|
||||
|
||||
Self {
|
||||
|
|
@ -542,6 +552,9 @@ impl From<CachedSpaceHierarchySummary> for SpaceHierarchyRoomsChunk {
|
|||
join_rule,
|
||||
room_type,
|
||||
children_state,
|
||||
encryption,
|
||||
room_version,
|
||||
allowed_room_ids,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -562,7 +575,9 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR
|
|||
join_rule,
|
||||
room_type,
|
||||
children_state,
|
||||
..
|
||||
allowed_room_ids,
|
||||
encryption,
|
||||
room_version,
|
||||
} = summary;
|
||||
|
||||
SpaceHierarchyRoomsChunk {
|
||||
|
|
@ -577,5 +592,8 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR
|
|||
join_rule,
|
||||
room_type,
|
||||
children_state,
|
||||
encryption,
|
||||
room_version,
|
||||
allowed_room_ids,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,21 +3,13 @@ mod server_can;
|
|||
mod state;
|
||||
mod user_can;
|
||||
|
||||
use std::{
|
||||
fmt::Write,
|
||||
sync::{Arc, Mutex as StdMutex, Mutex},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use conduwuit::{
|
||||
Result, err, utils,
|
||||
utils::math::{Expected, usize_from_f64},
|
||||
};
|
||||
use conduwuit::{Result, err};
|
||||
use database::Map;
|
||||
use lru_cache::LruCache;
|
||||
use ruma::{
|
||||
EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedRoomId, OwnedServerName,
|
||||
OwnedUserId, RoomId, UserId,
|
||||
EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedRoomId, RoomId, UserId,
|
||||
events::{
|
||||
StateEventType,
|
||||
room::{
|
||||
|
|
@ -37,11 +29,9 @@ use ruma::{
|
|||
space::SpaceRoomJoinRule,
|
||||
};
|
||||
|
||||
use crate::{Dep, rooms, rooms::short::ShortStateHash};
|
||||
use crate::{Dep, rooms};
|
||||
|
||||
pub struct Service {
|
||||
pub server_visibility_cache: Mutex<LruCache<(OwnedServerName, ShortStateHash), bool>>,
|
||||
pub user_visibility_cache: Mutex<LruCache<(OwnedUserId, ShortStateHash), bool>>,
|
||||
services: Services,
|
||||
db: Data,
|
||||
}
|
||||
|
|
@ -61,19 +51,7 @@ struct Data {
|
|||
#[async_trait]
|
||||
impl crate::Service for Service {
|
||||
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||
let config = &args.server.config;
|
||||
let server_visibility_cache_capacity =
|
||||
f64::from(config.server_visibility_cache_capacity) * config.cache_capacity_modifier;
|
||||
let user_visibility_cache_capacity =
|
||||
f64::from(config.user_visibility_cache_capacity) * config.cache_capacity_modifier;
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
server_visibility_cache: StdMutex::new(LruCache::new(usize_from_f64(
|
||||
server_visibility_cache_capacity,
|
||||
)?)),
|
||||
user_visibility_cache: StdMutex::new(LruCache::new(usize_from_f64(
|
||||
user_visibility_cache_capacity,
|
||||
)?)),
|
||||
services: Services {
|
||||
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
|
||||
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
|
||||
|
|
@ -88,44 +66,6 @@ impl crate::Service for Service {
|
|||
}))
|
||||
}
|
||||
|
||||
async fn memory_usage(&self, out: &mut (dyn Write + Send)) -> Result {
|
||||
use utils::bytes::pretty;
|
||||
|
||||
let (svc_count, svc_bytes) = self.server_visibility_cache.lock()?.iter().fold(
|
||||
(0_usize, 0_usize),
|
||||
|(count, bytes), (key, _)| {
|
||||
(
|
||||
count.expected_add(1),
|
||||
bytes
|
||||
.expected_add(key.0.capacity())
|
||||
.expected_add(size_of_val(&key.1)),
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
let (uvc_count, uvc_bytes) = self.user_visibility_cache.lock()?.iter().fold(
|
||||
(0_usize, 0_usize),
|
||||
|(count, bytes), (key, _)| {
|
||||
(
|
||||
count.expected_add(1),
|
||||
bytes
|
||||
.expected_add(key.0.capacity())
|
||||
.expected_add(size_of_val(&key.1)),
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
writeln!(out, "server_visibility_cache: {svc_count} ({})", pretty(svc_bytes))?;
|
||||
writeln!(out, "user_visibility_cache: {uvc_count} ({})", pretty(uvc_bytes))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn clear_cache(&self) {
|
||||
self.server_visibility_cache.lock().expect("locked").clear();
|
||||
self.user_visibility_cache.lock().expect("locked").clear();
|
||||
}
|
||||
|
||||
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||
}
|
||||
|
||||
|
|
@ -189,22 +129,34 @@ impl Service {
|
|||
.map(|c: RoomTopicEventContent| c.topic)
|
||||
}
|
||||
|
||||
/// Returns the join rule (`SpaceRoomJoinRule`) for a given room
|
||||
pub async fn get_join_rule(
|
||||
/// Returns the space join rule (`SpaceRoomJoinRule`) for a given room and
|
||||
/// any allowed room IDs if available. Will default to Invite and empty vec
|
||||
/// if doesnt exist or invalid,
|
||||
pub async fn get_space_join_rule(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
) -> Result<(SpaceRoomJoinRule, Vec<OwnedRoomId>)> {
|
||||
) -> (SpaceRoomJoinRule, Vec<OwnedRoomId>) {
|
||||
self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "")
|
||||
.await
|
||||
.map(|c: RoomJoinRulesEventContent| {
|
||||
.map_or_else(
|
||||
|_| (SpaceRoomJoinRule::Invite, vec![]),
|
||||
|c: RoomJoinRulesEventContent| {
|
||||
(c.join_rule.clone().into(), self.allowed_room_ids(c.join_rule))
|
||||
})
|
||||
.or_else(|_| Ok((SpaceRoomJoinRule::Invite, vec![])))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the join rules for a given room (`JoinRule` type). Will default
|
||||
/// to Invite if doesnt exist or invalid
|
||||
pub async fn get_join_rules(&self, room_id: &RoomId) -> JoinRule {
|
||||
self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "")
|
||||
.await
|
||||
.map_or_else(|_| JoinRule::Invite, |c: RoomJoinRulesEventContent| (c.join_rule))
|
||||
}
|
||||
|
||||
/// Returns an empty vec if not a restricted room
|
||||
pub fn allowed_room_ids(&self, join_rule: JoinRule) -> Vec<OwnedRoomId> {
|
||||
let mut room_ids = Vec::with_capacity(1);
|
||||
let mut room_ids = Vec::with_capacity(1); // restricted rooms generally only have 1 allowed room ID
|
||||
if let JoinRule::Restricted(r) | JoinRule::KnockRestricted(r) = join_rule {
|
||||
for rule in r.allow {
|
||||
if let AllowRule::RoomMembership(RoomMembership { room_id: membership }) = rule {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use conduwuit::{error, implement, utils::stream::ReadyExt};
|
||||
use conduwuit::{implement, utils::stream::ReadyExt};
|
||||
use futures::StreamExt;
|
||||
use ruma::{
|
||||
EventId, RoomId, ServerName,
|
||||
|
|
@ -22,15 +22,6 @@ pub async fn server_can_see_event(
|
|||
return true;
|
||||
};
|
||||
|
||||
if let Some(visibility) = self
|
||||
.server_visibility_cache
|
||||
.lock()
|
||||
.expect("locked")
|
||||
.get_mut(&(origin.to_owned(), shortstatehash))
|
||||
{
|
||||
return *visibility;
|
||||
}
|
||||
|
||||
let history_visibility = self
|
||||
.state_get_content(shortstatehash, &StateEventType::RoomHistoryVisibility, "")
|
||||
.await
|
||||
|
|
@ -44,8 +35,7 @@ pub async fn server_can_see_event(
|
|||
.room_members(room_id)
|
||||
.ready_filter(|member| member.server_name() == origin);
|
||||
|
||||
let visibility = match history_visibility {
|
||||
| HistoryVisibility::WorldReadable | HistoryVisibility::Shared => true,
|
||||
match history_visibility {
|
||||
| HistoryVisibility::Invited => {
|
||||
// Allow if any member on requesting server was AT LEAST invited, else deny
|
||||
current_server_members
|
||||
|
|
@ -58,16 +48,6 @@ pub async fn server_can_see_event(
|
|||
.any(|member| self.user_was_joined(shortstatehash, member))
|
||||
.await
|
||||
},
|
||||
| _ => {
|
||||
error!("Unknown history visibility {history_visibility}");
|
||||
false
|
||||
},
|
||||
};
|
||||
|
||||
self.server_visibility_cache
|
||||
.lock()
|
||||
.expect("locked")
|
||||
.insert((origin.to_owned(), shortstatehash), visibility);
|
||||
|
||||
visibility
|
||||
| HistoryVisibility::WorldReadable | HistoryVisibility::Shared | _ => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use conduwuit::{Err, Error, Result, error, implement, pdu::PduBuilder};
|
||||
use conduwuit::{Err, Result, implement, pdu::PduBuilder};
|
||||
use ruma::{
|
||||
EventId, RoomId, UserId,
|
||||
events::{
|
||||
|
|
@ -76,8 +76,8 @@ pub async fn user_can_redact(
|
|||
|| redacting_event
|
||||
.as_ref()
|
||||
.is_ok_and(|redacting_event| redacting_event.sender == sender)),
|
||||
| _ => Err(Error::bad_database(
|
||||
"No m.room.power_levels or m.room.create events in database for room",
|
||||
| _ => Err!(Database(
|
||||
"No m.room.power_levels or m.room.create events in database for room"
|
||||
)),
|
||||
}
|
||||
},
|
||||
|
|
@ -98,15 +98,6 @@ pub async fn user_can_see_event(
|
|||
return true;
|
||||
};
|
||||
|
||||
if let Some(visibility) = self
|
||||
.user_visibility_cache
|
||||
.lock()
|
||||
.expect("locked")
|
||||
.get_mut(&(user_id.to_owned(), shortstatehash))
|
||||
{
|
||||
return *visibility;
|
||||
}
|
||||
|
||||
let currently_member = self.services.state_cache.is_joined(user_id, room_id).await;
|
||||
|
||||
let history_visibility = self
|
||||
|
|
@ -116,9 +107,7 @@ pub async fn user_can_see_event(
|
|||
c.history_visibility
|
||||
});
|
||||
|
||||
let visibility = match history_visibility {
|
||||
| HistoryVisibility::WorldReadable => true,
|
||||
| HistoryVisibility::Shared => currently_member,
|
||||
match history_visibility {
|
||||
| HistoryVisibility::Invited => {
|
||||
// Allow if any member on requesting server was AT LEAST invited, else deny
|
||||
self.user_was_invited(shortstatehash, user_id).await
|
||||
|
|
@ -127,18 +116,9 @@ pub async fn user_can_see_event(
|
|||
// Allow if any member on requested server was joined, else deny
|
||||
self.user_was_joined(shortstatehash, user_id).await
|
||||
},
|
||||
| _ => {
|
||||
error!("Unknown history visibility {history_visibility}");
|
||||
false
|
||||
},
|
||||
};
|
||||
|
||||
self.user_visibility_cache
|
||||
.lock()
|
||||
.expect("locked")
|
||||
.insert((user_id.to_owned(), shortstatehash), visibility);
|
||||
|
||||
visibility
|
||||
| HistoryVisibility::WorldReadable => true,
|
||||
| HistoryVisibility::Shared | _ => currently_member,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a user is allowed to see an event, based on
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct Services {
|
|||
account_data: Dep<account_data::Service>,
|
||||
config: Dep<config::Service>,
|
||||
globals: Dep<globals::Service>,
|
||||
metadata: Dep<rooms::metadata::Service>,
|
||||
state_accessor: Dep<rooms::state_accessor::Service>,
|
||||
users: Dep<users::Service>,
|
||||
}
|
||||
|
|
@ -73,6 +74,7 @@ impl crate::Service for Service {
|
|||
account_data: args.depend::<account_data::Service>("account_data"),
|
||||
config: args.depend::<config::Service>("config"),
|
||||
globals: args.depend::<globals::Service>("globals"),
|
||||
metadata: args.depend::<rooms::metadata::Service>("rooms::metadata"),
|
||||
state_accessor: args
|
||||
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
|
||||
users: args.depend::<users::Service>("users"),
|
||||
|
|
@ -271,7 +273,9 @@ impl Service {
|
|||
self.mark_as_left(user_id, room_id);
|
||||
|
||||
if self.services.globals.user_is_local(user_id)
|
||||
&& self.services.config.forget_forced_upon_leave
|
||||
&& (self.services.config.forget_forced_upon_leave
|
||||
|| self.services.metadata.is_banned(room_id).await
|
||||
|| self.services.metadata.is_disabled(room_id).await)
|
||||
{
|
||||
self.forget(room_id, user_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ where
|
|||
return Ok(None);
|
||||
};
|
||||
|
||||
if dest == *"null" || dest.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
trace!("Appservice URL \"{dest}\", Appservice ID: {}", registration.id);
|
||||
|
||||
let hs_token = registration.hs_token.as_str();
|
||||
|
|
@ -34,7 +38,11 @@ where
|
|||
SendAccessToken::IfRequired(hs_token),
|
||||
&VERSIONS,
|
||||
)
|
||||
.map_err(|e| err!(BadServerResponse(warn!("Failed to find destination {dest}: {e}"))))?
|
||||
.map_err(|e| {
|
||||
err!(BadServerResponse(
|
||||
warn!(appservice = %registration.id, "Failed to find destination {dest}: {e:?}")
|
||||
))
|
||||
})?
|
||||
.map(BytesMut::freeze);
|
||||
|
||||
let mut parts = http_request.uri().clone().into_parts();
|
||||
|
|
@ -51,7 +59,7 @@ where
|
|||
let reqwest_request = reqwest::Request::try_from(http_request)?;
|
||||
|
||||
let mut response = client.execute(reqwest_request).await.map_err(|e| {
|
||||
warn!("Could not send request to appservice \"{}\" at {dest}: {e}", registration.id);
|
||||
warn!("Could not send request to appservice \"{}\" at {dest}: {e:?}", registration.id);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
|
@ -71,7 +79,7 @@ where
|
|||
|
||||
if !status.is_success() {
|
||||
debug_error!("Appservice response bytes: {:?}", utils::string_from_bytes(&body));
|
||||
return Err!(BadServerResponse(error!(
|
||||
return Err!(BadServerResponse(warn!(
|
||||
"Appservice \"{}\" returned unsuccessful HTTP response {status} at {dest}",
|
||||
registration.id
|
||||
)));
|
||||
|
|
@ -84,8 +92,8 @@ where
|
|||
);
|
||||
|
||||
response.map(Some).map_err(|e| {
|
||||
err!(BadServerResponse(error!(
|
||||
"Appservice \"{}\" returned invalid response bytes {dest}: {e}",
|
||||
err!(BadServerResponse(warn!(
|
||||
"Appservice \"{}\" returned invalid/malformed response bytes {dest}: {e}",
|
||||
registration.id
|
||||
)))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -350,7 +350,6 @@ impl Service {
|
|||
token: &str,
|
||||
) -> Result<()> {
|
||||
let key = (user_id, device_id);
|
||||
// should not be None, but we shouldn't assert either lol...
|
||||
if self.db.userdeviceid_metadata.qry(&key).await.is_err() {
|
||||
return Err!(Database(error!(
|
||||
?user_id,
|
||||
|
|
@ -594,7 +593,7 @@ impl Service {
|
|||
key_id: &str,
|
||||
signature: (String, String),
|
||||
sender_id: &UserId,
|
||||
) -> Result<()> {
|
||||
) -> Result {
|
||||
let key = (target_id, key_id);
|
||||
|
||||
let mut cross_signing_key: serde_json::Value = self
|
||||
|
|
@ -602,21 +601,27 @@ impl Service {
|
|||
.keyid_key
|
||||
.qry(&key)
|
||||
.await
|
||||
.map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key."))))?
|
||||
.map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key"))))?
|
||||
.deserialized()
|
||||
.map_err(|e| err!(Database("key in keyid_key is invalid. {e:?}")))?;
|
||||
.map_err(|e| err!(Database(debug_warn!("key in keyid_key is invalid: {e:?}"))))?;
|
||||
|
||||
let signatures = cross_signing_key
|
||||
.get_mut("signatures")
|
||||
.ok_or_else(|| err!(Database("key in keyid_key has no signatures field.")))?
|
||||
.ok_or_else(|| {
|
||||
err!(Database(debug_warn!("key in keyid_key has no signatures field")))
|
||||
})?
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| err!(Database("key in keyid_key has invalid signatures field.")))?
|
||||
.ok_or_else(|| {
|
||||
err!(Database(debug_warn!("key in keyid_key has invalid signatures field.")))
|
||||
})?
|
||||
.entry(sender_id.to_string())
|
||||
.or_insert_with(|| serde_json::Map::new().into());
|
||||
|
||||
signatures
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| err!(Database("signatures in keyid_key for a user is invalid.")))?
|
||||
.ok_or_else(|| {
|
||||
err!(Database(debug_warn!("signatures in keyid_key for a user is invalid.")))
|
||||
})?
|
||||
.insert(signature.0, signature.1.into());
|
||||
|
||||
let key = (target_id, key_id);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue