Compare commits
31 commits
main
...
01-09-2024
Author | SHA1 | Date | |
---|---|---|---|
![]() |
59e764b4a6 | ||
![]() |
e35627cb54 | ||
![]() |
749b0348c9 | ||
![]() |
5fdcb69ea1 | ||
![]() |
2da710bb3c | ||
![]() |
ed28378c41 | ||
![]() |
bb34cedda1 | ||
![]() |
deac34cc43 | ||
![]() |
7d44f1083e | ||
![]() |
ac389084f6 | ||
![]() |
932dc35c1f | ||
![]() |
349c804436 | ||
![]() |
856eae7686 | ||
![]() |
a3d9382389 | ||
![]() |
d1da1ae790 | ||
![]() |
eec672a55a | ||
![]() |
8d7f00d88f | ||
![]() |
7f5de5968b | ||
![]() |
33f583c906 | ||
![]() |
163f9113e8 | ||
![]() |
fcebcf94b6 | ||
![]() |
ab63447043 | ||
![]() |
6196757ba1 | ||
![]() |
c551402b44 | ||
![]() |
36671b6172 | ||
![]() |
eb4944df2a | ||
![]() |
6c5b13b9db | ||
![]() |
eae084c1bd | ||
![]() |
74be41c5de | ||
![]() |
0a5095b575 | ||
![]() |
98f83d1d0c |
40 changed files with 507 additions and 902 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
|||
run: rm -rf "$HOME/.rustup" "$HOME/.cargo"
|
||||
|
||||
- name: Install Nix (with flakes and nix-command enabled)
|
||||
uses: cachix/install-nix-action@v24
|
||||
uses: cachix/install-nix-action@v25
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ docker build debugging:
|
|||
|
||||
cargo check:
|
||||
stage: test
|
||||
image: docker.io/rust:1.70.0-bullseye
|
||||
image: docker.io/rust:1.74.1-bullseye
|
||||
needs: []
|
||||
interruptible: true
|
||||
before_script:
|
||||
|
|
169
Cargo.lock
generated
169
Cargo.lock
generated
|
@ -205,9 +205,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.5"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
|
@ -215,15 +215,6 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.1"
|
||||
|
@ -347,9 +338,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.13"
|
||||
version = "4.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
|
||||
checksum = "58e54881c004cec7895b0068a0a954cd5d62da01aef83fa35b1e594497bf5445"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -357,9 +348,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.12"
|
||||
version = "4.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
|
||||
checksum = "59cb82d7f531603d2fd1f507441cdd35184fa81beff7bd489570de7f773460bb"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
|
@ -391,7 +382,7 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
|||
|
||||
[[package]]
|
||||
name = "conduwuit"
|
||||
version = "0.7.0-alpha+conduwuit-0.1.1"
|
||||
version = "0.7.0-alpha+conduwuit-0.1.2"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-trait",
|
||||
|
@ -404,7 +395,6 @@ dependencies = [
|
|||
"directories",
|
||||
"figment",
|
||||
"futures-util",
|
||||
"heed",
|
||||
"hmac",
|
||||
"http",
|
||||
"hyper",
|
||||
|
@ -421,7 +411,6 @@ dependencies = [
|
|||
"opentelemetry-jaeger",
|
||||
"opentelemetry_sdk",
|
||||
"parking_lot",
|
||||
"persy",
|
||||
"rand",
|
||||
"regex",
|
||||
"reqwest",
|
||||
|
@ -488,21 +477,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
|
@ -792,16 +766,6 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.28"
|
||||
|
@ -991,42 +955,6 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "heed"
|
||||
version = "0.10.6"
|
||||
source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"heed-traits",
|
||||
"heed-types",
|
||||
"libc",
|
||||
"lmdb-rkv-sys",
|
||||
"once_cell",
|
||||
"page_size",
|
||||
"serde",
|
||||
"synchronoise",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heed-traits"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d"
|
||||
|
||||
[[package]]
|
||||
name = "heed-types"
|
||||
version = "0.7.2"
|
||||
source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"heed-traits",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.2"
|
||||
|
@ -1347,8 +1275,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librocksdb-sys"
|
||||
version = "0.15.0+8.9.1"
|
||||
source = "git+https://github.com/rust-rocksdb/rust-rocksdb?rev=66f04df013b6e6bd42b5a8c353406e09a7c7da2a#66f04df013b6e6bd42b5a8c353406e09a7c7da2a"
|
||||
version = "0.16.0+8.10.0"
|
||||
source = "git+https://github.com/rust-rocksdb/rust-rocksdb?rev=8fccdf5473e3e75a5ce0f42e5ff5e89c2012305b#8fccdf5473e3e75a5ce0f42e5ff5e89c2012305b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bzip2-sys",
|
||||
|
@ -1389,17 +1317,6 @@ version = "0.5.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "lmdb-rkv-sys"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
|
@ -1703,16 +1620,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "page_size"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
@ -1798,22 +1705,6 @@ version = "2.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "persy"
|
||||
version = "1.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cd38c602b23c2f451842d89f27cd5e0d4b292176daf40feeda859c658dcdc76"
|
||||
dependencies = [
|
||||
"crc",
|
||||
"data-encoding",
|
||||
"fs2",
|
||||
"linked-hash-map",
|
||||
"rand",
|
||||
"thiserror",
|
||||
"unsigned-varint",
|
||||
"zigzag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.3"
|
||||
|
@ -2119,7 +2010,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "rocksdb"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/rust-rocksdb/rust-rocksdb?rev=66f04df013b6e6bd42b5a8c353406e09a7c7da2a#66f04df013b6e6bd42b5a8c353406e09a7c7da2a"
|
||||
source = "git+https://github.com/rust-rocksdb/rust-rocksdb?rev=8fccdf5473e3e75a5ce0f42e5ff5e89c2012305b#8fccdf5473e3e75a5ce0f42e5ff5e89c2012305b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"librocksdb-sys",
|
||||
|
@ -2465,18 +2356,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.194"
|
||||
version = "1.0.195"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773"
|
||||
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.194"
|
||||
version = "1.0.195"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
|
||||
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2498,9 +2389,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.109"
|
||||
version = "1.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
|
||||
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -2540,9 +2431,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.29"
|
||||
version = "0.9.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129"
|
||||
checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38"
|
||||
dependencies = [
|
||||
"indexmap 2.0.0",
|
||||
"itoa",
|
||||
|
@ -2721,15 +2612,6 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "synchronoise"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2"
|
||||
dependencies = [
|
||||
"crossbeam-queue",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
|
@ -3228,12 +3110,6 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
|
||||
|
||||
[[package]]
|
||||
name = "unsigned-varint"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
|
@ -3528,15 +3404,6 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
||||
|
||||
[[package]]
|
||||
name = "zigzag"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70b40401a28d86ce16a330b863b86fd7dbee4d7c940587ab09ab8c019f9e3fdf"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.0"
|
||||
|
|
73
Cargo.toml
73
Cargo.toml
|
@ -6,14 +6,14 @@ authors = ["strawberry <strawberry@puppygock.gay>", "timokoesters <timo@koesters
|
|||
homepage = "https://puppygock.gay/conduwuit"
|
||||
repository = "https://gitlab.com/girlbossceo/conduwuit"
|
||||
readme = "README.md"
|
||||
version = "0.7.0-alpha+conduwuit-0.1.1"
|
||||
version = "0.7.0-alpha+conduwuit-0.1.2"
|
||||
edition = "2021"
|
||||
|
||||
# When changing this, make sure to update the `flake.lock` file by running
|
||||
# `nix flake update`. If you don't have Nix installed or otherwise don't know
|
||||
# how to do this, ping `@charles:computer.surgery` or `@dusk:gaze.systems` in
|
||||
# the matrix room.
|
||||
rust-version = "1.70.0"
|
||||
rust-version = "1.74.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -37,10 +37,6 @@ hyperlocal = { git = "https://github.com/softprops/hyperlocal", rev = "2ee4d1496
|
|||
hyper = { version = "0.14", features = ["server", "http1", "http2"] }
|
||||
tokio = { version = "1.35.1", features = ["fs", "macros", "signal", "sync"] }
|
||||
loole = "0.3"
|
||||
# Used for storing data permanently
|
||||
#sled = { version = "0.34.7", features = ["compression", "no_metrics"], optional = true }
|
||||
#sled = { git = "https://github.com/spacejam/sled.git", rev = "e4640e0773595229f398438886f19bca6f7326a2", features = ["compression"] }
|
||||
persy = { version = "1.4.7", optional = true, features = ["background_ops"] }
|
||||
|
||||
# Used for the http request / response body type for Ruma endpoints used with reqwest
|
||||
bytes = "1.5.0"
|
||||
|
@ -48,11 +44,11 @@ http = "0.2.11"
|
|||
# Used to find data directory for default db path
|
||||
directories = "5.0.1"
|
||||
# Used for ruma wrapper
|
||||
serde_json = { version = "1.0.109", features = ["raw_value"] }
|
||||
serde_json = { version = "1.0.111", features = ["raw_value"] }
|
||||
# Used for appservice registration files
|
||||
serde_yaml = "0.9.29"
|
||||
serde_yaml = "0.9.30"
|
||||
# Used for pdu definition
|
||||
serde = { version = "1.0.194", features = ["rc"] }
|
||||
serde = { version = "1.0.195", features = ["rc"] }
|
||||
# Used for secure identifiers
|
||||
rand = "0.8.5"
|
||||
# Used to hash passwords
|
||||
|
@ -63,7 +59,7 @@ thiserror = "1.0.56"
|
|||
# Used to generate thumbnails for images
|
||||
image = { version = "0.24.7", default-features = false, features = ["jpeg", "png", "gif", "webp"] }
|
||||
# Used to encode server public key
|
||||
base64 = "0.21.5"
|
||||
base64 = "0.21.7"
|
||||
# Used when hashing the state
|
||||
ring = "0.17.7"
|
||||
# Used when querying the SRV record of other servers
|
||||
|
@ -86,11 +82,10 @@ parking_lot = { version = "0.12.1", optional = true }
|
|||
crossbeam = { version = "0.8.3", optional = true }
|
||||
num_cpus = "1.16.0"
|
||||
threadpool = "1.8.1"
|
||||
heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true }
|
||||
# Used for ruma wrapper
|
||||
serde_html_form = "0.2.3"
|
||||
|
||||
rocksdb = { git = "https://github.com/rust-rocksdb/rust-rocksdb", rev = "66f04df013b6e6bd42b5a8c353406e09a7c7da2a", default-features = false, features = ["multi-threaded-cf", "snappy", "lz4", "zstd"], optional = true }
|
||||
rocksdb = { git = "https://github.com/rust-rocksdb/rust-rocksdb", rev = "8fccdf5473e3e75a5ce0f42e5ff5e89c2012305b", default-features = false, features = ["multi-threaded-cf", "snappy", "lz4", "zstd"], optional = true }
|
||||
|
||||
thread_local = "1.1.7"
|
||||
# used for TURN server authentication
|
||||
|
@ -98,7 +93,7 @@ hmac = "0.12.1"
|
|||
sha-1 = "0.10.1"
|
||||
sha2 = { version = "0.10.8" }
|
||||
# used for conduit's CLI and admin room command parsing
|
||||
clap = { version = "4.4.13", default-features = false, features = ["std", "derive", "help", "usage", "error-context"] }
|
||||
clap = { version = "4.4.16", default-features = false, features = ["std", "derive", "help", "usage", "error-context"] }
|
||||
futures-util = { version = "0.3.30", default-features = false }
|
||||
# Used for reading the configuration from conduit.toml & environment variables
|
||||
figment = { version = "0.10.13", features = ["env", "toml"] }
|
||||
|
@ -118,10 +113,7 @@ nix = { version = "0.27.1", features = ["resource"] }
|
|||
|
||||
[features]
|
||||
default = ["conduit_bin", "backend_rocksdb", "systemd", "zstd_compression"]
|
||||
#backend_sled = ["sled"]
|
||||
backend_persy = ["persy", "parking_lot"]
|
||||
backend_sqlite = ["sqlite"]
|
||||
#backend_heed = ["heed", "crossbeam"]
|
||||
backend_rocksdb = ["rocksdb"]
|
||||
jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"]
|
||||
sqlite = ["rusqlite", "parking_lot", "tokio/signal"]
|
||||
|
@ -191,3 +183,52 @@ codegen-units=1
|
|||
debug = 0
|
||||
opt-level = 3
|
||||
codegen-units=1
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[workspace.lints.rust]
|
||||
# missing_abi = "warn"
|
||||
# missing_docs = "warn"
|
||||
# noop_method_call = "warn"
|
||||
# pointer_structural_match = "warn"
|
||||
# unreachable_pub = "warn"
|
||||
# unused_extern_crates = "warn"
|
||||
# unused_import_braces = "warn"
|
||||
# unused_lifetimes = "warn"
|
||||
unused_qualifications = "warn"
|
||||
# unused_tuple_struct_fields = "warn"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
suspicious = "warn" # assume deny in practice
|
||||
perf = "warn" # assume deny in practice
|
||||
# redundant_clone = "warn"
|
||||
# cloned_instead_of_copied = "warn"
|
||||
expl_impl_clone_on_copy = "warn"
|
||||
# pedantic = "warn"
|
||||
# as_conversions = "warn"
|
||||
dbg_macro = "warn"
|
||||
# empty_structs_with_brackets = "warn"
|
||||
# get_unwrap = "warn"
|
||||
# if_then_some_else_none = "warn"
|
||||
# let_underscore_must_use = "warn"
|
||||
# map_err_ignore = "warn"
|
||||
# missing_docs_in_private_items = "warn"
|
||||
# negative_feature_names = "warn"
|
||||
# pub_without_shorthand = "warn"
|
||||
rc_buffer = "warn"
|
||||
rc_mutex = "warn"
|
||||
# redundant_feature_names = "warn"
|
||||
# redundant_type_annotations = "warn"
|
||||
# ref_patterns = "warn"
|
||||
# rest_pat_in_fully_bound_structs = "warn"
|
||||
# str_to_string = "warn"
|
||||
# string_add = "warn"
|
||||
# string_slice = "warn"
|
||||
# string_to_string = "warn"
|
||||
tests_outside_test_module = "warn"
|
||||
undocumented_unsafe_blocks = "warn"
|
||||
# unneeded_field_pattern = "warn"
|
||||
# unseparated_literal_suffix = "warn"
|
||||
# unwrap_used = "warn"
|
||||
# wildcard_dependencies = "warn"
|
|
@ -180,7 +180,7 @@ allow_check_for_updates = true
|
|||
trusted_servers = ["matrix.org"]
|
||||
|
||||
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
||||
#log = "warn,state_res=warn,rocket=off,_=off,sled=off"
|
||||
#log = "warn,state_res=warn,rocket=off,_=off"
|
||||
|
||||
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
||||
#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it.
|
||||
|
|
|
@ -40,3 +40,15 @@
|
|||
- Add non-standard sliding sync proxy health check (?) endpoint at `/client/server.json` that some clients such as Element Web query using the `well_known_client` or `well_known_server` config options
|
||||
- Send a User-Agent on all of our requests (`conduwuit/0.7.0-alpha+conduwuit-0.1.1`) which strangely was not done upstream since forever. Some providers consider no User-Agent suspicious and block said requests.
|
||||
- Safer and cleaner shutdowns on both database side as we run cleanup on shutdown and exits database loop better (no potential hanging issues in database loop), overall cleaner shutdown logic
|
||||
- Basic binary commands like `conduwuit --version` work (interested in expanding it more)
|
||||
- Allow HEAD HTTP requests in CORS for clients (despite not being explicity mentioned in Matrix spec, HTTP spec says all HEAD requests need to behave the same as GET requests, Synapse supports HEAD requests)
|
||||
- Bump MSRV to 1.74.1
|
||||
- Purge unmaintained/irrelevant/broken database backends (heed, sled, persy)
|
||||
- webp support for images
|
||||
- Support for suggesting servers to join at `/_matrix/client/v3/directory/room/{roomAlias}`
|
||||
- Prevent admin credential commands like reset password and deactivate user from modifying non-local users (https://gitlab.com/famedly/conduit/-/issues/377)
|
||||
- Fixed spec compliance issue with room version 8 - 11 joins (https://github.com/matrix-org/synapse/issues/16717 / https://github.com/matrix-org/matrix-spec/issues/1708)
|
||||
- Add basic cache eviction for true destinations when requests fail if we use a cached destination (e.g. a server has modified their well-known and we're still connecting to the old destination)
|
||||
- Only follow 6 redirects total in our default reqwest ClientBuilder
|
||||
- Generate passwords with 25 characters instead of 15
|
||||
- Add missing `reason` field to user ban events (`/ban`)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
FROM docker.io/rust:1.70-bullseye AS base
|
||||
FROM docker.io/rust:1.74.1-bullseye AS base
|
||||
|
||||
FROM base AS builder
|
||||
WORKDIR /usr/src/conduit
|
||||
|
|
|
@ -33,7 +33,7 @@ RUN echo "allow_federation = true" >> conduit.toml
|
|||
RUN echo "allow_check_for_updates = true" >> conduit.toml
|
||||
RUN echo "allow_encryption = true" >> conduit.toml
|
||||
RUN echo "allow_registration = true" >> conduit.toml
|
||||
RUN echo "log = \"warn,_=off,sled=off\"" >> conduit.toml
|
||||
RUN echo "log = \"warn,_=off\"" >> conduit.toml
|
||||
RUN sed -i "s/address = \"127.0.0.1\"/address = \"0.0.0.0\"/g" conduit.toml
|
||||
|
||||
COPY --from=builder /workdir/target/release/conduit /workdir/conduit
|
||||
|
|
|
@ -61,8 +61,8 @@ enable_lightning_bolt = true
|
|||
# servers.)
|
||||
trusted_servers = ["matrix.org"]
|
||||
|
||||
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
||||
#log = "warn,state_res=warn,rocket=off,_=off,sled=off"
|
||||
#max_concurrent_requests = 400 # How many requests Conduit sends to other servers at the same time
|
||||
#log = "warn,state_res=warn"
|
||||
|
||||
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
||||
#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it.
|
||||
|
|
4
debian/postinst
vendored
4
debian/postinst
vendored
|
@ -77,8 +77,8 @@ allow_check_for_updates = true
|
|||
|
||||
trusted_servers = ["matrix.org"]
|
||||
|
||||
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
||||
#log = "warn,state_res=warn,rocket=off,_=off,sled=off"
|
||||
#max_concurrent_requests = 400 # How many requests Conduit sends to other servers at the same time
|
||||
#log = "warn,state_res=warn"
|
||||
EOF
|
||||
fi
|
||||
;;
|
||||
|
|
|
@ -64,7 +64,7 @@ docker run -d -p 8448:6167 \
|
|||
-e CONDUIT_MAX_REQUEST_SIZE="20_000_000" \
|
||||
-e CONDUIT_TRUSTED_SERVERS="[\"matrix.org\"]" \
|
||||
-e CONDUIT_MAX_CONCURRENT_REQUESTS="100" \
|
||||
-e CONDUIT_LOG="warn,rocket=off,_=off,sled=off" \
|
||||
-e CONDUIT_LOG="warn,state_res=warn" \
|
||||
--name conduit <link>
|
||||
```
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ services:
|
|||
CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#CONDUIT_MAX_CONCURRENT_REQUESTS: 100
|
||||
#CONDUIT_LOG: warn,rocket=off,_=off,sled=off
|
||||
#CONDUIT_LOG: warn,state_res=warn
|
||||
CONDUIT_ADDRESS: 0.0.0.0
|
||||
CONDUIT_CONFIG: '' # Ignore this
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ services:
|
|||
# CONDUIT_PORT: 6167
|
||||
# CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string ''
|
||||
# Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging
|
||||
# CONDUIT_LOG: info # default is: "warn,_=off,sled=off"
|
||||
# CONDUIT_LOG: info # default is: "warn,state_res=warn"
|
||||
# CONDUIT_ALLOW_JAEGER: 'false'
|
||||
# CONDUIT_ALLOW_ENCRYPTION: 'true'
|
||||
# CONDUIT_ALLOW_FEDERATION: 'true'
|
||||
|
|
|
@ -31,8 +31,8 @@ services:
|
|||
CONDUIT_ALLOW_FEDERATION: 'true'
|
||||
CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#CONDUIT_MAX_CONCURRENT_REQUESTS: 100
|
||||
#CONDUIT_LOG: warn,rocket=off,_=off,sled=off
|
||||
#CONDUIT_MAX_CONCURRENT_REQUESTS: 400
|
||||
#CONDUIT_LOG: warn,state_res=warn
|
||||
CONDUIT_ADDRESS: 0.0.0.0
|
||||
CONDUIT_CONFIG: '' # Ignore this
|
||||
#
|
||||
|
|
24
flake.lock
generated
24
flake.lock
generated
|
@ -7,11 +7,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701622587,
|
||||
"narHash": "sha256-o3XhxCCyrUHZ0tlta2W7/MuXzy+n0+BUt3rKFK3DIK4=",
|
||||
"lastModified": 1704819371,
|
||||
"narHash": "sha256-oFUfPWrWGQTZaCM3byxwYwrMLwshDxVGOrMH5cVP/X8=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "c09d2cbe84cc2adfe1943cb2a0b55a71c835ca9a",
|
||||
"rev": "5c234301a1277e4cc759c23a2a7a00a06ddd7111",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -28,11 +28,11 @@
|
|||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701884128,
|
||||
"narHash": "sha256-8PiBdXnFkbDlV6NMWgqNcnlHJr87g9mvyZVRUy9uDqs=",
|
||||
"lastModified": 1705126891,
|
||||
"narHash": "sha256-RnCWzRghSpyxKs3kXgYPkZv6TvzV3Pmve1je6RQHe1o=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "3c94b1be4688e3ddc8897a26c60dcd67a69a1845",
|
||||
"rev": "89a02ff13d98d54f0b3b41f9b8326eb26d7cdc2e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -61,11 +61,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1701436327,
|
||||
"narHash": "sha256-tRHbnoNI8SIM5O5xuxOmtSLnswEByzmnQcGGyNRjxsE=",
|
||||
"lastModified": 1704722960,
|
||||
"narHash": "sha256-mKGJ3sPsT6//s+Knglai5YflJUF2DGj7Ai6Ynopz0kI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "91050ea1e57e50388fa87a3302ba12d188ef723a",
|
||||
"rev": "317484b1ead87b9c1b8ac5261a8d2dd748a0492d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -86,11 +86,11 @@
|
|||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1701792945,
|
||||
"narHash": "sha256-sDsGXchaAIqq/UsRcgQh/BtX6WzaIN8wa7FNhwhZ540=",
|
||||
"lastModified": 1704974004,
|
||||
"narHash": "sha256-H3RdtMxH8moTInVmracgtF8bgFpaEE3zYoSkuv7PBs0=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "05df6c52cac9f5ce37a543a0b81d3bd6a1ec9d6d",
|
||||
"rev": "9d8889cdfcc3aa0302353fc988ed21ff9bc9925c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
(final: prev: {
|
||||
rocksdb = prev.rocksdb.overrideAttrs (old:
|
||||
let
|
||||
version = "8.9.1";
|
||||
version = "8.10.0";
|
||||
in
|
||||
{
|
||||
inherit version;
|
||||
|
@ -38,7 +38,7 @@
|
|||
owner = "facebook";
|
||||
repo = "rocksdb";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-Pl7t4FVOvnORWFS+gjy2EEUQlPxjLukWW5I5gzCQwkI=";
|
||||
hash = "sha256-KGsYDBc1fz/90YYNGwlZ0LUKXYsP1zyhP29TnRQwgjQ=";
|
||||
};
|
||||
});
|
||||
})
|
||||
|
@ -59,7 +59,7 @@
|
|||
channel = cargoToml.package.rust-version;
|
||||
|
||||
# THE rust-version HASH
|
||||
sha256 = "sha256-gdYqng0y9iHYzYPAdkC/ka3DRny3La/S5G8ASj0Ayyc=";
|
||||
sha256 = "sha256-PjvuouwTsYfNKW5Vi5Ye7y+lL7SsWGBxCtBOOm2z14c=";
|
||||
};
|
||||
|
||||
mkToolchain = fenix.packages.${system}.combine;
|
||||
|
|
|
@ -205,7 +205,8 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
|
|||
|
||||
services()
|
||||
.users
|
||||
.set_displayname(&user_id, Some(displayname.clone()))?;
|
||||
.set_displayname(&user_id, Some(displayname.clone()))
|
||||
.await?;
|
||||
|
||||
// Initial account data
|
||||
services().account_data.update(
|
||||
|
|
|
@ -10,7 +10,7 @@ use ruma::{
|
|||
},
|
||||
federation,
|
||||
},
|
||||
OwnedRoomAliasId,
|
||||
OwnedRoomAliasId, OwnedServerName,
|
||||
};
|
||||
|
||||
/// # `PUT /_matrix/client/r0/directory/room/{roomAlias}`
|
||||
|
@ -66,11 +66,9 @@ pub async fn delete_alias_route(
|
|||
Ok(delete_alias::v3::Response::new())
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/r0/directory/room/{roomAlias}`
|
||||
/// # `GET /_matrix/client/v3/directory/room/{roomAlias}`
|
||||
///
|
||||
/// Resolve an alias locally or over federation.
|
||||
///
|
||||
/// - TODO: Suggest more servers to join via
|
||||
pub async fn get_alias_route(
|
||||
body: Ruma<get_alias::v3::Request>,
|
||||
) -> Result<get_alias::v3::Response> {
|
||||
|
@ -91,10 +89,37 @@ pub(crate) async fn get_alias_helper(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let room_id = response.room_id;
|
||||
|
||||
let mut servers = response.servers;
|
||||
|
||||
// find active servers in room state cache to suggest
|
||||
for extra_servers in services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_servers(&room_id)
|
||||
.filter_map(|r| r.ok())
|
||||
{
|
||||
servers.push(extra_servers);
|
||||
}
|
||||
|
||||
// insert our server as the very first choice if in list
|
||||
if let Some(server_index) = servers
|
||||
.clone()
|
||||
.into_iter()
|
||||
.position(|server| server == services().globals.server_name())
|
||||
{
|
||||
servers.remove(server_index);
|
||||
servers.insert(0, services().globals.server_name().to_owned());
|
||||
}
|
||||
|
||||
servers.sort_unstable();
|
||||
servers.dedup();
|
||||
|
||||
// shuffle list of servers randomly after sort and dedupe
|
||||
servers.shuffle(&mut rand::thread_rng());
|
||||
|
||||
return Ok(get_alias::v3::Response::new(response.room_id, servers));
|
||||
return Ok(get_alias::v3::Response::new(room_id, servers));
|
||||
}
|
||||
|
||||
let mut room_id = None;
|
||||
|
@ -152,8 +177,33 @@ pub(crate) async fn get_alias_helper(
|
|||
}
|
||||
};
|
||||
|
||||
Ok(get_alias::v3::Response::new(
|
||||
room_id,
|
||||
vec![services().globals.server_name().to_owned()],
|
||||
))
|
||||
let mut servers: Vec<OwnedServerName> = Vec::new();
|
||||
|
||||
// find active servers in room state cache to suggest
|
||||
for extra_servers in services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_servers(&room_id)
|
||||
.filter_map(|r| r.ok())
|
||||
{
|
||||
servers.push(extra_servers);
|
||||
}
|
||||
|
||||
// insert our server as the very first choice if in list
|
||||
if let Some(server_index) = servers
|
||||
.clone()
|
||||
.into_iter()
|
||||
.position(|server| server == services().globals.server_name())
|
||||
{
|
||||
servers.remove(server_index);
|
||||
servers.insert(0, services().globals.server_name().to_owned());
|
||||
}
|
||||
|
||||
servers.sort_unstable();
|
||||
servers.dedup();
|
||||
|
||||
// shuffle list of servers randomly after sort and dedupe
|
||||
servers.shuffle(&mut rand::thread_rng());
|
||||
|
||||
Ok(get_alias::v3::Response::new(room_id, servers))
|
||||
}
|
||||
|
|
|
@ -259,6 +259,7 @@ pub async fn ban_user_route(body: Ruma<ban_user::v3::Request>) -> Result<ban_use
|
|||
serde_json::from_str(event.content.get())
|
||||
.map(|event: RoomMemberEventContent| RoomMemberEventContent {
|
||||
membership: MembershipState::Ban,
|
||||
reason: event.reason,
|
||||
..event
|
||||
})
|
||||
.map_err(|_| Error::bad_database("Invalid member event in database."))
|
||||
|
@ -559,7 +560,7 @@ async fn join_room_by_id_helper(
|
|||
third_party_invite: None,
|
||||
blurhash: services().users.blurhash(sender_user)?,
|
||||
reason,
|
||||
join_authorized_via_users_server,
|
||||
join_authorized_via_users_server: join_authorized_via_users_server.clone(),
|
||||
})
|
||||
.expect("event is valid, we just created it"),
|
||||
);
|
||||
|
@ -594,7 +595,7 @@ async fn join_room_by_id_helper(
|
|||
// It has enough fields to be called a proper event now
|
||||
let mut join_event = join_event_stub;
|
||||
|
||||
info!("Asking {remote_server} for send_join");
|
||||
info!("Asking {remote_server} for send_join in room {room_id}");
|
||||
let send_join_response = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
|
@ -610,51 +611,77 @@ async fn join_room_by_id_helper(
|
|||
|
||||
info!("send_join finished");
|
||||
|
||||
if let Some(signed_raw) = &send_join_response.room_state.event {
|
||||
info!("There is a signed event. This room is probably using restricted joins. Adding signature to our event");
|
||||
let (signed_event_id, signed_value) =
|
||||
match gen_event_id_canonical_json(signed_raw, &room_version_id) {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
// Event could not be converted to canonical json
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Could not convert event to canonical json.",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if signed_event_id != event_id {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server sent event with wrong event id",
|
||||
));
|
||||
}
|
||||
|
||||
match signed_value["signatures"]
|
||||
.as_object()
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server sent invalid signatures type",
|
||||
))
|
||||
.and_then(|e| {
|
||||
e.get(remote_server.as_str()).ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server did not send its signature",
|
||||
))
|
||||
}) {
|
||||
Ok(signature) => {
|
||||
join_event
|
||||
.get_mut("signatures")
|
||||
.expect("we created a valid pdu")
|
||||
.as_object_mut()
|
||||
.expect("we created a valid pdu")
|
||||
.insert(remote_server.to_string(), signature.clone());
|
||||
if join_authorized_via_users_server.is_some() {
|
||||
match &room_version_id {
|
||||
RoomVersionId::V1
|
||||
| RoomVersionId::V2
|
||||
| RoomVersionId::V3
|
||||
| RoomVersionId::V4
|
||||
| RoomVersionId::V5
|
||||
| RoomVersionId::V6
|
||||
| RoomVersionId::V7 => {
|
||||
warn!("Found `join_authorised_via_users_server` but room {} is version {}. Ignoring.", room_id, &room_version_id);
|
||||
}
|
||||
Err(e) => {
|
||||
// only room versions 8 and above using `join_authorized_via_users_server` (restricted joins) need to validate and send signatures
|
||||
RoomVersionId::V8 | RoomVersionId::V9 | RoomVersionId::V10 | RoomVersionId::V11 => {
|
||||
if let Some(signed_raw) = &send_join_response.room_state.event {
|
||||
info!("There is a signed event. This room is probably using restricted joins. Adding signature to our event");
|
||||
let (signed_event_id, signed_value) =
|
||||
match gen_event_id_canonical_json(signed_raw, &room_version_id) {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
// Event could not be converted to canonical json
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Could not convert event to canonical json.",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if signed_event_id != event_id {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server sent event with wrong event id",
|
||||
));
|
||||
}
|
||||
|
||||
match signed_value["signatures"]
|
||||
.as_object()
|
||||
.ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server sent invalid signatures type",
|
||||
))
|
||||
.and_then(|e| {
|
||||
e.get(remote_server.as_str()).ok_or(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Server did not send its signature",
|
||||
))
|
||||
}) {
|
||||
Ok(signature) => {
|
||||
join_event
|
||||
.get_mut("signatures")
|
||||
.expect("we created a valid pdu")
|
||||
.as_object_mut()
|
||||
.expect("we created a valid pdu")
|
||||
.insert(remote_server.to_string(), signature.clone());
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Server {remote_server} sent invalid signature in sendjoin signatures for event {signed_value:?}: {e:?}",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!(
|
||||
"Server {remote_server} sent invalid signature in sendjoin signatures for event {signed_value:?}: {e:?}",
|
||||
);
|
||||
"Unexpected or unsupported room version {} for room {}",
|
||||
&room_version_id, room_id
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1426,7 +1453,7 @@ pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option<Strin
|
|||
.update_membership(
|
||||
room_id,
|
||||
user_id,
|
||||
MembershipState::Leave,
|
||||
RoomMemberEventContent::new(MembershipState::Leave),
|
||||
user_id,
|
||||
last_state,
|
||||
true,
|
||||
|
@ -1461,7 +1488,7 @@ pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option<Strin
|
|||
.update_membership(
|
||||
room_id,
|
||||
user_id,
|
||||
MembershipState::Leave,
|
||||
RoomMemberEventContent::new(MembershipState::Leave),
|
||||
user_id,
|
||||
None,
|
||||
true,
|
||||
|
|
|
@ -71,4 +71,4 @@ pub use voip::*;
|
|||
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||
pub const TOKEN_LENGTH: usize = 32;
|
||||
pub const SESSION_ID_LENGTH: usize = 32;
|
||||
pub const AUTO_GEN_PASSWORD_LENGTH: usize = 15;
|
||||
pub const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
|
||||
|
|
|
@ -27,7 +27,8 @@ pub async fn set_displayname_route(
|
|||
|
||||
services()
|
||||
.users
|
||||
.set_displayname(sender_user, body.displayname.clone())?;
|
||||
.set_displayname(sender_user, body.displayname.clone())
|
||||
.await?;
|
||||
|
||||
// Send a new membership event and presence update into all joined rooms
|
||||
let all_rooms_joined: Vec<_> = services()
|
||||
|
@ -103,15 +104,18 @@ pub async fn set_displayname_route(
|
|||
Ok(set_display_name::v3::Response {})
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/r0/profile/{userId}/displayname`
|
||||
/// # `GET /_matrix/client/v3/profile/{userId}/displayname`
|
||||
///
|
||||
/// Returns the displayname of the user.
|
||||
///
|
||||
/// - If user is on another server: Fetches displayname over federation
|
||||
/// - If user is on another server and we do not have a local copy already
|
||||
/// fetch displayname over federation
|
||||
pub async fn get_displayname_route(
|
||||
body: Ruma<get_display_name::v3::Request>,
|
||||
) -> Result<get_display_name::v3::Response> {
|
||||
if body.user_id.server_name() != services().globals.server_name() {
|
||||
if (services().users.exists(&body.user_id)?)
|
||||
&& (body.user_id.server_name() != services().globals.server_name())
|
||||
{
|
||||
let response = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
|
@ -123,6 +127,26 @@ pub async fn get_displayname_route(
|
|||
)
|
||||
.await?;
|
||||
|
||||
/*
|
||||
TODO: ignore errors properly?
|
||||
// Create and update our local copy of the user
|
||||
// these are `let _` because it's fine if we can't find these for the user.
|
||||
// also these requests are sent on room join so dead servers will make room joins annoying again
|
||||
let _ = services().users.create(&body.user_id, None);
|
||||
let _ = services()
|
||||
.users
|
||||
.set_displayname(&body.user_id, response.displayname.clone())
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_avatar_url(&body.user_id, response.avatar_url)
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_blurhash(&body.user_id, response.blurhash)
|
||||
.await;
|
||||
*/
|
||||
|
||||
return Ok(get_display_name::v3::Response {
|
||||
displayname: response.displayname,
|
||||
});
|
||||
|
@ -145,11 +169,13 @@ pub async fn set_avatar_url_route(
|
|||
|
||||
services()
|
||||
.users
|
||||
.set_avatar_url(sender_user, body.avatar_url.clone())?;
|
||||
.set_avatar_url(sender_user, body.avatar_url.clone())
|
||||
.await?;
|
||||
|
||||
services()
|
||||
.users
|
||||
.set_blurhash(sender_user, body.blurhash.clone())?;
|
||||
.set_blurhash(sender_user, body.blurhash.clone())
|
||||
.await?;
|
||||
|
||||
// Send a new membership event and presence update into all joined rooms
|
||||
let all_joined_rooms: Vec<_> = services()
|
||||
|
@ -225,15 +251,18 @@ pub async fn set_avatar_url_route(
|
|||
Ok(set_avatar_url::v3::Response {})
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/r0/profile/{userId}/avatar_url`
|
||||
/// # `GET /_matrix/client/v3/profile/{userId}/avatar_url`
|
||||
///
|
||||
/// Returns the avatar_url and blurhash of the user.
|
||||
///
|
||||
/// - If user is on another server: Fetches avatar_url and blurhash over federation
|
||||
/// - If user is on another server and we do not have a local copy already
|
||||
/// fetch avatar_url and blurhash over federation
|
||||
pub async fn get_avatar_url_route(
|
||||
body: Ruma<get_avatar_url::v3::Request>,
|
||||
) -> Result<get_avatar_url::v3::Response> {
|
||||
if body.user_id.server_name() != services().globals.server_name() {
|
||||
if (services().users.exists(&body.user_id)?)
|
||||
&& (body.user_id.server_name() != services().globals.server_name())
|
||||
{
|
||||
let response = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
|
@ -245,6 +274,26 @@ pub async fn get_avatar_url_route(
|
|||
)
|
||||
.await?;
|
||||
|
||||
/*
|
||||
TODO: ignore errors properly?
|
||||
// Create and update our local copy of the user
|
||||
// these are `let _` because it's fine if we can't find these for the user.
|
||||
// also these requests are sent on room join so dead servers will make room joins annoying again
|
||||
let _ = services().users.create(&body.user_id, None);
|
||||
let _ = services()
|
||||
.users
|
||||
.set_displayname(&body.user_id, response.displayname)
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_avatar_url(&body.user_id, response.avatar_url.clone())
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_blurhash(&body.user_id, response.blurhash.clone())
|
||||
.await;
|
||||
*/
|
||||
|
||||
return Ok(get_avatar_url::v3::Response {
|
||||
avatar_url: response.avatar_url,
|
||||
blurhash: response.blurhash,
|
||||
|
@ -257,15 +306,18 @@ pub async fn get_avatar_url_route(
|
|||
})
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/r0/profile/{userId}`
|
||||
/// # `GET /_matrix/client/v3/profile/{userId}`
|
||||
///
|
||||
/// Returns the displayname, avatar_url and blurhash of the user.
|
||||
///
|
||||
/// - If user is on another server: Fetches profile over federation
|
||||
/// - If user is on another server and we do not have a local copy already,
|
||||
/// fetch profile over federation.
|
||||
pub async fn get_profile_route(
|
||||
body: Ruma<get_profile::v3::Request>,
|
||||
) -> Result<get_profile::v3::Response> {
|
||||
if body.user_id.server_name() != services().globals.server_name() {
|
||||
if (services().users.exists(&body.user_id)?)
|
||||
&& (body.user_id.server_name() != services().globals.server_name())
|
||||
{
|
||||
let response = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
|
@ -277,6 +329,26 @@ pub async fn get_profile_route(
|
|||
)
|
||||
.await?;
|
||||
|
||||
/*
|
||||
TODO: ignore errors properly?
|
||||
// Create and update our local copy of the user
|
||||
// these are `let _` because it's fine if we can't find these for the user.
|
||||
// also these requests are sent on room join so dead servers will make room joins annoying again
|
||||
let _ = services().users.create(&body.user_id, None);
|
||||
let _ = services()
|
||||
.users
|
||||
.set_displayname(&body.user_id, response.displayname.clone())
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_avatar_url(&body.user_id, response.avatar_url.clone())
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_blurhash(&body.user_id, response.blurhash.clone())
|
||||
.await;
|
||||
*/
|
||||
|
||||
return Ok(get_profile::v3::Response {
|
||||
displayname: response.displayname,
|
||||
avatar_url: response.avatar_url,
|
||||
|
@ -285,7 +357,7 @@ pub async fn get_profile_route(
|
|||
}
|
||||
|
||||
if !services().users.exists(&body.user_id)? {
|
||||
// Return 404 if this user doesn't exist
|
||||
// Return 404 if this user doesn't exist and we couldn't fetch it over federation
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::NotFound,
|
||||
"Profile was not found.",
|
||||
|
|
|
@ -147,7 +147,13 @@ pub async fn create_room_route(
|
|||
);
|
||||
}
|
||||
RoomVersionId::V11 => {} // V11 removed the "creator" key
|
||||
_ => panic!("Unexpected room version {}", room_version),
|
||||
_ => {
|
||||
warn!("Unexpected or unsupported room version {}", room_version);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
content.insert(
|
||||
|
@ -172,7 +178,13 @@ pub async fn create_room_route(
|
|||
| RoomVersionId::V9
|
||||
| RoomVersionId::V10 => RoomCreateEventContent::new_v1(sender_user.clone()),
|
||||
RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
|
||||
_ => panic!("Unexpected room version {}", room_version),
|
||||
_ => {
|
||||
warn!("Unexpected or unsupported room version {}", room_version);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
};
|
||||
let mut content = serde_json::from_str::<CanonicalJsonObject>(
|
||||
to_raw_value(&content)
|
||||
|
@ -673,7 +685,16 @@ pub async fn upgrade_room_route(
|
|||
// "creator" key no longer exists in V11 rooms
|
||||
create_event_content.remove("creator");
|
||||
}
|
||||
_ => panic!("Unexpected room version {}", body.new_version),
|
||||
_ => {
|
||||
warn!(
|
||||
"Unexpected or unsupported room version {}",
|
||||
body.new_version
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
create_event_content.insert(
|
||||
|
|
|
@ -185,6 +185,9 @@ pub async fn logout_route(body: Ruma<logout::v3::Request>) -> Result<logout::v3:
|
|||
|
||||
services().users.remove_device(sender_user, sender_device)?;
|
||||
|
||||
// send device list update for user after logout
|
||||
services().users.mark_device_key_update(sender_user)?;
|
||||
|
||||
Ok(logout::v3::Response::new())
|
||||
}
|
||||
|
||||
|
@ -208,5 +211,8 @@ pub async fn logout_all_route(
|
|||
services().users.remove_device(sender_user, &device_id)?;
|
||||
}
|
||||
|
||||
// send device list update for user after logout
|
||||
services().users.mark_device_key_update(sender_user)?;
|
||||
|
||||
Ok(logout_all::v3::Response::new())
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ pub async fn get_supported_versions_route(
|
|||
unstable_features: BTreeMap::from_iter([
|
||||
("org.matrix.e2e_cross_signing".to_owned(), true),
|
||||
("org.matrix.msc2836".to_owned(), true),
|
||||
("org.matrix.msc3827".to_owned(), true),
|
||||
("org.matrix.msc2946".to_owned(), true),
|
||||
]),
|
||||
};
|
||||
|
|
|
@ -160,7 +160,7 @@ where
|
|||
.try_into_http_request::<Vec<u8>>(
|
||||
&actual_destination_str,
|
||||
SendAccessToken::IfRequired(""),
|
||||
&[MatrixVersion::V1_4],
|
||||
&[MatrixVersion::V1_5],
|
||||
)
|
||||
.map_err(|e| {
|
||||
warn!(
|
||||
|
@ -308,6 +308,18 @@ where
|
|||
})
|
||||
} else {
|
||||
debug!("Returning error from {destination}");
|
||||
|
||||
// remove potentially dead destinations from our cache that may be from modified well-knowns
|
||||
if !write_destination_to_cache {
|
||||
info!("Evicting {destination} from our true destination cache due to failed request.");
|
||||
services()
|
||||
.globals
|
||||
.actual_destination_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(destination);
|
||||
}
|
||||
|
||||
Err(Error::FederationError(
|
||||
destination.to_owned(),
|
||||
RumaError::from_http_response(http_response),
|
||||
|
@ -550,12 +562,14 @@ async fn request_well_known(destination: &str) -> Option<String> {
|
|||
.send()
|
||||
.await;
|
||||
debug!("Got well known response");
|
||||
debug!("Well known response: {:?}", response);
|
||||
if let Err(e) = &response {
|
||||
debug!("Well known error: {e:?}");
|
||||
return None;
|
||||
}
|
||||
let text = response.ok()?.text().await;
|
||||
debug!("Got well known response text");
|
||||
debug!("Well known response text: {:?}", text);
|
||||
let body: serde_json::Value = serde_json::from_str(&text.ok()?).ok()?;
|
||||
Some(body.get("m.server")?.as_str()?.to_owned())
|
||||
}
|
||||
|
@ -1883,7 +1897,7 @@ pub async fn create_invite_route(
|
|||
.update_membership(
|
||||
&body.room_id,
|
||||
&invited_user,
|
||||
MembershipState::Invite,
|
||||
RoomMemberEventContent::new(MembershipState::Invite),
|
||||
&sender,
|
||||
Some(invite_state),
|
||||
true,
|
||||
|
|
|
@ -381,7 +381,7 @@ fn default_presence_idle_timeout_s() -> u64 {
|
|||
}
|
||||
|
||||
fn default_presence_offline_timeout_s() -> u64 {
|
||||
15 * 60
|
||||
30 * 60
|
||||
}
|
||||
|
||||
fn default_rocksdb_log_level() -> String {
|
||||
|
|
|
@ -3,27 +3,13 @@ use crate::Result;
|
|||
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
|
||||
#[cfg(feature = "sled")]
|
||||
pub mod sled;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
pub mod sqlite;
|
||||
|
||||
#[cfg(feature = "heed")]
|
||||
pub mod heed;
|
||||
|
||||
#[cfg(feature = "rocksdb")]
|
||||
pub mod rocksdb;
|
||||
|
||||
#[cfg(feature = "persy")]
|
||||
pub mod persy;
|
||||
|
||||
#[cfg(any(
|
||||
feature = "sqlite",
|
||||
feature = "rocksdb",
|
||||
feature = "heed",
|
||||
feature = "persy"
|
||||
))]
|
||||
#[cfg(any(feature = "sqlite", feature = "rocksdb"))]
|
||||
pub mod watchers;
|
||||
|
||||
pub trait KeyValueDatabaseEngine: Send + Sync {
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
use super::{super::Config, watchers::Watchers};
|
||||
use crossbeam::channel::{bounded, Sender as ChannelSender};
|
||||
use threadpool::ThreadPool;
|
||||
|
||||
use crate::{Error, Result};
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use super::{DatabaseEngine, Tree};
|
||||
|
||||
type TupleOfBytes = (Vec<u8>, Vec<u8>);
|
||||
|
||||
pub struct Engine {
|
||||
env: heed::Env,
|
||||
iter_pool: Mutex<ThreadPool>,
|
||||
}
|
||||
|
||||
pub struct EngineTree {
|
||||
engine: Arc<Engine>,
|
||||
tree: Arc<heed::UntypedDatabase>,
|
||||
watchers: Watchers,
|
||||
}
|
||||
|
||||
fn convert_error(error: heed::Error) -> Error {
|
||||
Error::HeedError {
|
||||
error: error.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseEngine for Engine {
|
||||
fn open(config: &Config) -> Result<Arc<Self>> {
|
||||
let mut env_builder = heed::EnvOpenOptions::new();
|
||||
env_builder.map_size(1024 * 1024 * 1024 * 1024); // 1 Terabyte
|
||||
env_builder.max_readers(126);
|
||||
env_builder.max_dbs(128);
|
||||
unsafe {
|
||||
env_builder.flag(heed::flags::Flags::MdbWriteMap);
|
||||
env_builder.flag(heed::flags::Flags::MdbMapAsync);
|
||||
}
|
||||
|
||||
Ok(Arc::new(Engine {
|
||||
env: env_builder
|
||||
.open(&config.database_path)
|
||||
.map_err(convert_error)?,
|
||||
iter_pool: Mutex::new(ThreadPool::new(10)),
|
||||
}))
|
||||
}
|
||||
|
||||
fn open_tree(self: &Arc<Self>, name: &'static str) -> Result<Arc<dyn Tree>> {
|
||||
// Creates the db if it doesn't exist already
|
||||
Ok(Arc::new(EngineTree {
|
||||
engine: Arc::clone(self),
|
||||
tree: Arc::new(
|
||||
self.env
|
||||
.create_database(Some(name))
|
||||
.map_err(convert_error)?,
|
||||
),
|
||||
watchers: Default::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn flush(self: &Arc<Self>) -> Result<()> {
|
||||
self.env.force_sync().map_err(convert_error)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineTree {
|
||||
fn iter_from_thread(
|
||||
&self,
|
||||
tree: Arc<heed::UntypedDatabase>,
|
||||
from: Vec<u8>,
|
||||
backwards: bool,
|
||||
) -> Box<dyn Iterator<Item = TupleOfBytes> + Send + Sync> {
|
||||
let (s, r) = bounded::<TupleOfBytes>(100);
|
||||
let engine = Arc::clone(&self.engine);
|
||||
|
||||
let lock = self.engine.iter_pool.lock().await;
|
||||
if lock.active_count() < lock.max_count() {
|
||||
lock.execute(move || {
|
||||
iter_from_thread_work(tree, &engine.env.read_txn().unwrap(), from, backwards, &s);
|
||||
});
|
||||
} else {
|
||||
std::thread::spawn(move || {
|
||||
iter_from_thread_work(tree, &engine.env.read_txn().unwrap(), from, backwards, &s);
|
||||
});
|
||||
}
|
||||
|
||||
Box::new(r.into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_from_thread_work(
|
||||
tree: Arc<heed::UntypedDatabase>,
|
||||
txn: &heed::RoTxn<'_>,
|
||||
from: Vec<u8>,
|
||||
backwards: bool,
|
||||
s: &ChannelSender<(Vec<u8>, Vec<u8>)>,
|
||||
) {
|
||||
if backwards {
|
||||
for (k, v) in tree.rev_range(txn, ..=&*from).unwrap().map(|r| r.unwrap()) {
|
||||
if s.send((k.to_vec(), v.to_vec())).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if from.is_empty() {
|
||||
for (k, v) in tree.iter(txn).unwrap().map(|r| r.unwrap()) {
|
||||
if s.send((k.to_vec(), v.to_vec())).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (k, v) in tree.range(txn, &*from..).unwrap().map(|r| r.unwrap()) {
|
||||
if s.send((k.to_vec(), v.to_vec())).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tree for EngineTree {
|
||||
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
|
||||
let txn = self.engine.env.read_txn().map_err(convert_error)?;
|
||||
Ok(self
|
||||
.tree
|
||||
.get(&txn, &key)
|
||||
.map_err(convert_error)?
|
||||
.map(|s| s.to_vec()))
|
||||
}
|
||||
|
||||
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||
let mut txn = self.engine.env.write_txn().map_err(convert_error)?;
|
||||
self.tree
|
||||
.put(&mut txn, &key, &value)
|
||||
.map_err(convert_error)?;
|
||||
txn.commit().map_err(convert_error)?;
|
||||
self.watchers.wake(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove(&self, key: &[u8]) -> Result<()> {
|
||||
let mut txn = self.engine.env.write_txn().map_err(convert_error)?;
|
||||
self.tree.delete(&mut txn, &key).map_err(convert_error)?;
|
||||
txn.commit().map_err(convert_error)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + Send + 'a> {
|
||||
self.iter_from(&[], false)
|
||||
}
|
||||
|
||||
fn iter_from(
|
||||
&self,
|
||||
from: &[u8],
|
||||
backwards: bool,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + Send> {
|
||||
self.iter_from_thread(Arc::clone(&self.tree), from.to_vec(), backwards)
|
||||
}
|
||||
|
||||
fn increment(&self, key: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut txn = self.engine.env.write_txn().map_err(convert_error)?;
|
||||
|
||||
let old = self.tree.get(&txn, &key).map_err(convert_error)?;
|
||||
let new =
|
||||
crate::utils::increment(old.as_deref()).expect("utils::increment always returns Some");
|
||||
|
||||
self.tree
|
||||
.put(&mut txn, &key, &&*new)
|
||||
.map_err(convert_error)?;
|
||||
|
||||
txn.commit().map_err(convert_error)?;
|
||||
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn scan_prefix<'a>(
|
||||
&'a self,
|
||||
prefix: Vec<u8>,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + Send + 'a> {
|
||||
Box::new(
|
||||
self.iter_from(&prefix, false)
|
||||
.take_while(move |(key, _)| key.starts_with(&prefix)),
|
||||
)
|
||||
}
|
||||
|
||||
fn watch_prefix<'a>(&'a self, prefix: &[u8]) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
self.watchers.watch(prefix)
|
||||
}
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
use crate::{
|
||||
database::{
|
||||
abstraction::{watchers::Watchers, KeyValueDatabaseEngine, KvTree},
|
||||
Config,
|
||||
},
|
||||
Result,
|
||||
};
|
||||
use persy::{ByteVec, OpenOptions, Persy, Transaction, TransactionConfig, ValueMode};
|
||||
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
|
||||
use tracing::warn;
|
||||
|
||||
pub struct Engine {
|
||||
persy: Persy,
|
||||
}
|
||||
|
||||
impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||
fn open(config: &Config) -> Result<Self> {
|
||||
let mut cfg = persy::Config::new();
|
||||
cfg.change_cache_size((config.db_cache_capacity_mb * 1024.0 * 1024.0) as u64);
|
||||
|
||||
let persy = OpenOptions::new()
|
||||
.create(true)
|
||||
.config(cfg)
|
||||
.open(&format!("{}/db.persy", config.database_path))?;
|
||||
Ok(Arc::new(Engine { persy }))
|
||||
}
|
||||
|
||||
fn open_tree(&self, name: &'static str) -> Result<Arc<dyn KvTree>> {
|
||||
// Create if it doesn't exist
|
||||
if !self.persy.exists_index(name)? {
|
||||
let mut tx = self.persy.begin()?;
|
||||
tx.create_index::<ByteVec, ByteVec>(name, ValueMode::Replace)?;
|
||||
tx.prepare()?.commit()?;
|
||||
}
|
||||
|
||||
Ok(Arc::new(PersyTree {
|
||||
persy: self.persy.clone(),
|
||||
name: name.to_owned(),
|
||||
watchers: Watchers::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn flush(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PersyTree {
|
||||
persy: Persy,
|
||||
name: String,
|
||||
watchers: Watchers,
|
||||
}
|
||||
|
||||
impl PersyTree {
|
||||
fn begin(&self) -> Result<Transaction> {
|
||||
Ok(self
|
||||
.persy
|
||||
.begin_with(TransactionConfig::new().set_background_sync(true))?)
|
||||
}
|
||||
}
|
||||
|
||||
impl KvTree for PersyTree {
|
||||
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
|
||||
let result = self
|
||||
.persy
|
||||
.get::<ByteVec, ByteVec>(&self.name, &ByteVec::from(key))?
|
||||
.next()
|
||||
.map(|v| (*v).to_owned());
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||
self.insert_batch(&mut Some((key.to_owned(), value.to_owned())).into_iter())?;
|
||||
self.watchers.wake(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert_batch<'a>(&self, iter: &mut dyn Iterator<Item = (Vec<u8>, Vec<u8>)>) -> Result<()> {
|
||||
let mut tx = self.begin()?;
|
||||
for (key, value) in iter {
|
||||
tx.put::<ByteVec, ByteVec>(
|
||||
&self.name,
|
||||
ByteVec::from(key.clone()),
|
||||
ByteVec::from(value),
|
||||
)?;
|
||||
}
|
||||
tx.prepare()?.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn increment_batch<'a>(&self, iter: &mut dyn Iterator<Item = Vec<u8>>) -> Result<()> {
|
||||
let mut tx = self.begin()?;
|
||||
for key in iter {
|
||||
let old = tx
|
||||
.get::<ByteVec, ByteVec>(&self.name, &ByteVec::from(key.clone()))?
|
||||
.next()
|
||||
.map(|v| (*v).to_owned());
|
||||
let new = crate::utils::increment(old.as_deref()).unwrap();
|
||||
tx.put::<ByteVec, ByteVec>(&self.name, ByteVec::from(key), ByteVec::from(new))?;
|
||||
}
|
||||
tx.prepare()?.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove(&self, key: &[u8]) -> Result<()> {
|
||||
let mut tx = self.begin()?;
|
||||
tx.remove::<ByteVec, ByteVec>(&self.name, ByteVec::from(key), None)?;
|
||||
tx.prepare()?.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
|
||||
let iter = self.persy.range::<ByteVec, ByteVec, _>(&self.name, ..);
|
||||
match iter {
|
||||
Ok(iter) => Box::new(iter.filter_map(|(k, v)| {
|
||||
v.into_iter()
|
||||
.map(|val| ((*k).to_owned().into(), (*val).to_owned().into()))
|
||||
.next()
|
||||
})),
|
||||
Err(e) => {
|
||||
warn!("error iterating {:?}", e);
|
||||
Box::new(std::iter::empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_from<'a>(
|
||||
&'a self,
|
||||
from: &[u8],
|
||||
backwards: bool,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
|
||||
let range = if backwards {
|
||||
self.persy
|
||||
.range::<ByteVec, ByteVec, _>(&self.name, ..=ByteVec::from(from))
|
||||
} else {
|
||||
self.persy
|
||||
.range::<ByteVec, ByteVec, _>(&self.name, ByteVec::from(from)..)
|
||||
};
|
||||
match range {
|
||||
Ok(iter) => {
|
||||
let map = iter.filter_map(|(k, v)| {
|
||||
v.into_iter()
|
||||
.map(|val| ((*k).to_owned().into(), (*val).to_owned().into()))
|
||||
.next()
|
||||
});
|
||||
if backwards {
|
||||
Box::new(map.rev())
|
||||
} else {
|
||||
Box::new(map)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("error iterating with prefix {:?}", e);
|
||||
Box::new(std::iter::empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(&self, key: &[u8]) -> Result<Vec<u8>> {
|
||||
self.increment_batch(&mut Some(key.to_owned()).into_iter())?;
|
||||
Ok(self.get(key)?.unwrap())
|
||||
}
|
||||
|
||||
fn scan_prefix<'a>(
|
||||
&'a self,
|
||||
prefix: Vec<u8>,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
|
||||
let range_prefix = ByteVec::from(prefix.clone());
|
||||
let range = self
|
||||
.persy
|
||||
.range::<ByteVec, ByteVec, _>(&self.name, range_prefix..);
|
||||
|
||||
match range {
|
||||
Ok(iter) => {
|
||||
let owned_prefix = prefix.clone();
|
||||
Box::new(
|
||||
iter.take_while(move |(k, _)| (*k).starts_with(&owned_prefix))
|
||||
.filter_map(|(k, v)| {
|
||||
v.into_iter()
|
||||
.map(|val| ((*k).to_owned().into(), (*val).to_owned().into()))
|
||||
.next()
|
||||
}),
|
||||
)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("error scanning prefix {:?}", e);
|
||||
Box::new(std::iter::empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn watch_prefix<'a>(&'a self, prefix: &[u8]) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
self.watchers.watch(prefix)
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
use super::super::Config;
|
||||
use crate::{utils, Result};
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
use tracing::warn;
|
||||
|
||||
use super::{DatabaseEngine, Tree};
|
||||
|
||||
pub struct Engine(sled::Db);
|
||||
|
||||
pub struct SledEngineTree(sled::Tree);
|
||||
|
||||
impl DatabaseEngine for Engine {
|
||||
fn open(config: &Config) -> Result<Arc<Self>> {
|
||||
Ok(Arc::new(Engine(
|
||||
sled::Config::default()
|
||||
.path(&config.database_path)
|
||||
.cache_capacity((config.db_cache_capacity_mb * 1024.0 * 1024.0) as u64)
|
||||
.use_compression(true)
|
||||
.open()?,
|
||||
)))
|
||||
}
|
||||
|
||||
fn open_tree(self: &Arc<Self>, name: &'static str) -> Result<Arc<dyn Tree>> {
|
||||
Ok(Arc::new(SledEngineTree(self.0.open_tree(name)?)))
|
||||
}
|
||||
|
||||
fn flush(self: &Arc<Self>) -> Result<()> {
|
||||
Ok(()) // noop
|
||||
}
|
||||
}
|
||||
|
||||
impl Tree for SledEngineTree {
|
||||
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
|
||||
Ok(self.0.get(key)?.map(|v| v.to_vec()))
|
||||
}
|
||||
|
||||
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()> {
|
||||
self.0.insert(key, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert_batch<'a>(&self, iter: &mut dyn Iterator<Item = (Vec<u8>, Vec<u8>)>) -> Result<()> {
|
||||
for (key, value) in iter {
|
||||
self.0.insert(key, value)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove(&self, key: &[u8]) -> Result<()> {
|
||||
self.0.remove(key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
|
||||
Box::new(
|
||||
self.0
|
||||
.iter()
|
||||
.filter_map(|r| {
|
||||
if let Err(e) = &r {
|
||||
warn!("Error: {}", e);
|
||||
}
|
||||
r.ok()
|
||||
})
|
||||
.map(|(k, v)| (k.to_vec().into(), v.to_vec().into())),
|
||||
)
|
||||
}
|
||||
|
||||
fn iter_from(
|
||||
&self,
|
||||
from: &[u8],
|
||||
backwards: bool,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)>> {
|
||||
let iter = if backwards {
|
||||
self.0.range(..=from)
|
||||
} else {
|
||||
self.0.range(from..)
|
||||
};
|
||||
|
||||
let iter = iter
|
||||
.filter_map(|r| {
|
||||
if let Err(e) = &r {
|
||||
warn!("Error: {}", e);
|
||||
}
|
||||
r.ok()
|
||||
})
|
||||
.map(|(k, v)| (k.to_vec().into(), v.to_vec().into()));
|
||||
|
||||
if backwards {
|
||||
Box::new(iter.rev())
|
||||
} else {
|
||||
Box::new(iter)
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(&self, key: &[u8]) -> Result<Vec<u8>> {
|
||||
Ok(self
|
||||
.0
|
||||
.update_and_fetch(key, utils::increment)
|
||||
.map(|o| o.expect("increment always sets a value").to_vec())?)
|
||||
}
|
||||
|
||||
fn scan_prefix<'a>(
|
||||
&'a self,
|
||||
prefix: Vec<u8>,
|
||||
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
|
||||
let iter = self
|
||||
.0
|
||||
.scan_prefix(prefix)
|
||||
.filter_map(|r| {
|
||||
if let Err(e) = &r {
|
||||
warn!("Error: {}", e);
|
||||
}
|
||||
r.ok()
|
||||
})
|
||||
.map(|(k, v)| (k.to_vec().into(), v.to_vec().into()));
|
||||
|
||||
Box::new(iter)
|
||||
}
|
||||
|
||||
fn watch_prefix<'a>(&'a self, prefix: &[u8]) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
let prefix = prefix.to_vec();
|
||||
Box::pin(async move {
|
||||
self.0.watch_prefix(prefix).await;
|
||||
})
|
||||
}
|
||||
}
|
|
@ -192,16 +192,11 @@ impl KeyValueDatabase {
|
|||
fn check_db_setup(config: &Config) -> Result<()> {
|
||||
let path = Path::new(&config.database_path);
|
||||
|
||||
let sled_exists = path.join("db").exists();
|
||||
let sqlite_exists = path.join("conduit.db").exists();
|
||||
let rocksdb_exists = path.join("IDENTITY").exists();
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
if sled_exists {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if sqlite_exists {
|
||||
count += 1;
|
||||
}
|
||||
|
@ -215,12 +210,6 @@ impl KeyValueDatabase {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
if sled_exists && config.database_backend != "sled" {
|
||||
return Err(Error::bad_config(
|
||||
"Found sled at database_path, but is not specified in config.",
|
||||
));
|
||||
}
|
||||
|
||||
if sqlite_exists && config.database_backend != "sqlite" {
|
||||
return Err(Error::bad_config(
|
||||
"Found sqlite at database_path, but is not specified in config.",
|
||||
|
@ -260,14 +249,8 @@ impl KeyValueDatabase {
|
|||
#[cfg(feature = "rocksdb")]
|
||||
Arc::new(Arc::<abstraction::rocksdb::Engine>::open(&config)?)
|
||||
}
|
||||
"persy" => {
|
||||
#[cfg(not(feature = "persy"))]
|
||||
return Err(Error::BadConfig("Database backend not found."));
|
||||
#[cfg(feature = "persy")]
|
||||
Arc::new(Arc::<abstraction::persy::Engine>::open(&config)?)
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::BadConfig("Database backend not found."));
|
||||
return Err(Error::BadConfig("Database backend not found. sqlite (not recommended) and rocksdb are the only supported backends."));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
#![warn(
|
||||
rust_2018_idioms,
|
||||
unused_qualifications,
|
||||
clippy::cloned_instead_of_copied,
|
||||
clippy::str_to_string
|
||||
)]
|
||||
#![deny(clippy::dbg_macro)]
|
||||
|
||||
pub mod api;
|
||||
mod config;
|
||||
mod database;
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -1,12 +1,3 @@
|
|||
#![warn(
|
||||
rust_2018_idioms,
|
||||
unused_qualifications,
|
||||
clippy::cloned_instead_of_copied,
|
||||
clippy::str_to_string,
|
||||
clippy::future_not_send
|
||||
)]
|
||||
#![deny(clippy::dbg_macro)]
|
||||
|
||||
use std::{
|
||||
fs::Permissions, future::Future, io, net::SocketAddr, os::unix::fs::PermissionsExt,
|
||||
sync::atomic, time::Duration,
|
||||
|
@ -211,6 +202,7 @@ async fn run_server() -> io::Result<()> {
|
|||
.allow_origin(cors::Any)
|
||||
.allow_methods([
|
||||
Method::GET,
|
||||
Method::HEAD,
|
||||
Method::POST,
|
||||
Method::PUT,
|
||||
Method::DELETE,
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::fmt::Write;
|
|||
use clap::{Parser, Subcommand};
|
||||
use regex::Regex;
|
||||
use ruma::{
|
||||
api::client::error::ErrorKind,
|
||||
events::{
|
||||
relation::InReplyTo,
|
||||
room::{
|
||||
|
@ -30,6 +31,7 @@ use ruma::{
|
|||
};
|
||||
use serde_json::value::to_raw_value;
|
||||
use tokio::sync::{mpsc, Mutex};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
api::client_server::{leave_all_rooms, AUTO_GEN_PASSWORD_LENGTH},
|
||||
|
@ -598,7 +600,8 @@ impl Service {
|
|||
|
||||
services()
|
||||
.users
|
||||
.set_displayname(&user_id, Some(displayname))?;
|
||||
.set_displayname(&user_id, Some(displayname))
|
||||
.await?;
|
||||
|
||||
// Initial account data
|
||||
services().account_data.update(
|
||||
|
@ -619,7 +622,7 @@ impl Service {
|
|||
|
||||
// Inhibit login does not work for guests
|
||||
RoomMessageEventContent::text_plain(format!(
|
||||
"Created user with user_id: {user_id} and password: {password}"
|
||||
"Created user with user_id: {user_id} and password: `{password}`"
|
||||
))
|
||||
}
|
||||
UserCommand::Deactivate {
|
||||
|
@ -627,6 +630,14 @@ impl Service {
|
|||
user_id,
|
||||
} => {
|
||||
let user_id = Arc::<UserId>::from(user_id);
|
||||
|
||||
// check if user belongs to our server
|
||||
if user_id.server_name() != services().globals.server_name() {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"User {user_id} does not belong to our server."
|
||||
)));
|
||||
}
|
||||
|
||||
if services().users.exists(&user_id)? {
|
||||
RoomMessageEventContent::text_plain(format!(
|
||||
"Making {user_id} leave all rooms before deactivation..."
|
||||
|
@ -660,6 +671,13 @@ impl Service {
|
|||
}
|
||||
};
|
||||
|
||||
// check if user belongs to our server
|
||||
if user_id.server_name() != services().globals.server_name() {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"User {user_id} does not belong to our server."
|
||||
)));
|
||||
}
|
||||
|
||||
// Check if the specified user is valid
|
||||
if !services().users.exists(&user_id)?
|
||||
|| user_id
|
||||
|
@ -681,7 +699,7 @@ impl Service {
|
|||
.set_password(&user_id, Some(new_password.as_str()))
|
||||
{
|
||||
Ok(()) => RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully reset the password for user {user_id}: {new_password}"
|
||||
"Successfully reset the password for user {user_id}: `{new_password}`"
|
||||
)),
|
||||
Err(e) => RoomMessageEventContent::text_plain(format!(
|
||||
"Couldn't reset the password for user {user_id}: {e}"
|
||||
|
@ -725,6 +743,11 @@ impl Service {
|
|||
}
|
||||
|
||||
for &user_id in &user_ids {
|
||||
// check if user belongs to our server and skips over non-local users
|
||||
if user_id.server_name() != services().globals.server_name() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if services().users.deactivate_account(user_id).is_ok() {
|
||||
deactivation_count += 1
|
||||
}
|
||||
|
@ -1400,7 +1423,13 @@ impl Service {
|
|||
| RoomVersionId::V9
|
||||
| RoomVersionId::V10 => RoomCreateEventContent::new_v1(conduit_user.clone()),
|
||||
RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
|
||||
_ => panic!("Unexpected room version {}", room_version),
|
||||
_ => {
|
||||
warn!("Unexpected or unsupported room version {}", room_version);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
content.federate = true;
|
||||
|
|
|
@ -539,10 +539,19 @@ impl Service<'_> {
|
|||
}
|
||||
|
||||
fn reqwest_client_builder(config: &Config) -> Result<reqwest::ClientBuilder> {
|
||||
let redirect_policy = reqwest::redirect::Policy::custom(|attempt| {
|
||||
if attempt.previous().len() > 6 {
|
||||
attempt.error("Too many redirects (max is 6)")
|
||||
} else {
|
||||
attempt.follow()
|
||||
}
|
||||
});
|
||||
|
||||
let mut reqwest_client_builder = reqwest::Client::builder()
|
||||
.pool_max_idle_per_host(0)
|
||||
.connect_timeout(Duration::from_secs(60))
|
||||
.timeout(Duration::from_secs(60 * 5))
|
||||
.redirect(redirect_policy)
|
||||
.user_agent(concat!(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
"/",
|
||||
|
|
|
@ -8,14 +8,13 @@ pub use data::Data;
|
|||
use ruma::{
|
||||
api::client::error::ErrorKind,
|
||||
events::{
|
||||
room::{create::RoomCreateEventContent, member::MembershipState},
|
||||
room::{create::RoomCreateEventContent, member::RoomMemberEventContent},
|
||||
AnyStrippedStateEvent, StateEventType, TimelineEventType,
|
||||
},
|
||||
serde::Raw,
|
||||
state_res::{self, StateMap},
|
||||
EventId, OwnedEventId, RoomId, RoomVersionId, UserId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::MutexGuard;
|
||||
use tracing::warn;
|
||||
|
||||
|
@ -59,14 +58,9 @@ impl Service {
|
|||
|
||||
match pdu.kind {
|
||||
TimelineEventType::RoomMember => {
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractMembership {
|
||||
membership: MembershipState,
|
||||
}
|
||||
|
||||
let membership =
|
||||
match serde_json::from_str::<ExtractMembership>(pdu.content.get()) {
|
||||
Ok(e) => e.membership,
|
||||
let membership_event =
|
||||
match serde_json::from_str::<RoomMemberEventContent>(pdu.content.get()) {
|
||||
Ok(e) => e,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
|
@ -83,7 +77,14 @@ impl Service {
|
|||
services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.update_membership(room_id, &user_id, membership, &pdu.sender, None, false)
|
||||
.update_membership(
|
||||
room_id,
|
||||
&user_id,
|
||||
membership_event,
|
||||
&pdu.sender,
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
TimelineEventType::SpaceChild => {
|
||||
|
|
|
@ -7,7 +7,10 @@ use ruma::{
|
|||
events::{
|
||||
direct::DirectEvent,
|
||||
ignored_user_list::IgnoredUserListEvent,
|
||||
room::{create::RoomCreateEventContent, member::MembershipState},
|
||||
room::{
|
||||
create::RoomCreateEventContent,
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
},
|
||||
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
|
||||
RoomAccountDataEventType, StateEventType,
|
||||
},
|
||||
|
@ -29,15 +32,47 @@ impl Service {
|
|||
&self,
|
||||
room_id: &RoomId,
|
||||
user_id: &UserId,
|
||||
membership: MembershipState,
|
||||
membership_event: RoomMemberEventContent,
|
||||
sender: &UserId,
|
||||
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
update_joined_count: bool,
|
||||
) -> Result<()> {
|
||||
let membership = membership_event.membership;
|
||||
// Keep track what remote users exist by adding them as "deactivated" users
|
||||
if user_id.server_name() != services().globals.server_name() {
|
||||
services().users.create(user_id, None)?;
|
||||
// TODO: displayname, avatar url
|
||||
/*
|
||||
// Try to update our local copy of the user if ours does not match
|
||||
// TODO: ignore errors properly?
|
||||
if ((services().users.displayname(user_id)? != membership_event.displayname)
|
||||
|| (services().users.avatar_url(user_id)? != membership_event.avatar_url)
|
||||
|| (services().users.blurhash(user_id)? != membership_event.blurhash))
|
||||
&& (membership != MembershipState::Leave)
|
||||
{
|
||||
let response = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
user_id.server_name(),
|
||||
federation::query::get_profile_information::v1::Request {
|
||||
user_id: user_id.into(),
|
||||
field: Some(ProfileField::AvatarUrl),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_displayname(user_id, response.displayname.clone())
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_avatar_url(user_id, response.avatar_url)
|
||||
.await;
|
||||
let _ = services()
|
||||
.users
|
||||
.set_blurhash(user_id, response.blurhash)
|
||||
.await;
|
||||
};
|
||||
*/
|
||||
}
|
||||
|
||||
match &membership {
|
||||
|
|
|
@ -18,7 +18,9 @@ use ruma::{
|
|||
events::{
|
||||
push_rules::PushRulesEvent,
|
||||
room::{
|
||||
create::RoomCreateEventContent, encrypted::Relation, member::MembershipState,
|
||||
create::RoomCreateEventContent,
|
||||
encrypted::Relation,
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
power_levels::RoomPowerLevelsEventContent,
|
||||
},
|
||||
GlobalAccountDataEventType, StateEventType, TimelineEventType,
|
||||
|
@ -437,7 +439,13 @@ impl Service {
|
|||
self.redact_pdu(redact_id, pdu)?;
|
||||
}
|
||||
}
|
||||
_ => panic!("Unexpected room version {}", room_version_id),
|
||||
_ => {
|
||||
warn!("Unexpected or unsupported room version {}", room_version_id);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Unexpected or unsupported room version found",
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
TimelineEventType::SpaceChild => {
|
||||
|
@ -453,17 +461,15 @@ impl Service {
|
|||
}
|
||||
TimelineEventType::RoomMember => {
|
||||
if let Some(state_key) = &pdu.state_key {
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractMembership {
|
||||
membership: MembershipState,
|
||||
}
|
||||
|
||||
// if the state_key fails
|
||||
let target_user_id = UserId::parse(state_key.clone())
|
||||
.expect("This state_key was previously validated");
|
||||
|
||||
let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
let content = serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
|
||||
.map_err(|e| {
|
||||
error!("Invalid room member event content in pdu: {e}");
|
||||
Error::bad_database("Invalid room member event content in pdu.")
|
||||
})?;
|
||||
|
||||
let invite_state = match content.membership {
|
||||
MembershipState::Invite => {
|
||||
|
@ -481,7 +487,7 @@ impl Service {
|
|||
.update_membership(
|
||||
&pdu.room_id,
|
||||
&target_user_id,
|
||||
content.membership,
|
||||
content,
|
||||
&pdu.sender,
|
||||
invite_state,
|
||||
true,
|
||||
|
|
|
@ -314,7 +314,11 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Sets a new displayname or removes it if displayname is None. You still need to nofify all rooms of this change.
|
||||
pub fn set_displayname(&self, user_id: &UserId, displayname: Option<String>) -> Result<()> {
|
||||
pub async fn set_displayname(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
displayname: Option<String>,
|
||||
) -> Result<()> {
|
||||
self.db.set_displayname(user_id, displayname)
|
||||
}
|
||||
|
||||
|
@ -324,7 +328,11 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Sets a new avatar_url or removes it if avatar_url is None.
|
||||
pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<OwnedMxcUri>) -> Result<()> {
|
||||
pub async fn set_avatar_url(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
avatar_url: Option<OwnedMxcUri>,
|
||||
) -> Result<()> {
|
||||
self.db.set_avatar_url(user_id, avatar_url)
|
||||
}
|
||||
|
||||
|
@ -334,7 +342,7 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Sets a new avatar_url or removes it if avatar_url is None.
|
||||
pub fn set_blurhash(&self, user_id: &UserId, blurhash: Option<String>) -> Result<()> {
|
||||
pub async fn set_blurhash(&self, user_id: &UserId, blurhash: Option<String>) -> Result<()> {
|
||||
self.db.set_blurhash(user_id, blurhash)
|
||||
}
|
||||
|
||||
|
|
|
@ -11,33 +11,18 @@ use ruma::{
|
|||
use thiserror::Error;
|
||||
use tracing::{error, info};
|
||||
|
||||
#[cfg(feature = "persy")]
|
||||
use persy::PersyError;
|
||||
|
||||
use crate::RumaResponse;
|
||||
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[cfg(feature = "sled")]
|
||||
#[error("There was a problem with the connection to the sled database.")]
|
||||
SledError {
|
||||
#[from]
|
||||
source: sled::Error,
|
||||
},
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[error("There was a problem with the connection to the sqlite database: {source}")]
|
||||
SqliteError {
|
||||
#[from]
|
||||
source: rusqlite::Error,
|
||||
},
|
||||
#[cfg(feature = "persy")]
|
||||
#[error("There was a problem with the connection to the persy database.")]
|
||||
PersyError { source: PersyError },
|
||||
#[cfg(feature = "heed")]
|
||||
#[error("There was a problem with the connection to the heed database: {error}")]
|
||||
HeedError { error: String },
|
||||
#[cfg(feature = "rocksdb")]
|
||||
#[error("There was a problem with the connection to the rocksdb database: {source}")]
|
||||
RocksDbError {
|
||||
|
@ -150,14 +135,8 @@ impl Error {
|
|||
let db_error = String::from("Database or I/O error occurred.");
|
||||
|
||||
match self {
|
||||
#[cfg(feature = "sled")]
|
||||
Self::SledError { .. } => db_error,
|
||||
#[cfg(feature = "sqlite")]
|
||||
Self::SqliteError { .. } => db_error,
|
||||
#[cfg(feature = "persy")]
|
||||
Self::PersyError { .. } => db_error,
|
||||
#[cfg(feature = "heed")]
|
||||
Self::HeedError => db_error,
|
||||
#[cfg(feature = "rocksdb")]
|
||||
Self::RocksDbError { .. } => db_error,
|
||||
Self::IoError { .. } => db_error,
|
||||
|
@ -168,15 +147,6 @@ impl Error {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "persy")]
|
||||
impl<T: Into<PersyError>> From<persy::PE<T>> for Error {
|
||||
fn from(err: persy::PE<T>) -> Self {
|
||||
Error::PersyError {
|
||||
source: err.error().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Infallible> for Error {
|
||||
fn from(i: Infallible) -> Self {
|
||||
match i {}
|
||||
|
|
Reference in a new issue