mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a8c409ff9 |
@@ -30,22 +30,22 @@ jobs:
|
|||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "distribution=$DISTRIBUTION" >> $GITHUB_OUTPUT
|
echo "distribution=$DISTRIBUTION" >> $GITHUB_OUTPUT
|
||||||
echo "Debian distribution: $DISTRIBUTION ($VERSION)"
|
echo "Debian distribution: $DISTRIBUTION ($VERSION)"
|
||||||
#- name: Work around llvm-project#153385
|
- name: Work around llvm-project#153385
|
||||||
# id: llvm-workaround
|
id: llvm-workaround
|
||||||
# run: |
|
run: |
|
||||||
# if [ -f /usr/share/apt/default-sequoia.config ]; then
|
if [ -f /usr/share/apt/default-sequoia.config ]; then
|
||||||
# echo "Applying workaround for llvm-project#153385"
|
echo "Applying workaround for llvm-project#153385"
|
||||||
# mkdir -p /etc/crypto-policies/back-ends/
|
mkdir -p /etc/crypto-policies/back-ends/
|
||||||
# cp /usr/share/apt/default-sequoia.config /etc/crypto-policies/back-ends/apt-sequoia.config
|
cp /usr/share/apt/default-sequoia.config /etc/crypto-policies/back-ends/apt-sequoia.config
|
||||||
# sed -i 's/\(sha1\.second_preimage_resistance = \)2026-02-01/\12026-06-01/' /etc/crypto-policies/back-ends/apt-sequoia.config
|
sed -i 's/\(sha1\.second_preimage_resistance = \)2026-02-01/\12026-06-01/' /etc/crypto-policies/back-ends/apt-sequoia.config
|
||||||
# else
|
else
|
||||||
# echo "No workaround needed for llvm-project#153385"
|
echo "No workaround needed for llvm-project#153385"
|
||||||
# fi
|
fi
|
||||||
- name: Pick compatible clang version
|
- name: Pick compatible clang version
|
||||||
id: clang-version
|
id: clang-version
|
||||||
run: |
|
run: |
|
||||||
# both latest need to use clang-23, but oldstable and previous can just use clang
|
# both latest need to use clang-23, but oldstable and previous can just use clang
|
||||||
if [[ "${{ matrix.container }}" == "ubuntu-latest" ]]; then
|
if [[ "${{ matrix.container }}" == "ubuntu-latest" || "${{ matrix.container }}" == "debian-latest" ]]; then
|
||||||
echo "Using clang-23 package for ${{ matrix.container }}"
|
echo "Using clang-23 package for ${{ matrix.container }}"
|
||||||
echo "version=clang-23" >> $GITHUB_OUTPUT
|
echo "version=clang-23" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
|
|||||||
+2
-14
@@ -1,6 +1,5 @@
|
|||||||
default_install_hook_types:
|
default_install_hook_types:
|
||||||
- pre-commit
|
- pre-commit
|
||||||
- pre-push
|
|
||||||
- commit-msg
|
- commit-msg
|
||||||
default_stages:
|
default_stages:
|
||||||
- pre-commit
|
- pre-commit
|
||||||
@@ -24,7 +23,7 @@ repos:
|
|||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
|
|
||||||
- repo: https://github.com/crate-ci/typos
|
- repo: https://github.com/crate-ci/typos
|
||||||
rev: v1.44.0
|
rev: v1.43.5
|
||||||
hooks:
|
hooks:
|
||||||
- id: typos
|
- id: typos
|
||||||
- id: typos
|
- id: typos
|
||||||
@@ -32,7 +31,7 @@ repos:
|
|||||||
stages: [commit-msg]
|
stages: [commit-msg]
|
||||||
|
|
||||||
- repo: https://github.com/crate-ci/committed
|
- repo: https://github.com/crate-ci/committed
|
||||||
rev: v1.1.11
|
rev: v1.1.10
|
||||||
hooks:
|
hooks:
|
||||||
- id: committed
|
- id: committed
|
||||||
|
|
||||||
@@ -46,14 +45,3 @@ repos:
|
|||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
stages:
|
stages:
|
||||||
- pre-commit
|
- pre-commit
|
||||||
|
|
||||||
- repo: local
|
|
||||||
hooks:
|
|
||||||
- id: cargo-clippy
|
|
||||||
name: cargo clippy
|
|
||||||
entry: cargo clippy -- -D warnings
|
|
||||||
language: system
|
|
||||||
pass_filenames: false
|
|
||||||
types: [rust]
|
|
||||||
stages:
|
|
||||||
- pre-push
|
|
||||||
|
|||||||
@@ -1,32 +1,3 @@
|
|||||||
# Continuwuity 0.5.6 (2026-03-03)
|
|
||||||
|
|
||||||
## Security
|
|
||||||
|
|
||||||
- Admin escape commands received over federation will never be executed, as this is never valid in a genuine situation. Contributed by @Jade.
|
|
||||||
- Fixed data amplification vulnerability (CWE-409) that affected configurations with server-side compression enabled (non-default). Contributed by @nex.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Outgoing presence is now disabled by default, and the config option documentation has been adjusted to more accurately represent the weight of presence, typing indicators, and read receipts. Contributed by @nex. ([#1399](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1399))
|
|
||||||
- Improved the concurrency handling of federation transactions, vastly improving performance and reliability by more accurately handling inbound transactions and reducing the amount of repeated wasted work. Contributed by @nex and @Jade. ([#1428](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1428))
|
|
||||||
- Added [MSC3202](https://github.com/matrix-org/matrix-spec-proposals/pull/3202) Device masquerading (not all of MSC3202). This should fix issues with enabling [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190) for some Mautrix bridges. Contributed by @Jade ([#1435](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1435))
|
|
||||||
- Added [MSC3814](https://github.com/matrix-org/matrix-spec-proposals/pull/3814) Dehydrated Devices - you can now decrypt messages sent while all devices were logged out. ([#1436](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1436))
|
|
||||||
- Implement [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) MatrixRTC transport discovery endpoint. Move RTC foci configuration from `[global.well_known]` to a new `[global.matrix_rtc]` section with a `foci` field. Contributed by @0xnim ([#1442](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1442))
|
|
||||||
- Updated `list-backups` admin command to output one backup per line. ([#1394](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1394))
|
|
||||||
- Improved URL preview fetching with a more compatible user agent for sites like YouTube Music. Added `!admin media delete-url-preview <url>` command to clear cached URL previews that were stuck and broken. ([#1434](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1434))
|
|
||||||
|
|
||||||
## Bugfixes
|
|
||||||
|
|
||||||
- Removed non-compliant nor functional room alias lookups over federation. Contributed by @nex ([#1393](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1393))
|
|
||||||
- Removed ability to set rocksdb as read only. Doing so would cause unintentional and buggy behaviour. Contributed by @Terryiscool160. ([#1418](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1418))
|
|
||||||
- Fixed a startup crash in the sender service if we can't detect the number of CPU cores, even if the `sender_workers` config option is set correctly. Contributed by @katie. ([#1421](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1421))
|
|
||||||
- Removed the `allow_public_room_directory_without_auth` config option. Contributed by @0xnim. ([#1441](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1441))
|
|
||||||
- Fixed sliding sync v5 list ranges always starting from 0, causing extra rooms to be unnecessarily processed and returned. Contributed by @0xnim ([#1445](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1445))
|
|
||||||
- Fixed a bug that (repairably) caused a room split between continuwuity and non-continuwuity servers when the room had both `m.room.policy` and `org.matrix.msc4284.policy` in its room state. Contributed by @nex ([#1481](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1481))
|
|
||||||
- Fixed `!admin media delete --mxc <url>` responding with an error message when the media was deleted successfully. Contributed by @lynxize
|
|
||||||
- Fixed spurious 404 media errors in the logs. Contributed by @benbot.
|
|
||||||
- Fixed spurious warn about needed backfill via federation for non-federated rooms. Contributed by @kraem.
|
|
||||||
|
|
||||||
# Continuwuity v0.5.5 (2026-02-15)
|
# Continuwuity v0.5.5 (2026-02-15)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|||||||
Generated
+53
-45
@@ -445,14 +445,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-extra"
|
name = "axum-extra"
|
||||||
version = "0.12.5"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fef252edff26ddba56bbcdf2ee3307b8129acb86f5749b68990c168a6fcc9c76"
|
checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"headers",
|
"headers",
|
||||||
"http",
|
"http",
|
||||||
@@ -460,6 +459,8 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"mime",
|
"mime",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"rustversion",
|
||||||
|
"serde_core",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -887,7 +888,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit"
|
name = "conduwuit"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"conduwuit_admin",
|
"conduwuit_admin",
|
||||||
@@ -919,7 +920,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_admin"
|
name = "conduwuit_admin"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"conduwuit_api",
|
"conduwuit_api",
|
||||||
@@ -940,7 +941,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_api"
|
name = "conduwuit_api"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -972,14 +973,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_build_metadata"
|
name = "conduwuit_build_metadata"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"built",
|
"built",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_core"
|
name = "conduwuit_core"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
@@ -1013,6 +1014,7 @@ dependencies = [
|
|||||||
"nix",
|
"nix",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"paste",
|
||||||
"rand 0.10.0",
|
"rand 0.10.0",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"regex",
|
"regex",
|
||||||
@@ -1026,7 +1028,7 @@ dependencies = [
|
|||||||
"serde_regex",
|
"serde_regex",
|
||||||
"smallstr",
|
"smallstr",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.18",
|
"snafu",
|
||||||
"tikv-jemalloc-ctl",
|
"tikv-jemalloc-ctl",
|
||||||
"tikv-jemalloc-sys",
|
"tikv-jemalloc-sys",
|
||||||
"tikv-jemallocator",
|
"tikv-jemallocator",
|
||||||
@@ -1041,7 +1043,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_database"
|
name = "conduwuit_database"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"conduwuit_core",
|
"conduwuit_core",
|
||||||
@@ -1059,7 +1061,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_macros"
|
name = "conduwuit_macros"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -1069,7 +1071,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_router"
|
name = "conduwuit_router"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-client-ip",
|
"axum-client-ip",
|
||||||
@@ -1103,7 +1105,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_service"
|
name = "conduwuit_service"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -1145,7 +1147,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_web"
|
name = "conduwuit_web"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -1153,7 +1155,7 @@ dependencies = [
|
|||||||
"conduwuit_service",
|
"conduwuit_service",
|
||||||
"futures",
|
"futures",
|
||||||
"rand 0.10.0",
|
"rand 0.10.0",
|
||||||
"thiserror 2.0.18",
|
"snafu",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1221,7 +1223,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "continuwuity-admin-api"
|
name = "continuwuity-admin-api"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1600,7 +1602,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "draupnir-antispam"
|
name = "draupnir-antispam"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3002,7 +3004,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "meowlnir-antispam"
|
name = "meowlnir-antispam"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -4055,14 +4057,12 @@ dependencies = [
|
|||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-util",
|
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
@@ -4096,7 +4096,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"continuwuity-admin-api",
|
"continuwuity-admin-api",
|
||||||
@@ -4119,7 +4119,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-appservice-api"
|
name = "ruma-appservice-api"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -4131,7 +4131,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"assign",
|
"assign",
|
||||||
@@ -4154,7 +4154,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@@ -4186,7 +4186,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.28.1"
|
version = "0.28.1"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -4211,7 +4211,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"headers",
|
"headers",
|
||||||
@@ -4233,7 +4233,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
@@ -4242,7 +4242,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identity-service-api"
|
name = "ruma-identity-service-api"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -4252,7 +4252,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-macros"
|
name = "ruma-macros"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
@@ -4267,7 +4267,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-push-gateway-api"
|
name = "ruma-push-gateway-api"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -4279,7 +4279,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=bb12ed288a31a23aa11b10ba0fad22b7f985eb88#bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
@@ -4912,6 +4912,27 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
|
||||||
|
dependencies = [
|
||||||
|
"snafu-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.10"
|
version = "0.5.10"
|
||||||
@@ -5870,19 +5891,6 @@ dependencies = [
|
|||||||
"wasmparser",
|
"wasmparser",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-streams"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
|
|
||||||
dependencies = [
|
|
||||||
"futures-util",
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.244.0"
|
version = "0.244.0"
|
||||||
@@ -6347,7 +6355,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtask"
|
name = "xtask"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
|
|||||||
+10
-8
@@ -12,7 +12,7 @@ license = "Apache-2.0"
|
|||||||
# See also `rust-toolchain.toml`
|
# See also `rust-toolchain.toml`
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
||||||
version = "0.5.6"
|
version = "0.5.5"
|
||||||
|
|
||||||
[workspace.metadata.crane]
|
[workspace.metadata.crane]
|
||||||
name = "conduwuit"
|
name = "conduwuit"
|
||||||
@@ -97,7 +97,7 @@ features = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies.axum-extra]
|
[workspace.dependencies.axum-extra]
|
||||||
version = "0.12.0"
|
version = "0.10.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["typed-header", "tracing"]
|
features = ["typed-header", "tracing"]
|
||||||
|
|
||||||
@@ -144,7 +144,6 @@ features = [
|
|||||||
"socks",
|
"socks",
|
||||||
"hickory-dns",
|
"hickory-dns",
|
||||||
"http2",
|
"http2",
|
||||||
"stream",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies.serde]
|
[workspace.dependencies.serde]
|
||||||
@@ -308,9 +307,14 @@ features = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Used for conduwuit::Error type
|
# Used for conduwuit::Error type
|
||||||
[workspace.dependencies.thiserror]
|
[workspace.dependencies.snafu]
|
||||||
version = "2.0.12"
|
version = "0.8"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
features = ["std", "rust_1_81"]
|
||||||
|
|
||||||
|
# Used for macro name generation
|
||||||
|
[workspace.dependencies.paste]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
# Used when hashing the state
|
# Used when hashing the state
|
||||||
[workspace.dependencies.ring]
|
[workspace.dependencies.ring]
|
||||||
@@ -344,7 +348,7 @@ version = "0.1.2"
|
|||||||
[workspace.dependencies.ruma]
|
[workspace.dependencies.ruma]
|
||||||
git = "https://forgejo.ellis.link/continuwuation/ruwuma"
|
git = "https://forgejo.ellis.link/continuwuation/ruwuma"
|
||||||
#branch = "conduwuit-changes"
|
#branch = "conduwuit-changes"
|
||||||
rev = "bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
|
rev = "e087ff15888156942ca2ffe6097d1b4c3fd27628"
|
||||||
features = [
|
features = [
|
||||||
"compat",
|
"compat",
|
||||||
"rand",
|
"rand",
|
||||||
@@ -364,7 +368,6 @@ features = [
|
|||||||
"unstable-msc2870",
|
"unstable-msc2870",
|
||||||
"unstable-msc3026",
|
"unstable-msc3026",
|
||||||
"unstable-msc3061",
|
"unstable-msc3061",
|
||||||
"unstable-msc3814",
|
|
||||||
"unstable-msc3245",
|
"unstable-msc3245",
|
||||||
"unstable-msc3266",
|
"unstable-msc3266",
|
||||||
"unstable-msc3381", # polls
|
"unstable-msc3381", # polls
|
||||||
@@ -383,7 +386,6 @@ features = [
|
|||||||
"unstable-pdu",
|
"unstable-pdu",
|
||||||
"unstable-msc4155",
|
"unstable-msc4155",
|
||||||
"unstable-msc4143", # livekit well_known response
|
"unstable-msc4143", # livekit well_known response
|
||||||
"unstable-msc4284"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies.rust-rocksdb]
|
[workspace.dependencies.rust-rocksdb]
|
||||||
|
|||||||
@@ -57,15 +57,10 @@ Continuwuity aims to:
|
|||||||
|
|
||||||
### Can I try it out?
|
### Can I try it out?
|
||||||
|
|
||||||
Check out the [documentation](https://continuwuity.org) for installation instructions.
|
Check out the [documentation](https://continuwuity.org) for installation instructions, or join one of these vetted public homeservers running Continuwuity to get a feel for things!
|
||||||
|
|
||||||
If you want to try it out as a user, we have some partnered homeservers you can use:
|
- https://continuwuity.rocks -- A public demo server operated by the Continuwuity Team.
|
||||||
* You can head over to [https://federated.nexus](https://federated.nexus/) in your browser.
|
- https://federated.nexus -- Federated Nexus is a community resource hosting multiple FOSS (especially federated) services, including Matrix and Forgejo.
|
||||||
* Hit the `Apply to Join` button. Once your request has been accepted, you will receive an email with your username and password.
|
|
||||||
* Head over to [https://app.federated.nexus](https://app.federated.nexus/) and you can sign in there, or use any other matrix chat client you wish elsewhere.
|
|
||||||
* Your username for matrix will be in the form of `@username:federated.nexus`, however you can simply use the `username` part to log in. Your password is your password.
|
|
||||||
|
|
||||||
* There's also [https://continuwuity.rocks/](https://continuwuity.rocks/). You can register a new account using Cinny via [this convenient link](https://app.cinny.in/register/continuwuity.rocks), or you can use Element or another matrix client *that supports registration*.
|
|
||||||
|
|
||||||
### What are we working on?
|
### What are we working on?
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,10 +6,10 @@ set -euo pipefail
|
|||||||
COMPLEMENT_SRC="${COMPLEMENT_SRC:-$1}"
|
COMPLEMENT_SRC="${COMPLEMENT_SRC:-$1}"
|
||||||
|
|
||||||
# A `.jsonl` file to write test logs to
|
# A `.jsonl` file to write test logs to
|
||||||
LOG_FILE="${2:-tests/test_results/complement/test_logs.jsonl}"
|
LOG_FILE="${2:-complement_test_logs.jsonl}"
|
||||||
|
|
||||||
# A `.jsonl` file to write test results to
|
# A `.jsonl` file to write test results to
|
||||||
RESULTS_FILE="${3:-tests/test_results/complement/test_results.jsonl}"
|
RESULTS_FILE="${3:-complement_test_results.jsonl}"
|
||||||
|
|
||||||
# The base docker image to use for complement tests
|
# The base docker image to use for complement tests
|
||||||
# You can build the default with `docker build -t continuwuity:complement -f ./docker/complement.Dockerfile .`
|
# You can build the default with `docker build -t continuwuity:complement -f ./docker/complement.Dockerfile .`
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
Stopped left rooms from being unconditionally sent on initial sync, hopefully fixing spurious appearances of left rooms in some clients (and making sync faster as a bonus). Contributed by @ginger
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Re-added support for reading registration tokens from a file. Contributed by @ginger and @benbot.
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Removed non-compliant nor functional room alias lookups over federation. Contributed by @nex
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Outgoing presence is now disabled by default, and the config option documentation has been adjusted to more accurately represent the weight of presence, typing indicators, and read receipts. Contributed by @nex.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Removed ability to set rocksdb as read only. Doing so would cause unintentional and buggy behaviour. Contributed by @Terryiscool160.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Fixed a startup crash in the sender service if we can't detect the number of CPU cores, even if the `sender_workers' config option is set correctly. Contributed by @katie.
|
||||||
@@ -1 +0,0 @@
|
|||||||
Prevent removing the admin room alias (`#admins`) to avoid accidentally breaking admin room functionality. Contributed by @0xnim
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Updated `list-backups` admin command to output one backup per line.
|
||||||
+3
-15
@@ -15,18 +15,6 @@ disallowed-macros = [
|
|||||||
{ path = "log::trace", reason = "use conduwuit_core::trace" },
|
{ path = "log::trace", reason = "use conduwuit_core::trace" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[disallowed-methods]]
|
disallowed-methods = [
|
||||||
path = "tokio::spawn"
|
{ path = "tokio::spawn", reason = "use and pass conduuwit_core::server::Server::runtime() to spawn from" },
|
||||||
reason = "use and pass conduwuit_core::server::Server::runtime() to spawn from"
|
]
|
||||||
|
|
||||||
[[disallowed-methods]]
|
|
||||||
path = "reqwest::Response::bytes"
|
|
||||||
reason = "bytes is unsafe, use limit_read via the conduwuit_core::utils::LimitReadExt trait instead"
|
|
||||||
|
|
||||||
[[disallowed-methods]]
|
|
||||||
path = "reqwest::Response::text"
|
|
||||||
reason = "text is unsafe, use limit_read_text via the conduwuit_core::utils::LimitReadExt trait instead"
|
|
||||||
|
|
||||||
[[disallowed-methods]]
|
|
||||||
path = "reqwest::Response::json"
|
|
||||||
reason = "json is unsafe, use limit_read_text via the conduwuit_core::utils::LimitReadExt trait instead"
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ address = "0.0.0.0"
|
|||||||
allow_device_name_federation = true
|
allow_device_name_federation = true
|
||||||
allow_guest_registration = true
|
allow_guest_registration = true
|
||||||
allow_public_room_directory_over_federation = true
|
allow_public_room_directory_over_federation = true
|
||||||
|
allow_public_room_directory_without_auth = true
|
||||||
allow_registration = true
|
allow_registration = true
|
||||||
database_path = "/database"
|
database_path = "/database"
|
||||||
log = "trace,h2=debug,hyper=debug,conduwuit_database=warn,conduwuit_service::manager=info,conduwuit_api::router=error,conduwuit_router=error,tower_http=error"
|
log = "trace,h2=debug,hyper=debug"
|
||||||
port = [8008, 8448]
|
port = [8008, 8448]
|
||||||
trusted_servers = []
|
trusted_servers = []
|
||||||
only_query_trusted_key_servers = false
|
only_query_trusted_key_servers = false
|
||||||
@@ -24,7 +25,7 @@ url_preview_domain_explicit_denylist = ["*"]
|
|||||||
media_compat_file_link = false
|
media_compat_file_link = false
|
||||||
media_startup_check = true
|
media_startup_check = true
|
||||||
prune_missing_media = true
|
prune_missing_media = true
|
||||||
log_colors = false
|
log_colors = true
|
||||||
admin_room_notices = false
|
admin_room_notices = false
|
||||||
allow_check_for_updates = false
|
allow_check_for_updates = false
|
||||||
intentionally_unknown_config_option_for_testing = true
|
intentionally_unknown_config_option_for_testing = true
|
||||||
@@ -47,7 +48,6 @@ federation_idle_timeout = 300
|
|||||||
sender_timeout = 300
|
sender_timeout = 300
|
||||||
sender_idle_timeout = 300
|
sender_idle_timeout = 300
|
||||||
sender_retry_backoff_limit = 300
|
sender_retry_backoff_limit = 300
|
||||||
force_disable_first_run_mode = true
|
|
||||||
|
|
||||||
[global.tls]
|
[global.tls]
|
||||||
dual_protocol = true
|
dual_protocol = true
|
||||||
|
|||||||
+19
-55
@@ -290,25 +290,6 @@
|
|||||||
#
|
#
|
||||||
#max_fetch_prev_events = 192
|
#max_fetch_prev_events = 192
|
||||||
|
|
||||||
# How many incoming federation transactions the server is willing to be
|
|
||||||
# processing at any given time before it becomes overloaded and starts
|
|
||||||
# rejecting further transactions until some slots become available.
|
|
||||||
#
|
|
||||||
# Setting this value too low or too high may result in unstable
|
|
||||||
# federation, and setting it too high may cause runaway resource usage.
|
|
||||||
#
|
|
||||||
#max_concurrent_inbound_transactions = 150
|
|
||||||
|
|
||||||
# Maximum age (in seconds) for cached federation transaction responses.
|
|
||||||
# Entries older than this will be removed during cleanup.
|
|
||||||
#
|
|
||||||
#transaction_id_cache_max_age_secs = 7200 (2 hours)
|
|
||||||
|
|
||||||
# Maximum number of cached federation transaction responses.
|
|
||||||
# When the cache exceeds this limit, older entries will be removed.
|
|
||||||
#
|
|
||||||
#transaction_id_cache_max_entries = 8192
|
|
||||||
|
|
||||||
# Default/base connection timeout (seconds). This is used only by URL
|
# Default/base connection timeout (seconds). This is used only by URL
|
||||||
# previews and update/news endpoint checks.
|
# previews and update/news endpoint checks.
|
||||||
#
|
#
|
||||||
@@ -476,25 +457,18 @@
|
|||||||
#yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = false
|
#yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = false
|
||||||
|
|
||||||
# A static registration token that new users will have to provide when
|
# A static registration token that new users will have to provide when
|
||||||
# creating an account. This token does not supersede tokens from other
|
# creating an account. If unset and `allow_registration` is true,
|
||||||
# sources, such as the `!admin token` command or the
|
# you must set
|
||||||
# `registration_token_file` configuration option.
|
# `yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse`
|
||||||
|
# to true to allow open registration without any conditions.
|
||||||
|
#
|
||||||
|
# If you do not want to set a static token, the `!admin token` commands
|
||||||
|
# may also be used to manage registration tokens.
|
||||||
#
|
#
|
||||||
# example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
|
# example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
|
||||||
#
|
#
|
||||||
#registration_token =
|
#registration_token =
|
||||||
|
|
||||||
# A path to a file containing static registration tokens, one per line.
|
|
||||||
# Tokens in this file do not supersede tokens from other sources, such as
|
|
||||||
# the `!admin token` command or the `registration_token` configuration
|
|
||||||
# option.
|
|
||||||
#
|
|
||||||
# The file will be read once, when Continuwuity starts. It is not
|
|
||||||
# currently reread when the server configuration is reloaded. If the file
|
|
||||||
# cannot be read, Continuwuity will fail to start.
|
|
||||||
#
|
|
||||||
#registration_token_file =
|
|
||||||
|
|
||||||
# The public site key for reCaptcha. If this is provided, reCaptcha
|
# The public site key for reCaptcha. If this is provided, reCaptcha
|
||||||
# becomes required during registration. If both captcha *and*
|
# becomes required during registration. If both captcha *and*
|
||||||
# registration token are enabled, both will be required during
|
# registration token are enabled, both will be required during
|
||||||
@@ -553,6 +527,12 @@
|
|||||||
#
|
#
|
||||||
#allow_public_room_directory_over_federation = false
|
#allow_public_room_directory_over_federation = false
|
||||||
|
|
||||||
|
# Set this to true to allow your server's public room directory to be
|
||||||
|
# queried without client authentication (access token) through the Client
|
||||||
|
# APIs. Set this to false to protect against /publicRooms spiders.
|
||||||
|
#
|
||||||
|
#allow_public_room_directory_without_auth = false
|
||||||
|
|
||||||
# Allow guests/unauthenticated users to access TURN credentials.
|
# Allow guests/unauthenticated users to access TURN credentials.
|
||||||
#
|
#
|
||||||
# This is the equivalent of Synapse's `turn_allow_guests` config option.
|
# This is the equivalent of Synapse's `turn_allow_guests` config option.
|
||||||
@@ -1851,13 +1831,14 @@
|
|||||||
#
|
#
|
||||||
#support_mxid =
|
#support_mxid =
|
||||||
|
|
||||||
# **DEPRECATED**: Use `[global.matrix_rtc].foci` instead.
|
|
||||||
#
|
|
||||||
# A list of MatrixRTC foci URLs which will be served as part of the
|
# A list of MatrixRTC foci URLs which will be served as part of the
|
||||||
# MSC4143 client endpoint at /.well-known/matrix/client.
|
# MSC4143 client endpoint at /.well-known/matrix/client. If you're
|
||||||
|
# setting up livekit, you'd want something like:
|
||||||
|
# rtc_focus_server_urls = [
|
||||||
|
# { type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
||||||
|
# ]
|
||||||
#
|
#
|
||||||
# This option is deprecated and will be removed in a future release.
|
# To disable, set this to be an empty vector (`[]`).
|
||||||
# Please migrate to the new `[global.matrix_rtc]` config section.
|
|
||||||
#
|
#
|
||||||
#rtc_focus_server_urls = []
|
#rtc_focus_server_urls = []
|
||||||
|
|
||||||
@@ -1879,23 +1860,6 @@
|
|||||||
#
|
#
|
||||||
#blurhash_max_raw_size = 33554432
|
#blurhash_max_raw_size = 33554432
|
||||||
|
|
||||||
[global.matrix_rtc]
|
|
||||||
|
|
||||||
# A list of MatrixRTC foci (transports) which will be served via the
|
|
||||||
# MSC4143 RTC transports endpoint at
|
|
||||||
# `/_matrix/client/v1/rtc/transports`. If you're setting up livekit,
|
|
||||||
# you'd want something like:
|
|
||||||
# ```toml
|
|
||||||
# [global.matrix_rtc]
|
|
||||||
# foci = [
|
|
||||||
# { type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
|
||||||
# ]
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# To disable, set this to an empty list (`[]`).
|
|
||||||
#
|
|
||||||
#foci = []
|
|
||||||
|
|
||||||
[global.ldap]
|
[global.ldap]
|
||||||
|
|
||||||
# Whether to enable LDAP login.
|
# Whether to enable LDAP login.
|
||||||
|
|||||||
+3
-8
@@ -48,7 +48,7 @@ EOF
|
|||||||
|
|
||||||
# Developer tool versions
|
# Developer tool versions
|
||||||
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
||||||
ENV BINSTALL_VERSION=1.17.6
|
ENV BINSTALL_VERSION=1.17.5
|
||||||
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
||||||
ENV CARGO_SBOM_VERSION=0.9.1
|
ENV CARGO_SBOM_VERSION=0.9.1
|
||||||
# renovate: datasource=crate depName=lddtree
|
# renovate: datasource=crate depName=lddtree
|
||||||
@@ -180,11 +180,6 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|||||||
export RUSTFLAGS="${RUSTFLAGS}"
|
export RUSTFLAGS="${RUSTFLAGS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RUST_PROFILE_DIR="${RUST_PROFILE}"
|
|
||||||
if [[ "${RUST_PROFILE}" == "dev" ]]; then
|
|
||||||
RUST_PROFILE_DIR="debug"
|
|
||||||
fi
|
|
||||||
|
|
||||||
TARGET_DIR=($(cargo metadata --no-deps --format-version 1 | \
|
TARGET_DIR=($(cargo metadata --no-deps --format-version 1 | \
|
||||||
jq -r ".target_directory"))
|
jq -r ".target_directory"))
|
||||||
mkdir /out/sbin
|
mkdir /out/sbin
|
||||||
@@ -196,8 +191,8 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|||||||
jq -r ".packages[] | select(.name == \"$PACKAGE\") | .targets[] | select( .kind | map(. == \"bin\") | any ) | .name"))
|
jq -r ".packages[] | select(.name == \"$PACKAGE\") | .targets[] | select( .kind | map(. == \"bin\") | any ) | .name"))
|
||||||
for BINARY in "${BINARIES[@]}"; do
|
for BINARY in "${BINARIES[@]}"; do
|
||||||
echo $BINARY
|
echo $BINARY
|
||||||
xx-verify $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE_DIR}/$BINARY
|
xx-verify $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE}/$BINARY
|
||||||
cp $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE_DIR}/$BINARY /out/sbin/$BINARY
|
cp $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE}/$BINARY /out/sbin/$BINARY
|
||||||
done
|
done
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ RUN --mount=type=cache,target=/etc/apk/cache apk add \
|
|||||||
|
|
||||||
# Developer tool versions
|
# Developer tool versions
|
||||||
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
||||||
ENV BINSTALL_VERSION=1.17.6
|
ENV BINSTALL_VERSION=1.17.5
|
||||||
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
||||||
ENV CARGO_SBOM_VERSION=0.9.1
|
ENV CARGO_SBOM_VERSION=0.9.1
|
||||||
# renovate: datasource=crate depName=lddtree
|
# renovate: datasource=crate depName=lddtree
|
||||||
|
|||||||
@@ -34,11 +34,6 @@
|
|||||||
"name": "troubleshooting",
|
"name": "troubleshooting",
|
||||||
"label": "Troubleshooting"
|
"label": "Troubleshooting"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "dir",
|
|
||||||
"name": "advanced",
|
|
||||||
"label": "Advanced"
|
|
||||||
},
|
|
||||||
"security",
|
"security",
|
||||||
{
|
{
|
||||||
"type": "dir-section-header",
|
"type": "dir-section-header",
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"text": "Guide",
|
"text": "Guide",
|
||||||
"link": "/introduction",
|
"link": "/introduction",
|
||||||
"activeMatch": "^/(introduction|configuration|deploying|calls|appservices|maintenance|troubleshooting|advanced)"
|
"activeMatch": "^/(introduction|configuration|deploying|calls|appservices|maintenance|troubleshooting)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Development",
|
"text": "Development",
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"name": "delegation",
|
|
||||||
"label": "Delegation / split-domain"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
# Delegation/split-domain deployment
|
|
||||||
|
|
||||||
Matrix allows clients and servers to discover a homeserver's "true" destination via **`.well-known` delegation**. This is especially useful if you would like to:
|
|
||||||
|
|
||||||
- Serve Continuwuity on a subdomain while having only the base domain for your usernames
|
|
||||||
- Use a port other than `:8448` for server-to-server connections
|
|
||||||
|
|
||||||
This guide will show you how to have `@user:example.com` usernames while serving Continuwuity on `https://matrix.example.com`. It assumes you are using port 443 for both client-to-server connections and server-to-server federation.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
First, ensure you have set up A/AAAA records for `matrix.example.com` and `example.com` pointing to your IP.
|
|
||||||
|
|
||||||
Then, ensure that the `server_name` field matches your intended username suffix. If this is not the case, you **MUST** wipe the database directory and reinstall Continuwuity with your desired `server_name`.
|
|
||||||
|
|
||||||
Then, in the `[global.well_known]` section of your config file, add the following fields:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[global.well_known]
|
|
||||||
|
|
||||||
client = "https://matrix.example.com"
|
|
||||||
|
|
||||||
# port number MUST be specified
|
|
||||||
server = "matrix.example.com:443"
|
|
||||||
|
|
||||||
# (optional) customize your support contacts
|
|
||||||
#support_page =
|
|
||||||
#support_role = "m.role.admin"
|
|
||||||
#support_email =
|
|
||||||
#support_mxid = "@user:example.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively if you are using Docker, you can set the `CONTINUWUITY_WELL_KNOWN` environment variable as below:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
continuwuity:
|
|
||||||
...
|
|
||||||
environment:
|
|
||||||
CONTINUWUITY_WELL_KNOWN: |
|
|
||||||
{
|
|
||||||
client=https://matrix.example.com,
|
|
||||||
server=matrix.example.com:443
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Serving with a reverse proxy
|
|
||||||
|
|
||||||
After doing the steps above, Continuwuity will serve these 3 JSON files:
|
|
||||||
|
|
||||||
- `/.well-known/matrix/client`: for Client-Server discovery
|
|
||||||
- `/.well-known/matrix/server`: for Server-Server (federation) discovery
|
|
||||||
- `/.well-known/matrix/support`: admin contact details (strongly recommended to have)
|
|
||||||
|
|
||||||
To enable full discovery, you will need to reverse proxy these paths from the base domain back to Continuwuity.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
|
|
||||||
<summary>For Caddy</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
matrix.example.com:443 {
|
|
||||||
reverse_proxy 127.0.0.1:8008
|
|
||||||
}
|
|
||||||
|
|
||||||
example.com:443 {
|
|
||||||
reverse_proxy /.well-known/matrix* 127.0.0.1:8008
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
|
|
||||||
<summary>For Traefik (via Docker labels)</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
services:
|
|
||||||
continuwuity:
|
|
||||||
...
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.continuwuity.rule=(Host(`matrix.example.com`) || (Host(`example.com`) && PathPrefix(`/.well-known/matrix`)))"
|
|
||||||
- "traefik.http.routers.continuwuity.service=continuwuity"
|
|
||||||
- "traefik.http.services.continuwuity.loadbalancer.server.port=8008"
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
Restart Continuwuity and your reverse proxy. Once that's done, visit these routes and check that the responses match the examples below:
|
|
||||||
|
|
||||||
<details open>
|
|
||||||
|
|
||||||
<summary>`https://example.com/.well-known/matrix/server`</summary>
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"m.server": "matrix.example.com:443"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details open>
|
|
||||||
|
|
||||||
<summary>`https://example.com/.well-known/matrix/client`</summary>
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"m.homeserver": {
|
|
||||||
"base_url": "https://matrix.example.com/"
|
|
||||||
},
|
|
||||||
"org.matrix.msc3575.proxy": {
|
|
||||||
"url": "https://matrix.example.com/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Cannot log in with web clients
|
|
||||||
|
|
||||||
Make sure there is an `Access-Control-Allow-Origin: *` header in your `/.well-known/matrix/client` path. While Continuwuity serves this header by default, it may be dropped by reverse proxies or other middlewares.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Using SRV records (not recommended)
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
The following methods are **not recommended** due to increased complexity with little benefits. If you have already set up `.well-known` delegation as above, you can safely skip this part.
|
|
||||||
:::
|
|
||||||
|
|
||||||
The following methods uses SRV DNS records and only work with federation traffic. They are only included for completeness.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
|
|
||||||
<summary>Using only SRV records</summary>
|
|
||||||
|
|
||||||
If you can't set up `/.well-known/matrix/server` on :443 for some reason, you can set up a SRV record (via your DNS provider) as below:
|
|
||||||
|
|
||||||
- Service and name: `_matrix-fed._tcp.example.com.`
|
|
||||||
- Priority: `10` (can be any number)
|
|
||||||
- Weight: `10` (can be any number)
|
|
||||||
- Port: `443`
|
|
||||||
- Target: `matrix.example.com.`
|
|
||||||
|
|
||||||
On the target's IP at port 443, you must configure a valid route and cert for your server name, `example.com`. Therefore, this method only works to redirect traffic into the right IP/port combo, and can not delegate your federation to a different domain.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
|
|
||||||
<summary>Using SRV records + .well-known</summary>
|
|
||||||
|
|
||||||
You can also set up `/.well-known/matrix/server` with a delegated domain but no ports:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[global.well_known]
|
|
||||||
server = "matrix.example.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, set up a SRV record (via your DNS provider) to announce the port number as below:
|
|
||||||
|
|
||||||
- Service and name: `_matrix-fed._tcp.matrix.example.com.`
|
|
||||||
- Priority: `10` (can be any number)
|
|
||||||
- Weight: `10` (can be any number)
|
|
||||||
- Port: `443`
|
|
||||||
- Target: `matrix.example.com.`
|
|
||||||
|
|
||||||
On the target's IP at port 443, you'll need to provide a valid route and cert for `matrix.example.com`. It provides the same feature as pure `.well-known` delegation, albeit with more parts to handle.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
|
|
||||||
<summary>Using SRV records as a fallback for .well-known delegation</summary>
|
|
||||||
|
|
||||||
Assume your delegation is as below:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[global.well_known]
|
|
||||||
server = "example.com:443"
|
|
||||||
```
|
|
||||||
|
|
||||||
If your Continuwuity instance becomes temporarily unreachable, other servers will not be able to find your `/.well-known/matrix/server` file, and defaults to using `server_name:8448`. This incorrect cache can persist for a long time, and would hinder re-federation when your server eventually comes back online.
|
|
||||||
|
|
||||||
If you want other servers to default to using port :443 even when it is offline, you could set up a SRV record (via your DNS provider) as follows:
|
|
||||||
|
|
||||||
- Service and name: `_matrix-fed._tcp.example.com.`
|
|
||||||
- Priority: `10` (can be any number)
|
|
||||||
- Weight: `10` (can be any number)
|
|
||||||
- Port: `443`
|
|
||||||
- Target: `example.com.`
|
|
||||||
|
|
||||||
On the target's IP at port 443, you'll need to provide a valid route and cert for `example.com`.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Related Documentation
|
|
||||||
|
|
||||||
See the following Matrix Specs for full details on client/server resolution mechanisms:
|
|
||||||
|
|
||||||
- [Server-to-Server resolution](https://spec.matrix.org/v1.17/server-server-api/#resolving-server-names) (see this for more information on SRV records)
|
|
||||||
- [Client-to-Server resolution](https://spec.matrix.org/v1.17/client-server-api/#server-discovery)
|
|
||||||
- [MSC1929: Homeserver Admin Contact and Support page](https://github.com/matrix-org/matrix-spec-proposals/pull/1929)
|
|
||||||
+32
-4
@@ -78,19 +78,47 @@ You will need to allow ports `7881/tcp` and `50100:50200/udp` through your firew
|
|||||||
|
|
||||||
### 3. Telling clients where to find LiveKit
|
### 3. Telling clients where to find LiveKit
|
||||||
|
|
||||||
To tell clients where to find LiveKit, you need to add the address of your `lk-jwt-service` to the `[global.matrix_rtc]` config section using the `foci` option.
|
To tell clients where to find LiveKit, you need to add the address of your `lk-jwt-service` to your client .well-known file. To do so, in the config section `global.well-known`, add (or modify) the option `rtc_focus_server_urls`.
|
||||||
|
|
||||||
The variable should be a list of servers serving as MatrixRTC endpoints. Clients discover these via the `/_matrix/client/v1/rtc/transports` endpoint (MSC4143).
|
The variable should be a list of servers serving as MatrixRTC endpoints to serve in the well-known file to the client.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[global.matrix_rtc]
|
rtc_focus_server_urls = [
|
||||||
foci = [
|
|
||||||
{ type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
{ type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Remember to replace the URL with the address you are deploying your instance of lk-jwt-service to.
|
Remember to replace the URL with the address you are deploying your instance of lk-jwt-service to.
|
||||||
|
|
||||||
|
#### Serving .well-known manually
|
||||||
|
|
||||||
|
If you don't let Continuwuity serve your `.well-known` files, you need to add the following lines to your `.well-known/matrix/client` file, remembering to replace the URL with your own `lk-jwt-service` deployment:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"org.matrix.msc4143.rtc_foci": [
|
||||||
|
{
|
||||||
|
"type": "livekit",
|
||||||
|
"livekit_service_url": "https://livekit.example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
The final file should look something like this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"m.homeserver": {
|
||||||
|
"base_url":"https://matrix.example.com"
|
||||||
|
},
|
||||||
|
"org.matrix.msc4143.rtc_foci": [
|
||||||
|
{
|
||||||
|
"type": "livekit",
|
||||||
|
"livekit_service_url": "https://livekit.example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 4. Configure your Reverse Proxy
|
### 4. Configure your Reverse Proxy
|
||||||
|
|
||||||
Reverse proxies can be configured in many different ways - so we can't provide a step by step for this.
|
Reverse proxies can be configured in many different ways - so we can't provide a step by step for this.
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ settings.
|
|||||||
|
|
||||||
The config file to use can be specified on the commandline when running
|
The config file to use can be specified on the commandline when running
|
||||||
Continuwuity by specifying the `-c`, `--config` flag. Alternatively, you can use
|
Continuwuity by specifying the `-c`, `--config` flag. Alternatively, you can use
|
||||||
the environment variable `CONTINUWUITY_CONFIG` to specify the config file to be
|
the environment variable `CONDUWUIT_CONFIG` to specify the config file to used.
|
||||||
used; see [the section on environment variables](#environment-variables) for
|
Conduit's environment variables are supported for backwards compatibility.
|
||||||
more information.
|
|
||||||
|
|
||||||
## Option commandline flag
|
## Option commandline flag
|
||||||
|
|
||||||
@@ -53,15 +52,13 @@ This commandline argument can be paired with the `--option` flag.
|
|||||||
|
|
||||||
All of the settings that are found in the config file can be specified by using
|
All of the settings that are found in the config file can be specified by using
|
||||||
environment variables. The environment variable names should be all caps and
|
environment variables. The environment variable names should be all caps and
|
||||||
prefixed with `CONTINUWUITY_`.
|
prefixed with `CONDUWUIT_`.
|
||||||
|
|
||||||
For example, if the setting you are changing is `max_request_size`, then the
|
For example, if the setting you are changing is `max_request_size`, then the
|
||||||
environment variable to set is `CONTINUWUITY_MAX_REQUEST_SIZE`.
|
environment variable to set is `CONDUWUIT_MAX_REQUEST_SIZE`.
|
||||||
|
|
||||||
To modify config options not in the `[global]` context such as
|
To modify config options not in the `[global]` context such as
|
||||||
`[global.well_known]`, use the `__` suffix split:
|
`[global.well_known]`, use the `__` suffix split: `CONDUWUIT_WELL_KNOWN__SERVER`
|
||||||
`CONTINUWUITY_WELL_KNOWN__SERVER`
|
|
||||||
|
|
||||||
Conduit and conduwuit's environment variables are also supported for backwards
|
Conduit's environment variables are supported for backwards compatibility (e.g.
|
||||||
compatibility, via the `CONDUIT_` and `CONDUWUIT_` prefixes respectively (e.g.
|
|
||||||
`CONDUIT_SERVER_NAME`).
|
`CONDUIT_SERVER_NAME`).
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
labels:
|
labels:
|
||||||
caddy: example.com
|
caddy: example.com
|
||||||
caddy.reverse_proxy: /.well-known/matrix/* homeserver:6167
|
caddy.0_respond: /.well-known/matrix/server {"m.server":"matrix.example.com:443"}
|
||||||
|
caddy.1_respond: /.well-known/matrix/client {"m.server":{"base_url":"https://matrix.example.com"},"m.homeserver":{"base_url":"https://matrix.example.com"},"org.matrix.msc3575.proxy":{"url":"https://matrix.example.com"}}
|
||||||
|
|
||||||
homeserver:
|
homeserver:
|
||||||
### If you already built the Continuwuity image with 'docker build' or want to use a registry image,
|
### If you already built the Continuwuity image with 'docker build' or want to use a registry image,
|
||||||
@@ -41,10 +42,6 @@ services:
|
|||||||
#CONTINUWUITY_LOG: warn,state_res=warn
|
#CONTINUWUITY_LOG: warn,state_res=warn
|
||||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||||
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||||
|
|
||||||
# Required for .well-known delegation - edit these according to your chosen domain
|
|
||||||
CONTINUWUITY_WELL_KNOWN__CLIENT: https://matrix.example.com
|
|
||||||
CONTINUWUITY_WELL_KNOWN__SERVER: matrix.example.com:443
|
|
||||||
networks:
|
networks:
|
||||||
- caddy
|
- caddy
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
@@ -51,13 +51,7 @@ continuwuity aims to:
|
|||||||
|
|
||||||
Check out the [documentation](https://continuwuity.org) for installation instructions.
|
Check out the [documentation](https://continuwuity.org) for installation instructions.
|
||||||
|
|
||||||
If you want to try it out as a user, we have some partnered homeservers you can use:
|
There are currently no open registration continuwuity instances available.
|
||||||
* You can head over to [https://federated.nexus](https://federated.nexus/) in your browser.
|
|
||||||
* Hit the `Apply to Join` button. Once your request has been accepted, you will receive an email with your username and password.
|
|
||||||
* Head over to [https://app.federated.nexus](https://app.federated.nexus/) and you can sign in there, or use any other matrix chat client you wish elsewhere.
|
|
||||||
* Your username for matrix will be in the form of `@username:federated.nexus`, however you can simply use the `username` part to log in. Your password is your password.
|
|
||||||
|
|
||||||
* There's also [https://continuwuity.rocks/](https://continuwuity.rocks/). You can register a new account using Cinny via [this convenient link](https://app.cinny.in/register/continuwuity.rocks), or you can use Element or another matrix client *that supports registration*.
|
|
||||||
|
|
||||||
## What are we working on?
|
## What are we working on?
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
|
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 9,
|
||||||
"mention_room": false,
|
"mention_room": false,
|
||||||
"date": "2026-03-03",
|
"date": "2026-02-09",
|
||||||
"message": "We've just released [v0.5.6](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.6), which contains a few security improvements - plus significant reliability and performance improvements. Please update as soon as possible. \n\nWe released [v0.5.5](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.5) two weeks ago, but it skipped your admin room straight to [our announcements channel](https://matrix.to/#/!jIdNjSM5X-V5JVx2h2kAhUZIIQ08GyzPL55NFZAH1vM?via=ellis.link&via=gingershaped.computer&via=matrix.org). Make sure you're there to get important information as soon as we announce it! [Our space](https://matrix.to/#/!8cR4g-i9ucof69E4JHNg9LbPVkGprHb3SzcrGBDDJgk?via=continuwuity.org&via=ellis.link&via=matrix.org) has also gained a bunch of new and interesting rooms - be there or be square."
|
"message": "Yesterday we released [v0.5.4](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.4). Bugfixes, performance improvements and more moderation features! There's also a security fix, so please update as soon as possible. Don't forget to join [our announcements channel](https://matrix.to/#/!jIdNjSM5X-V5JVx2h2kAhUZIIQ08GyzPL55NFZAH1vM/%2489TY9CqRg4-ff1MGo3Ulc5r5X4pakfdzT-99RD8Docc?via=ellis.link&via=explodie.org&via=matrix.org) to get important information sooner <3 "
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ default.
|
|||||||
* Delete all remote and local media from 3 days ago, up until now:
|
* Delete all remote and local media from 3 days ago, up until now:
|
||||||
|
|
||||||
`!admin media delete-past-remote-media -a 3d
|
`!admin media delete-past-remote-media -a 3d
|
||||||
--yes-i-want-to-delete-local-media`
|
-yes-i-want-to-delete-local-media`
|
||||||
|
|
||||||
## `!admin media delete-all-from-user`
|
## `!admin media delete-all-from-user`
|
||||||
|
|
||||||
@@ -36,7 +36,3 @@ Deletes all the local media from a local user on our server. This will always ig
|
|||||||
## `!admin media delete-all-from-server`
|
## `!admin media delete-all-from-server`
|
||||||
|
|
||||||
Deletes all remote media from the specified remote server. This will always ignore errors by default
|
Deletes all remote media from the specified remote server. This will always ignore errors by default
|
||||||
|
|
||||||
## `!admin media delete-url-preview`
|
|
||||||
|
|
||||||
Deletes a cached URL preview, forcing it to be re-fetched. Use --all to purge all cached URL previews
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
rocksdbAllFeatures = self'.packages.rocksdb.override {
|
rocksdbAllFeatures = self'.packages.rocksdb.override {
|
||||||
enableJemalloc = true;
|
enableJemalloc = true;
|
||||||
|
enableLiburing = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
commonAttrs = (uwulib.build.commonAttrs { }) // {
|
commonAttrs = (uwulib.build.commonAttrs { }) // {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
commonAttrsArgs.profile = "release";
|
commonAttrsArgs.profile = "release";
|
||||||
rocksdb = self'.packages.rocksdb.override {
|
rocksdb = self'.packages.rocksdb.override {
|
||||||
enableJemalloc = true;
|
enableJemalloc = true;
|
||||||
|
enableLiburing = true;
|
||||||
};
|
};
|
||||||
features = {
|
features = {
|
||||||
enabledFeatures = "all";
|
enabledFeatures = "all";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
rust-jemalloc-sys-unprefixed,
|
rust-jemalloc-sys-unprefixed,
|
||||||
|
|
||||||
enableJemalloc ? false,
|
enableJemalloc ? false,
|
||||||
|
enableLiburing ? false,
|
||||||
|
|
||||||
fetchFromGitea,
|
fetchFromGitea,
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ in
|
|||||||
|
|
||||||
# for some reason enableLiburing in nixpkgs rocksdb is default true
|
# for some reason enableLiburing in nixpkgs rocksdb is default true
|
||||||
# which breaks Darwin entirely
|
# which breaks Darwin entirely
|
||||||
enableLiburing = notDarwin;
|
enableLiburing = enableLiburing && notDarwin;
|
||||||
}).overrideAttrs
|
}).overrideAttrs
|
||||||
(old: {
|
(old: {
|
||||||
src = fetchFromGitea {
|
src = fetchFromGitea {
|
||||||
@@ -73,7 +74,7 @@ in
|
|||||||
"USE_RTTI"
|
"USE_RTTI"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
enableLiburing = notDarwin;
|
enableLiburing = enableLiburing && notDarwin;
|
||||||
|
|
||||||
# outputs has "tools" which we don't need or use
|
# outputs has "tools" which we don't need or use
|
||||||
outputs = [ "out" ];
|
outputs = [ "out" ];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
uwulib = inputs.self.uwulib.init pkgs;
|
uwulib = inputs.self.uwulib.init pkgs;
|
||||||
rocksdbAllFeatures = self'.packages.rocksdb.override {
|
rocksdbAllFeatures = self'.packages.rocksdb.override {
|
||||||
enableJemalloc = true;
|
enableJemalloc = true;
|
||||||
|
enableLiburing = true;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
Generated
+153
-188
@@ -119,14 +119,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rsbuild/core": {
|
"node_modules/@rsbuild/core": {
|
||||||
"version": "2.0.0-beta.6",
|
"version": "2.0.0-beta.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.0.0-beta.6.tgz",
|
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.0.0-beta.3.tgz",
|
||||||
"integrity": "sha512-DUBhUzvzj6xlGUAHTTipFskSuZmVEuTX7lGU+ToPuo8n3bsQrWn/UBOEQAd45g66k7QfXadoZ/v7eodQErpvGQ==",
|
"integrity": "sha512-dfH+Pt2GuF3rWOWGsf5XOhn3Zarvr4DoHwoI1arAsCGvpzoeud3DNGmWPy13tngj0r/YvQRcPTRBCRV4RP5CMw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rspack/core": "2.0.0-beta.3",
|
"@rspack/core": "2.0.0-beta.0",
|
||||||
"@swc/helpers": "^0.5.19"
|
"@swc/helpers": "^0.5.18",
|
||||||
|
"jiti": "^2.6.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"rsbuild": "bin/rsbuild.js"
|
"rsbuild": "bin/rsbuild.js"
|
||||||
@@ -158,28 +159,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding": {
|
"node_modules/@rspack/binding": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-GSj+d8AlLs1oElhYq32vIN/eAsxWG9jy0EiNgSxWTt5Gdamv87kcvsV4jwfWIjlltdnBIJgey2RnU+hDZlTAvw==",
|
"integrity": "sha512-L6PPqhwZWC2vzwdhBItNPXw+7V4sq+MBDRXLdd8NMqaJSCB5iKdJIbpbEQucST9Nn7V28IYoQTXs6+ol5vWUBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rspack/binding-darwin-arm64": "2.0.0-beta.3",
|
"@rspack/binding-darwin-arm64": "2.0.0-beta.0",
|
||||||
"@rspack/binding-darwin-x64": "2.0.0-beta.3",
|
"@rspack/binding-darwin-x64": "2.0.0-beta.0",
|
||||||
"@rspack/binding-linux-arm64-gnu": "2.0.0-beta.3",
|
"@rspack/binding-linux-arm64-gnu": "2.0.0-beta.0",
|
||||||
"@rspack/binding-linux-arm64-musl": "2.0.0-beta.3",
|
"@rspack/binding-linux-arm64-musl": "2.0.0-beta.0",
|
||||||
"@rspack/binding-linux-x64-gnu": "2.0.0-beta.3",
|
"@rspack/binding-linux-x64-gnu": "2.0.0-beta.0",
|
||||||
"@rspack/binding-linux-x64-musl": "2.0.0-beta.3",
|
"@rspack/binding-linux-x64-musl": "2.0.0-beta.0",
|
||||||
"@rspack/binding-wasm32-wasi": "2.0.0-beta.3",
|
"@rspack/binding-wasm32-wasi": "2.0.0-beta.0",
|
||||||
"@rspack/binding-win32-arm64-msvc": "2.0.0-beta.3",
|
"@rspack/binding-win32-arm64-msvc": "2.0.0-beta.0",
|
||||||
"@rspack/binding-win32-ia32-msvc": "2.0.0-beta.3",
|
"@rspack/binding-win32-ia32-msvc": "2.0.0-beta.0",
|
||||||
"@rspack/binding-win32-x64-msvc": "2.0.0-beta.3"
|
"@rspack/binding-win32-x64-msvc": "2.0.0-beta.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-darwin-arm64": {
|
"node_modules/@rspack/binding-darwin-arm64": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-QebSomLWlCbFsC0sfDuGqLJtkgyrnr38vrCepWukaAXIY4ANy5QB49LDKdLpVv6bKlC95MpnW37NvSNWY5GMYA==",
|
"integrity": "sha512-PPx1+SPEROSvDKmBuCbsE7W9tk07ajPosyvyuafv2wbBI6PW2rNcz62uzpIFS+FTgwwZ5u/06WXRtlD2xW9bKg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -191,9 +192,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-darwin-x64": {
|
"node_modules/@rspack/binding-darwin-x64": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-EysmBq+sz+Ph0bu0gXpU1uuZG9gXgjqY+w3MJel+ieTFyQO3L/R56V32McgssMbheJbYcviDDn7Tz4D+lTvdJA==",
|
"integrity": "sha512-GucsfjrSKBZ9cuOTXmHWxeY2wPmaNyvGNxTyzttjRcfwqOWz8r+ku6PCsMSXUqxZRYWW1L9mvtTdlDrzTYJZ0w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -205,9 +206,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-linux-arm64-gnu": {
|
"node_modules/@rspack/binding-linux-arm64-gnu": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-iFPj4TQZKewnqWPfTbyk3F8QCBI/Edv7TVSRIPBHRnCM0lvYZl/8IZlUzXSamLvrtDpouF0nUzht/fktoWOhAg==",
|
"integrity": "sha512-nTtYtklRZD4sb2RIFCF9YS8tZ/MjpqIBKVS3YIvdXcfHUdVfmQHTZGtwEuZGg6AxTC5L1hcvkYmTXCG0ok7auw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -219,9 +220,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-linux-arm64-musl": {
|
"node_modules/@rspack/binding-linux-arm64-musl": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-355mygfCNb0eF/y4HgtJcd0i9csNTG4Z15PCCplIkSAKJpFpkORM2xJb50BqsbhVafYl6AHoBlGWAo9iIzUb/w==",
|
"integrity": "sha512-S2fshx0Rf7/XYwoMLaqFsVg4y+VAfHzubrczy8AW5xIs6UNC3eRLVTgShLerUPtF6SG+v6NQxQ9JI3vOo2qPOA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -233,9 +234,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-linux-x64-gnu": {
|
"node_modules/@rspack/binding-linux-x64-gnu": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-U8a+bcP/tkMyiwiO9XfeRYYO20YPGiZNxWWt7FEsdmRuRAl6M+EmWaJllJFQtKH+GG8IN93pNoVPMvARjLoJOQ==",
|
"integrity": "sha512-yx5Fk1gl7lfkvqcjolNLCNeduIs6C2alMsQ/kZ1pLeP5MPquVOYNqs6EcDPIp+fUjo3lZYtnJBiZKK+QosbzYg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -247,9 +248,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-linux-x64-musl": {
|
"node_modules/@rspack/binding-linux-x64-musl": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-g81rqkaqDFRTID2VrHBYeM+xZe8yWov7IcryTrl9RGXXr61s+6Tu/mWyM378PuHOCyMNu7G3blVaSjLvKauG6Q==",
|
"integrity": "sha512-sBX4b2W0PgehlAVT224k0Q6GaH6t9HP+hBNDrbX/g6d0hfxZN56gm5NfOTOD1Rien4v7OBEejJ3/uFbm1WjwYQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -261,9 +262,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-wasm32-wasi": {
|
"node_modules/@rspack/binding-wasm32-wasi": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-tzGd8H2oj5F3oR/Hxp+J68zVU/nG+9ndH2KK3/RieVjNAiVNHCR0/ZU9D47s6fnmvWOqAQ1qO8gnVoVLopC4YA==",
|
"integrity": "sha512-o6OatnNvb4kCzXbCaomhENGaCsO3naIyAqqErew90HeAwa1lfY3NhRfDLeIyuANQ+xqFl34/R7n8q3ZDx3nd4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
],
|
],
|
||||||
@@ -275,9 +276,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-win32-arm64-msvc": {
|
"node_modules/@rspack/binding-win32-arm64-msvc": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-TZZRSWa34sm5WyoQHwnyBjLJ4w3fcWRYA9ybYjSVWjUU6tVGdMiHiZp+WexUpIETvChLXU1JENNmBg/U7wvZEA==",
|
"integrity": "sha512-neCzVllXzIqM8p8qKb89qV7wyk233gC/V9VrHIKbGeQjAEzpBsk5GOWlFbq5DDL6tivQ+uzYaTrZWm9tb2qxXg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -289,9 +290,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-win32-ia32-msvc": {
|
"node_modules/@rspack/binding-win32-ia32-msvc": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-VFnfdbJhyl6gNW1VzTyd1ZrHCboHPR7vrOalEsulQRqVNbtDkjm1sqLHtDcLmhTEv0a9r4lli8uubWDwmel8KQ==",
|
"integrity": "sha512-/f0n2eO+DxMKQm9IebeMQJITx8M/+RvY/i8d3sAQZBgR53izn8y7EcDlidXpr24/2DvkLbiub8IyCKPlhLB+1A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -303,9 +304,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/binding-win32-x64-msvc": {
|
"node_modules/@rspack/binding-win32-x64-msvc": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-rwZ6Y3b3oqPj+ZDPPRxr3136HUPKDSlPQa4v7bBOPLDlrFDFOynMIEqDUUi5+8lPaUQ8WWR0aJK4cgcTTT0Siw==",
|
"integrity": "sha512-dx4zgiAT88EQE7kEUpr7Z9EZAwLnO5FhzWzvd/cDK4bkqYsx+rTklgf/c0EYPBeroXCxlGiMsuC9wHAFNK7sFw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -317,19 +318,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rspack/core": {
|
"node_modules/@rspack/core": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.0.0-beta.0.tgz",
|
||||||
"integrity": "sha512-VuLteRIesuyFFTXZaciUY0lwDZiwMc7JcpE8guvjArztDhtpVvlaOcLlVBp/Yza8c/Tk8Dxwe1ARzFL7xG1/0w==",
|
"integrity": "sha512-aEqlQQjiXixT5i9S4DFtiAap8ZjF6pOgfY2ALHOizins/QqWyB8dyLxSoXdzt7JixmKcFmHkbL9XahO28BlVUA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rspack/binding": "2.0.0-beta.3"
|
"@rspack/binding": "2.0.0-beta.0",
|
||||||
|
"@rspack/lite-tapable": "1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@module-federation/runtime-tools": "^0.24.1 || ^2.0.0",
|
"@module-federation/runtime-tools": ">=0.22.0",
|
||||||
"@swc/helpers": ">=0.5.1"
|
"@swc/helpers": ">=0.5.1"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
@@ -341,6 +343,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@rspack/lite-tapable": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@rspack/plugin-react-refresh": {
|
"node_modules/@rspack/plugin-react-refresh": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.6.0.tgz",
|
||||||
@@ -362,22 +371,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspress/core": {
|
"node_modules/@rspress/core": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rspress/core/-/core-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rspress/core/-/core-2.0.3.tgz",
|
||||||
"integrity": "sha512-OdeGMY75OFzyRZvXuBEMre3q8Y4/OjYJa4vVBDp4Z2E65LSt8+hYkzzkarEl6sFWqbp8c1o9qfSUf4xMctmKvw==",
|
"integrity": "sha512-a+JJFiALqMxGJBqR38/lkN6tas42UF4jRIhu6RilC/3DdqpfqR8j6jjQFOmqoNKo6ZGXW2W+i1Pscn6drvoG3w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdx-js/mdx": "^3.1.1",
|
"@mdx-js/mdx": "^3.1.1",
|
||||||
"@mdx-js/react": "^3.1.1",
|
"@mdx-js/react": "^3.1.1",
|
||||||
"@rsbuild/core": "2.0.0-beta.6",
|
"@rsbuild/core": "2.0.0-beta.3",
|
||||||
"@rsbuild/plugin-react": "~1.4.5",
|
"@rsbuild/plugin-react": "~1.4.5",
|
||||||
"@rspress/shared": "2.0.4",
|
"@rspress/shared": "2.0.3",
|
||||||
"@shikijs/rehype": "^4.0.1",
|
"@shikijs/rehype": "^3.21.0",
|
||||||
"@types/unist": "^3.0.3",
|
"@types/unist": "^3.0.3",
|
||||||
"@unhead/react": "^2.1.9",
|
"@unhead/react": "^2.1.4",
|
||||||
"body-scroll-lock": "4.0.0-beta.0",
|
"body-scroll-lock": "4.0.0-beta.0",
|
||||||
"cac": "^7.0.0",
|
"cac": "^6.7.14",
|
||||||
"chokidar": "^3.6.0",
|
"chokidar": "^3.6.0",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"copy-to-clipboard": "^3.3.3",
|
"copy-to-clipboard": "^3.3.3",
|
||||||
@@ -395,8 +404,7 @@
|
|||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"react-lazy-with-preload": "^2.2.1",
|
"react-lazy-with-preload": "^2.2.1",
|
||||||
"react-reconciler": "0.33.0",
|
"react-reconciler": "0.33.0",
|
||||||
"react-render-to-markdown": "19.0.1",
|
"react-router-dom": "^7.13.0",
|
||||||
"react-router-dom": "^7.13.1",
|
|
||||||
"rehype-external-links": "^3.0.0",
|
"rehype-external-links": "^3.0.0",
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
@@ -404,7 +412,7 @@
|
|||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
"remark-stringify": "^11.0.0",
|
"remark-stringify": "^11.0.0",
|
||||||
"scroll-into-view-if-needed": "^3.1.0",
|
"scroll-into-view-if-needed": "^3.1.0",
|
||||||
"shiki": "^4.0.1",
|
"shiki": "^3.21.0",
|
||||||
"tinyglobby": "^0.2.15",
|
"tinyglobby": "^0.2.15",
|
||||||
"tinypool": "^1.1.1",
|
"tinypool": "^1.1.1",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
@@ -420,162 +428,125 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspress/plugin-client-redirects": {
|
"node_modules/@rspress/plugin-client-redirects": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-client-redirects/-/plugin-client-redirects-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rspress/plugin-client-redirects/-/plugin-client-redirects-2.0.3.tgz",
|
||||||
"integrity": "sha512-cm7VNfisVCHe+YHNjd9YrWt6/WtJ5I/oNRyjt+tqCeOcC1IJSX2LhNXpNN5h9az3wxYn37kVctBUjzqkj2FQ+A==",
|
"integrity": "sha512-9+SoAbfoxM6OCRWx8jWHHi2zwJDcNaej/URx0CWZk8tvQ618yJW5mXJydknlac62399eYh/F7C3w8TZM3ORGVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@rspress/core": "^2.0.4"
|
"@rspress/core": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspress/plugin-sitemap": {
|
"node_modules/@rspress/plugin-sitemap": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-sitemap/-/plugin-sitemap-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rspress/plugin-sitemap/-/plugin-sitemap-2.0.3.tgz",
|
||||||
"integrity": "sha512-TKaj3/8+P1fP3sD5NOaWVMXvRvJFQmuJQlUBxhRM0oiUHhzNNkVy/2YXkjYJuXuMhFPLnOWCjrYjTG3xcZE7Wg==",
|
"integrity": "sha512-SKa7YEAdkUqya2YjMKbakg3kcYMkXgXhTQdDsHd+QlJWN8j8cDPiCcctMZu8iIPeKZlb+hTJkTWvh27LSIKdOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@rspress/core": "^2.0.4"
|
"@rspress/core": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rspress/shared": {
|
"node_modules/@rspress/shared": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rspress/shared/-/shared-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rspress/shared/-/shared-2.0.3.tgz",
|
||||||
"integrity": "sha512-os2nzsPgHKVFXjDoW7N53rmhLChCw/y2O2TGilT4w2A4HNJa2oJwRk0UryXbxxWD5C85HErTjovs2uBdhdOTtA==",
|
"integrity": "sha512-yI9G4P165fSsmm6QoYTUrdgUis1aFnDh04GcM4SQIpL3itvEZhGtItgoeGkX9EWbnEjhriwI8mTqDDJIp+vrGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rsbuild/core": "2.0.0-beta.6",
|
"@rsbuild/core": "2.0.0-beta.3",
|
||||||
"@shikijs/rehype": "^4.0.1",
|
"@shikijs/rehype": "^3.21.0",
|
||||||
"gray-matter": "4.0.3",
|
"gray-matter": "4.0.3",
|
||||||
"lodash-es": "^4.17.23",
|
"lodash-es": "^4.17.23",
|
||||||
"unified": "^11.0.5"
|
"unified": "^11.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/core": {
|
"node_modules/@shikijs/core": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.22.0.tgz",
|
||||||
"integrity": "sha512-vWvqi9JNgz1dRL9Nvog5wtx7RuNkf7MEPl2mU/cyUUxJeH1CAr3t+81h8zO8zs7DK6cKLMoU9TvukWIDjP4Lzg==",
|
"integrity": "sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/primitive": "4.0.1",
|
"@shikijs/types": "3.22.0",
|
||||||
"@shikijs/types": "4.0.1",
|
|
||||||
"@shikijs/vscode-textmate": "^10.0.2",
|
"@shikijs/vscode-textmate": "^10.0.2",
|
||||||
"@types/hast": "^3.0.4",
|
"@types/hast": "^3.0.4",
|
||||||
"hast-util-to-html": "^9.0.5"
|
"hast-util-to-html": "^9.0.5"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/engine-javascript": {
|
"node_modules/@shikijs/engine-javascript": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.22.0.tgz",
|
||||||
"integrity": "sha512-DJK9NiwtGYqMuKCRO4Ip0FKNDQpmaiS+K5bFjJ7DWFn4zHueDWgaUG8kAofkrnXF6zPPYYQY7J5FYVW9MbZyBg==",
|
"integrity": "sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/types": "4.0.1",
|
"@shikijs/types": "3.22.0",
|
||||||
"@shikijs/vscode-textmate": "^10.0.2",
|
"@shikijs/vscode-textmate": "^10.0.2",
|
||||||
"oniguruma-to-es": "^4.3.4"
|
"oniguruma-to-es": "^4.3.4"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/engine-oniguruma": {
|
"node_modules/@shikijs/engine-oniguruma": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.22.0.tgz",
|
||||||
"integrity": "sha512-oCWdCTDch3J8Kc0OZJ98KuUPC02O1VqIE3W/e2uvrHqTxYRR21RGEJMtchrgrxhsoJJCzmIciKsqG+q/yD+Cxg==",
|
"integrity": "sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/types": "4.0.1",
|
"@shikijs/types": "3.22.0",
|
||||||
"@shikijs/vscode-textmate": "^10.0.2"
|
"@shikijs/vscode-textmate": "^10.0.2"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/langs": {
|
"node_modules/@shikijs/langs": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.22.0.tgz",
|
||||||
"integrity": "sha512-v/mluaybWdnGJR4GqAR6zh8qAZohW9k+cGYT28Y7M8+jLbC0l4yG085O1A+WkseHTn+awd+P3UBymb2+MXFc8w==",
|
"integrity": "sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/types": "4.0.1"
|
"@shikijs/types": "3.22.0"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@shikijs/primitive": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-ns0hHZc5eWZuvuIEJz2pTx3Qecz0aRVYumVQJ8JgWY2tq/dH8WxdcVM49Fc2NsHEILNIT6vfdW9MF26RANWiTA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@shikijs/types": "4.0.1",
|
|
||||||
"@shikijs/vscode-textmate": "^10.0.2",
|
|
||||||
"@types/hast": "^3.0.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/rehype": {
|
"node_modules/@shikijs/rehype": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/rehype/-/rehype-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/rehype/-/rehype-3.22.0.tgz",
|
||||||
"integrity": "sha512-bx7bYA0/p/pgeEICaPO0jT6TXrXHmr9tGRUDhOMy1cAUN2YA0iANfXX7seBnImy8DGu/rxm1ij9/ZofYrAaUjQ==",
|
"integrity": "sha512-69b2VPc6XBy/VmAJlpBU5By+bJSBdE2nvgRCZXav7zujbrjXuT0F60DIrjKuutjPqNufuizE+E8tIZr2Yn8Z+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/types": "4.0.1",
|
"@shikijs/types": "3.22.0",
|
||||||
"@types/hast": "^3.0.4",
|
"@types/hast": "^3.0.4",
|
||||||
"hast-util-to-string": "^3.0.1",
|
"hast-util-to-string": "^3.0.1",
|
||||||
"shiki": "4.0.1",
|
"shiki": "3.22.0",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
"unist-util-visit": "^5.1.0"
|
"unist-util-visit": "^5.1.0"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/themes": {
|
"node_modules/@shikijs/themes": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.22.0.tgz",
|
||||||
"integrity": "sha512-FW41C/D6j/yKQkzVdjrRPiJCtgeDaYRJFEyCKFCINuRJRj9WcmubhP4KQHPZ4+9eT87jruSrYPyoblNRyDFzvA==",
|
"integrity": "sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/types": "4.0.1"
|
"@shikijs/types": "3.22.0"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/types": {
|
"node_modules/@shikijs/types": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.22.0.tgz",
|
||||||
"integrity": "sha512-EaygPEn57+jJ76mw+nTLvIpJMAcMPokFbrF8lufsZP7Ukk+ToJYEcswN1G0e49nUZAq7aCQtoeW219A8HK1ZOw==",
|
"integrity": "sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/vscode-textmate": "^10.0.2",
|
"@shikijs/vscode-textmate": "^10.0.2",
|
||||||
"@types/hast": "^3.0.4"
|
"@types/hast": "^3.0.4"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shikijs/vscode-textmate": {
|
"node_modules/@shikijs/vscode-textmate": {
|
||||||
@@ -586,9 +557,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.19",
|
"version": "0.5.18",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz",
|
||||||
"integrity": "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==",
|
"integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -693,13 +664,13 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/@unhead/react": {
|
"node_modules/@unhead/react": {
|
||||||
"version": "2.1.10",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@unhead/react/-/react-2.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/@unhead/react/-/react-2.1.4.tgz",
|
||||||
"integrity": "sha512-z9IzzkaCI1GyiBwVRMt4dGc2mOvsj9drbAdXGMy6DWpu9FwTR37ZTmAi7UeCVyIkpVdIaNalz7vkbvGG8afFng==",
|
"integrity": "sha512-3DzMi5nJkUyLVfQF/q78smCvcSy84TTYgTwXVz5s3AjUcLyHro5Z7bLWriwk1dn5+YRfEsec8aPkLCMi5VjMZg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"unhead": "2.1.10"
|
"unhead": "2.1.4"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/harlan-zw"
|
"url": "https://github.com/sponsors/harlan-zw"
|
||||||
@@ -810,13 +781,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cac": {
|
"node_modules/cac": {
|
||||||
"version": "7.0.0",
|
"version": "6.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||||
"integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==",
|
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ccount": {
|
"node_modules/ccount": {
|
||||||
@@ -1727,6 +1698,16 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jiti": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "3.14.2",
|
"version": "3.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||||
@@ -3038,23 +3019,10 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-render-to-markdown": {
|
|
||||||
"version": "19.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-render-to-markdown/-/react-render-to-markdown-19.0.1.tgz",
|
|
||||||
"integrity": "sha512-BPv48o+ubcu2JyUDIktvJXFqLIZqR7hA4mvGu1eFIofz9fogT2me9UvXwRvqvGs9jEtNaJkxZIUKUX0oiK4hDA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"react-reconciler": "0.33.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=19"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.13.1",
|
"version": "7.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz",
|
||||||
"integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==",
|
"integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3075,13 +3043,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "7.13.1",
|
"version": "7.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz",
|
||||||
"integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==",
|
"integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-router": "7.13.1"
|
"react-router": "7.13.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
@@ -3377,23 +3345,20 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/shiki": {
|
"node_modules/shiki": {
|
||||||
"version": "4.0.1",
|
"version": "3.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/shiki/-/shiki-3.22.0.tgz",
|
||||||
"integrity": "sha512-EkAEhDTN5WhpoQFXFw79OHIrSAfHhlImeCdSyg4u4XvrpxKEmdo/9x/HWSowujAnUrFsGOwWiE58a6GVentMnQ==",
|
"integrity": "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shikijs/core": "4.0.1",
|
"@shikijs/core": "3.22.0",
|
||||||
"@shikijs/engine-javascript": "4.0.1",
|
"@shikijs/engine-javascript": "3.22.0",
|
||||||
"@shikijs/engine-oniguruma": "4.0.1",
|
"@shikijs/engine-oniguruma": "3.22.0",
|
||||||
"@shikijs/langs": "4.0.1",
|
"@shikijs/langs": "3.22.0",
|
||||||
"@shikijs/themes": "4.0.1",
|
"@shikijs/themes": "3.22.0",
|
||||||
"@shikijs/types": "4.0.1",
|
"@shikijs/types": "3.22.0",
|
||||||
"@shikijs/vscode-textmate": "^10.0.2",
|
"@shikijs/vscode-textmate": "^10.0.2",
|
||||||
"@types/hast": "^3.0.4"
|
"@types/hast": "^3.0.4"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
@@ -3598,9 +3563,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unhead": {
|
"node_modules/unhead": {
|
||||||
"version": "2.1.10",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/unhead/-/unhead-2.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/unhead/-/unhead-2.1.4.tgz",
|
||||||
"integrity": "sha512-We8l9uNF8zz6U8lfQaVG70+R/QBfQx1oPIgXin4BtZnK2IQpz6yazQ0qjMNVBDw2ADgF2ea58BtvSK+XX5AS7g==",
|
"integrity": "sha512-+5091sJqtNNmgfQ07zJOgUnMIMKzVKAWjeMlSrTdSGPB6JSozhpjUKuMfWEoLxlMAfhIvgOU8Me0XJvmMA/0fA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use conduwuit::{Err, Result, utils::response::LimitReadExt};
|
use conduwuit::{Err, Result};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{OwnedRoomId, OwnedServerName, OwnedUserId};
|
use ruma::{OwnedRoomId, OwnedServerName, OwnedUserId};
|
||||||
|
|
||||||
@@ -30,15 +30,12 @@ pub(super) async fn incoming_federation(&self) -> Result {
|
|||||||
.federation_handletime
|
.federation_handletime
|
||||||
.read();
|
.read();
|
||||||
|
|
||||||
let mut msg = format!(
|
let mut msg = format!("Handling {} incoming pdus:\n", map.len());
|
||||||
"Handling {} incoming PDUs across {} active transactions:\n",
|
|
||||||
map.len(),
|
|
||||||
self.services.transactions.txn_active_handle_count()
|
|
||||||
);
|
|
||||||
for (r, (e, i)) in map.iter() {
|
for (r, (e, i)) in map.iter() {
|
||||||
let elapsed = i.elapsed();
|
let elapsed = i.elapsed();
|
||||||
writeln!(msg, "{} {}: {}m{}s", r, e, elapsed.as_secs() / 60, elapsed.as_secs() % 60)?;
|
writeln!(msg, "{} {}: {}m{}s", r, e, elapsed.as_secs() / 60, elapsed.as_secs() % 60)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg
|
msg
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,15 +52,7 @@ pub(super) async fn fetch_support_well_known(&self, server_name: OwnedServerName
|
|||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let text = response
|
let text = response.text().await?;
|
||||||
.limit_read_text(
|
|
||||||
self.services
|
|
||||||
.config
|
|
||||||
.max_request_size
|
|
||||||
.try_into()
|
|
||||||
.expect("u64 fits into usize"),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
return Err!("Response text/body is empty.");
|
return Err!("Response text/body is empty.");
|
||||||
|
|||||||
@@ -29,9 +29,7 @@ pub(super) async fn delete(
|
|||||||
.delete(&mxc.as_str().try_into()?)
|
.delete(&mxc.as_str().try_into()?)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
return self
|
return Err!("Deleted the MXC from our database and on our filesystem.",);
|
||||||
.write_str("Deleted the MXC from our database and on our filesystem.")
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(event_id) = event_id {
|
if let Some(event_id) = event_id {
|
||||||
@@ -390,19 +388,3 @@ pub(super) async fn get_remote_thumbnail(
|
|||||||
self.write_str(&format!("```\n{result:#?}\nreceived {len} bytes for file content.\n```"))
|
self.write_str(&format!("```\n{result:#?}\nreceived {len} bytes for file content.\n```"))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[admin_command]
|
|
||||||
pub(super) async fn delete_url_preview(&self, url: Option<String>, all: bool) -> Result {
|
|
||||||
if all {
|
|
||||||
self.services.media.clear_url_previews().await;
|
|
||||||
|
|
||||||
return self.write_str("Deleted all cached URL previews.").await;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = url.expect("clap enforces url is required unless --all");
|
|
||||||
|
|
||||||
self.services.media.remove_url_preview(&url).await?;
|
|
||||||
|
|
||||||
self.write_str(&format!("Deleted cached URL preview for: {url}"))
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-13
@@ -40,7 +40,7 @@ pub enum MediaCommand {
|
|||||||
/// * Delete all remote and local media from 3 days ago, up until now:
|
/// * Delete all remote and local media from 3 days ago, up until now:
|
||||||
///
|
///
|
||||||
/// `!admin media delete-past-remote-media -a 3d
|
/// `!admin media delete-past-remote-media -a 3d
|
||||||
///--yes-i-want-to-delete-local-media`
|
///-yes-i-want-to-delete-local-media`
|
||||||
#[command(verbatim_doc_comment)]
|
#[command(verbatim_doc_comment)]
|
||||||
DeletePastRemoteMedia {
|
DeletePastRemoteMedia {
|
||||||
/// The relative time (e.g. 30s, 5m, 7d) from now within which to
|
/// The relative time (e.g. 30s, 5m, 7d) from now within which to
|
||||||
@@ -108,16 +108,4 @@ pub enum MediaCommand {
|
|||||||
#[arg(long, default_value("800"))]
|
#[arg(long, default_value("800"))]
|
||||||
height: u32,
|
height: u32,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Deletes a cached URL preview, forcing it to be re-fetched.
|
|
||||||
/// Use --all to purge all cached URL previews.
|
|
||||||
DeleteUrlPreview {
|
|
||||||
/// The URL to clear from the saved preview data
|
|
||||||
#[arg(required_unless_present = "all")]
|
|
||||||
url: Option<String>,
|
|
||||||
|
|
||||||
/// Purge all cached URL previews
|
|
||||||
#[arg(long, conflicts_with = "url")]
|
|
||||||
all: bool,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ pub(super) async fn compact(
|
|||||||
let parallelism = parallelism.unwrap_or(1);
|
let parallelism = parallelism.unwrap_or(1);
|
||||||
let results = maps
|
let results = maps
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_stream::<conduwuit::Error>()
|
.try_stream()
|
||||||
.paralleln_and_then(runtime, parallelism, move |map| {
|
.paralleln_and_then(runtime, parallelism, move |map| {
|
||||||
map.compact_blocking(options.clone())?;
|
map.compact_blocking(options.clone())?;
|
||||||
Ok(map.name().to_owned())
|
Ok(map.name().to_owned())
|
||||||
|
|||||||
@@ -20,17 +20,7 @@ pub enum ResolverCommand {
|
|||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Flush a given server from the resolver caches or flush them completely
|
/// Flush a specific server from the resolver caches or everything
|
||||||
///
|
|
||||||
/// * Examples:
|
|
||||||
/// * Flush a specific server:
|
|
||||||
///
|
|
||||||
/// `!admin query resolver flush-cache matrix.example.com`
|
|
||||||
///
|
|
||||||
/// * Flush all resolver caches completely:
|
|
||||||
///
|
|
||||||
/// `!admin query resolver flush-cache --all`
|
|
||||||
#[command(verbatim_doc_comment)]
|
|
||||||
FlushCache {
|
FlushCache {
|
||||||
name: Option<OwnedServerName>,
|
name: Option<OwnedServerName>,
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::fmt::Write;
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Event, Result, debug_info, err, error, info,
|
Err, Event, Result, debug_info, err, error, info,
|
||||||
matrix::pdu::PduBuilder,
|
matrix::pdu::PduBuilder,
|
||||||
utils::{self, ReadyExt, stream::BroadbandExt},
|
utils::{self, ReadyExt, stream::BroadbandExt},
|
||||||
warn,
|
warn,
|
||||||
@@ -387,7 +387,7 @@ pub(crate) async fn register_route(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
},
|
},
|
||||||
@@ -401,7 +401,7 @@ pub(crate) async fn register_route(
|
|||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
json,
|
json,
|
||||||
);
|
);
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err!(Request(NotJson("JSON body is not valid")));
|
return Err!(Request(NotJson("JSON body is not valid")));
|
||||||
@@ -661,7 +661,7 @@ pub(crate) async fn change_password_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success!
|
// Success!
|
||||||
@@ -673,7 +673,7 @@ pub(crate) async fn change_password_route(
|
|||||||
.uiaa
|
.uiaa
|
||||||
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
||||||
|
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err!(Request(NotJson("JSON body is not valid")));
|
return Err!(Request(NotJson("JSON body is not valid")));
|
||||||
@@ -791,7 +791,7 @@ pub(crate) async fn deactivate_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
},
|
},
|
||||||
@@ -802,7 +802,7 @@ pub(crate) async fn deactivate_route(
|
|||||||
.uiaa
|
.uiaa
|
||||||
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
||||||
|
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err!(Request(NotJson("JSON body is not valid")));
|
return Err!(Request(NotJson("JSON body is not valid")));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
events::{
|
events::{
|
||||||
AnyGlobalAccountDataEventContent, AnyRoomAccountDataEventContent,
|
AnyGlobalAccountDataEventContent, AnyRoomAccountDataEventContent,
|
||||||
RoomAccountDataEventType,
|
GlobalAccountDataEventType, RoomAccountDataEventType,
|
||||||
},
|
},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
};
|
};
|
||||||
@@ -126,6 +126,12 @@ async fn set_account_data(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event_type_s == GlobalAccountDataEventType::PushRules.to_cow_str() {
|
||||||
|
return Err!(Request(BadJson(
|
||||||
|
"This endpoint cannot be used for setting/configuring push rules."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let data: serde_json::Value = serde_json::from_str(data.get())
|
let data: serde_json::Value = serde_json::from_str(data.get())
|
||||||
.map_err(|e| err!(Request(BadJson(warn!("Invalid JSON provided: {e}")))))?;
|
.map_err(|e| err!(Request(BadJson(warn!("Invalid JSON provided: {e}")))))?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
use axum::extract::State;
|
|
||||||
use axum_client_ip::InsecureClientIp;
|
|
||||||
use conduwuit::{Err, Result, at};
|
|
||||||
use futures::StreamExt;
|
|
||||||
use ruma::api::client::dehydrated_device::{
|
|
||||||
delete_dehydrated_device::unstable as delete_dehydrated_device,
|
|
||||||
get_dehydrated_device::unstable as get_dehydrated_device, get_events::unstable as get_events,
|
|
||||||
put_dehydrated_device::unstable as put_dehydrated_device,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::Ruma;
|
|
||||||
|
|
||||||
const MAX_BATCH_EVENTS: usize = 50;
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/../dehydrated_device`
|
|
||||||
///
|
|
||||||
/// Creates or overwrites the user's dehydrated device.
|
|
||||||
#[tracing::instrument(skip_all, fields(%client))]
|
|
||||||
pub(crate) async fn put_dehydrated_device_route(
|
|
||||||
State(services): State<crate::State>,
|
|
||||||
InsecureClientIp(client): InsecureClientIp,
|
|
||||||
body: Ruma<put_dehydrated_device::Request>,
|
|
||||||
) -> Result<put_dehydrated_device::Response> {
|
|
||||||
let sender_user = body
|
|
||||||
.sender_user
|
|
||||||
.as_deref()
|
|
||||||
.expect("AccessToken authentication required");
|
|
||||||
|
|
||||||
let device_id = body.body.device_id.clone();
|
|
||||||
|
|
||||||
services
|
|
||||||
.users
|
|
||||||
.set_dehydrated_device(sender_user, body.body)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(put_dehydrated_device::Response { device_id })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/../dehydrated_device`
|
|
||||||
///
|
|
||||||
/// Deletes the user's dehydrated device without replacement.
|
|
||||||
#[tracing::instrument(skip_all, fields(%client))]
|
|
||||||
pub(crate) async fn delete_dehydrated_device_route(
|
|
||||||
State(services): State<crate::State>,
|
|
||||||
InsecureClientIp(client): InsecureClientIp,
|
|
||||||
body: Ruma<delete_dehydrated_device::Request>,
|
|
||||||
) -> Result<delete_dehydrated_device::Response> {
|
|
||||||
let sender_user = body.sender_user();
|
|
||||||
|
|
||||||
let device_id = services.users.get_dehydrated_device_id(sender_user).await?;
|
|
||||||
|
|
||||||
services.users.remove_device(sender_user, &device_id).await;
|
|
||||||
|
|
||||||
Ok(delete_dehydrated_device::Response { device_id })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/../dehydrated_device`
|
|
||||||
///
|
|
||||||
/// Gets the user's dehydrated device
|
|
||||||
#[tracing::instrument(skip_all, fields(%client))]
|
|
||||||
pub(crate) async fn get_dehydrated_device_route(
|
|
||||||
State(services): State<crate::State>,
|
|
||||||
InsecureClientIp(client): InsecureClientIp,
|
|
||||||
body: Ruma<get_dehydrated_device::Request>,
|
|
||||||
) -> Result<get_dehydrated_device::Response> {
|
|
||||||
let sender_user = body.sender_user();
|
|
||||||
|
|
||||||
let device = services.users.get_dehydrated_device(sender_user).await?;
|
|
||||||
|
|
||||||
Ok(get_dehydrated_device::Response {
|
|
||||||
device_id: device.device_id,
|
|
||||||
device_data: device.device_data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/../dehydrated_device/{device_id}/events`
|
|
||||||
///
|
|
||||||
/// Paginates the events of the dehydrated device.
|
|
||||||
#[tracing::instrument(skip_all, fields(%client))]
|
|
||||||
pub(crate) async fn get_dehydrated_events_route(
|
|
||||||
State(services): State<crate::State>,
|
|
||||||
InsecureClientIp(client): InsecureClientIp,
|
|
||||||
body: Ruma<get_events::Request>,
|
|
||||||
) -> Result<get_events::Response> {
|
|
||||||
let sender_user = body.sender_user();
|
|
||||||
|
|
||||||
let device_id = &body.body.device_id;
|
|
||||||
let existing_id = services.users.get_dehydrated_device_id(sender_user).await;
|
|
||||||
|
|
||||||
if existing_id.as_ref().is_err()
|
|
||||||
|| existing_id
|
|
||||||
.as_ref()
|
|
||||||
.is_ok_and(|existing_id| existing_id != device_id)
|
|
||||||
{
|
|
||||||
return Err!(Request(Forbidden("Not the dehydrated device_id.")));
|
|
||||||
}
|
|
||||||
|
|
||||||
let since: Option<u64> = body
|
|
||||||
.body
|
|
||||||
.next_batch
|
|
||||||
.as_deref()
|
|
||||||
.map(str::parse)
|
|
||||||
.transpose()?;
|
|
||||||
|
|
||||||
let mut next_batch: Option<u64> = None;
|
|
||||||
let events = services
|
|
||||||
.users
|
|
||||||
.get_to_device_events(sender_user, device_id, since, None)
|
|
||||||
.take(MAX_BATCH_EVENTS)
|
|
||||||
.inspect(|&(count, _)| {
|
|
||||||
next_batch.replace(count);
|
|
||||||
})
|
|
||||||
.map(at!(1))
|
|
||||||
.collect()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(get_events::Response {
|
|
||||||
events,
|
|
||||||
next_batch: next_batch.as_ref().map(ToString::to_string),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{Err, Error, Result, debug, err, utils};
|
use conduwuit::{Err, Result, debug, err, utils};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
MilliSecondsSinceUnixEpoch, OwnedDeviceId,
|
MilliSecondsSinceUnixEpoch, OwnedDeviceId,
|
||||||
@@ -232,7 +232,7 @@ pub(crate) async fn delete_devices_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
},
|
},
|
||||||
@@ -243,10 +243,10 @@ pub(crate) async fn delete_devices_route(
|
|||||||
.uiaa
|
.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, json);
|
.create(sender_user, sender_device, &uiaainfo, json);
|
||||||
|
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err!(BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Result, debug, debug_warn, err,
|
Err, Result, debug, debug_warn, err,
|
||||||
result::NotFound,
|
result::NotFound,
|
||||||
utils,
|
utils,
|
||||||
utils::{IterStream, stream::WidebandExt},
|
utils::{IterStream, stream::WidebandExt},
|
||||||
@@ -215,7 +215,7 @@ pub(crate) async fn upload_signing_keys_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
},
|
},
|
||||||
@@ -226,10 +226,10 @@ pub(crate) async fn upload_signing_keys_route(
|
|||||||
.uiaa
|
.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, json);
|
.create(sender_user, sender_device, &uiaainfo, json);
|
||||||
|
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err!(BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -396,12 +396,12 @@ pub(crate) async fn get_key_changes_route(
|
|||||||
let from = body
|
let from = body
|
||||||
.from
|
.from
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `from`."))?;
|
.map_err(|_| err!(BadRequest(ErrorKind::InvalidParam, "Invalid `from`.")))?;
|
||||||
|
|
||||||
let to = body
|
let to = body
|
||||||
.to
|
.to
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `to`."))?;
|
.map_err(|_| err!(BadRequest(ErrorKind::InvalidParam, "Invalid `to`.")))?;
|
||||||
|
|
||||||
device_list_updates.extend(
|
device_list_updates.extend(
|
||||||
services
|
services
|
||||||
|
|||||||
+5
-27
@@ -3,10 +3,9 @@ use std::time::Duration;
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Result, err,
|
Err, Result, err, error,
|
||||||
utils::{self, content_disposition::make_content_disposition, math::ruma_from_usize},
|
utils::{self, content_disposition::make_content_disposition, math::ruma_from_usize},
|
||||||
};
|
};
|
||||||
use conduwuit_core::error;
|
|
||||||
use conduwuit_service::{
|
use conduwuit_service::{
|
||||||
Services,
|
Services,
|
||||||
media::{CACHE_CONTROL_IMMUTABLE, CORP_CROSS_ORIGIN, Dim, FileMeta, MXC_LENGTH},
|
media::{CACHE_CONTROL_IMMUTABLE, CORP_CROSS_ORIGIN, Dim, FileMeta, MXC_LENGTH},
|
||||||
@@ -70,7 +69,7 @@ pub(crate) async fn create_content_route(
|
|||||||
.create(mxc, Some(user), Some(&content_disposition), content_type, &body.file)
|
.create(mxc, Some(user), Some(&content_disposition), content_type, &body.file)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
err!("Failed to save uploaded media: {e}");
|
error!("Failed to save uploaded media: {e}");
|
||||||
return Err!(Request(Unknown("Failed to save uploaded media")));
|
return Err!(Request(Unknown("Failed to save uploaded media")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,22 +144,12 @@ pub(crate) async fn get_content_route(
|
|||||||
server_name: &body.server_name,
|
server_name: &body.server_name,
|
||||||
media_id: &body.media_id,
|
media_id: &body.media_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let FileMeta {
|
let FileMeta {
|
||||||
content,
|
content,
|
||||||
content_type,
|
content_type,
|
||||||
content_disposition,
|
content_disposition,
|
||||||
} = match fetch_file(&services, &mxc, user, body.timeout_ms, None).await {
|
} = fetch_file(&services, &mxc, user, body.timeout_ms, None).await?;
|
||||||
| Ok(meta) => meta,
|
|
||||||
| Err(conduwuit::Error::Io(e)) => match e.kind() {
|
|
||||||
| std::io::ErrorKind::NotFound => return Err!(Request(NotFound("Media not found."))),
|
|
||||||
| std::io::ErrorKind::PermissionDenied => {
|
|
||||||
error!("Permission denied when trying to read file: {e:?}");
|
|
||||||
return Err!(Request(Unknown("Unknown error when fetching file.")));
|
|
||||||
},
|
|
||||||
| _ => return Err!(Request(Unknown("Unknown error when fetching file."))),
|
|
||||||
},
|
|
||||||
| Err(_) => return Err!(Request(Unknown("Unknown error when fetching file."))),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(get_content::v1::Response {
|
Ok(get_content::v1::Response {
|
||||||
file: content.expect("entire file contents"),
|
file: content.expect("entire file contents"),
|
||||||
@@ -196,18 +185,7 @@ pub(crate) async fn get_content_as_filename_route(
|
|||||||
content,
|
content,
|
||||||
content_type,
|
content_type,
|
||||||
content_disposition,
|
content_disposition,
|
||||||
} = match fetch_file(&services, &mxc, user, body.timeout_ms, None).await {
|
} = fetch_file(&services, &mxc, user, body.timeout_ms, Some(&body.filename)).await?;
|
||||||
| Ok(meta) => meta,
|
|
||||||
| Err(conduwuit::Error::Io(e)) => match e.kind() {
|
|
||||||
| std::io::ErrorKind::NotFound => return Err!(Request(NotFound("Media not found."))),
|
|
||||||
| std::io::ErrorKind::PermissionDenied => {
|
|
||||||
error!("Permission denied when trying to read file: {e:?}");
|
|
||||||
return Err!(Request(Unknown("Unknown error when fetching file.")));
|
|
||||||
},
|
|
||||||
| _ => return Err!(Request(Unknown("Unknown error when fetching file."))),
|
|
||||||
},
|
|
||||||
| Err(_) => return Err!(Request(Unknown("Unknown error when fetching file."))),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(get_content_as_filename::v1::Response {
|
Ok(get_content_as_filename::v1::Response {
|
||||||
file: content.expect("entire file contents"),
|
file: content.expect("entire file contents"),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Result, at, debug_warn,
|
Err, Result, at, debug_warn,
|
||||||
matrix::{
|
matrix::{
|
||||||
event::{Event, Matches},
|
event::{Event, Matches},
|
||||||
pdu::PduCount,
|
pdu::PduCount,
|
||||||
@@ -322,7 +322,7 @@ where
|
|||||||
|
|
||||||
if server_ignored {
|
if server_ignored {
|
||||||
// the sender's server is ignored, so ignore this event
|
// the sender's server is ignored, so ignore this event
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::SenderIgnored { sender: None },
|
ErrorKind::SenderIgnored { sender: None },
|
||||||
"The sender's server is ignored by this server.",
|
"The sender's server is ignored by this server.",
|
||||||
));
|
));
|
||||||
@@ -331,7 +331,7 @@ where
|
|||||||
if user_ignored && !services.config.send_messages_from_ignored_users_to_client {
|
if user_ignored && !services.config.send_messages_from_ignored_users_to_client {
|
||||||
// the recipient of this PDU has the sender ignored, and we're not
|
// the recipient of this PDU has the sender ignored, and we're not
|
||||||
// configured to send ignored messages to clients
|
// configured to send ignored messages to clients
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::SenderIgnored { sender: Some(event.sender().to_owned()) },
|
ErrorKind::SenderIgnored { sender: Some(event.sender().to_owned()) },
|
||||||
"You have ignored this sender.",
|
"You have ignored this sender.",
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ pub(super) mod appservice;
|
|||||||
pub(super) mod backup;
|
pub(super) mod backup;
|
||||||
pub(super) mod capabilities;
|
pub(super) mod capabilities;
|
||||||
pub(super) mod context;
|
pub(super) mod context;
|
||||||
pub(super) mod dehydrated_device;
|
|
||||||
pub(super) mod device;
|
pub(super) mod device;
|
||||||
pub(super) mod directory;
|
pub(super) mod directory;
|
||||||
pub(super) mod filter;
|
pub(super) mod filter;
|
||||||
@@ -50,7 +49,6 @@ pub(super) use appservice::*;
|
|||||||
pub(super) use backup::*;
|
pub(super) use backup::*;
|
||||||
pub(super) use capabilities::*;
|
pub(super) use capabilities::*;
|
||||||
pub(super) use context::*;
|
pub(super) use context::*;
|
||||||
pub(super) use dehydrated_device::*;
|
|
||||||
pub(super) use device::*;
|
pub(super) use device::*;
|
||||||
pub(super) use directory::*;
|
pub(super) use directory::*;
|
||||||
pub(super) use filter::*;
|
pub(super) use filter::*;
|
||||||
|
|||||||
+16
-16
@@ -1,5 +1,5 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Err, Error, Result, err};
|
use conduwuit::{Err, Result, err};
|
||||||
use conduwuit_service::Services;
|
use conduwuit_service::Services;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
CanonicalJsonObject, CanonicalJsonValue,
|
CanonicalJsonObject, CanonicalJsonValue,
|
||||||
@@ -243,27 +243,27 @@ pub(crate) async fn set_pushrule_route(
|
|||||||
body.before.as_deref(),
|
body.before.as_deref(),
|
||||||
) {
|
) {
|
||||||
let err = match error {
|
let err = match error {
|
||||||
| InsertPushRuleError::ServerDefaultRuleId => Error::BadRequest(
|
| InsertPushRuleError::ServerDefaultRuleId => err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Rule IDs starting with a dot are reserved for server-default rules.",
|
"Rule IDs starting with a dot are reserved for server-default rules.",
|
||||||
),
|
)),
|
||||||
| InsertPushRuleError::InvalidRuleId => Error::BadRequest(
|
| InsertPushRuleError::InvalidRuleId => err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Rule ID containing invalid characters.",
|
"Rule ID containing invalid characters.",
|
||||||
),
|
)),
|
||||||
| InsertPushRuleError::RelativeToServerDefaultRule => Error::BadRequest(
|
| InsertPushRuleError::RelativeToServerDefaultRule => err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Can't place a push rule relatively to a server-default rule.",
|
"Can't place a push rule relatively to a server-default rule.",
|
||||||
),
|
)),
|
||||||
| InsertPushRuleError::UnknownRuleId => Error::BadRequest(
|
| InsertPushRuleError::UnknownRuleId => err!(BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"The before or after rule could not be found.",
|
"The before or after rule could not be found.",
|
||||||
),
|
)),
|
||||||
| InsertPushRuleError::BeforeHigherThanAfter => Error::BadRequest(
|
| InsertPushRuleError::BeforeHigherThanAfter => err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"The before rule has a higher priority than the after rule.",
|
"The before rule has a higher priority than the after rule.",
|
||||||
),
|
)),
|
||||||
| _ => Error::BadRequest(ErrorKind::InvalidParam, "Invalid data."),
|
| _ => err!(BadRequest(ErrorKind::InvalidParam, "Invalid data.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Err(err);
|
return Err(err);
|
||||||
@@ -433,13 +433,13 @@ pub(crate) async fn delete_pushrule_route(
|
|||||||
.remove(body.kind.clone(), &body.rule_id)
|
.remove(body.kind.clone(), &body.rule_id)
|
||||||
{
|
{
|
||||||
let err = match error {
|
let err = match error {
|
||||||
| RemovePushRuleError::ServerDefault => Error::BadRequest(
|
| RemovePushRuleError::ServerDefault => err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Cannot delete a server-default pushrule.",
|
"Cannot delete a server-default pushrule.",
|
||||||
),
|
)),
|
||||||
| RemovePushRuleError::NotFound =>
|
| RemovePushRuleError::NotFound =>
|
||||||
Error::BadRequest(ErrorKind::NotFound, "Push rule not found."),
|
err!(BadRequest(ErrorKind::NotFound, "Push rule not found.")),
|
||||||
| _ => Error::BadRequest(ErrorKind::InvalidParam, "Invalid data."),
|
| _ => err!(BadRequest(ErrorKind::InvalidParam, "Invalid data.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::cmp::max;
|
|||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Event, Result, RoomVersion, debug, err, info,
|
Err, Event, Result, RoomVersion, debug, err, info,
|
||||||
matrix::{StateKey, pdu::PduBuilder},
|
matrix::{StateKey, pdu::PduBuilder},
|
||||||
};
|
};
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
@@ -58,7 +58,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if !services.server.supported_room_version(&body.new_version) {
|
if !services.server.supported_room_version(&body.new_version) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::UnsupportedRoomVersion,
|
ErrorKind::UnsupportedRoomVersion,
|
||||||
"This server does not support that room version.",
|
"This server does not support that room version.",
|
||||||
));
|
));
|
||||||
@@ -170,7 +170,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
"creator".into(),
|
"creator".into(),
|
||||||
json!(&sender_user).try_into().map_err(|e| {
|
json!(&sender_user).try_into().map_err(|e| {
|
||||||
info!("Error forming creation event: {e}");
|
info!("Error forming creation event: {e}");
|
||||||
Error::BadRequest(ErrorKind::BadJson, "Error forming creation event")
|
err!(BadRequest(ErrorKind::BadJson, "Error forming creation event"))
|
||||||
})?,
|
})?,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -186,13 +186,13 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
"room_version".into(),
|
"room_version".into(),
|
||||||
json!(&body.new_version)
|
json!(&body.new_version)
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
|
.map_err(|_| err!(BadRequest(ErrorKind::BadJson, "Error forming creation event")))?,
|
||||||
);
|
);
|
||||||
create_event_content.insert(
|
create_event_content.insert(
|
||||||
"predecessor".into(),
|
"predecessor".into(),
|
||||||
json!(predecessor)
|
json!(predecessor)
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
|
.map_err(|_| err!(BadRequest(ErrorKind::BadJson, "Error forming creation event")))?,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Validate creation event content
|
// Validate creation event content
|
||||||
@@ -203,7 +203,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
)
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
|
return Err!(BadRequest(ErrorKind::BadJson, "Error forming creation event"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let create_event_id = services
|
let create_event_id = services
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ pub(crate) async fn send_message_event_route(
|
|||||||
|
|
||||||
// Check if this is a new transaction id
|
// Check if this is a new transaction id
|
||||||
if let Ok(response) = services
|
if let Ok(response) = services
|
||||||
.transactions
|
.transaction_ids
|
||||||
.get_client_txn(sender_user, sender_device, &body.txn_id)
|
.existing_txnid(sender_user, sender_device, &body.txn_id)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// The client might have sent a txnid of the /sendToDevice endpoint
|
// The client might have sent a txnid of the /sendToDevice endpoint
|
||||||
@@ -92,7 +92,7 @@ pub(crate) async fn send_message_event_route(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
services.transactions.add_client_txnid(
|
services.transaction_ids.add_txnid(
|
||||||
sender_user,
|
sender_user,
|
||||||
sender_device,
|
sender_device,
|
||||||
&body.txn_id,
|
&body.txn_id,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::time::Duration;
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Result, debug, err, info,
|
Err, Result, debug, err, info,
|
||||||
utils::{self, ReadyExt, hash},
|
utils::{self, ReadyExt, hash},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -191,7 +191,7 @@ pub(crate) async fn handle_login(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if services.users.is_locked(&user_id).await? {
|
if services.users.is_locked(&user_id).await? {
|
||||||
return Err(Error::BadRequest(ErrorKind::UserLocked, "This account has been locked."));
|
return Err!(BadRequest(ErrorKind::UserLocked, "This account has been locked."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.users.is_login_disabled(&user_id).await {
|
if services.users.is_login_disabled(&user_id).await {
|
||||||
@@ -390,7 +390,7 @@ pub(crate) async fn login_token_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !worked {
|
if !worked {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success!
|
// Success!
|
||||||
@@ -402,7 +402,7 @@ pub(crate) async fn login_token_route(
|
|||||||
.uiaa
|
.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, json);
|
.create(sender_user, sender_device, &uiaainfo, json);
|
||||||
|
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err!(Uiaa(uiaainfo));
|
||||||
},
|
},
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err!(Request(NotJson("No JSON body was sent when required.")));
|
return Err!(Request(NotJson("No JSON body was sent when required.")));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Event, PduEvent, Result, at, debug_warn,
|
Event, PduCount, PduEvent, Result, at, debug_warn,
|
||||||
pdu::EventHash,
|
pdu::EventHash,
|
||||||
trace,
|
trace,
|
||||||
utils::{self, IterStream, future::ReadyEqExt, stream::WidebandExt as _},
|
utils::{self, IterStream, future::ReadyEqExt, stream::WidebandExt as _},
|
||||||
@@ -68,13 +68,9 @@ pub(super) async fn load_left_room(
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return early if:
|
// return early if this is an incremental sync, and we've already synced this
|
||||||
// - this is an initial sync and the room filter doesn't include leaves, or
|
// leave to the user, and `include_leave` isn't set on the filter.
|
||||||
// - this is an incremental sync, and we've already synced the leave, and the
|
if !filter.room.include_leave && last_sync_end_count >= Some(left_count) {
|
||||||
// room filter doesn't include leaves
|
|
||||||
if last_sync_end_count.is_none_or(|last_sync_end_count| last_sync_end_count >= left_count)
|
|
||||||
&& !filter.room.include_leave
|
|
||||||
{
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,13 +195,27 @@ async fn build_left_state_and_timeline(
|
|||||||
leave_shortstatehash: ShortStateHash,
|
leave_shortstatehash: ShortStateHash,
|
||||||
prev_membership_event: PduEvent,
|
prev_membership_event: PduEvent,
|
||||||
) -> Result<(TimelinePdus, Vec<PduEvent>)> {
|
) -> Result<(TimelinePdus, Vec<PduEvent>)> {
|
||||||
let SyncContext { syncing_user, filter, .. } = sync_context;
|
let SyncContext {
|
||||||
|
syncing_user,
|
||||||
|
last_sync_end_count,
|
||||||
|
filter,
|
||||||
|
..
|
||||||
|
} = sync_context;
|
||||||
|
|
||||||
let timeline_start_count = services
|
let timeline_start_count = if let Some(last_sync_end_count) = last_sync_end_count {
|
||||||
.rooms
|
// for incremental syncs, start the timeline after `since`
|
||||||
.timeline
|
PduCount::Normal(last_sync_end_count)
|
||||||
.get_pdu_count(&prev_membership_event.event_id)
|
} else {
|
||||||
.await?;
|
// for initial syncs, start the timeline after the previous membership
|
||||||
|
// event. we don't want to include the membership event itself
|
||||||
|
// because clients get confused when they see a `join`
|
||||||
|
// membership event in a `leave` room.
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_count(&prev_membership_event.event_id)
|
||||||
|
.await?
|
||||||
|
};
|
||||||
|
|
||||||
// end the timeline at the user's leave event
|
// end the timeline at the user's leave event
|
||||||
let timeline_end_count = services
|
let timeline_end_count = services
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::{
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Result, at, extract_variant,
|
Result, extract_variant,
|
||||||
utils::{
|
utils::{
|
||||||
ReadyExt, TryFutureExtExt,
|
ReadyExt, TryFutureExtExt,
|
||||||
stream::{BroadbandExt, Tools, WidebandExt},
|
stream::{BroadbandExt, Tools, WidebandExt},
|
||||||
@@ -297,18 +297,12 @@ pub(crate) async fn build_sync_events(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.rooms_left(syncing_user)
|
.rooms_left(syncing_user)
|
||||||
.broad_filter_map(|(room_id, leave_pdu)| async {
|
.broad_filter_map(|(room_id, leave_pdu)| {
|
||||||
let left_room = load_left_room(services, context, room_id.clone(), leave_pdu).await;
|
load_left_room(services, context, room_id.clone(), leave_pdu)
|
||||||
|
.map_ok(move |left_room| (room_id, left_room))
|
||||||
match left_room {
|
.ok()
|
||||||
| Ok(Some(left_room)) => Some((room_id, left_room)),
|
|
||||||
| Ok(None) => None,
|
|
||||||
| Err(err) => {
|
|
||||||
warn!(?err, %room_id, "error loading joined room");
|
|
||||||
None
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.ready_filter_map(|(room_id, left_room)| left_room.map(|left_room| (room_id, left_room)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let invited_rooms = services
|
let invited_rooms = services
|
||||||
@@ -391,7 +385,6 @@ pub(crate) async fn build_sync_events(
|
|||||||
last_sync_end_count,
|
last_sync_end_count,
|
||||||
Some(current_count),
|
Some(current_count),
|
||||||
)
|
)
|
||||||
.map(at!(1))
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let device_one_time_keys_count = services
|
let device_one_time_keys_count = services
|
||||||
|
|||||||
@@ -336,9 +336,7 @@ where
|
|||||||
let ranges = list.ranges.clone();
|
let ranges = list.ranges.clone();
|
||||||
|
|
||||||
for mut range in ranges {
|
for mut range in ranges {
|
||||||
range.0 = range
|
range.0 = uint!(0);
|
||||||
.0
|
|
||||||
.min(UInt::try_from(active_rooms.len()).unwrap_or(UInt::MAX));
|
|
||||||
range.1 = range.1.checked_add(uint!(1)).unwrap_or(range.1);
|
range.1 = range.1.checked_add(uint!(1)).unwrap_or(range.1);
|
||||||
range.1 = range
|
range.1 = range
|
||||||
.1
|
.1
|
||||||
@@ -1029,7 +1027,6 @@ async fn collect_to_device(
|
|||||||
events: services
|
events: services
|
||||||
.users
|
.users
|
||||||
.get_to_device_events(sender_user, sender_device, None, Some(next_batch))
|
.get_to_device_events(sender_user, sender_device, None, Some(next_batch))
|
||||||
.map(at!(1))
|
|
||||||
.collect()
|
.collect()
|
||||||
.await,
|
.await,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Result, err};
|
||||||
use conduwuit_service::sending::EduBuf;
|
use conduwuit_service::sending::EduBuf;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
@@ -26,8 +26,8 @@ pub(crate) async fn send_event_to_device_route(
|
|||||||
|
|
||||||
// Check if this is a new transaction id
|
// Check if this is a new transaction id
|
||||||
if services
|
if services
|
||||||
.transactions
|
.transaction_ids
|
||||||
.get_client_txn(sender_user, sender_device, &body.txn_id)
|
.existing_txnid(sender_user, sender_device, &body.txn_id)
|
||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@ pub(crate) async fn send_event_to_device_route(
|
|||||||
|
|
||||||
let event = event
|
let event = event
|
||||||
.deserialize_as()
|
.deserialize_as()
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Event is invalid"))?;
|
.map_err(|_| err!(BadRequest(ErrorKind::InvalidParam, "Event is invalid")))?;
|
||||||
|
|
||||||
match target_device_id_maybe {
|
match target_device_id_maybe {
|
||||||
| DeviceIdOrAllDevices::DeviceId(target_device_id) => {
|
| DeviceIdOrAllDevices::DeviceId(target_device_id) => {
|
||||||
@@ -104,8 +104,8 @@ pub(crate) async fn send_event_to_device_route(
|
|||||||
|
|
||||||
// Save transaction id with empty data
|
// Save transaction id with empty data
|
||||||
services
|
services
|
||||||
.transactions
|
.transaction_ids
|
||||||
.add_client_txnid(sender_user, sender_device, &body.txn_id, &[]);
|
.add_txnid(sender_user, sender_device, &body.txn_id, &[]);
|
||||||
|
|
||||||
Ok(send_event_to_device::v3::Response {})
|
Ok(send_event_to_device::v3::Response {})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ pub(crate) async fn get_supported_versions_route(
|
|||||||
("org.matrix.msc2836".to_owned(), true), /* threading/threads (https://github.com/matrix-org/matrix-spec-proposals/pull/2836) */
|
("org.matrix.msc2836".to_owned(), true), /* threading/threads (https://github.com/matrix-org/matrix-spec-proposals/pull/2836) */
|
||||||
("org.matrix.msc2946".to_owned(), true), /* spaces/hierarchy summaries (https://github.com/matrix-org/matrix-spec-proposals/pull/2946) */
|
("org.matrix.msc2946".to_owned(), true), /* spaces/hierarchy summaries (https://github.com/matrix-org/matrix-spec-proposals/pull/2946) */
|
||||||
("org.matrix.msc3026.busy_presence".to_owned(), true), /* busy presence status (https://github.com/matrix-org/matrix-spec-proposals/pull/3026) */
|
("org.matrix.msc3026.busy_presence".to_owned(), true), /* busy presence status (https://github.com/matrix-org/matrix-spec-proposals/pull/3026) */
|
||||||
("org.matrix.msc3814".to_owned(), true), /* dehydrated devices */
|
|
||||||
("org.matrix.msc3827".to_owned(), true), /* filtering of /publicRooms by room type (https://github.com/matrix-org/matrix-spec-proposals/pull/3827) */
|
("org.matrix.msc3827".to_owned(), true), /* filtering of /publicRooms by room type (https://github.com/matrix-org/matrix-spec-proposals/pull/3827) */
|
||||||
("org.matrix.msc3952_intentional_mentions".to_owned(), true), /* intentional mentions (https://github.com/matrix-org/matrix-spec-proposals/pull/3952) */
|
("org.matrix.msc3952_intentional_mentions".to_owned(), true), /* intentional mentions (https://github.com/matrix-org/matrix-spec-proposals/pull/3952) */
|
||||||
("org.matrix.msc3916.stable".to_owned(), true), /* authenticated media (https://github.com/matrix-org/matrix-spec-proposals/pull/3916) */
|
("org.matrix.msc3916.stable".to_owned(), true), /* authenticated media (https://github.com/matrix-org/matrix-spec-proposals/pull/3916) */
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
use axum::{Json, extract::State, response::IntoResponse};
|
use axum::{Json, extract::State, response::IntoResponse};
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Err, Result};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::discovery::{
|
||||||
discovery::{
|
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
|
||||||
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
|
discover_support::{self, Contact},
|
||||||
discover_support::{self, Contact},
|
|
||||||
},
|
|
||||||
error::ErrorKind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
@@ -19,7 +16,7 @@ pub(crate) async fn well_known_client(
|
|||||||
) -> Result<discover_homeserver::Response> {
|
) -> Result<discover_homeserver::Response> {
|
||||||
let client_url = match services.config.well_known.client.as_ref() {
|
let client_url = match services.config.well_known.client.as_ref() {
|
||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
| None => return Err!(BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(discover_homeserver::Response {
|
Ok(discover_homeserver::Response {
|
||||||
@@ -27,32 +24,10 @@ pub(crate) async fn well_known_client(
|
|||||||
identity_server: None,
|
identity_server: None,
|
||||||
sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }),
|
sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }),
|
||||||
tile_server: None,
|
tile_server: None,
|
||||||
rtc_foci: services
|
rtc_foci: services.config.well_known.rtc_focus_server_urls.clone(),
|
||||||
.config
|
|
||||||
.matrix_rtc
|
|
||||||
.effective_foci(&services.config.well_known.rtc_focus_server_urls)
|
|
||||||
.to_vec(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/v1/rtc/transports`
|
|
||||||
/// # `GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports`
|
|
||||||
///
|
|
||||||
/// Returns the list of MatrixRTC foci (transports) configured for this
|
|
||||||
/// homeserver, implementing MSC4143.
|
|
||||||
pub(crate) async fn get_rtc_transports(
|
|
||||||
State(services): State<crate::State>,
|
|
||||||
_body: Ruma<ruma::api::client::discovery::get_rtc_transports::Request>,
|
|
||||||
) -> Result<ruma::api::client::discovery::get_rtc_transports::Response> {
|
|
||||||
Ok(ruma::api::client::discovery::get_rtc_transports::Response::new(
|
|
||||||
services
|
|
||||||
.config
|
|
||||||
.matrix_rtc
|
|
||||||
.effective_foci(&services.config.well_known.rtc_focus_server_urls)
|
|
||||||
.to_vec(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # `GET /.well-known/matrix/support`
|
/// # `GET /.well-known/matrix/support`
|
||||||
///
|
///
|
||||||
/// Server support contact and support page of a homeserver's domain.
|
/// Server support contact and support page of a homeserver's domain.
|
||||||
@@ -110,7 +85,7 @@ pub(crate) async fn well_known_support(
|
|||||||
|
|
||||||
if contacts.is_empty() && support_page.is_none() {
|
if contacts.is_empty() && support_page.is_none() {
|
||||||
// No admin room, no configured contacts, and no support page
|
// No admin room, no configured contacts, and no support page
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
return Err!(BadRequest(ErrorKind::NotFound, "Not found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(discover_support::Response { contacts, support_page })
|
Ok(discover_support::Response { contacts, support_page })
|
||||||
@@ -127,7 +102,7 @@ pub(crate) async fn syncv3_client_server_json(
|
|||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => match services.config.well_known.server.as_ref() {
|
| None => match services.config.well_known.server.as_ref() {
|
||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
| None => return Err!(BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -160,10 +160,6 @@ pub fn build(router: Router<State>, server: &Server) -> Router<State> {
|
|||||||
.ruma_route(&client::update_device_route)
|
.ruma_route(&client::update_device_route)
|
||||||
.ruma_route(&client::delete_device_route)
|
.ruma_route(&client::delete_device_route)
|
||||||
.ruma_route(&client::delete_devices_route)
|
.ruma_route(&client::delete_devices_route)
|
||||||
.ruma_route(&client::put_dehydrated_device_route)
|
|
||||||
.ruma_route(&client::delete_dehydrated_device_route)
|
|
||||||
.ruma_route(&client::get_dehydrated_device_route)
|
|
||||||
.ruma_route(&client::get_dehydrated_events_route)
|
|
||||||
.ruma_route(&client::get_tags_route)
|
.ruma_route(&client::get_tags_route)
|
||||||
.ruma_route(&client::update_tag_route)
|
.ruma_route(&client::update_tag_route)
|
||||||
.ruma_route(&client::delete_tag_route)
|
.ruma_route(&client::delete_tag_route)
|
||||||
@@ -188,7 +184,6 @@ pub fn build(router: Router<State>, server: &Server) -> Router<State> {
|
|||||||
.ruma_route(&client::put_suspended_status)
|
.ruma_route(&client::put_suspended_status)
|
||||||
.ruma_route(&client::well_known_support)
|
.ruma_route(&client::well_known_support)
|
||||||
.ruma_route(&client::well_known_client)
|
.ruma_route(&client::well_known_client)
|
||||||
.ruma_route(&client::get_rtc_transports)
|
|
||||||
.route("/_conduwuit/server_version", get(client::conduwuit_server_version))
|
.route("/_conduwuit/server_version", get(client::conduwuit_server_version))
|
||||||
.route("/_continuwuity/server_version", get(client::conduwuit_server_version))
|
.route("/_continuwuity/server_version", get(client::conduwuit_server_version))
|
||||||
.ruma_route(&client::room_initial_sync_route)
|
.ruma_route(&client::room_initial_sync_route)
|
||||||
|
|||||||
+28
-46
@@ -4,7 +4,7 @@ use axum_extra::{
|
|||||||
headers::{Authorization, authorization::Bearer},
|
headers::{Authorization, authorization::Bearer},
|
||||||
typed_header::TypedHeaderRejectionReason,
|
typed_header::TypedHeaderRejectionReason,
|
||||||
};
|
};
|
||||||
use conduwuit::{Err, Error, Result, debug_error, err, warn};
|
use conduwuit::{Err, Result, debug_error, err, warn};
|
||||||
use futures::{
|
use futures::{
|
||||||
TryFutureExt,
|
TryFutureExt,
|
||||||
future::{
|
future::{
|
||||||
@@ -14,8 +14,7 @@ use futures::{
|
|||||||
pin_mut,
|
pin_mut,
|
||||||
};
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
CanonicalJsonObject, CanonicalJsonValue, DeviceId, OwnedDeviceId, OwnedServerName,
|
CanonicalJsonObject, CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId,
|
||||||
OwnedUserId, UserId,
|
|
||||||
api::{
|
api::{
|
||||||
AuthScheme, IncomingRequest, Metadata,
|
AuthScheme, IncomingRequest, Metadata,
|
||||||
client::{
|
client::{
|
||||||
@@ -67,17 +66,23 @@ pub(super) async fn auth(
|
|||||||
if metadata.authentication == AuthScheme::None {
|
if metadata.authentication == AuthScheme::None {
|
||||||
match metadata {
|
match metadata {
|
||||||
| &get_public_rooms::v3::Request::METADATA => {
|
| &get_public_rooms::v3::Request::METADATA => {
|
||||||
match token {
|
if !services
|
||||||
| Token::Appservice(_) | Token::User(_) => {
|
.server
|
||||||
// we should have validated the token above
|
.config
|
||||||
// already
|
.allow_public_room_directory_without_auth
|
||||||
},
|
{
|
||||||
| Token::None | Token::Invalid => {
|
match token {
|
||||||
return Err(Error::BadRequest(
|
| Token::Appservice(_) | Token::User(_) => {
|
||||||
ErrorKind::MissingToken,
|
// we should have validated the token above
|
||||||
"Missing or invalid access token.",
|
// already
|
||||||
));
|
},
|
||||||
},
|
| Token::None | Token::Invalid => {
|
||||||
|
return Err!(BadRequest(
|
||||||
|
ErrorKind::MissingToken,
|
||||||
|
"Missing or invalid access token.",
|
||||||
|
));
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
| &get_profile::v3::Request::METADATA
|
| &get_profile::v3::Request::METADATA
|
||||||
@@ -91,7 +96,7 @@ pub(super) async fn auth(
|
|||||||
// already
|
// already
|
||||||
},
|
},
|
||||||
| Token::None | Token::Invalid => {
|
| Token::None | Token::Invalid => {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::MissingToken,
|
ErrorKind::MissingToken,
|
||||||
"Missing or invalid access token.",
|
"Missing or invalid access token.",
|
||||||
));
|
));
|
||||||
@@ -125,10 +130,10 @@ pub(super) async fn auth(
|
|||||||
appservice_info: None,
|
appservice_info: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token."))
|
Err!(BadRequest(ErrorKind::MissingToken, "Missing access token."))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
| _ => Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token.")),
|
| _ => Err!(BadRequest(ErrorKind::MissingToken, "Missing access token.")),
|
||||||
},
|
},
|
||||||
| (
|
| (
|
||||||
AuthScheme::AccessToken | AuthScheme::AccessTokenOptional | AuthScheme::None,
|
AuthScheme::AccessToken | AuthScheme::AccessTokenOptional | AuthScheme::None,
|
||||||
@@ -144,7 +149,7 @@ pub(super) async fn auth(
|
|||||||
&ruma::api::client::session::logout::v3::Request::METADATA
|
&ruma::api::client::session::logout::v3::Request::METADATA
|
||||||
| &ruma::api::client::session::logout_all::v3::Request::METADATA
|
| &ruma::api::client::session::logout_all::v3::Request::METADATA
|
||||||
) {
|
) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::UserLocked,
|
ErrorKind::UserLocked,
|
||||||
"This account has been locked.",
|
"This account has been locked.",
|
||||||
));
|
));
|
||||||
@@ -169,11 +174,11 @@ pub(super) async fn auth(
|
|||||||
appservice_info: None,
|
appservice_info: None,
|
||||||
}),
|
}),
|
||||||
| (AuthScheme::ServerSignatures, Token::Appservice(_) | Token::User(_)) =>
|
| (AuthScheme::ServerSignatures, Token::Appservice(_) | Token::User(_)) =>
|
||||||
Err(Error::BadRequest(
|
Err!(BadRequest(
|
||||||
ErrorKind::Unauthorized,
|
ErrorKind::Unauthorized,
|
||||||
"Only server signatures should be used on this endpoint.",
|
"Only server signatures should be used on this endpoint.",
|
||||||
)),
|
)),
|
||||||
| (AuthScheme::AppserviceToken, Token::User(_)) => Err(Error::BadRequest(
|
| (AuthScheme::AppserviceToken, Token::User(_)) => Err!(BadRequest(
|
||||||
ErrorKind::Unauthorized,
|
ErrorKind::Unauthorized,
|
||||||
"Only appservice access tokens should be used on this endpoint.",
|
"Only appservice access tokens should be used on this endpoint.",
|
||||||
)),
|
)),
|
||||||
@@ -191,13 +196,13 @@ pub(super) async fn auth(
|
|||||||
appservice_info: None,
|
appservice_info: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(
|
Err!(BadRequest(
|
||||||
ErrorKind::UnknownToken { soft_logout: false },
|
ErrorKind::UnknownToken { soft_logout: false },
|
||||||
"Unknown access token.",
|
"Unknown access token.",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
| (_, Token::Invalid) => Err(Error::BadRequest(
|
| (_, Token::Invalid) => Err!(BadRequest(
|
||||||
ErrorKind::UnknownToken { soft_logout: false },
|
ErrorKind::UnknownToken { soft_logout: false },
|
||||||
"Unknown access token.",
|
"Unknown access token.",
|
||||||
)),
|
)),
|
||||||
@@ -229,33 +234,10 @@ async fn auth_appservice(
|
|||||||
return Err!(Request(Exclusive("User is not in namespace.")));
|
return Err!(Request(Exclusive("User is not in namespace.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSC3202/MSC4190: Handle device_id masquerading for appservices.
|
|
||||||
// The device_id can be provided via `device_id` or
|
|
||||||
// `org.matrix.msc3202.device_id` query parameter.
|
|
||||||
let sender_device = if let Some(ref device_id_str) = request.query.device_id {
|
|
||||||
let device_id: &DeviceId = device_id_str.as_str().into();
|
|
||||||
|
|
||||||
// Verify the device exists for this user
|
|
||||||
if services
|
|
||||||
.users
|
|
||||||
.get_device_metadata(&user_id, device_id)
|
|
||||||
.await
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
return Err!(Request(Forbidden(
|
|
||||||
"Device does not exist for user or appservice cannot masquerade as this device."
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(device_id.to_owned())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Auth {
|
Ok(Auth {
|
||||||
origin: None,
|
origin: None,
|
||||||
sender_user: Some(user_id),
|
sender_user: Some(user_id),
|
||||||
sender_device,
|
sender_device: None,
|
||||||
appservice_info: Some(*info),
|
appservice_info: Some(*info),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ use service::Services;
|
|||||||
pub(super) struct QueryParams {
|
pub(super) struct QueryParams {
|
||||||
pub(super) access_token: Option<String>,
|
pub(super) access_token: Option<String>,
|
||||||
pub(super) user_id: Option<String>,
|
pub(super) user_id: Option<String>,
|
||||||
/// Device ID for appservice device masquerading (MSC3202/MSC4190).
|
|
||||||
/// Can be provided as `device_id` or `org.matrix.msc3202.device_id`.
|
|
||||||
#[serde(alias = "org.matrix.msc3202.device_id")]
|
|
||||||
pub(super) device_id: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct Request {
|
pub(super) struct Request {
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
use std::{borrow::Borrow, iter::once};
|
use std::{borrow::Borrow, iter::once};
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Err, Error, Result, info, utils::stream::ReadyExt};
|
use conduwuit::{Err, Error, Result, err, info, utils::stream::ReadyExt};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{RoomId, api::federation::authorization::get_event_authorization};
|
||||||
RoomId,
|
|
||||||
api::{client::error::ErrorKind, federation::authorization::get_event_authorization},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::AccessCheck;
|
use super::AccessCheck;
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
@@ -47,7 +44,7 @@ pub(crate) async fn get_event_authorization_route(
|
|||||||
.timeline
|
.timeline
|
||||||
.get_pdu_json(&body.event_id)
|
.get_pdu_json(&body.event_id)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::NotFound, "Event not found."))?;
|
.map_err(|_| err!(BadRequest(ErrorKind::NotFound, "Event not found.")))?;
|
||||||
|
|
||||||
let room_id_str = event
|
let room_id_str = event
|
||||||
.get("room_id")
|
.get("room_id")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use axum::extract::State;
|
|||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use base64::{Engine as _, engine::general_purpose};
|
use base64::{Engine as _, engine::general_purpose};
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, PduEvent, Result, err, error,
|
Err, PduEvent, Result, err, error,
|
||||||
matrix::{Event, event::gen_event_id},
|
matrix::{Event, event::gen_event_id},
|
||||||
utils::{self, hash::sha256},
|
utils::{self, hash::sha256},
|
||||||
warn,
|
warn,
|
||||||
@@ -33,7 +33,7 @@ pub(crate) async fn create_invite_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !services.server.supported_room_version(&body.room_version) {
|
if !services.server.supported_room_version(&body.room_version) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone() },
|
ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone() },
|
||||||
"Server does not support this room version.",
|
"Server does not support this room version.",
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Err, Error, Result, debug, debug_info, info, matrix::pdu::PduBuilder, warn};
|
use conduwuit::{Err, Result, debug, debug_info, info, matrix::pdu::PduBuilder, warn};
|
||||||
use conduwuit_service::Services;
|
use conduwuit_service::Services;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
@@ -80,7 +80,7 @@ pub(crate) async fn create_join_event_template_route(
|
|||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
||||||
if !body.ver.contains(&room_version_id) {
|
if !body.ver.contains(&room_version_id) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
||||||
"Room version not supported.",
|
"Room version not supported.",
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use RoomVersionId::*;
|
use RoomVersionId::*;
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Err, Error, Result, debug_warn, info, matrix::pdu::PduBuilder, warn};
|
use conduwuit::{Err, Result, debug_warn, info, matrix::pdu::PduBuilder, warn};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
RoomVersionId,
|
RoomVersionId,
|
||||||
api::{client::error::ErrorKind, federation::knock::create_knock_event_template},
|
api::{client::error::ErrorKind, federation::knock::create_knock_event_template},
|
||||||
@@ -67,14 +67,14 @@ pub(crate) async fn create_knock_event_template_route(
|
|||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
||||||
|
|
||||||
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
||||||
"Room version does not support knocking.",
|
"Room version does not support knocking.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !body.ver.contains(&room_version_id) {
|
if !body.ver.contains(&room_version_id) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
||||||
"Your homeserver does not support the features required to knock on this room.",
|
"Your homeserver does not support the features required to knock on this room.",
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Err, Result, err};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::error::ErrorKind,
|
client::error::ErrorKind,
|
||||||
@@ -25,7 +25,7 @@ pub(crate) async fn get_public_rooms_filtered_route(
|
|||||||
.config
|
.config
|
||||||
.allow_public_room_directory_over_federation
|
.allow_public_room_directory_over_federation
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(ErrorKind::forbidden(), "Room directory is not public"));
|
return Err!(BadRequest(ErrorKind::forbidden(), "Room directory is not public"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = crate::client::get_public_rooms_filtered_helper(
|
let response = crate::client::get_public_rooms_filtered_helper(
|
||||||
@@ -38,7 +38,10 @@ pub(crate) async fn get_public_rooms_filtered_route(
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::BadRequest(ErrorKind::Unknown, "Failed to return this server's public room list.")
|
err!(BadRequest(
|
||||||
|
ErrorKind::Unknown,
|
||||||
|
"Failed to return this server's public room list."
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(get_public_rooms_filtered::v1::Response {
|
Ok(get_public_rooms_filtered::v1::Response {
|
||||||
@@ -62,7 +65,7 @@ pub(crate) async fn get_public_rooms_route(
|
|||||||
.globals
|
.globals
|
||||||
.allow_public_room_directory_over_federation()
|
.allow_public_room_directory_over_federation()
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(ErrorKind::forbidden(), "Room directory is not public"));
|
return Err!(BadRequest(ErrorKind::forbidden(), "Room directory is not public"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = crate::client::get_public_rooms_filtered_helper(
|
let response = crate::client::get_public_rooms_filtered_helper(
|
||||||
@@ -75,7 +78,10 @@ pub(crate) async fn get_public_rooms_route(
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::BadRequest(ErrorKind::Unknown, "Failed to return this server's public room list.")
|
err!(BadRequest(
|
||||||
|
ErrorKind::Unknown,
|
||||||
|
"Failed to return this server's public room list."
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(get_public_rooms::v1::Response {
|
Ok(get_public_rooms::v1::Response {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Error, Result, err};
|
use conduwuit::{Err, Result, err};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use get_profile_information::v1::ProfileField;
|
use get_profile_information::v1::ProfileField;
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
@@ -67,17 +67,16 @@ pub(crate) async fn get_profile_information_route(
|
|||||||
.config
|
.config
|
||||||
.allow_inbound_profile_lookup_federation_requests
|
.allow_inbound_profile_lookup_federation_requests
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::forbidden(),
|
ErrorKind::forbidden(),
|
||||||
"Profile lookup over federation is not allowed on this homeserver.",
|
"Profile lookup over federation is not allowed on this homeserver.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services.globals.server_is_ours(body.user_id.server_name()) {
|
if !services.globals.server_is_ours(body.user_id.server_name()) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(
|
||||||
ErrorKind::InvalidParam,
|
BadRequest(ErrorKind::InvalidParam, "User does not belong to this server.",)
|
||||||
"User does not belong to this server.",
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut displayname = None;
|
let mut displayname = None;
|
||||||
|
|||||||
+64
-214
@@ -1,33 +1,27 @@
|
|||||||
use std::{
|
use std::{collections::BTreeMap, net::IpAddr, time::Instant};
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
|
||||||
net::IpAddr,
|
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Result, debug, debug_warn, err, error,
|
Err, Error, Result, debug, debug_warn, err, error,
|
||||||
result::LogErr,
|
result::LogErr,
|
||||||
state_res::lexicographical_topological_sort,
|
|
||||||
trace,
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
IterStream, ReadyExt, millis_since_unix_epoch,
|
IterStream, ReadyExt, millis_since_unix_epoch,
|
||||||
stream::{BroadbandExt, TryBroadbandExt, automatic_width},
|
stream::{BroadbandExt, TryBroadbandExt, automatic_width},
|
||||||
},
|
},
|
||||||
|
warn,
|
||||||
};
|
};
|
||||||
use conduwuit_service::{
|
use conduwuit_service::{
|
||||||
Services,
|
Services,
|
||||||
sending::{EDU_LIMIT, PDU_LIMIT},
|
sending::{EDU_LIMIT, PDU_LIMIT},
|
||||||
};
|
};
|
||||||
use futures::{FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt};
|
use futures::{FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt};
|
||||||
use http::StatusCode;
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
CanonicalJsonObject, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId,
|
CanonicalJsonObject, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, ServerName, UserId,
|
||||||
RoomId, ServerName, UserId,
|
|
||||||
api::{
|
api::{
|
||||||
client::error::{ErrorKind, ErrorKind::LimitExceeded},
|
client::error::ErrorKind,
|
||||||
federation::transactions::{
|
federation::transactions::{
|
||||||
edu::{
|
edu::{
|
||||||
DeviceListUpdateContent, DirectDeviceContent, Edu, PresenceContent,
|
DeviceListUpdateContent, DirectDeviceContent, Edu, PresenceContent,
|
||||||
@@ -38,16 +32,9 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
events::receipt::{ReceiptEvent, ReceiptEventContent, ReceiptType},
|
events::receipt::{ReceiptEvent, ReceiptEventContent, ReceiptType},
|
||||||
int,
|
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
to_device::DeviceIdOrAllDevices,
|
to_device::DeviceIdOrAllDevices,
|
||||||
uint,
|
|
||||||
};
|
};
|
||||||
use service::transactions::{
|
|
||||||
FederationTxnState, TransactionError, TxnKey, WrappedTransactionResponse,
|
|
||||||
};
|
|
||||||
use tokio::sync::watch::{Receiver, Sender};
|
|
||||||
use tracing::instrument;
|
|
||||||
|
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
@@ -57,6 +44,15 @@ type Pdu = (OwnedRoomId, OwnedEventId, CanonicalJsonObject);
|
|||||||
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
||||||
///
|
///
|
||||||
/// Push EDUs and PDUs to this server.
|
/// Push EDUs and PDUs to this server.
|
||||||
|
#[tracing::instrument(
|
||||||
|
name = "txn",
|
||||||
|
level = "debug",
|
||||||
|
skip_all,
|
||||||
|
fields(
|
||||||
|
%client,
|
||||||
|
origin = body.origin().as_str()
|
||||||
|
),
|
||||||
|
)]
|
||||||
pub(crate) async fn send_transaction_message_route(
|
pub(crate) async fn send_transaction_message_route(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
@@ -80,73 +76,16 @@ pub(crate) async fn send_transaction_message_route(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let txn_key = (body.origin().to_owned(), body.transaction_id.clone());
|
|
||||||
|
|
||||||
// Atomically check cache, join active, or start new transaction
|
|
||||||
match services
|
|
||||||
.transactions
|
|
||||||
.get_or_start_federation_txn(txn_key.clone())?
|
|
||||||
{
|
|
||||||
| FederationTxnState::Cached(response) => {
|
|
||||||
// Already responded
|
|
||||||
Ok(response)
|
|
||||||
},
|
|
||||||
| FederationTxnState::Active(receiver) => {
|
|
||||||
// Another thread is processing
|
|
||||||
wait_for_result(receiver).await
|
|
||||||
},
|
|
||||||
| FederationTxnState::Started { receiver, sender } => {
|
|
||||||
// We're the first, spawn the processing task
|
|
||||||
services
|
|
||||||
.server
|
|
||||||
.runtime()
|
|
||||||
.spawn(process_inbound_transaction(services, body, client, txn_key, sender));
|
|
||||||
// and wait for it
|
|
||||||
wait_for_result(receiver).await
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn wait_for_result(
|
|
||||||
mut recv: Receiver<WrappedTransactionResponse>,
|
|
||||||
) -> Result<send_transaction_message::v1::Response> {
|
|
||||||
if tokio::time::timeout(Duration::from_secs(50), recv.changed())
|
|
||||||
.await
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
// Took too long, return 429 to encourage the sender to try again
|
|
||||||
return Err(Error::BadRequest(
|
|
||||||
LimitExceeded { retry_after: None },
|
|
||||||
"Transaction is being still being processed. Please try again later.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let value = recv.borrow_and_update();
|
|
||||||
match value.clone() {
|
|
||||||
| Some(Ok(response)) => Ok(response),
|
|
||||||
| Some(Err(err)) => Err(transaction_error_to_response(&err)),
|
|
||||||
| None => Err(Error::Request(
|
|
||||||
ErrorKind::Unknown,
|
|
||||||
"Transaction processing failed unexpectedly".into(),
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(
|
|
||||||
skip_all,
|
|
||||||
fields(
|
|
||||||
id = ?body.transaction_id.as_str(),
|
|
||||||
origin = ?body.origin()
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
async fn process_inbound_transaction(
|
|
||||||
services: crate::State,
|
|
||||||
body: Ruma<send_transaction_message::v1::Request>,
|
|
||||||
client: IpAddr,
|
|
||||||
txn_key: TxnKey,
|
|
||||||
sender: Sender<WrappedTransactionResponse>,
|
|
||||||
) {
|
|
||||||
let txn_start_time = Instant::now();
|
let txn_start_time = Instant::now();
|
||||||
|
trace!(
|
||||||
|
pdus = body.pdus.len(),
|
||||||
|
edus = body.edus.len(),
|
||||||
|
elapsed = ?txn_start_time.elapsed(),
|
||||||
|
id = %body.transaction_id,
|
||||||
|
origin = %body.origin(),
|
||||||
|
"Starting txn",
|
||||||
|
);
|
||||||
|
|
||||||
let pdus = body
|
let pdus = body
|
||||||
.pdus
|
.pdus
|
||||||
.iter()
|
.iter()
|
||||||
@@ -163,79 +102,40 @@ async fn process_inbound_transaction(
|
|||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
.stream();
|
.stream();
|
||||||
|
|
||||||
debug!(pdus = body.pdus.len(), edus = body.edus.len(), "Processing transaction",);
|
let results = handle(&services, &client, body.origin(), txn_start_time, pdus, edus).await?;
|
||||||
let results = match handle(&services, &client, body.origin(), pdus, edus).await {
|
|
||||||
| Ok(results) => results,
|
|
||||||
| Err(err) => {
|
|
||||||
fail_federation_txn(services, &txn_key, &sender, err);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (id, result) in &results {
|
|
||||||
if let Err(e) = result {
|
|
||||||
if matches!(e, Error::BadRequest(ErrorKind::NotFound, _)) {
|
|
||||||
debug_warn!("Incoming PDU failed {id}: {e:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
pdus = body.pdus.len(),
|
pdus = body.pdus.len(),
|
||||||
edus = body.edus.len(),
|
edus = body.edus.len(),
|
||||||
elapsed = ?txn_start_time.elapsed(),
|
elapsed = ?txn_start_time.elapsed(),
|
||||||
"Finished processing transaction"
|
id = %body.transaction_id,
|
||||||
|
origin = %body.origin(),
|
||||||
|
"Finished txn",
|
||||||
);
|
);
|
||||||
|
for (id, result) in &results {
|
||||||
|
if let Err(e) = result {
|
||||||
|
if matches!(e, Error::BadRequest { kind: ErrorKind::NotFound, .. }) {
|
||||||
|
warn!("Incoming PDU failed {id}: {e:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let response = send_transaction_message::v1::Response {
|
Ok(send_transaction_message::v1::Response {
|
||||||
pdus: results
|
pdus: results
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(e, r)| (e, r.map_err(error::sanitized_message)))
|
.map(|(e, r)| (e, r.map_err(error::sanitized_message)))
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
})
|
||||||
|
|
||||||
services
|
|
||||||
.transactions
|
|
||||||
.finish_federation_txn(txn_key, sender, response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a failed federation transaction by sending the error through
|
|
||||||
/// the channel and cleaning up the transaction state. This allows waiters to
|
|
||||||
/// receive an appropriate error response.
|
|
||||||
fn fail_federation_txn(
|
|
||||||
services: crate::State,
|
|
||||||
txn_key: &TxnKey,
|
|
||||||
sender: &Sender<WrappedTransactionResponse>,
|
|
||||||
err: TransactionError,
|
|
||||||
) {
|
|
||||||
debug!("Transaction failed: {err}");
|
|
||||||
|
|
||||||
// Remove from active state so the transaction can be retried
|
|
||||||
services.transactions.remove_federation_txn(txn_key);
|
|
||||||
|
|
||||||
// Send the error to any waiters
|
|
||||||
if let Err(e) = sender.send(Some(Err(err))) {
|
|
||||||
debug_warn!("Failed to send transaction error to receivers: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a TransactionError into an appropriate HTTP error response.
|
|
||||||
fn transaction_error_to_response(err: &TransactionError) -> Error {
|
|
||||||
match err {
|
|
||||||
| TransactionError::ShuttingDown => Error::Request(
|
|
||||||
ErrorKind::Unknown,
|
|
||||||
"Server is shutting down, please retry later".into(),
|
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async fn handle(
|
async fn handle(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
client: &IpAddr,
|
client: &IpAddr,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
|
started: Instant,
|
||||||
pdus: impl Stream<Item = Pdu> + Send,
|
pdus: impl Stream<Item = Pdu> + Send,
|
||||||
edus: impl Stream<Item = Edu> + Send,
|
edus: impl Stream<Item = Edu> + Send,
|
||||||
) -> std::result::Result<ResolvedMap, TransactionError> {
|
) -> Result<ResolvedMap> {
|
||||||
// group pdus by room
|
// group pdus by room
|
||||||
let pdus = pdus
|
let pdus = pdus
|
||||||
.collect()
|
.collect()
|
||||||
@@ -252,7 +152,7 @@ async fn handle(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.try_stream()
|
.try_stream()
|
||||||
.broad_and_then(|(room_id, pdus): (_, Vec<_>)| {
|
.broad_and_then(|(room_id, pdus): (_, Vec<_>)| {
|
||||||
handle_room(services, client, origin, room_id, pdus.into_iter())
|
handle_room(services, client, origin, started, room_id, pdus.into_iter())
|
||||||
.map_ok(Vec::into_iter)
|
.map_ok(Vec::into_iter)
|
||||||
.map_ok(IterStream::try_stream)
|
.map_ok(IterStream::try_stream)
|
||||||
})
|
})
|
||||||
@@ -269,51 +169,14 @@ async fn handle(
|
|||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to build a localised directed acyclic graph out of the given PDUs,
|
|
||||||
/// returning them in a topologically sorted order.
|
|
||||||
///
|
|
||||||
/// This is used to attempt to process PDUs in an order that respects their
|
|
||||||
/// dependencies, however it is ultimately the sender's responsibility to send
|
|
||||||
/// them in a processable order, so this is just a best effort attempt. It does
|
|
||||||
/// not account for power levels or other tie breaks.
|
|
||||||
async fn build_local_dag(
|
|
||||||
pdu_map: &HashMap<OwnedEventId, CanonicalJsonObject>,
|
|
||||||
) -> Result<Vec<OwnedEventId>> {
|
|
||||||
debug_assert!(pdu_map.len() >= 2, "needless call to build_local_dag with less than 2 PDUs");
|
|
||||||
let mut dag: HashMap<OwnedEventId, HashSet<OwnedEventId>> = HashMap::new();
|
|
||||||
|
|
||||||
for (event_id, value) in pdu_map {
|
|
||||||
let prev_events = value
|
|
||||||
.get("prev_events")
|
|
||||||
.expect("pdu must have prev_events")
|
|
||||||
.as_array()
|
|
||||||
.expect("prev_events must be an array")
|
|
||||||
.iter()
|
|
||||||
.map(|v| {
|
|
||||||
OwnedEventId::parse(v.as_str().expect("prev_events values must be strings"))
|
|
||||||
.expect("prev_events must be valid event IDs")
|
|
||||||
})
|
|
||||||
.collect::<HashSet<OwnedEventId>>();
|
|
||||||
|
|
||||||
dag.insert(event_id.clone(), prev_events);
|
|
||||||
}
|
|
||||||
lexicographical_topological_sort(&dag, &|_| async {
|
|
||||||
// Note: we don't bother fetching power levels because that would massively slow
|
|
||||||
// this function down. This is a best-effort attempt to order events correctly
|
|
||||||
// for processing, however ultimately that should be the sender's job.
|
|
||||||
Ok((int!(0), MilliSecondsSinceUnixEpoch(uint!(0))))
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.map_err(|e| err!("failed to resolve local graph: {e}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_room(
|
async fn handle_room(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
_client: &IpAddr,
|
_client: &IpAddr,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
|
txn_start_time: Instant,
|
||||||
room_id: OwnedRoomId,
|
room_id: OwnedRoomId,
|
||||||
pdus: impl Iterator<Item = Pdu> + Send,
|
pdus: impl Iterator<Item = Pdu> + Send,
|
||||||
) -> std::result::Result<Vec<(OwnedEventId, Result)>, TransactionError> {
|
) -> Result<Vec<(OwnedEventId, Result)>> {
|
||||||
let _room_lock = services
|
let _room_lock = services
|
||||||
.rooms
|
.rooms
|
||||||
.event_handler
|
.event_handler
|
||||||
@@ -322,40 +185,27 @@ async fn handle_room(
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let room_id = &room_id;
|
let room_id = &room_id;
|
||||||
let pdu_map: HashMap<OwnedEventId, CanonicalJsonObject> = pdus
|
pdus.try_stream()
|
||||||
.into_iter()
|
.and_then(|(_, event_id, value)| async move {
|
||||||
.map(|(_, event_id, value)| (event_id, value))
|
services.server.check_running()?;
|
||||||
.collect();
|
let pdu_start_time = Instant::now();
|
||||||
// Try to sort PDUs by their dependencies, but fall back to arbitrary order on
|
let result = services
|
||||||
// failure (e.g., cycles). This is best-effort; proper ordering is the sender's
|
.rooms
|
||||||
// responsibility.
|
.event_handler
|
||||||
let sorted_event_ids = if pdu_map.len() >= 2 {
|
.handle_incoming_pdu(origin, room_id, &event_id, value, true)
|
||||||
build_local_dag(&pdu_map).await.unwrap_or_else(|e| {
|
.await
|
||||||
debug_warn!("Failed to build local DAG for room {room_id}: {e}");
|
.map(|_| ());
|
||||||
pdu_map.keys().cloned().collect()
|
|
||||||
|
debug!(
|
||||||
|
pdu_elapsed = ?pdu_start_time.elapsed(),
|
||||||
|
txn_elapsed = ?txn_start_time.elapsed(),
|
||||||
|
"Finished PDU {event_id}",
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((event_id, result))
|
||||||
})
|
})
|
||||||
} else {
|
.try_collect()
|
||||||
pdu_map.keys().cloned().collect()
|
.await
|
||||||
};
|
|
||||||
let mut results = Vec::with_capacity(sorted_event_ids.len());
|
|
||||||
for event_id in sorted_event_ids {
|
|
||||||
let value = pdu_map
|
|
||||||
.get(&event_id)
|
|
||||||
.expect("sorted event IDs must be from the original map")
|
|
||||||
.clone();
|
|
||||||
services
|
|
||||||
.server
|
|
||||||
.check_running()
|
|
||||||
.map_err(|_| TransactionError::ShuttingDown)?;
|
|
||||||
let result = services
|
|
||||||
.rooms
|
|
||||||
.event_handler
|
|
||||||
.handle_incoming_pdu(origin, room_id, &event_id, value, true)
|
|
||||||
.await
|
|
||||||
.map(|_| ());
|
|
||||||
results.push((event_id, result));
|
|
||||||
}
|
|
||||||
Ok(results)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_edu(services: &Services, client: &IpAddr, origin: &ServerName, edu: Edu) {
|
async fn handle_edu(services: &Services, client: &IpAddr, origin: &ServerName, edu: Edu) {
|
||||||
@@ -628,8 +478,8 @@ async fn handle_edu_direct_to_device(
|
|||||||
|
|
||||||
// Check if this is a new transaction id
|
// Check if this is a new transaction id
|
||||||
if services
|
if services
|
||||||
.transactions
|
.transaction_ids
|
||||||
.get_client_txn(sender, None, message_id)
|
.existing_txnid(sender, None, message_id)
|
||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
@@ -648,8 +498,8 @@ async fn handle_edu_direct_to_device(
|
|||||||
|
|
||||||
// Save transaction id with empty data
|
// Save transaction id with empty data
|
||||||
services
|
services
|
||||||
.transactions
|
.transaction_ids
|
||||||
.add_client_txnid(sender, None, message_id, &[]);
|
.add_txnid(sender, None, message_id, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_edu_direct_to_device_user<Event: Send + Sync>(
|
async fn handle_edu_direct_to_device_user<Event: Send + Sync>(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Err, Result};
|
||||||
use futures::{FutureExt, StreamExt, TryFutureExt};
|
use futures::{FutureExt, StreamExt, TryFutureExt};
|
||||||
use ruma::api::{
|
use ruma::api::{
|
||||||
client::error::ErrorKind,
|
client::error::ErrorKind,
|
||||||
@@ -24,7 +24,7 @@ pub(crate) async fn get_devices_route(
|
|||||||
body: Ruma<get_devices::v1::Request>,
|
body: Ruma<get_devices::v1::Request>,
|
||||||
) -> Result<get_devices::v1::Response> {
|
) -> Result<get_devices::v1::Response> {
|
||||||
if !services.globals.user_is_local(&body.user_id) {
|
if !services.globals.user_is_local(&body.user_id) {
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Tried to access user from other server.",
|
"Tried to access user from other server.",
|
||||||
));
|
));
|
||||||
@@ -86,10 +86,9 @@ pub(crate) async fn get_keys_route(
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|(u, _)| !services.globals.user_is_local(u))
|
.any(|(u, _)| !services.globals.user_is_local(u))
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err!(
|
||||||
ErrorKind::InvalidParam,
|
BadRequest(ErrorKind::InvalidParam, "User does not belong to this server.",)
|
||||||
"User does not belong to this server.",
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = get_keys_helper(
|
let result = get_keys_helper(
|
||||||
@@ -121,7 +120,7 @@ pub(crate) async fn claim_keys_route(
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|(u, _)| !services.globals.user_is_local(u))
|
.any(|(u, _)| !services.globals.user_is_local(u))
|
||||||
{
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err!(BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Tried to access user from other server.",
|
"Tried to access user from other server.",
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Err, Result};
|
||||||
use ruma::api::{client::error::ErrorKind, federation::discovery::discover_homeserver};
|
use ruma::api::federation::discovery::discover_homeserver;
|
||||||
|
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ pub(crate) async fn well_known_server(
|
|||||||
Ok(discover_homeserver::Response {
|
Ok(discover_homeserver::Response {
|
||||||
server: match services.server.config.well_known.server.as_ref() {
|
server: match services.server.config.well_known.server.as_ref() {
|
||||||
| Some(server_name) => server_name.to_owned(),
|
| Some(server_name) => server_name.to_owned(),
|
||||||
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
| None => return Err!(BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -98,7 +98,8 @@ serde-saphyr.workspace = true
|
|||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
smallstr.workspace = true
|
smallstr.workspace = true
|
||||||
thiserror.workspace = true
|
snafu.workspace = true
|
||||||
|
paste.workspace = true
|
||||||
tikv-jemallocator.optional = true
|
tikv-jemallocator.optional = true
|
||||||
tikv-jemallocator.workspace = true
|
tikv-jemallocator.workspace = true
|
||||||
tikv-jemalloc-ctl.optional = true
|
tikv-jemalloc-ctl.optional = true
|
||||||
|
|||||||
@@ -174,7 +174,6 @@ pub fn check(config: &Config) -> Result {
|
|||||||
if config.allow_registration
|
if config.allow_registration
|
||||||
&& config.yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse
|
&& config.yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse
|
||||||
&& config.registration_token.is_none()
|
&& config.registration_token.is_none()
|
||||||
&& config.registration_token_file.is_none()
|
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"Open registration is enabled via setting \
|
"Open registration is enabled via setting \
|
||||||
|
|||||||
+23
-104
@@ -368,31 +368,6 @@ pub struct Config {
|
|||||||
#[serde(default = "default_max_fetch_prev_events")]
|
#[serde(default = "default_max_fetch_prev_events")]
|
||||||
pub max_fetch_prev_events: u16,
|
pub max_fetch_prev_events: u16,
|
||||||
|
|
||||||
/// How many incoming federation transactions the server is willing to be
|
|
||||||
/// processing at any given time before it becomes overloaded and starts
|
|
||||||
/// rejecting further transactions until some slots become available.
|
|
||||||
///
|
|
||||||
/// Setting this value too low or too high may result in unstable
|
|
||||||
/// federation, and setting it too high may cause runaway resource usage.
|
|
||||||
///
|
|
||||||
/// default: 150
|
|
||||||
#[serde(default = "default_max_concurrent_inbound_transactions")]
|
|
||||||
pub max_concurrent_inbound_transactions: usize,
|
|
||||||
|
|
||||||
/// Maximum age (in seconds) for cached federation transaction responses.
|
|
||||||
/// Entries older than this will be removed during cleanup.
|
|
||||||
///
|
|
||||||
/// default: 7200 (2 hours)
|
|
||||||
#[serde(default = "default_transaction_id_cache_max_age_secs")]
|
|
||||||
pub transaction_id_cache_max_age_secs: u64,
|
|
||||||
|
|
||||||
/// Maximum number of cached federation transaction responses.
|
|
||||||
/// When the cache exceeds this limit, older entries will be removed.
|
|
||||||
///
|
|
||||||
/// default: 8192
|
|
||||||
#[serde(default = "default_transaction_id_cache_max_entries")]
|
|
||||||
pub transaction_id_cache_max_entries: usize,
|
|
||||||
|
|
||||||
/// Default/base connection timeout (seconds). This is used only by URL
|
/// Default/base connection timeout (seconds). This is used only by URL
|
||||||
/// previews and update/news endpoint checks.
|
/// previews and update/news endpoint checks.
|
||||||
///
|
///
|
||||||
@@ -609,25 +584,19 @@ pub struct Config {
|
|||||||
pub yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse: bool,
|
pub yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse: bool,
|
||||||
|
|
||||||
/// A static registration token that new users will have to provide when
|
/// A static registration token that new users will have to provide when
|
||||||
/// creating an account. This token does not supersede tokens from other
|
/// creating an account. If unset and `allow_registration` is true,
|
||||||
/// sources, such as the `!admin token` command or the
|
/// you must set
|
||||||
/// `registration_token_file` configuration option.
|
/// `yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse`
|
||||||
|
/// to true to allow open registration without any conditions.
|
||||||
|
///
|
||||||
|
/// If you do not want to set a static token, the `!admin token` commands
|
||||||
|
/// may also be used to manage registration tokens.
|
||||||
///
|
///
|
||||||
/// example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
|
/// example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
|
||||||
///
|
///
|
||||||
/// display: sensitive
|
/// display: sensitive
|
||||||
pub registration_token: Option<String>,
|
pub registration_token: Option<String>,
|
||||||
|
|
||||||
/// A path to a file containing static registration tokens, one per line.
|
|
||||||
/// Tokens in this file do not supersede tokens from other sources, such as
|
|
||||||
/// the `!admin token` command or the `registration_token` configuration
|
|
||||||
/// option.
|
|
||||||
///
|
|
||||||
/// The file will be read once, when Continuwuity starts. It is not
|
|
||||||
/// currently reread when the server configuration is reloaded. If the file
|
|
||||||
/// cannot be read, Continuwuity will fail to start.
|
|
||||||
pub registration_token_file: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// The public site key for reCaptcha. If this is provided, reCaptcha
|
/// The public site key for reCaptcha. If this is provided, reCaptcha
|
||||||
/// becomes required during registration. If both captcha *and*
|
/// becomes required during registration. If both captcha *and*
|
||||||
/// registration token are enabled, both will be required during
|
/// registration token are enabled, both will be required during
|
||||||
@@ -684,6 +653,12 @@ pub struct Config {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub allow_public_room_directory_over_federation: bool,
|
pub allow_public_room_directory_over_federation: bool,
|
||||||
|
|
||||||
|
/// Set this to true to allow your server's public room directory to be
|
||||||
|
/// queried without client authentication (access token) through the Client
|
||||||
|
/// APIs. Set this to false to protect against /publicRooms spiders.
|
||||||
|
#[serde(default)]
|
||||||
|
pub allow_public_room_directory_without_auth: bool,
|
||||||
|
|
||||||
/// Allow guests/unauthenticated users to access TURN credentials.
|
/// Allow guests/unauthenticated users to access TURN credentials.
|
||||||
///
|
///
|
||||||
/// This is the equivalent of Synapse's `turn_allow_guests` config option.
|
/// This is the equivalent of Synapse's `turn_allow_guests` config option.
|
||||||
@@ -2074,16 +2049,6 @@ pub struct Config {
|
|||||||
pub allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure:
|
pub allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure:
|
||||||
bool,
|
bool,
|
||||||
|
|
||||||
/// Forcibly disables first-run mode.
|
|
||||||
///
|
|
||||||
/// This is intended to be used for Complement testing to allow the test
|
|
||||||
/// suite to register users, because first-run mode interferes with open
|
|
||||||
/// registration.
|
|
||||||
///
|
|
||||||
/// display: hidden
|
|
||||||
#[serde(default)]
|
|
||||||
pub force_disable_first_run_mode: bool,
|
|
||||||
|
|
||||||
/// display: nested
|
/// display: nested
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub ldap: LdapConfig,
|
pub ldap: LdapConfig,
|
||||||
@@ -2096,12 +2061,6 @@ pub struct Config {
|
|||||||
/// display: nested
|
/// display: nested
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub blurhashing: BlurhashConfig,
|
pub blurhashing: BlurhashConfig,
|
||||||
|
|
||||||
/// Configuration for MatrixRTC (MSC4143) transport discovery.
|
|
||||||
/// display: nested
|
|
||||||
#[serde(default)]
|
|
||||||
pub matrix_rtc: MatrixRtcConfig,
|
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
#[allow(clippy::zero_sized_map_values)]
|
#[allow(clippy::zero_sized_map_values)]
|
||||||
// this is a catchall, the map shouldn't be zero at runtime
|
// this is a catchall, the map shouldn't be zero at runtime
|
||||||
@@ -2167,16 +2126,17 @@ pub struct WellKnownConfig {
|
|||||||
/// listed.
|
/// listed.
|
||||||
pub support_mxid: Option<OwnedUserId>,
|
pub support_mxid: Option<OwnedUserId>,
|
||||||
|
|
||||||
/// **DEPRECATED**: Use `[global.matrix_rtc].foci` instead.
|
|
||||||
///
|
|
||||||
/// A list of MatrixRTC foci URLs which will be served as part of the
|
/// A list of MatrixRTC foci URLs which will be served as part of the
|
||||||
/// MSC4143 client endpoint at /.well-known/matrix/client.
|
/// MSC4143 client endpoint at /.well-known/matrix/client. If you're
|
||||||
|
/// setting up livekit, you'd want something like:
|
||||||
|
/// rtc_focus_server_urls = [
|
||||||
|
/// { type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
||||||
|
/// ]
|
||||||
///
|
///
|
||||||
/// This option is deprecated and will be removed in a future release.
|
/// To disable, set this to be an empty vector (`[]`).
|
||||||
/// Please migrate to the new `[global.matrix_rtc]` config section.
|
|
||||||
///
|
///
|
||||||
/// default: []
|
/// default: []
|
||||||
#[serde(default)]
|
#[serde(default = "default_rtc_focus_urls")]
|
||||||
pub rtc_focus_server_urls: Vec<RtcFocusInfo>,
|
pub rtc_focus_server_urls: Vec<RtcFocusInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2205,43 +2165,6 @@ pub struct BlurhashConfig {
|
|||||||
pub blurhash_max_raw_size: u64,
|
pub blurhash_max_raw_size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
|
||||||
#[config_example_generator(filename = "conduwuit-example.toml", section = "global.matrix_rtc")]
|
|
||||||
pub struct MatrixRtcConfig {
|
|
||||||
/// A list of MatrixRTC foci (transports) which will be served via the
|
|
||||||
/// MSC4143 RTC transports endpoint at
|
|
||||||
/// `/_matrix/client/v1/rtc/transports`. If you're setting up livekit,
|
|
||||||
/// you'd want something like:
|
|
||||||
/// ```toml
|
|
||||||
/// [global.matrix_rtc]
|
|
||||||
/// foci = [
|
|
||||||
/// { type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
|
||||||
/// ]
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// To disable, set this to an empty list (`[]`).
|
|
||||||
///
|
|
||||||
/// default: []
|
|
||||||
#[serde(default)]
|
|
||||||
pub foci: Vec<RtcFocusInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MatrixRtcConfig {
|
|
||||||
/// Returns the effective foci, falling back to the deprecated
|
|
||||||
/// `rtc_focus_server_urls` if the new config is empty.
|
|
||||||
#[must_use]
|
|
||||||
pub fn effective_foci<'a>(
|
|
||||||
&'a self,
|
|
||||||
deprecated_foci: &'a [RtcFocusInfo],
|
|
||||||
) -> &'a [RtcFocusInfo] {
|
|
||||||
if !self.foci.is_empty() {
|
|
||||||
&self.foci
|
|
||||||
} else {
|
|
||||||
deprecated_foci
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize)]
|
#[derive(Clone, Debug, Default, Deserialize)]
|
||||||
#[config_example_generator(filename = "conduwuit-example.toml", section = "global.ldap")]
|
#[config_example_generator(filename = "conduwuit-example.toml", section = "global.ldap")]
|
||||||
pub struct LdapConfig {
|
pub struct LdapConfig {
|
||||||
@@ -2435,7 +2358,6 @@ const DEPRECATED_KEYS: &[&str] = &[
|
|||||||
"well_known_support_email",
|
"well_known_support_email",
|
||||||
"well_known_support_mxid",
|
"well_known_support_mxid",
|
||||||
"registration_token_file",
|
"registration_token_file",
|
||||||
"well_known.rtc_focus_server_urls",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -2618,12 +2540,6 @@ fn default_pusher_idle_timeout() -> u64 { 15 }
|
|||||||
|
|
||||||
fn default_max_fetch_prev_events() -> u16 { 192_u16 }
|
fn default_max_fetch_prev_events() -> u16 { 192_u16 }
|
||||||
|
|
||||||
fn default_max_concurrent_inbound_transactions() -> usize { 150 }
|
|
||||||
|
|
||||||
fn default_transaction_id_cache_max_age_secs() -> u64 { 60 * 60 * 2 }
|
|
||||||
|
|
||||||
fn default_transaction_id_cache_max_entries() -> usize { 8192 }
|
|
||||||
|
|
||||||
fn default_tracing_flame_filter() -> String {
|
fn default_tracing_flame_filter() -> String {
|
||||||
cfg!(debug_assertions)
|
cfg!(debug_assertions)
|
||||||
.then_some("trace,h2=off")
|
.then_some("trace,h2=off")
|
||||||
@@ -2719,6 +2635,9 @@ fn default_rocksdb_stats_level() -> u8 { 1 }
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V11 }
|
pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V11 }
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn default_rtc_focus_urls() -> Vec<RtcFocusInfo> { vec![] }
|
||||||
|
|
||||||
fn default_ip_range_denylist() -> Vec<String> {
|
fn default_ip_range_denylist() -> Vec<String> {
|
||||||
vec![
|
vec![
|
||||||
"127.0.0.0/8".to_owned(),
|
"127.0.0.0/8".to_owned(),
|
||||||
|
|||||||
+129
-30
@@ -45,63 +45,162 @@ macro_rules! Err {
|
|||||||
macro_rules! err {
|
macro_rules! err {
|
||||||
(Request(Forbidden($level:ident!($($args:tt)+)))) => {{
|
(Request(Forbidden($level:ident!($($args:tt)+)))) => {{
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request {
|
||||||
$crate::ruma::api::client::error::ErrorKind::forbidden(),
|
kind: $crate::ruma::api::client::error::ErrorKind::forbidden(),
|
||||||
$crate::err_log!(buf, $level, $($args)+),
|
message: $crate::err_log!(buf, $level, $($args)+),
|
||||||
$crate::http::StatusCode::BAD_REQUEST
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
)
|
backtrace: Some($crate::snafu::Backtrace::capture()),
|
||||||
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(Request(Forbidden($($args:tt)+))) => {
|
(Request(Forbidden($($args:tt)+))) => {
|
||||||
$crate::error::Error::Request(
|
{
|
||||||
$crate::ruma::api::client::error::ErrorKind::forbidden(),
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
$crate::format_maybe!($($args)+),
|
$crate::error::Error::Request {
|
||||||
$crate::http::StatusCode::BAD_REQUEST
|
kind: $crate::ruma::api::client::error::ErrorKind::forbidden(),
|
||||||
)
|
message,
|
||||||
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
|
backtrace: Some($crate::snafu::Backtrace::capture()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(Request(NotFound($level:ident!($($args:tt)+)))) => {{
|
||||||
|
let mut buf = String::new();
|
||||||
|
$crate::error::Error::Request {
|
||||||
|
kind: $crate::ruma::api::client::error::ErrorKind::NotFound,
|
||||||
|
message: $crate::err_log!(buf, $level, $($args)+),
|
||||||
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
|
backtrace: None,
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
(Request(NotFound($($args:tt)+))) => {
|
||||||
|
{
|
||||||
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::Error::Request {
|
||||||
|
kind: $crate::ruma::api::client::error::ErrorKind::NotFound,
|
||||||
|
message,
|
||||||
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
|
backtrace: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(Request($variant:ident($level:ident!($($args:tt)+)))) => {{
|
(Request($variant:ident($level:ident!($($args:tt)+)))) => {{
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request {
|
||||||
$crate::ruma::api::client::error::ErrorKind::$variant,
|
kind: $crate::ruma::api::client::error::ErrorKind::$variant,
|
||||||
$crate::err_log!(buf, $level, $($args)+),
|
message: $crate::err_log!(buf, $level, $($args)+),
|
||||||
$crate::http::StatusCode::BAD_REQUEST
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
)
|
backtrace: Some($crate::snafu::Backtrace::capture()),
|
||||||
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(Request($variant:ident($($args:tt)+))) => {
|
(Request($variant:ident($($args:tt)+))) => {
|
||||||
$crate::error::Error::Request(
|
{
|
||||||
$crate::ruma::api::client::error::ErrorKind::$variant,
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
$crate::format_maybe!($($args)+),
|
$crate::error::Error::Request {
|
||||||
$crate::http::StatusCode::BAD_REQUEST
|
kind: $crate::ruma::api::client::error::ErrorKind::$variant,
|
||||||
)
|
message,
|
||||||
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
|
backtrace: Some($crate::snafu::Backtrace::capture()),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(Config($item:literal, $($args:tt)+)) => {{
|
(Config($item:literal, $($args:tt)+)) => {{
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Config($item, $crate::err_log!(buf, error, config = %$item, $($args)+))
|
$crate::error::ConfigSnafu {
|
||||||
|
directive: $item,
|
||||||
|
message: $crate::err_log!(buf, error, config = %$item, $($args)+),
|
||||||
|
}.build()
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
(BadRequest(ErrorKind::NotFound, $($args:tt)+)) => {
|
||||||
|
{
|
||||||
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::Error::Request {
|
||||||
|
kind: $crate::ruma::api::client::error::ErrorKind::NotFound,
|
||||||
|
message,
|
||||||
|
code: $crate::http::StatusCode::BAD_REQUEST,
|
||||||
|
backtrace: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(BadRequest($kind:expr, $($args:tt)+)) => {
|
||||||
|
{
|
||||||
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::BadRequestSnafu {
|
||||||
|
kind: $kind,
|
||||||
|
message,
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(FeatureDisabled($($args:tt)+)) => {
|
||||||
|
{
|
||||||
|
let feature: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::FeatureDisabledSnafu { feature }.build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(Federation($server:expr, $error:expr $(,)?)) => {
|
||||||
|
{
|
||||||
|
$crate::error::FederationSnafu {
|
||||||
|
server: $server,
|
||||||
|
error: $error,
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(InconsistentRoomState($message:expr, $room_id:expr $(,)?)) => {
|
||||||
|
{
|
||||||
|
$crate::error::InconsistentRoomStateSnafu {
|
||||||
|
message: $message,
|
||||||
|
room_id: $room_id,
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(Uiaa($info:expr $(,)?)) => {
|
||||||
|
{
|
||||||
|
$crate::error::UiaaSnafu {
|
||||||
|
info: $info,
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
($variant:ident($level:ident!($($args:tt)+))) => {{
|
($variant:ident($level:ident!($($args:tt)+))) => {{
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
$crate::error::Error::$variant($crate::err_log!(buf, $level, $($args)+))
|
$crate::paste::paste! {
|
||||||
|
$crate::error::[<$variant Snafu>] {
|
||||||
|
message: $crate::err_log!(buf, $level, $($args)+),
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
($variant:ident($($args:ident),+)) => {
|
|
||||||
$crate::error::Error::$variant($($args),+)
|
|
||||||
};
|
|
||||||
|
|
||||||
($variant:ident($($args:tt)+)) => {
|
($variant:ident($($args:tt)+)) => {
|
||||||
$crate::error::Error::$variant($crate::format_maybe!($($args)+))
|
$crate::paste::paste! {
|
||||||
|
{
|
||||||
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::[<$variant Snafu>] { message }.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
($level:ident!($($args:tt)+)) => {{
|
($level:ident!($($args:tt)+)) => {{
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Err($crate::err_log!(buf, $level, $($args)+))
|
let message: std::borrow::Cow<'static, str> = $crate::err_log!(buf, $level, $($args)+);
|
||||||
|
$crate::error::ErrSnafu { message }.build()
|
||||||
}};
|
}};
|
||||||
|
|
||||||
($($args:tt)+) => {
|
($($args:tt)+) => {
|
||||||
$crate::error::Error::Err($crate::format_maybe!($($args)+))
|
{
|
||||||
|
let message: std::borrow::Cow<'static, str> = $crate::format_maybe!($($args)+);
|
||||||
|
$crate::error::ErrSnafu { message }.build()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +233,7 @@ macro_rules! err_log {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($crate::error::visit)(&mut $out, LEVEL, &__CALLSITE, &mut valueset_all!(__CALLSITE.metadata().fields(), $($fields)+));
|
($crate::error::visit)(&mut $out, LEVEL, &__CALLSITE, &mut valueset_all!(__CALLSITE.metadata().fields(), $($fields)+));
|
||||||
($out).into()
|
std::borrow::Cow::<'static, str>::from($out)
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+448
-140
@@ -6,151 +6,391 @@ mod serde;
|
|||||||
|
|
||||||
use std::{any::Any, borrow::Cow, convert::Infallible, sync::PoisonError};
|
use std::{any::Any, borrow::Cow, convert::Infallible, sync::PoisonError};
|
||||||
|
|
||||||
|
use snafu::{IntoError, prelude::*};
|
||||||
|
|
||||||
pub use self::{err::visit, log::*};
|
pub use self::{err::visit, log::*};
|
||||||
|
|
||||||
#[derive(thiserror::Error)]
|
#[derive(Debug, Snafu)]
|
||||||
|
#[snafu(visibility(pub))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("PANIC!")]
|
#[snafu(display("PANIC!"))]
|
||||||
PanicAny(Box<dyn Any + Send>),
|
PanicAny {
|
||||||
#[error("PANIC! {0}")]
|
panic: Box<dyn Any + Send>,
|
||||||
Panic(&'static str, Box<dyn Any + Send + 'static>),
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("PANIC! {message}"))]
|
||||||
|
Panic {
|
||||||
|
message: &'static str,
|
||||||
|
panic: Box<dyn Any + Send + 'static>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
// std
|
// std
|
||||||
#[error(transparent)]
|
#[snafu(display("Format error: {source}"))]
|
||||||
Fmt(#[from] std::fmt::Error),
|
Fmt {
|
||||||
#[error(transparent)]
|
source: std::fmt::Error,
|
||||||
FromUtf8(#[from] std::string::FromUtf8Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error("I/O error: {0}")]
|
},
|
||||||
Io(#[from] std::io::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("UTF-8 conversion error: {source}"))]
|
||||||
ParseFloat(#[from] std::num::ParseFloatError),
|
FromUtf8 {
|
||||||
#[error(transparent)]
|
source: std::string::FromUtf8Error,
|
||||||
ParseInt(#[from] std::num::ParseIntError),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
Std(#[from] Box<dyn std::error::Error + Send>),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("I/O error: {source}"))]
|
||||||
ThreadAccessError(#[from] std::thread::AccessError),
|
Io {
|
||||||
#[error(transparent)]
|
source: std::io::Error,
|
||||||
TryFromInt(#[from] std::num::TryFromIntError),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
TryFromSlice(#[from] std::array::TryFromSliceError),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Parse float error: {source}"))]
|
||||||
Utf8(#[from] std::str::Utf8Error),
|
ParseFloat {
|
||||||
|
source: std::num::ParseFloatError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Parse int error: {source}"))]
|
||||||
|
ParseInt {
|
||||||
|
source: std::num::ParseIntError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Error: {source}"))]
|
||||||
|
Std {
|
||||||
|
source: Box<dyn std::error::Error + Send>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Thread access error: {source}"))]
|
||||||
|
ThreadAccessError {
|
||||||
|
source: std::thread::AccessError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Integer conversion error: {source}"))]
|
||||||
|
TryFromInt {
|
||||||
|
source: std::num::TryFromIntError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Slice conversion error: {source}"))]
|
||||||
|
TryFromSlice {
|
||||||
|
source: std::array::TryFromSliceError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("UTF-8 error: {source}"))]
|
||||||
|
Utf8 {
|
||||||
|
source: std::str::Utf8Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
// third-party
|
// third-party
|
||||||
#[error(transparent)]
|
#[snafu(display("Capacity error: {source}"))]
|
||||||
CapacityError(#[from] arrayvec::CapacityError),
|
CapacityError {
|
||||||
#[error(transparent)]
|
source: arrayvec::CapacityError,
|
||||||
CargoToml(#[from] cargo_toml::Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
Clap(#[from] clap::error::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Cargo.toml error: {source}"))]
|
||||||
Extension(#[from] axum::extract::rejection::ExtensionRejection),
|
CargoToml {
|
||||||
#[error(transparent)]
|
source: cargo_toml::Error,
|
||||||
Figment(#[from] figment::error::Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
Http(#[from] http::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Clap error: {source}"))]
|
||||||
HttpHeader(#[from] http::header::InvalidHeaderValue),
|
Clap {
|
||||||
#[error("Join error: {0}")]
|
source: clap::error::Error,
|
||||||
JoinError(#[from] tokio::task::JoinError),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
Json(#[from] serde_json::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Extension rejection: {source}"))]
|
||||||
JsParseInt(#[from] ruma::JsParseIntError), // js_int re-export
|
Extension {
|
||||||
#[error(transparent)]
|
source: axum::extract::rejection::ExtensionRejection,
|
||||||
JsTryFromInt(#[from] ruma::JsTryFromIntError), // js_int re-export
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
Path(#[from] axum::extract::rejection::PathRejection),
|
|
||||||
#[error("Mutex poisoned: {0}")]
|
#[snafu(display("Figment error: {source}"))]
|
||||||
Poison(Cow<'static, str>),
|
Figment {
|
||||||
#[error("Regex error: {0}")]
|
source: figment::error::Error,
|
||||||
Regex(#[from] regex::Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error("Request error: {0}")]
|
},
|
||||||
Reqwest(#[from] reqwest::Error),
|
|
||||||
#[error("{0}")]
|
#[snafu(display("HTTP error: {source}"))]
|
||||||
SerdeDe(Cow<'static, str>),
|
Http {
|
||||||
#[error("{0}")]
|
source: http::Error,
|
||||||
SerdeSer(Cow<'static, str>),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
TomlDe(#[from] toml::de::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Invalid HTTP header value: {source}"))]
|
||||||
TomlSer(#[from] toml::ser::Error),
|
HttpHeader {
|
||||||
#[error("Tracing filter error: {0}")]
|
source: http::header::InvalidHeaderValue,
|
||||||
TracingFilter(#[from] tracing_subscriber::filter::ParseError),
|
backtrace: snafu::Backtrace,
|
||||||
#[error("Tracing reload error: {0}")]
|
},
|
||||||
TracingReload(#[from] tracing_subscriber::reload::Error),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("Join error: {source}"))]
|
||||||
TypedHeader(#[from] axum_extra::typed_header::TypedHeaderRejection),
|
JoinError {
|
||||||
#[error(transparent)]
|
source: tokio::task::JoinError,
|
||||||
YamlDe(#[from] serde_saphyr::Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
YamlSer(#[from] serde_saphyr::ser_error::Error),
|
|
||||||
|
#[snafu(display("JSON error: {source}"))]
|
||||||
|
Json {
|
||||||
|
source: serde_json::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("JS parse int error: {source}"))]
|
||||||
|
JsParseInt {
|
||||||
|
source: ruma::JsParseIntError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("JS try from int error: {source}"))]
|
||||||
|
JsTryFromInt {
|
||||||
|
source: ruma::JsTryFromIntError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Path rejection: {source}"))]
|
||||||
|
Path {
|
||||||
|
source: axum::extract::rejection::PathRejection,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Mutex poisoned: {message}"))]
|
||||||
|
Poison {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Regex error: {source}"))]
|
||||||
|
Regex {
|
||||||
|
source: regex::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Request error: {source}"))]
|
||||||
|
Reqwest {
|
||||||
|
source: reqwest::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{message}"))]
|
||||||
|
SerdeDe {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{message}"))]
|
||||||
|
SerdeSer {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("TOML deserialization error: {source}"))]
|
||||||
|
TomlDe {
|
||||||
|
source: toml::de::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("TOML serialization error: {source}"))]
|
||||||
|
TomlSer {
|
||||||
|
source: toml::ser::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Tracing filter error: {source}"))]
|
||||||
|
TracingFilter {
|
||||||
|
source: tracing_subscriber::filter::ParseError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Tracing reload error: {source}"))]
|
||||||
|
TracingReload {
|
||||||
|
source: tracing_subscriber::reload::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Typed header rejection: {source}"))]
|
||||||
|
TypedHeader {
|
||||||
|
source: axum_extra::typed_header::TypedHeaderRejection,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("YAML deserialization error: {source}"))]
|
||||||
|
YamlDe {
|
||||||
|
source: serde_saphyr::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("YAML serialization error: {source}"))]
|
||||||
|
YamlSer {
|
||||||
|
source: serde_saphyr::ser_error::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
// ruma/conduwuit
|
// ruma/conduwuit
|
||||||
#[error("Arithmetic operation failed: {0}")]
|
#[snafu(display("Arithmetic operation failed: {message}"))]
|
||||||
Arithmetic(Cow<'static, str>),
|
Arithmetic {
|
||||||
#[error("{0}: {1}")]
|
message: Cow<'static, str>,
|
||||||
BadRequest(ruma::api::client::error::ErrorKind, &'static str), //TODO: remove
|
backtrace: snafu::Backtrace,
|
||||||
#[error("{0}")]
|
},
|
||||||
BadServerResponse(Cow<'static, str>),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("{kind}: {message}"))]
|
||||||
CanonicalJson(#[from] ruma::CanonicalJsonError),
|
BadRequest {
|
||||||
#[error("There was a problem with the '{0}' directive in your configuration: {1}")]
|
kind: ruma::api::client::error::ErrorKind,
|
||||||
Config(&'static str, Cow<'static, str>),
|
message: Cow<'static, str>,
|
||||||
#[error("{0}")]
|
backtrace: snafu::Backtrace,
|
||||||
Conflict(Cow<'static, str>), // This is only needed for when a room alias already exists
|
},
|
||||||
#[error(transparent)]
|
|
||||||
ContentDisposition(#[from] ruma::http_headers::ContentDispositionParseError),
|
#[snafu(display("{message}"))]
|
||||||
#[error("{0}")]
|
BadServerResponse {
|
||||||
Database(Cow<'static, str>),
|
message: Cow<'static, str>,
|
||||||
#[error("Feature '{0}' is not available on this server.")]
|
backtrace: snafu::Backtrace,
|
||||||
FeatureDisabled(Cow<'static, str>),
|
},
|
||||||
#[error("Remote server {0} responded with: {1}")]
|
|
||||||
Federation(ruma::OwnedServerName, ruma::api::client::error::Error),
|
#[snafu(display("Canonical JSON error: {source}"))]
|
||||||
#[error("{0} in {1}")]
|
CanonicalJson {
|
||||||
InconsistentRoomState(&'static str, ruma::OwnedRoomId),
|
source: ruma::CanonicalJsonError,
|
||||||
#[error(transparent)]
|
backtrace: snafu::Backtrace,
|
||||||
IntoHttp(#[from] ruma::api::error::IntoHttpError),
|
},
|
||||||
#[error("{0}")]
|
|
||||||
Ldap(Cow<'static, str>),
|
#[snafu(display(
|
||||||
#[error(transparent)]
|
"There was a problem with the '{directive}' directive in your configuration: {message}"
|
||||||
Mxc(#[from] ruma::MxcUriError),
|
))]
|
||||||
#[error(transparent)]
|
Config {
|
||||||
Mxid(#[from] ruma::IdParseError),
|
directive: &'static str,
|
||||||
#[error("from {0}: {1}")]
|
message: Cow<'static, str>,
|
||||||
Redaction(ruma::OwnedServerName, ruma::canonical_json::RedactionError),
|
backtrace: snafu::Backtrace,
|
||||||
#[error("{0}: {1}")]
|
},
|
||||||
Request(ruma::api::client::error::ErrorKind, Cow<'static, str>, http::StatusCode),
|
|
||||||
#[error(transparent)]
|
#[snafu(display("{message}"))]
|
||||||
Ruma(#[from] ruma::api::client::error::Error),
|
Conflict {
|
||||||
#[error(transparent)]
|
message: Cow<'static, str>,
|
||||||
Signatures(#[from] ruma::signatures::Error),
|
backtrace: snafu::Backtrace,
|
||||||
#[error(transparent)]
|
},
|
||||||
StateRes(#[from] crate::state_res::Error),
|
|
||||||
#[error("uiaa")]
|
#[snafu(display("Content disposition error: {source}"))]
|
||||||
Uiaa(ruma::api::client::uiaa::UiaaInfo),
|
ContentDisposition {
|
||||||
|
source: ruma::http_headers::ContentDispositionParseError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{message}"))]
|
||||||
|
Database {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Feature '{feature}' is not available on this server."))]
|
||||||
|
FeatureDisabled {
|
||||||
|
feature: Cow<'static, str>,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Remote server {server} responded with: {error}"))]
|
||||||
|
Federation {
|
||||||
|
server: ruma::OwnedServerName,
|
||||||
|
error: ruma::api::client::error::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{message} in {room_id}"))]
|
||||||
|
InconsistentRoomState {
|
||||||
|
message: &'static str,
|
||||||
|
room_id: ruma::OwnedRoomId,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("HTTP conversion error: {source}"))]
|
||||||
|
IntoHttp {
|
||||||
|
source: ruma::api::error::IntoHttpError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{message}"))]
|
||||||
|
Ldap {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("MXC URI error: {source}"))]
|
||||||
|
Mxc {
|
||||||
|
source: ruma::MxcUriError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Matrix ID parse error: {source}"))]
|
||||||
|
Mxid {
|
||||||
|
source: ruma::IdParseError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("from {server}: {error}"))]
|
||||||
|
Redaction {
|
||||||
|
server: ruma::OwnedServerName,
|
||||||
|
error: ruma::canonical_json::RedactionError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("{kind}: {message}"))]
|
||||||
|
Request {
|
||||||
|
kind: ruma::api::client::error::ErrorKind,
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
code: http::StatusCode,
|
||||||
|
backtrace: Option<snafu::Backtrace>,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Ruma error: {source}"))]
|
||||||
|
Ruma {
|
||||||
|
source: ruma::api::client::error::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("Signature error: {source}"))]
|
||||||
|
Signatures {
|
||||||
|
source: ruma::signatures::Error,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("State resolution error: {source}"))]
|
||||||
|
#[snafu(context(false))]
|
||||||
|
StateRes {
|
||||||
|
source: crate::state_res::Error,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("uiaa"))]
|
||||||
|
Uiaa {
|
||||||
|
info: ruma::api::client::uiaa::UiaaInfo,
|
||||||
|
},
|
||||||
|
|
||||||
// unique / untyped
|
// unique / untyped
|
||||||
#[error("{0}")]
|
#[snafu(display("{message}"))]
|
||||||
Err(Cow<'static, str>),
|
Err {
|
||||||
|
message: Cow<'static, str>,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_errno() -> Self { Self::Io(std::io::Error::last_os_error()) }
|
pub fn from_errno() -> Self { IoSnafu {}.into_error(std::io::Error::last_os_error()) }
|
||||||
|
|
||||||
//#[deprecated]
|
//#[deprecated]
|
||||||
|
#[must_use]
|
||||||
pub fn bad_database(message: &'static str) -> Self {
|
pub fn bad_database(message: &'static str) -> Self {
|
||||||
crate::err!(Database(error!("{message}")))
|
let message: Cow<'static, str> = message.into();
|
||||||
|
DatabaseSnafu { message }.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sanitizes public-facing errors that can leak sensitive information.
|
/// Sanitizes public-facing errors that can leak sensitive information.
|
||||||
pub fn sanitized_message(&self) -> String {
|
pub fn sanitized_message(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
| Self::Database(..) => String::from("Database error occurred."),
|
| Self::Database { .. } => String::from("Database error occurred."),
|
||||||
| Self::Io(..) => String::from("I/O error occurred."),
|
| Self::Io { .. } => String::from("I/O error occurred."),
|
||||||
| _ => self.message(),
|
| _ => self.message(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,8 +398,8 @@ impl Error {
|
|||||||
/// Generate the error message string.
|
/// Generate the error message string.
|
||||||
pub fn message(&self) -> String {
|
pub fn message(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
| Self::Federation(origin, error) => format!("Answer from {origin}: {error}"),
|
| Self::Federation { server, error, .. } => format!("Answer from {server}: {error}"),
|
||||||
| Self::Ruma(error) => response::ruma_error_message(error),
|
| Self::Ruma { source, .. } => response::ruma_error_message(source),
|
||||||
| _ => format!("{self}"),
|
| _ => format!("{self}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,10 +410,10 @@ impl Error {
|
|||||||
use ruma::api::client::error::ErrorKind::{FeatureDisabled, Unknown};
|
use ruma::api::client::error::ErrorKind::{FeatureDisabled, Unknown};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
| Self::Federation(_, error) | Self::Ruma(error) =>
|
| Self::Federation { error, .. } => response::ruma_error_kind(error).clone(),
|
||||||
response::ruma_error_kind(error).clone(),
|
| Self::Ruma { source, .. } => response::ruma_error_kind(source).clone(),
|
||||||
| Self::BadRequest(kind, ..) | Self::Request(kind, ..) => kind.clone(),
|
| Self::BadRequest { kind, .. } | Self::Request { kind, .. } => kind.clone(),
|
||||||
| Self::FeatureDisabled(..) => FeatureDisabled,
|
| Self::FeatureDisabled { .. } => FeatureDisabled,
|
||||||
| _ => Unknown,
|
| _ => Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,14 +424,15 @@ impl Error {
|
|||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
| Self::Federation(_, error) | Self::Ruma(error) => error.status_code,
|
| Self::Federation { error, .. } => error.status_code,
|
||||||
| Self::Request(kind, _, code) => response::status_code(kind, *code),
|
| Self::Ruma { source, .. } => source.status_code,
|
||||||
| Self::BadRequest(kind, ..) => response::bad_request_code(kind),
|
| Self::Request { kind, code, .. } => response::status_code(kind, *code),
|
||||||
| Self::FeatureDisabled(..) => response::bad_request_code(&self.kind()),
|
| Self::BadRequest { kind, .. } => response::bad_request_code(kind),
|
||||||
| Self::Reqwest(error) => error.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
|
| Self::FeatureDisabled { .. } => response::bad_request_code(&self.kind()),
|
||||||
| Self::Conflict(_) => StatusCode::CONFLICT,
|
| Self::Reqwest { source, .. } =>
|
||||||
| Self::Io(error) => response::io_error_code(error.kind()),
|
source.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
|
||||||
| Self::Uiaa(_) => StatusCode::UNAUTHORIZED,
|
| Self::Conflict { .. } => StatusCode::CONFLICT,
|
||||||
|
| Self::Io { source, .. } => response::io_error_code(source.kind()),
|
||||||
| _ => StatusCode::INTERNAL_SERVER_ERROR,
|
| _ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,16 +445,46 @@ impl Error {
|
|||||||
pub fn is_not_found(&self) -> bool { self.status_code() == http::StatusCode::NOT_FOUND }
|
pub fn is_not_found(&self) -> bool { self.status_code() == http::StatusCode::NOT_FOUND }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Error {
|
// Debug is already derived by Snafu
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self.message())
|
/// Macro to reduce boilerplate for From implementations using Snafu context
|
||||||
}
|
macro_rules! impl_from_snafu {
|
||||||
|
($source_ty:ty => $context:ident) => {
|
||||||
|
impl From<$source_ty> for Error {
|
||||||
|
fn from(source: $source_ty) -> Self { $context.into_error(source) }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for From impls that format messages into ErrSnafu or other
|
||||||
|
/// message-based contexts
|
||||||
|
macro_rules! impl_from_message {
|
||||||
|
($source_ty:ty => $context:ident, $msg:expr) => {
|
||||||
|
impl From<$source_ty> for Error {
|
||||||
|
fn from(source: $source_ty) -> Self {
|
||||||
|
let message: Cow<'static, str> = format!($msg, source).into();
|
||||||
|
$context { message }.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for From impls with constant messages (no formatting)
|
||||||
|
macro_rules! impl_from_const_message {
|
||||||
|
($source_ty:ty => $context:ident, $msg:expr) => {
|
||||||
|
impl From<$source_ty> for Error {
|
||||||
|
fn from(_source: $source_ty) -> Self {
|
||||||
|
let message: Cow<'static, str> = $msg.into();
|
||||||
|
$context { message }.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<PoisonError<T>> for Error {
|
impl<T> From<PoisonError<T>> for Error {
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn from(e: PoisonError<T>) -> Self { Self::Poison(e.to_string().into()) }
|
fn from(e: PoisonError<T>) -> Self { PoisonSnafu { message: e.to_string() }.build() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::fallible_impl_from)]
|
#[allow(clippy::fallible_impl_from)]
|
||||||
@@ -225,6 +496,43 @@ impl From<Infallible> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implementations using the macro
|
||||||
|
impl_from_snafu!(std::io::Error => IoSnafu);
|
||||||
|
impl_from_snafu!(std::string::FromUtf8Error => FromUtf8Snafu);
|
||||||
|
impl_from_snafu!(regex::Error => RegexSnafu);
|
||||||
|
impl_from_snafu!(ruma::http_headers::ContentDispositionParseError => ContentDispositionSnafu);
|
||||||
|
impl_from_snafu!(ruma::api::error::IntoHttpError => IntoHttpSnafu);
|
||||||
|
impl_from_snafu!(ruma::JsTryFromIntError => JsTryFromIntSnafu);
|
||||||
|
impl_from_snafu!(ruma::CanonicalJsonError => CanonicalJsonSnafu);
|
||||||
|
impl_from_snafu!(axum::extract::rejection::PathRejection => PathSnafu);
|
||||||
|
impl_from_snafu!(clap::error::Error => ClapSnafu);
|
||||||
|
impl_from_snafu!(ruma::MxcUriError => MxcSnafu);
|
||||||
|
impl_from_snafu!(serde_saphyr::ser_error::Error => YamlSerSnafu);
|
||||||
|
impl_from_snafu!(toml::de::Error => TomlDeSnafu);
|
||||||
|
impl_from_snafu!(http::header::InvalidHeaderValue => HttpHeaderSnafu);
|
||||||
|
impl_from_snafu!(serde_json::Error => JsonSnafu);
|
||||||
|
|
||||||
|
// Custom implementations using message formatting
|
||||||
|
impl_from_const_message!(std::fmt::Error => ErrSnafu, "formatting error");
|
||||||
|
impl_from_message!(std::str::Utf8Error => ErrSnafu, "UTF-8 error: {}");
|
||||||
|
impl_from_message!(std::num::TryFromIntError => ArithmeticSnafu, "integer conversion error: {}");
|
||||||
|
impl_from_message!(tracing_subscriber::reload::Error => ErrSnafu, "tracing reload error: {}");
|
||||||
|
impl_from_message!(reqwest::Error => ErrSnafu, "HTTP client error: {}");
|
||||||
|
impl_from_message!(ruma::signatures::Error => ErrSnafu, "Signature error: {}");
|
||||||
|
impl_from_message!(ruma::IdParseError => ErrSnafu, "ID parse error: {}");
|
||||||
|
impl_from_message!(std::num::ParseIntError => ErrSnafu, "Integer parse error: {}");
|
||||||
|
impl_from_message!(std::array::TryFromSliceError => ErrSnafu, "Slice conversion error: {}");
|
||||||
|
impl_from_message!(tokio::task::JoinError => ErrSnafu, "Task join error: {}");
|
||||||
|
impl_from_message!(serde_saphyr::Error => ErrSnafu, "YAML error: {}");
|
||||||
|
|
||||||
|
// Generic implementation for CapacityError
|
||||||
|
impl<T> From<arrayvec::CapacityError<T>> for Error {
|
||||||
|
fn from(_source: arrayvec::CapacityError<T>) -> Self {
|
||||||
|
let message: Cow<'static, str> = "capacity error: buffer is full".into();
|
||||||
|
ErrSnafu { message }.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn infallible(_e: &Infallible) {
|
pub fn infallible(_e: &Infallible) {
|
||||||
|
|||||||
@@ -15,13 +15,16 @@ impl Error {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_panic(e: Box<dyn Any + Send>) -> Self { Self::Panic(debug::panic_str(&e), e) }
|
pub fn from_panic(e: Box<dyn Any + Send>) -> Self {
|
||||||
|
use super::PanicSnafu;
|
||||||
|
PanicSnafu { message: debug::panic_str(&e), panic: e }.build()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_panic(self) -> Box<dyn Any + Send + 'static> {
|
pub fn into_panic(self) -> Box<dyn Any + Send + 'static> {
|
||||||
match self {
|
match self {
|
||||||
| Self::Panic(_, e) | Self::PanicAny(e) => e,
|
| Self::Panic { panic, .. } | Self::PanicAny { panic, .. } => panic,
|
||||||
| Self::JoinError(e) => e.into_panic(),
|
| Self::JoinError { source, .. } => source.into_panic(),
|
||||||
| _ => Box::new(self),
|
| _ => Box::new(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +40,8 @@ impl Error {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_panic(&self) -> bool {
|
pub fn is_panic(&self) -> bool {
|
||||||
match &self {
|
match &self {
|
||||||
| Self::Panic(..) | Self::PanicAny(..) => true,
|
| Self::Panic { .. } | Self::PanicAny { .. } => true,
|
||||||
| Self::JoinError(e) => e.is_panic(),
|
| Self::JoinError { source, .. } => source.is_panic(),
|
||||||
| _ => false,
|
| _ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ impl axum::response::IntoResponse for Error {
|
|||||||
impl From<Error> for UiaaResponse {
|
impl From<Error> for UiaaResponse {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(error: Error) -> Self {
|
fn from(error: Error) -> Self {
|
||||||
if let Error::Uiaa(uiaainfo) = error {
|
if let Error::Uiaa { info, .. } = error {
|
||||||
return Self::AuthResponse(uiaainfo);
|
return Self::AuthResponse(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = ErrorBody::Standard {
|
let body = ErrorBody::Standard {
|
||||||
|
|||||||
@@ -5,9 +5,15 @@ use serde::{de, ser};
|
|||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
fn custom<T: Display + ToString>(msg: T) -> Self { Self::SerdeDe(msg.to_string().into()) }
|
fn custom<T: Display + ToString>(msg: T) -> Self {
|
||||||
|
let message: std::borrow::Cow<'static, str> = msg.to_string().into();
|
||||||
|
super::SerdeDeSnafu { message }.build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ser::Error for Error {
|
impl ser::Error for Error {
|
||||||
fn custom<T: Display + ToString>(msg: T) -> Self { Self::SerdeSer(msg.to_string().into()) }
|
fn custom<T: Display + ToString>(msg: T) -> Self {
|
||||||
|
let message: std::borrow::Cow<'static, str> = msg.to_string().into();
|
||||||
|
super::SerdeSerSnafu { message }.build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ static SEMANTIC: &str = env!("CARGO_PKG_VERSION");
|
|||||||
static VERSION: OnceLock<String> = OnceLock::new();
|
static VERSION: OnceLock<String> = OnceLock::new();
|
||||||
static VERSION_UA: OnceLock<String> = OnceLock::new();
|
static VERSION_UA: OnceLock<String> = OnceLock::new();
|
||||||
static USER_AGENT: OnceLock<String> = OnceLock::new();
|
static USER_AGENT: OnceLock<String> = OnceLock::new();
|
||||||
static USER_AGENT_MEDIA: OnceLock<String> = OnceLock::new();
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -22,22 +21,14 @@ pub fn name() -> &'static str { BRANDING }
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn version() -> &'static str { VERSION.get_or_init(init_version) }
|
pub fn version() -> &'static str { VERSION.get_or_init(init_version) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn version_ua() -> &'static str { VERSION_UA.get_or_init(init_version_ua) }
|
pub fn version_ua() -> &'static str { VERSION_UA.get_or_init(init_version_ua) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn user_agent() -> &'static str { USER_AGENT.get_or_init(init_user_agent) }
|
pub fn user_agent() -> &'static str { USER_AGENT.get_or_init(init_user_agent) }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn user_agent_media() -> &'static str { USER_AGENT_MEDIA.get_or_init(init_user_agent_media) }
|
|
||||||
|
|
||||||
fn init_user_agent() -> String { format!("{}/{} (bot; +{WEBSITE})", name(), version_ua()) }
|
fn init_user_agent() -> String { format!("{}/{} (bot; +{WEBSITE})", name(), version_ua()) }
|
||||||
|
|
||||||
fn init_user_agent_media() -> String {
|
|
||||||
format!("{}/{} (embedbot; facebookexternalhit/1.1; +{WEBSITE})", name(), version_ua())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_version_ua() -> String {
|
fn init_version_ua() -> String {
|
||||||
conduwuit_build_metadata::version_tag()
|
conduwuit_build_metadata::version_tag()
|
||||||
.map_or_else(|| SEMANTIC.to_owned(), |extra| format!("{SEMANTIC}+{extra}"))
|
.map_or_else(|| SEMANTIC.to_owned(), |extra| format!("{SEMANTIC}+{extra}"))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use ruma::{RoomVersionId, canonical_json::redact_content_in_place};
|
use ruma::{RoomVersionId, canonical_json::redact_content_in_place};
|
||||||
use serde_json::{Value as JsonValue, json, value::to_raw_value};
|
use serde_json::{Value as JsonValue, json, value::to_raw_value};
|
||||||
|
|
||||||
use crate::{Error, Result, err, implement};
|
use crate::{Result, err, implement};
|
||||||
|
|
||||||
#[implement(super::Pdu)]
|
#[implement(super::Pdu)]
|
||||||
pub fn redact(&mut self, room_version_id: &RoomVersionId, reason: JsonValue) -> Result {
|
pub fn redact(&mut self, room_version_id: &RoomVersionId, reason: JsonValue) -> Result {
|
||||||
@@ -10,8 +10,15 @@ pub fn redact(&mut self, room_version_id: &RoomVersionId, reason: JsonValue) ->
|
|||||||
let mut content = serde_json::from_str(self.content.get())
|
let mut content = serde_json::from_str(self.content.get())
|
||||||
.map_err(|e| err!(Request(BadJson("Failed to deserialize content into type: {e}"))))?;
|
.map_err(|e| err!(Request(BadJson("Failed to deserialize content into type: {e}"))))?;
|
||||||
|
|
||||||
redact_content_in_place(&mut content, room_version_id, self.kind.to_string())
|
redact_content_in_place(&mut content, room_version_id, self.kind.to_string()).map_err(
|
||||||
.map_err(|e| Error::Redaction(self.sender.server_name().to_owned(), e))?;
|
|error| {
|
||||||
|
crate::error::RedactionSnafu {
|
||||||
|
server: self.sender.server_name().to_owned(),
|
||||||
|
error,
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
let reason = serde_json::to_value(reason).expect("Failed to preserialize reason");
|
let reason = serde_json::to_value(reason).expect("Failed to preserialize reason");
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use serde_json::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
matrix::{Event, Pdu, pdu::EventHash},
|
matrix::{Event, Pdu, pdu::EventHash},
|
||||||
state_res::{self as state_res, Error, Result, StateMap},
|
state_res::{self as state_res, Error, Result, StateMap, error::NotFoundSnafu},
|
||||||
};
|
};
|
||||||
|
|
||||||
static SERVER_TIMESTAMP: AtomicU64 = AtomicU64::new(0);
|
static SERVER_TIMESTAMP: AtomicU64 = AtomicU64::new(0);
|
||||||
@@ -170,10 +170,12 @@ struct TestStore<E: Event>(HashMap<OwnedEventId, E>);
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl<E: Event + Clone> TestStore<E> {
|
impl<E: Event + Clone> TestStore<E> {
|
||||||
fn get_event(&self, room_id: &RoomId, event_id: &EventId) -> Result<E> {
|
fn get_event(&self, room_id: &RoomId, event_id: &EventId) -> Result<E> {
|
||||||
self.0
|
self.0.get(event_id).cloned().ok_or_else(|| {
|
||||||
.get(event_id)
|
NotFoundSnafu {
|
||||||
.cloned()
|
message: format!("{} not found", event_id),
|
||||||
.ok_or_else(|| Error::NotFound(format!("{} not found", event_id)))
|
}
|
||||||
|
.build()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the events that correspond to the `event_ids` sorted in the same
|
/// Returns the events that correspond to the `event_ids` sorted in the same
|
||||||
|
|||||||
@@ -1,23 +1,40 @@
|
|||||||
use serde_json::Error as JsonError;
|
use serde_json::Error as JsonError;
|
||||||
use thiserror::Error;
|
use snafu::{IntoError, prelude::*};
|
||||||
|
|
||||||
/// Represents the various errors that arise when resolving state.
|
/// Represents the various errors that arise when resolving state.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Debug, Snafu)]
|
||||||
|
#[snafu(visibility(pub))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// A deserialization error.
|
/// A deserialization error.
|
||||||
#[error(transparent)]
|
#[snafu(display("JSON error: {source}"))]
|
||||||
SerdeJson(#[from] JsonError),
|
SerdeJson {
|
||||||
|
source: JsonError,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
/// The given option or version is unsupported.
|
/// The given option or version is unsupported.
|
||||||
#[error("Unsupported room version: {0}")]
|
#[snafu(display("Unsupported room version: {version}"))]
|
||||||
Unsupported(String),
|
Unsupported {
|
||||||
|
version: String,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
/// The given event was not found.
|
/// The given event was not found.
|
||||||
#[error("Not found error: {0}")]
|
#[snafu(display("Not found error: {message}"))]
|
||||||
NotFound(String),
|
NotFound {
|
||||||
|
message: String,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
|
||||||
/// Invalid fields in the given PDU.
|
/// Invalid fields in the given PDU.
|
||||||
#[error("Invalid PDU: {0}")]
|
#[snafu(display("Invalid PDU: {message}"))]
|
||||||
InvalidPdu(String),
|
InvalidPdu {
|
||||||
|
message: String,
|
||||||
|
backtrace: snafu::Backtrace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::Error> for Error {
|
||||||
|
fn from(source: serde_json::Error) -> Self { SerdeJsonSnafu.into_error(source) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Error, Event, Result, StateEventType, StateKey, TimelineEventType,
|
Error, Event, Result, StateEventType, StateKey, TimelineEventType,
|
||||||
|
error::InvalidPduSnafu,
|
||||||
power_levels::{
|
power_levels::{
|
||||||
deserialize_power_levels, deserialize_power_levels_content_fields,
|
deserialize_power_levels, deserialize_power_levels_content_fields,
|
||||||
deserialize_power_levels_content_invite, deserialize_power_levels_content_redact,
|
deserialize_power_levels_content_invite, deserialize_power_levels_content_redact,
|
||||||
@@ -383,8 +384,8 @@ where
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_user =
|
let target_user = <&UserId>::try_from(state_key)
|
||||||
<&UserId>::try_from(state_key).map_err(|e| Error::InvalidPdu(format!("{e}")))?;
|
.map_err(|e| InvalidPduSnafu { message: format!("{e}") }.build())?;
|
||||||
|
|
||||||
let user_for_join_auth = content
|
let user_for_join_auth = content
|
||||||
.join_authorised_via_users_server
|
.join_authorised_via_users_server
|
||||||
@@ -461,7 +462,7 @@ where
|
|||||||
?sender_membership_event_content,
|
?sender_membership_event_content,
|
||||||
"Sender membership event content missing membership field"
|
"Sender membership event content missing membership field"
|
||||||
);
|
);
|
||||||
return Err(Error::InvalidPdu("Missing membership field".to_owned()));
|
return Err(InvalidPduSnafu { message: "Missing membership field" }.build());
|
||||||
};
|
};
|
||||||
let membership_state = membership_state.deserialize()?;
|
let membership_state = membership_state.deserialize()?;
|
||||||
|
|
||||||
|
|||||||
@@ -29,18 +29,18 @@ use ruma::{
|
|||||||
};
|
};
|
||||||
use serde_json::from_str as from_json_str;
|
use serde_json::from_str as from_json_str;
|
||||||
|
|
||||||
pub(crate) use self::error::Error;
|
pub(crate) use self::error::{Error, InvalidPduSnafu, NotFoundSnafu};
|
||||||
use self::power_levels::PowerLevelsContentFields;
|
use self::power_levels::PowerLevelsContentFields;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
event_auth::{auth_check, auth_types_for_event},
|
event_auth::{auth_check, auth_types_for_event},
|
||||||
room_version::RoomVersion,
|
room_version::RoomVersion,
|
||||||
};
|
};
|
||||||
|
use super::{Event, StateKey};
|
||||||
use crate::{
|
use crate::{
|
||||||
debug, debug_error, err,
|
debug, debug_error,
|
||||||
matrix::{Event, StateKey},
|
|
||||||
state_res::room_version::StateResolutionVersion,
|
state_res::room_version::StateResolutionVersion,
|
||||||
trace,
|
trace,
|
||||||
utils::stream::{BroadbandExt, IterStream, ReadyExt, TryBroadbandExt, WidebandExt},
|
utils::stream::{BroadbandExt, IterStream, ReadyExt, TryBroadbandExt},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +118,10 @@ where
|
|||||||
let csg = calculate_conflicted_subgraph(&conflicting, event_fetch)
|
let csg = calculate_conflicted_subgraph(&conflicting, event_fetch)
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::InvalidPdu("Failed to calculate conflicted subgraph".to_owned())
|
InvalidPduSnafu {
|
||||||
|
message: "Failed to calculate conflicted subgraph",
|
||||||
|
}
|
||||||
|
.build()
|
||||||
})?;
|
})?;
|
||||||
debug!(count = csg.len(), "conflicted subgraph");
|
debug!(count = csg.len(), "conflicted subgraph");
|
||||||
trace!(set = ?csg, "conflicted subgraph");
|
trace!(set = ?csg, "conflicted subgraph");
|
||||||
@@ -149,10 +152,11 @@ where
|
|||||||
let control_events: Vec<_> = all_conflicted
|
let control_events: Vec<_> = all_conflicted
|
||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.wide_filter_map(async |id| {
|
.broad_filter_map(async |id| {
|
||||||
is_power_event_id(id, &event_fetch)
|
event_fetch(id.clone())
|
||||||
.await
|
.await
|
||||||
.then_some(id.clone())
|
.filter(|event| is_power_event(&event))
|
||||||
|
.map(|_| id.clone())
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
@@ -314,7 +318,10 @@ where
|
|||||||
trace!(event_id = event_id.as_str(), "fetching event for its auth events");
|
trace!(event_id = event_id.as_str(), "fetching event for its auth events");
|
||||||
let evt = fetch_event(event_id.clone()).await;
|
let evt = fetch_event(event_id.clone()).await;
|
||||||
if evt.is_none() {
|
if evt.is_none() {
|
||||||
err!("could not fetch event {} to calculate conflicted subgraph", event_id);
|
tracing::error!(
|
||||||
|
"could not fetch event {} to calculate conflicted subgraph",
|
||||||
|
event_id
|
||||||
|
);
|
||||||
path.pop();
|
path.pop();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -402,11 +409,11 @@ where
|
|||||||
let fetcher = async |event_id: OwnedEventId| {
|
let fetcher = async |event_id: OwnedEventId| {
|
||||||
let pl = *event_to_pl
|
let pl = *event_to_pl
|
||||||
.get(&event_id)
|
.get(&event_id)
|
||||||
.ok_or_else(|| Error::NotFound(String::new()))?;
|
.ok_or_else(|| NotFoundSnafu { message: "" }.build())?;
|
||||||
|
|
||||||
let ev = fetch_event(event_id)
|
let ev = fetch_event(event_id)
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| Error::NotFound(String::new()))?;
|
.ok_or_else(|| NotFoundSnafu { message: "" }.build())?;
|
||||||
|
|
||||||
Ok((pl, ev.origin_server_ts()))
|
Ok((pl, ev.origin_server_ts()))
|
||||||
};
|
};
|
||||||
@@ -612,9 +619,12 @@ where
|
|||||||
let events_to_check: Vec<_> = events_to_check
|
let events_to_check: Vec<_> = events_to_check
|
||||||
.map(Result::Ok)
|
.map(Result::Ok)
|
||||||
.broad_and_then(async |event_id| {
|
.broad_and_then(async |event_id| {
|
||||||
fetch_event(event_id.to_owned())
|
fetch_event(event_id.to_owned()).await.ok_or_else(|| {
|
||||||
.await
|
NotFoundSnafu {
|
||||||
.ok_or_else(|| Error::NotFound(format!("Failed to find {event_id}")))
|
message: format!("Failed to find {event_id}"),
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.boxed()
|
.boxed()
|
||||||
@@ -653,7 +663,7 @@ where
|
|||||||
trace!(event_id = event.event_id().as_str(), "checking event");
|
trace!(event_id = event.event_id().as_str(), "checking event");
|
||||||
let state_key = event
|
let state_key = event
|
||||||
.state_key()
|
.state_key()
|
||||||
.ok_or_else(|| Error::InvalidPdu("State event had no state key".to_owned()))?;
|
.ok_or_else(|| InvalidPduSnafu { message: "State event had no state key" }.build())?;
|
||||||
|
|
||||||
let auth_types = auth_types_for_event(
|
let auth_types = auth_types_for_event(
|
||||||
event.event_type(),
|
event.event_type(),
|
||||||
@@ -669,13 +679,14 @@ where
|
|||||||
trace!("room version uses hashed IDs, manually fetching create event");
|
trace!("room version uses hashed IDs, manually fetching create event");
|
||||||
let create_event_id_raw = event.room_id_or_hash().as_str().replace('!', "$");
|
let create_event_id_raw = event.room_id_or_hash().as_str().replace('!', "$");
|
||||||
let create_event_id = EventId::parse(&create_event_id_raw).map_err(|e| {
|
let create_event_id = EventId::parse(&create_event_id_raw).map_err(|e| {
|
||||||
Error::InvalidPdu(format!(
|
InvalidPduSnafu {
|
||||||
"Failed to parse create event ID from room ID/hash: {e}"
|
message: format!("Failed to parse create event ID from room ID/hash: {e}"),
|
||||||
))
|
}
|
||||||
|
.build()
|
||||||
|
})?;
|
||||||
|
let create_event = fetch_event(create_event_id.into()).await.ok_or_else(|| {
|
||||||
|
NotFoundSnafu { message: "Failed to find create event" }.build()
|
||||||
})?;
|
})?;
|
||||||
let create_event = fetch_event(create_event_id.into())
|
|
||||||
.await
|
|
||||||
.ok_or_else(|| Error::NotFound("Failed to find create event".into()))?;
|
|
||||||
auth_state.insert(create_event.event_type().with_state_key(""), create_event);
|
auth_state.insert(create_event.event_type().with_state_key(""), create_event);
|
||||||
}
|
}
|
||||||
for aid in event.auth_events() {
|
for aid in event.auth_events() {
|
||||||
@@ -686,7 +697,7 @@ where
|
|||||||
auth_state.insert(
|
auth_state.insert(
|
||||||
ev.event_type()
|
ev.event_type()
|
||||||
.with_state_key(ev.state_key().ok_or_else(|| {
|
.with_state_key(ev.state_key().ok_or_else(|| {
|
||||||
Error::InvalidPdu("State event had no state key".to_owned())
|
InvalidPduSnafu { message: "State event had no state key" }.build()
|
||||||
})?),
|
})?),
|
||||||
ev.clone(),
|
ev.clone(),
|
||||||
);
|
);
|
||||||
@@ -801,13 +812,13 @@ where
|
|||||||
|
|
||||||
let event = fetch_event(p.clone())
|
let event = fetch_event(p.clone())
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| Error::NotFound(format!("Failed to find {p}")))?;
|
.ok_or_else(|| NotFoundSnafu { message: format!("Failed to find {p}") }.build())?;
|
||||||
|
|
||||||
pl = None;
|
pl = None;
|
||||||
for aid in event.auth_events() {
|
for aid in event.auth_events() {
|
||||||
let ev = fetch_event(aid.to_owned())
|
let ev = fetch_event(aid.to_owned()).await.ok_or_else(|| {
|
||||||
.await
|
NotFoundSnafu { message: format!("Failed to find {aid}") }.build()
|
||||||
.ok_or_else(|| Error::NotFound(format!("Failed to find {aid}")))?;
|
})?;
|
||||||
|
|
||||||
if is_type_and_key(&ev, &TimelineEventType::RoomPowerLevels, "") {
|
if is_type_and_key(&ev, &TimelineEventType::RoomPowerLevels, "") {
|
||||||
pl = Some(aid.to_owned());
|
pl = Some(aid.to_owned());
|
||||||
@@ -869,9 +880,9 @@ where
|
|||||||
|
|
||||||
event = None;
|
event = None;
|
||||||
for aid in sort_ev.auth_events() {
|
for aid in sort_ev.auth_events() {
|
||||||
let aev = fetch_event(aid.to_owned())
|
let aev = fetch_event(aid.to_owned()).await.ok_or_else(|| {
|
||||||
.await
|
NotFoundSnafu { message: format!("Failed to find {aid}") }.build()
|
||||||
.ok_or_else(|| Error::NotFound(format!("Failed to find {aid}")))?;
|
})?;
|
||||||
|
|
||||||
if is_type_and_key(&aev, &TimelineEventType::RoomPowerLevels, "") {
|
if is_type_and_key(&aev, &TimelineEventType::RoomPowerLevels, "") {
|
||||||
event = Some(aev);
|
event = Some(aev);
|
||||||
@@ -915,6 +926,7 @@ async fn add_event_and_auth_chain_to_graph<E, F, Fut>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
async fn is_power_event_id<E, F, Fut>(event_id: &EventId, fetch: &F) -> bool
|
async fn is_power_event_id<E, F, Fut>(event_id: &EventId, fetch: &F) -> bool
|
||||||
where
|
where
|
||||||
F: Fn(OwnedEventId) -> Fut + Sync,
|
F: Fn(OwnedEventId) -> Fut + Sync,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ruma::RoomVersionId;
|
use ruma::RoomVersionId;
|
||||||
|
|
||||||
use super::{Error, Result};
|
use super::{Result, error::UnsupportedSnafu};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(clippy::exhaustive_enums)]
|
#[allow(clippy::exhaustive_enums)]
|
||||||
@@ -163,7 +163,11 @@ impl RoomVersion {
|
|||||||
| RoomVersionId::V10 => Self::V10,
|
| RoomVersionId::V10 => Self::V10,
|
||||||
| RoomVersionId::V11 => Self::V11,
|
| RoomVersionId::V11 => Self::V11,
|
||||||
| RoomVersionId::V12 => Self::V12,
|
| RoomVersionId::V12 => Self::V12,
|
||||||
| ver => return Err(Error::Unsupported(format!("found version `{ver}`"))),
|
| ver =>
|
||||||
|
return Err(UnsupportedSnafu {
|
||||||
|
version: format!("found version `{ver}`"),
|
||||||
|
}
|
||||||
|
.build()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use serde_json::{
|
|||||||
value::{RawValue as RawJsonValue, to_raw_value as to_raw_json_value},
|
value::{RawValue as RawJsonValue, to_raw_value as to_raw_json_value},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::auth_types_for_event;
|
use super::{auth_types_for_event, error::NotFoundSnafu};
|
||||||
use crate::{
|
use crate::{
|
||||||
Result, RoomVersion, info,
|
Result, RoomVersion, info,
|
||||||
matrix::{Event, EventTypeExt, Pdu, StateMap, pdu::EventHash},
|
matrix::{Event, EventTypeExt, Pdu, StateMap, pdu::EventHash},
|
||||||
@@ -232,7 +232,7 @@ impl<E: Event + Clone> TestStore<E> {
|
|||||||
self.0
|
self.0
|
||||||
.get(event_id)
|
.get(event_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| super::Error::NotFound(format!("{event_id} not found")))
|
.ok_or_else(|| NotFoundSnafu { message: format!("{event_id} not found") }.build())
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ pub mod utils;
|
|||||||
|
|
||||||
pub use ::arrayvec;
|
pub use ::arrayvec;
|
||||||
pub use ::http;
|
pub use ::http;
|
||||||
|
pub use ::paste;
|
||||||
pub use ::ruma;
|
pub use ::ruma;
|
||||||
pub use ::smallstr;
|
pub use ::smallstr;
|
||||||
pub use ::smallvec;
|
pub use ::smallvec;
|
||||||
|
pub use ::snafu;
|
||||||
pub use ::toml;
|
pub use ::toml;
|
||||||
pub use ::tracing;
|
pub use ::tracing;
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ pub mod json;
|
|||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod mutex_map;
|
pub mod mutex_map;
|
||||||
pub mod rand;
|
pub mod rand;
|
||||||
pub mod response;
|
|
||||||
pub mod result;
|
pub mod result;
|
||||||
pub mod set;
|
pub mod set;
|
||||||
pub mod stream;
|
pub mod stream;
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
use futures::StreamExt;
|
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
|
|
||||||
use crate::Err;
|
|
||||||
|
|
||||||
/// Reads the response body while enforcing a maximum size limit to prevent
|
|
||||||
/// memory exhaustion.
|
|
||||||
pub async fn limit_read(response: reqwest::Response, max_size: u64) -> crate::Result<Vec<u8>> {
|
|
||||||
if response.content_length().is_some_and(|len| len > max_size) {
|
|
||||||
return Err!(BadServerResponse("Response too large"));
|
|
||||||
}
|
|
||||||
let mut data = Vec::new();
|
|
||||||
let mut reader = response.bytes_stream();
|
|
||||||
|
|
||||||
while let Some(chunk) = reader.next().await {
|
|
||||||
let chunk = chunk?;
|
|
||||||
data.extend_from_slice(&chunk);
|
|
||||||
|
|
||||||
if data.len() > max_size.to_usize().expect("max_size must fit in usize") {
|
|
||||||
return Err!(BadServerResponse("Response too large"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads the response body as text while enforcing a maximum size limit to
|
|
||||||
/// prevent memory exhaustion.
|
|
||||||
pub async fn limit_read_text(
|
|
||||||
response: reqwest::Response,
|
|
||||||
max_size: u64,
|
|
||||||
) -> crate::Result<String> {
|
|
||||||
let text = String::from_utf8(limit_read(response, max_size).await?)?;
|
|
||||||
Ok(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(async_fn_in_trait)]
|
|
||||||
pub trait LimitReadExt {
|
|
||||||
async fn limit_read(self, max_size: u64) -> crate::Result<Vec<u8>>;
|
|
||||||
async fn limit_read_text(self, max_size: u64) -> crate::Result<String>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LimitReadExt for reqwest::Response {
|
|
||||||
async fn limit_read(self, max_size: u64) -> crate::Result<Vec<u8>> {
|
|
||||||
limit_read(self, max_size).await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn limit_read_text(self, max_size: u64) -> crate::Result<String> {
|
|
||||||
limit_read_text(self, max_size).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,17 +3,19 @@ use futures::{
|
|||||||
stream::{Stream, TryStream},
|
stream::{Stream, TryStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{Error, Result};
|
||||||
|
|
||||||
pub trait IterStream<I: IntoIterator + Send> {
|
pub trait IterStream<I: IntoIterator + Send> {
|
||||||
/// Convert an Iterator into a Stream
|
/// Convert an Iterator into a Stream
|
||||||
fn stream(self) -> impl Stream<Item = <I as IntoIterator>::Item> + Send;
|
fn stream(self) -> impl Stream<Item = <I as IntoIterator>::Item> + Send;
|
||||||
|
|
||||||
/// Convert an Iterator into a TryStream with a generic error type
|
/// Convert an Iterator into a TryStream
|
||||||
fn try_stream<E>(
|
fn try_stream(
|
||||||
self,
|
self,
|
||||||
) -> impl TryStream<
|
) -> impl TryStream<
|
||||||
Ok = <I as IntoIterator>::Item,
|
Ok = <I as IntoIterator>::Item,
|
||||||
Error = E,
|
Error = Error,
|
||||||
Item = Result<<I as IntoIterator>::Item, E>,
|
Item = Result<<I as IntoIterator>::Item, Error>,
|
||||||
> + Send;
|
> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,12 +28,12 @@ where
|
|||||||
fn stream(self) -> impl Stream<Item = <I as IntoIterator>::Item> + Send { stream::iter(self) }
|
fn stream(self) -> impl Stream<Item = <I as IntoIterator>::Item> + Send { stream::iter(self) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_stream<E>(
|
fn try_stream(
|
||||||
self,
|
self,
|
||||||
) -> impl TryStream<
|
) -> impl TryStream<
|
||||||
Ok = <I as IntoIterator>::Item,
|
Ok = <I as IntoIterator>::Item,
|
||||||
Error = E,
|
Error = Error,
|
||||||
Item = Result<<I as IntoIterator>::Item, E>,
|
Item = Result<<I as IntoIterator>::Item, Error>,
|
||||||
> + Send {
|
> + Send {
|
||||||
self.stream().map(Ok)
|
self.stream().map(Ok)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
//! Synchronous combinator extensions to futures::TryStream
|
//! Synchronous combinator extensions to futures::TryStream
|
||||||
|
|
||||||
use std::result::Result;
|
|
||||||
|
|
||||||
use futures::{TryFuture, TryStream, TryStreamExt};
|
use futures::{TryFuture, TryStream, TryStreamExt};
|
||||||
|
|
||||||
use super::automatic_width;
|
use super::automatic_width;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
/// Concurrency extensions to augment futures::TryStreamExt. broad_ combinators
|
/// Concurrency extensions to augment futures::TryStreamExt. broad_ combinators
|
||||||
/// produce out-of-order
|
/// produce out-of-order
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use std::{cell::Cell, fmt::Debug, path::PathBuf, sync::LazyLock};
|
use std::{cell::Cell, fmt::Debug, path::PathBuf, sync::LazyLock};
|
||||||
|
|
||||||
|
use snafu::IntoError;
|
||||||
|
|
||||||
use crate::{Result, is_equal_to};
|
use crate::{Result, is_equal_to};
|
||||||
|
|
||||||
type Id = usize;
|
type Id = usize;
|
||||||
@@ -142,7 +144,9 @@ pub fn getcpu() -> Result<usize> {
|
|||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn getcpu() -> Result<usize> { Err(crate::Error::Io(std::io::ErrorKind::Unsupported.into())) }
|
pub fn getcpu() -> Result<usize> {
|
||||||
|
Err(crate::error::IoSnafu.into_error(std::io::ErrorKind::Unsupported.into()))
|
||||||
|
}
|
||||||
|
|
||||||
fn query_cores_available() -> impl Iterator<Item = Id> {
|
fn query_cores_available() -> impl Iterator<Item = Id> {
|
||||||
core_affinity::get_core_ids()
|
core_affinity::get_core_ids()
|
||||||
|
|||||||
+12
-7
@@ -255,7 +255,10 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
| "$serde_json::private::RawValue" => visitor.visit_map(self),
|
| "$serde_json::private::RawValue" => visitor.visit_map(self),
|
||||||
| "Cbor" => visitor
|
| "Cbor" => visitor
|
||||||
.visit_newtype_struct(&mut minicbor_serde::Deserializer::new(self.record_trail()))
|
.visit_newtype_struct(&mut minicbor_serde::Deserializer::new(self.record_trail()))
|
||||||
.map_err(|e| Self::Error::SerdeDe(e.to_string().into())),
|
.map_err(|e| {
|
||||||
|
let message: std::borrow::Cow<'static, str> = e.to_string().into();
|
||||||
|
conduwuit_core::error::SerdeDeSnafu { message }.build()
|
||||||
|
}),
|
||||||
|
|
||||||
| _ => visitor.visit_newtype_struct(self),
|
| _ => visitor.visit_newtype_struct(self),
|
||||||
}
|
}
|
||||||
@@ -313,9 +316,10 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
|
|
||||||
let end = self.pos.saturating_add(BYTES).min(self.buf.len());
|
let end = self.pos.saturating_add(BYTES).min(self.buf.len());
|
||||||
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
|
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
|
||||||
let bytes = bytes
|
let bytes = bytes.into_inner().map_err(|_| {
|
||||||
.into_inner()
|
let message: std::borrow::Cow<'static, str> = "i64 buffer underflow".into();
|
||||||
.map_err(|_| Self::Error::SerdeDe("i64 buffer underflow".into()))?;
|
conduwuit_core::error::SerdeDeSnafu { message }.build()
|
||||||
|
})?;
|
||||||
|
|
||||||
self.inc_pos(BYTES);
|
self.inc_pos(BYTES);
|
||||||
visitor.visit_i64(i64::from_be_bytes(bytes))
|
visitor.visit_i64(i64::from_be_bytes(bytes))
|
||||||
@@ -345,9 +349,10 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
|
|
||||||
let end = self.pos.saturating_add(BYTES).min(self.buf.len());
|
let end = self.pos.saturating_add(BYTES).min(self.buf.len());
|
||||||
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
|
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
|
||||||
let bytes = bytes
|
let bytes = bytes.into_inner().map_err(|_| {
|
||||||
.into_inner()
|
let message: std::borrow::Cow<'static, str> = "u64 buffer underflow".into();
|
||||||
.map_err(|_| Self::Error::SerdeDe("u64 buffer underflow".into()))?;
|
conduwuit_core::error::SerdeDeSnafu { message }.build()
|
||||||
|
})?;
|
||||||
|
|
||||||
self.inc_pos(BYTES);
|
self.inc_pos(BYTES);
|
||||||
visitor.visit_u64(u64::from_be_bytes(bytes))
|
visitor.visit_u64(u64::from_be_bytes(bytes))
|
||||||
|
|||||||
@@ -362,10 +362,6 @@ pub(super) static MAPS: &[Descriptor] = &[
|
|||||||
name: "userid_blurhash",
|
name: "userid_blurhash",
|
||||||
..descriptor::RANDOM_SMALL
|
..descriptor::RANDOM_SMALL
|
||||||
},
|
},
|
||||||
Descriptor {
|
|
||||||
name: "userid_dehydrateddevice",
|
|
||||||
..descriptor::RANDOM_SMALL
|
|
||||||
},
|
|
||||||
Descriptor {
|
Descriptor {
|
||||||
name: "userid_devicelistversion",
|
name: "userid_devicelistversion",
|
||||||
..descriptor::RANDOM_SMALL
|
..descriptor::RANDOM_SMALL
|
||||||
|
|||||||
+4
-1
@@ -199,7 +199,10 @@ impl<W: Write> ser::Serializer for &mut Serializer<'_, W> {
|
|||||||
|
|
||||||
value
|
value
|
||||||
.serialize(&mut Serializer::new(&mut Writer::new(&mut self.out)))
|
.serialize(&mut Serializer::new(&mut Writer::new(&mut self.out)))
|
||||||
.map_err(|e| Self::Error::SerdeSer(e.to_string().into()))
|
.map_err(|e| {
|
||||||
|
let message: std::borrow::Cow<'static, str> = e.to_string().into();
|
||||||
|
conduwuit_core::error::SerdeSerSnafu { message }.build()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
| _ => unhandled!("Unrecognized serialization Newtype {name:?}"),
|
| _ => unhandled!("Unrecognized serialization Newtype {name:?}"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
|
||||||
use axum::{Router, response::IntoResponse};
|
use axum::{Router, response::IntoResponse};
|
||||||
use conduwuit::Error;
|
use conduwuit::Error;
|
||||||
@@ -18,5 +18,10 @@ pub(crate) fn build(services: &Arc<Services>) -> (Router, Guard) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn not_found(_uri: Uri) -> impl IntoResponse {
|
async fn not_found(_uri: Uri) -> impl IntoResponse {
|
||||||
Error::Request(ErrorKind::Unrecognized, "Not Found".into(), StatusCode::NOT_FOUND)
|
Error::Request {
|
||||||
|
kind: ErrorKind::Unrecognized,
|
||||||
|
message: Cow::Borrowed("Not Found"),
|
||||||
|
code: StatusCode::NOT_FOUND,
|
||||||
|
backtrace: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -530,12 +530,7 @@ impl Service {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_admin_command<E>(
|
pub async fn is_admin_command<E>(&self, event: &E, body: &str) -> Option<InvocationSource>
|
||||||
&self,
|
|
||||||
event: &E,
|
|
||||||
body: &str,
|
|
||||||
sent_locally: bool,
|
|
||||||
) -> Option<InvocationSource>
|
|
||||||
where
|
where
|
||||||
E: Event + Send + Sync,
|
E: Event + Send + Sync,
|
||||||
{
|
{
|
||||||
@@ -585,15 +580,6 @@ impl Service {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escaped commands must be sent locally (via client API), not via federation
|
|
||||||
if !sent_locally {
|
|
||||||
conduwuit::warn!(
|
|
||||||
"Ignoring escaped admin command from {} that arrived via federation",
|
|
||||||
event.sender()
|
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Looks good
|
// Looks good
|
||||||
Some(InvocationSource::EscapedCommand)
|
Some(InvocationSource::EscapedCommand)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use conduwuit::{Result, Server, debug, error, utils::response::LimitReadExt, warn};
|
use conduwuit::{Result, Server, debug, error, warn};
|
||||||
use database::{Deserialized, Map};
|
use database::{Deserialized, Map};
|
||||||
use ruma::events::{Mentions, room::message::RoomMessageEventContent};
|
use ruma::events::{Mentions, room::message::RoomMessageEventContent};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -137,7 +137,7 @@ impl Service {
|
|||||||
.get(CHECK_FOR_ANNOUNCEMENTS_URL)
|
.get(CHECK_FOR_ANNOUNCEMENTS_URL)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.limit_read_text(1024 * 1024)
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let response = serde_json::from_str::<CheckForAnnouncementsResponse>(&response)?;
|
let response = serde_json::from_str::<CheckForAnnouncementsResponse>(&response)?;
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ impl Service {
|
|||||||
// same appservice)
|
// same appservice)
|
||||||
if let Ok(existing) = self.find_from_token(®istration.as_token).await {
|
if let Ok(existing) = self.find_from_token(®istration.as_token).await {
|
||||||
if existing.registration.id != registration.id {
|
if existing.registration.id != registration.id {
|
||||||
return Err(err!(Request(InvalidParam(
|
return Err!(Request(InvalidParam(
|
||||||
"Cannot register appservice: Token is already used by appservice '{}'. \
|
"Cannot register appservice: Token is already used by appservice '{}'. \
|
||||||
Please generate a different token.",
|
Please generate a different token.",
|
||||||
existing.registration.id
|
existing.registration.id
|
||||||
))));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,10 +163,10 @@ impl Service {
|
|||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
return Err(err!(Request(InvalidParam(
|
return Err!(Request(InvalidParam(
|
||||||
"Cannot register appservice: The provided token is already in use by a user \
|
"Cannot register appservice: The provided token is already in use by a user \
|
||||||
device. Please generate a different token for the appservice."
|
device. Please generate a different token for the appservice."
|
||||||
))));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.db
|
self.db
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl crate::Service for Service {
|
|||||||
let url_preview_user_agent = config
|
let url_preview_user_agent = config
|
||||||
.url_preview_user_agent
|
.url_preview_user_agent
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| conduwuit::version::user_agent_media().to_owned());
|
.unwrap_or_else(|| conduwuit::version::user_agent().to_owned());
|
||||||
|
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
default: base(config)?
|
default: base(config)?
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user