mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-08-13 23:19:44 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6957ff7689 | ||
|
|
a460c4266c | ||
|
|
700fbe472d | ||
|
|
49a8f6f53b | ||
|
|
59c2649cde | ||
|
|
b0c1381f03 | ||
|
|
14ff018b9f | ||
|
|
1ca30e4268 | ||
|
|
71016a0d7f | ||
|
|
c7602a570c | ||
|
|
83cf15bccb | ||
|
|
e8a6a9ac9d | ||
|
|
4e4c6028ed | ||
|
|
9bfd41000e | ||
|
|
8d10613607 | ||
|
|
ca100e093b | ||
|
|
71bd471bb7 | ||
|
|
ec8815aa23 | ||
|
|
44d7e6cf4f | ||
|
|
4e001abe92 |
@@ -44,7 +44,7 @@ runs:
|
||||
|
||||
- name: Login to builtin registry
|
||||
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4
|
||||
with:
|
||||
registry: ${{ env.BUILTIN_REGISTRY }}
|
||||
username: ${{ inputs.registry_user }}
|
||||
|
||||
@@ -79,7 +79,7 @@ runs:
|
||||
|
||||
- name: Login to builtin registry
|
||||
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4
|
||||
with:
|
||||
registry: ${{ env.BUILTIN_REGISTRY }}
|
||||
username: ${{ inputs.registry_user }}
|
||||
|
||||
@@ -71,7 +71,7 @@ runs:
|
||||
|
||||
- name: Install timelord-cli and git-warp-time
|
||||
if: steps.check-binaries.outputs.need-install == 'true'
|
||||
uses: https://github.com/taiki-e/install-action@a6b2e2dcd845ddd7f509ce4f3ed3d922b80cc5d9 # v2
|
||||
uses: https://github.com/taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2
|
||||
with:
|
||||
tool: git-warp-time,timelord-cli@3.0.1
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
container: [ "ubuntu-latest", "ubuntu-previous", "debian-latest", "debian-oldstable" ]
|
||||
arch: [ "amd64", "arm64" ]
|
||||
container:
|
||||
image: "ghcr.io/tcpipuk/act-runner:${{ matrix.container }}"
|
||||
|
||||
@@ -54,9 +55,9 @@ jobs:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
cargo-debian-${{ steps.debian-version.outputs.distribution }}-
|
||||
cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}-
|
||||
|
||||
- name: Setup sccache
|
||||
uses: https://git.tomfos.tr/tom/sccache-action@v1
|
||||
@@ -70,11 +71,55 @@ jobs:
|
||||
# Aggressive GC since cache restores don't increment counter
|
||||
echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV
|
||||
|
||||
- name: Install cross-compilation tools for arm64
|
||||
if: matrix.arch == 'arm64'
|
||||
run: |
|
||||
dpkg --add-architecture arm64
|
||||
if ! apt-get update; then
|
||||
# Older Ubuntu releases (e.g. noble) advertise arm64 in their
|
||||
# Release files but only serve amd64/i386 from archive.ubuntu.com,
|
||||
# so apt update 404s. Restrict the main sources to amd64 and
|
||||
# fetch arm64 from ports.ubuntu.com instead.
|
||||
CODENAME=$(lsb_release -sc)
|
||||
# deb822 sources (noble and newer)
|
||||
if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then
|
||||
sed -i '/^Components:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources
|
||||
fi
|
||||
# one-line sources (jammy and older)
|
||||
if [ -f /etc/apt/sources.list ]; then
|
||||
sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
|
||||
fi
|
||||
printf 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports %s main restricted universe multiverse\n' \
|
||||
"$CODENAME" "$CODENAME-updates" "$CODENAME-security" \
|
||||
> /etc/apt/sources.list.d/arm64-ports.list
|
||||
apt-get update
|
||||
fi
|
||||
apt-get install -y \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
libc6-dev-arm64-cross
|
||||
|
||||
- name: Setup Rust
|
||||
uses: ./.forgejo/actions/setup-rust
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PUBLIC_RO }}
|
||||
|
||||
- name: Add Rust target
|
||||
run: |
|
||||
TARGET=${{ matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}
|
||||
rustup target add $TARGET
|
||||
|
||||
- name: Configure cross-compilation for arm64
|
||||
if: matrix.arch == 'arm64'
|
||||
run: |
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV
|
||||
# rust-rocksdb's build script probes liburing via pkg-config, which
|
||||
# refuses to run when host != target unless explicitly allowed
|
||||
echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH_aarch64_unknown_linux_gnu=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Get package version and component
|
||||
id: package-meta
|
||||
run: |
|
||||
@@ -120,21 +165,26 @@ jobs:
|
||||
apt-get update -y
|
||||
# Build dependencies for rocksdb
|
||||
apt-get install -y liburing-dev clang
|
||||
# For arm64 builds, install cross-compiled dependencies.
|
||||
# libstdc++6:arm64 is needed by dpkg-shlibdeps to resolve the
|
||||
# dynamically-linked libstdc++ when cargo-deb computes $auto depends.
|
||||
if [ "${{ matrix.arch }}" = "arm64" ]; then
|
||||
apt-get install -y liburing-dev:arm64 libstdc++6:arm64
|
||||
fi
|
||||
|
||||
- name: Run cargo-deb
|
||||
id: cargo-deb
|
||||
run: |
|
||||
DEB_PATH=$(cargo deb --deb-version ${{ steps.package-meta.outputs.version }})
|
||||
TARGET=${{ matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}
|
||||
DEB_PATH=$(cargo deb --target $TARGET --deb-version ${{ steps.package-meta.outputs.version }})
|
||||
echo "path=$DEB_PATH" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Test deb installation
|
||||
if: matrix.arch == 'amd64'
|
||||
run: |
|
||||
echo "Installing: ${{ steps.cargo-deb.outputs.path }}"
|
||||
|
||||
apt-get install -y ${{ steps.cargo-deb.outputs.path }}
|
||||
|
||||
dpkg -s continuwuity
|
||||
|
||||
[ -f /usr/bin/conduwuit ] && echo "✅ Binary installed successfully"
|
||||
[ -f /usr/lib/systemd/system/conduwuit.service ] && echo "✅ Systemd service installed"
|
||||
[ -f /etc/conduwuit/conduwuit.toml ] && echo "✅ Config file installed"
|
||||
@@ -142,7 +192,7 @@ jobs:
|
||||
- name: Upload deb artifact
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: continuwuity-${{ steps.debian-version.outputs.distribution }}
|
||||
name: continuwuity-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}
|
||||
path: ${{ steps.cargo-deb.outputs.path }}
|
||||
|
||||
- name: Publish to Forgejo package registry
|
||||
|
||||
@@ -1,3 +1,51 @@
|
||||
# Continuwuity 26.7.3 (2026-08-11)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fixed a vulnerability that enabled the server to leak certain events over federation. Contributed by @eleboucher. (SEC26)
|
||||
- Fixed an issue that allowed an attacker to take over another account on the same server under certain conditions. ([GHSA-v2x6-m99h-vqxx](https://github.com/continuwuity/continuwuity/security/advisories/GHSA-v2x6-m99h-vqxx)) Contributed by @gingershaped and reported by GlitchedAxiom. (SEC28)
|
||||
|
||||
|
||||
# Continuwuity 26.7.0 (2026-07-27)
|
||||
|
||||
## Features
|
||||
|
||||
- Build and publish arm64 .deb packages alongside amd64 for all supported Debian and Ubuntu releases. (#1235)
|
||||
- Dehydrated devices are now visible in the account panel. Contributed by @ginger. (#1970)
|
||||
- Introduce `accepted_ip_sources` as a multiple options variant of `request_ip_source`, allowing for more advanced deployments and making fallbacks an explicit choice. Contributed by @Omar007 (#1985)
|
||||
- Added an admin command to issue an access token for a bot account, to allow legacy bots to function while legacy authentication is disabled. Contributed by @ginger (#2044)
|
||||
- Added support for the OAuth2 device authorization flow. Contributed by @ginger
|
||||
- Added support for the stable mutual rooms query endpoint. Contributed by @ginger
|
||||
- Fetch the joined member count once per event instead of once per notified user.
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fix joining restricted rooms over federation failing with signature verification error. (fix-federation-signature)
|
||||
- Fixed the client space hierarchy endpoint returning a 500 "Space hierarchy is unreasonably large" error for cyclic space graphs (e.g. a space containing itself). Rooms are now deduplicated during traversal as required by the spec, and the traversal depth is bounded even when the client does not specify `max_depth`. (space-hierarchy-cycle)
|
||||
- Fixed simplified sliding sync holding account data for up to 30 seconds, which made encryption setup and cross-signing resets appear to hang. (sss-account-data-longpoll)
|
||||
- Fixed local invites and invite acceptances not being reflected in sync promptly. Contributed by @eleboucher (wake-local-member-sync)
|
||||
- Fixed the deeplink redirect for deleting devices. Contributed by @koen (#1965)
|
||||
- Fix status code for oauth registration. Contributed by @n00byking (#1984)
|
||||
- Exempt m.room.create from auth_events check. Contributed by @eleboucher (#1987)
|
||||
- Fixed `create` being returned as a supported prompt value regardless of if registration is enabled or not. Contributed by @ginger (#1994)
|
||||
- Fixed high CPU usage when multiple clients from the same account were connected at once. Each sync woke the account's other sync loops, causing them to wake each other in a loop. (#2006)
|
||||
- Fixed MSC4190 appservice device creation registering a random device ID instead of the requested one (and dropping the requested display name), which prevented encrypted mautrix bridges from starting on OIDC-enabled servers and leaked an orphan device on the bridge bot per startup attempt. (#2015)
|
||||
- Deactivated users and appservice puppets are no longer counted by `/_continuwuity/local_user_count`. Contributed by @ginger. (#2040)
|
||||
- Re-introduced admin room registration alerts that were accidentally removed in the OAuth2 update. (#2057)
|
||||
- Appservices are now properly able to create devices for E2EE.
|
||||
- Appservices may now specify both the unstable and stable `device_id` query parameters in a request. The stable parameter will take priority. Contributed by @ginger.
|
||||
- Fixed `roomuserid_lastnotificationread` being aliased to the highlight count table, which clobbered highlight counts when setting a read marker. Contributed by @eleboucher
|
||||
- Fixed freshly left room failing to sync.
|
||||
- Fixed newly created rooms failing to sync properly in clients using legacy sync.
|
||||
- Fixed newly joined rooms failing to sync their full state (including the room name) to clients using legacy sync.
|
||||
- Fixed requests returning `500 Internal Server Error` when the header selected by `request_ip_source` is absent, duplicated, or malformed (for example Envoy omitting `X-Envoy-External-Address` on internal requests). The client IP now falls back to the connection peer address instead of failing the request. Contributed by @eleboucher
|
||||
- Resolve alias service by correct name for auto-join. Contributed by @eleboucher
|
||||
|
||||
## Improved Documentation
|
||||
|
||||
- Updated an out-of-date statement about Oracle Linux release cadences. (#1999)
|
||||
|
||||
|
||||
# Continuwuity 26.6.2 (2026-07-12)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
Generated
+23
-23
@@ -816,7 +816,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"clap",
|
||||
@@ -854,7 +854,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_admin"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"clap",
|
||||
@@ -880,7 +880,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_api"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"async-trait",
|
||||
@@ -918,7 +918,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_build_metadata"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"built",
|
||||
"cargo_metadata",
|
||||
@@ -926,7 +926,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_core"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"arrayvec",
|
||||
@@ -994,7 +994,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_database"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"conduwuit_core",
|
||||
@@ -1015,7 +1015,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_macros"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"cargo_toml",
|
||||
"itertools 0.15.0",
|
||||
@@ -1026,7 +1026,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_router"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"axum",
|
||||
@@ -1063,7 +1063,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_service"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"askama",
|
||||
"assign",
|
||||
@@ -1115,7 +1115,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_web"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"askama",
|
||||
"assign",
|
||||
@@ -4567,7 +4567,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.16.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
@@ -4586,7 +4586,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.16.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -4598,7 +4598,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.24.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
@@ -4620,7 +4620,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.19.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64 0.22.1",
|
||||
@@ -4653,7 +4653,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.34.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap 2.14.0",
|
||||
@@ -4674,7 +4674,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"headers",
|
||||
@@ -4697,7 +4697,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.12.1"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.19",
|
||||
@@ -4706,7 +4706,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.19.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"cfg-if",
|
||||
@@ -4722,7 +4722,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -4734,7 +4734,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ed25519-dalek",
|
||||
@@ -4751,7 +4751,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-state-res"
|
||||
version = "0.17.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=3ad047126b321d5fdcf170e1f2e545fed820cf75#3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=e7284c31da289f0a3b885191f5b2b6b307fa059f#e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -4765,7 +4765,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruminuwuity"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"ruma",
|
||||
@@ -6874,7 +6874,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
dependencies = [
|
||||
"askama",
|
||||
"cargo_metadata",
|
||||
|
||||
+2
-4
@@ -12,7 +12,7 @@ license = "Apache-2.0"
|
||||
# See also `rust-toolchain.toml`
|
||||
readme = "README.md"
|
||||
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
||||
version = "26.6.2"
|
||||
version = "26.7.3"
|
||||
|
||||
[workspace.metadata.crane]
|
||||
name = "conduwuit"
|
||||
@@ -342,9 +342,8 @@ version = "1.1.1"
|
||||
|
||||
# Used for matrix spec type definitions and helpers
|
||||
[workspace.dependencies.ruma]
|
||||
# version = "0.14.1"
|
||||
git = "https://github.com/ruma/ruma.git"
|
||||
rev = "3ad047126b321d5fdcf170e1f2e545fed820cf75"
|
||||
rev = "e7284c31da289f0a3b885191f5b2b6b307fa059f"
|
||||
features = [
|
||||
"appservice-api-c",
|
||||
"client-api",
|
||||
@@ -357,7 +356,6 @@ features = [
|
||||
"compat-upload-signatures",
|
||||
"compat-optional-txn-pdus",
|
||||
"compat-get-3pids",
|
||||
"unstable-msc2666",
|
||||
"unstable-msc2867",
|
||||
"unstable-msc2870",
|
||||
"unstable-msc3061",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Added support for the OAuth2 device authorization flow. Contributed by @ginger
|
||||
@@ -1 +0,0 @@
|
||||
Fixed requests returning `500 Internal Server Error` when the header selected by `request_ip_source` is absent, duplicated, or malformed (for example Envoy omitting `X-Envoy-External-Address` on internal requests). The client IP now falls back to the connection peer address instead of failing the request. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Appservices are now properly able to create devices for E2EE.
|
||||
@@ -1 +0,0 @@
|
||||
Resolve alias service by correct name for auto-join. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Fixed newly created rooms failing to sync properly in clients using legacy sync.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed newly joined rooms failing to sync their full state (including the room name) to clients using legacy sync.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed `roomuserid_lastnotificationread` being aliased to the highlight count table, which clobbered highlight counts when setting a read marker. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Fixed freshly left room failing to sync.
|
||||
@@ -1 +0,0 @@
|
||||
Appservices may now specify both the unstable and stable `device_id` query parameters in a request. The stable parameter will take priority. Contributed by @ginger.
|
||||
@@ -1 +0,0 @@
|
||||
Fetch the joined member count once per event instead of once per notified user.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed the deeplink redirect for deleting devices. Contributed by @koen
|
||||
@@ -1 +0,0 @@
|
||||
Dehydrated devices are now visible in the account panel. Contributed by @ginger.
|
||||
@@ -1 +0,0 @@
|
||||
Fix status code for oauth registration. Contributed by @n00byking
|
||||
@@ -1 +0,0 @@
|
||||
Introduce `accepted_ip_sources` as a multiple options variant of `request_ip_source`, allowing for more advanced deployments and making fallbacks an explicit choice. Contributed by @Omar007
|
||||
@@ -1 +0,0 @@
|
||||
Exempt m.room.create from auth_events check. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Fixed `create` being returned as a supported prompt value regardless of if registration is enabled or not. Contributed by @ginger
|
||||
@@ -1 +0,0 @@
|
||||
Updated an out-of-date statement about Oracle Linux release cadences.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed high CPU usage when multiple clients from the same account were connected at once. Each sync woke the account's other sync loops, causing them to wake each other in a loop.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed MSC4190 appservice device creation registering a random device ID instead of the requested one (and dropping the requested display name), which prevented encrypted mautrix bridges from starting on OIDC-enabled servers and leaked an orphan device on the bridge bot per startup attempt.
|
||||
@@ -1 +0,0 @@
|
||||
Deactivated users and appservice puppets are no longer counted by `/_continuwuity/local_user_count`. Contributed by @ginger.
|
||||
@@ -1 +0,0 @@
|
||||
Added an admin command to issue an access token for a bot account, to allow legacy bots to function while legacy authentication is disabled.
|
||||
@@ -1 +0,0 @@
|
||||
Re-introduced admin room registration alerts that were accidentally removed in the OAuth2 update.
|
||||
@@ -1 +0,0 @@
|
||||
Fix joining restricted rooms over federation failing with signature verification error.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed the client space hierarchy endpoint returning a 500 "Space hierarchy is unreasonably large" error for cyclic space graphs (e.g. a space containing itself). Rooms are now deduplicated during traversal as required by the spec, and the traversal depth is bounded even when the client does not specify `max_depth`.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed simplified sliding sync holding account data for up to 30 seconds, which made encryption setup and cross-signing resets appear to hang.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed local invites and invite acceptances not being reflected in sync promptly. Contributed by @eleboucher
|
||||
@@ -8,6 +8,10 @@ ## `!admin users create-user`
|
||||
|
||||
Create a new user
|
||||
|
||||
## `!admin users issue-token`
|
||||
|
||||
Issue an access token for a user. This command will not work on shadow users, such as appservice puppets or accounts imported from an identity provider
|
||||
|
||||
## `!admin users reset-password`
|
||||
|
||||
Reset user password
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result};
|
||||
use futures::StreamExt;
|
||||
use ruma::api::client::membership::mutual_rooms;
|
||||
use ruma::{OwnedRoomId, api::client::membership::mutual_rooms};
|
||||
|
||||
use crate::Ruma;
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
///
|
||||
/// An implementation of [MSC2666](https://github.com/matrix-org/matrix-spec-proposals/pull/2666)
|
||||
#[tracing::instrument(skip_all, name = "mutual_rooms", level = "info")]
|
||||
pub(crate) async fn get_mutual_rooms_route(
|
||||
pub(crate) async fn get_mutual_rooms_unstable_route(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<mutual_rooms::unstable::Request>,
|
||||
) -> Result<mutual_rooms::unstable::Response> {
|
||||
let sender_user = body.identity.expect_sender_user()?;
|
||||
|
||||
if sender_user == body.user_id {
|
||||
return Err!(Request(Unknown("You cannot request rooms in common with yourself.")));
|
||||
return Err!(Request(InvalidParam("You cannot request rooms in common with yourself.")));
|
||||
}
|
||||
|
||||
let mutual_rooms = services
|
||||
@@ -30,3 +30,33 @@ pub(crate) async fn get_mutual_rooms_route(
|
||||
|
||||
Ok(mutual_rooms::unstable::Response::new(mutual_rooms))
|
||||
}
|
||||
|
||||
/// # `GET /_matrix/client/v1/mutual_rooms`
|
||||
///
|
||||
/// Gets all the rooms the sender shares with the specified user.
|
||||
#[tracing::instrument(skip_all, name = "mutual_rooms", level = "info")]
|
||||
pub(crate) async fn get_mutual_rooms_route(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<mutual_rooms::v1::Request>,
|
||||
) -> Result<mutual_rooms::v1::Response> {
|
||||
let sender_user = body.identity.expect_sender_user()?;
|
||||
|
||||
if sender_user == body.user_id {
|
||||
return Err!(Request(InvalidParam("You cannot request rooms in common with yourself.")));
|
||||
}
|
||||
|
||||
let mutual_rooms: Vec<OwnedRoomId> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_shared_rooms(sender_user, &body.user_id)
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
Ok(mutual_rooms::v1::Response::new(
|
||||
mutual_rooms
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("user should be in fewer than 9.1 quadrillion rooms"),
|
||||
mutual_rooms,
|
||||
))
|
||||
}
|
||||
|
||||
+112
-23
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
|
||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||
ops::Deref,
|
||||
time::Duration,
|
||||
};
|
||||
@@ -138,6 +138,13 @@ pub(crate) async fn sync_events_v5_route(
|
||||
let (all_joined_rooms, all_invited_rooms, all_knocked_rooms) =
|
||||
join3(all_joined_rooms, all_invited_rooms, all_knocked_rooms).await;
|
||||
|
||||
let allowed_rooms: BTreeSet<OwnedRoomId> = all_joined_rooms
|
||||
.iter()
|
||||
.chain(all_invited_rooms.iter())
|
||||
.chain(all_knocked_rooms.iter())
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let all_joined_rooms = all_joined_rooms.iter().map(AsRef::as_ref);
|
||||
let all_invited_rooms = all_invited_rooms.iter().map(AsRef::as_ref);
|
||||
let all_knocked_rooms = all_knocked_rooms.iter().map(AsRef::as_ref);
|
||||
@@ -190,13 +197,14 @@ pub(crate) async fn sync_events_v5_route(
|
||||
)
|
||||
.await;
|
||||
|
||||
fetch_subscriptions(services, sync_info, &known_rooms, &mut todo_rooms).await;
|
||||
fetch_subscriptions(services, sync_info, &known_rooms, &allowed_rooms, &mut todo_rooms).await;
|
||||
|
||||
response.rooms = process_rooms(
|
||||
services,
|
||||
sender_user,
|
||||
next_batch,
|
||||
all_invited_rooms.clone(),
|
||||
all_knocked_rooms.clone(),
|
||||
&todo_rooms,
|
||||
&mut response,
|
||||
&body,
|
||||
@@ -214,6 +222,7 @@ pub(crate) async fn sync_events_v5_route(
|
||||
let no_room_data = response.rooms.iter().all(|(id, r)| {
|
||||
r.timeline.is_empty()
|
||||
&& r.required_state.is_empty()
|
||||
&& r.invite_state.is_none()
|
||||
&& !response.extensions.receipts.rooms.contains_key(id)
|
||||
});
|
||||
|
||||
@@ -247,10 +256,17 @@ async fn fetch_subscriptions(
|
||||
services: &Services,
|
||||
(sender_user, sender_device, globalsince, body): SyncInfo<'_>,
|
||||
known_rooms: &KnownRooms,
|
||||
allowed_rooms: &BTreeSet<OwnedRoomId>,
|
||||
todo_rooms: &mut TodoRooms,
|
||||
) {
|
||||
let mut known_subscription_rooms = BTreeSet::new();
|
||||
for (room_id, room) in &body.room_subscriptions {
|
||||
// Silently ignore subscriptions to rooms the user is not a member of
|
||||
// (joined or invited).
|
||||
if !allowed_rooms.contains(room_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let not_exists = services.rooms.metadata.exists(room_id).eq(&false);
|
||||
|
||||
let is_disabled = services.rooms.metadata.is_disabled(room_id);
|
||||
@@ -409,11 +425,13 @@ async fn handle_lists<'a, Rooms, AllRooms>(
|
||||
BTreeMap::default()
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn process_rooms<'a, Rooms>(
|
||||
services: &Services,
|
||||
sender_user: &UserId,
|
||||
next_batch: u64,
|
||||
all_invited_rooms: Rooms,
|
||||
all_knocked_rooms: Rooms,
|
||||
todo_rooms: &TodoRooms,
|
||||
response: &mut sync_events::v5::Response,
|
||||
body: &sync_events::v5::Request,
|
||||
@@ -426,38 +444,101 @@ async fn process_rooms<'a, Rooms>(
|
||||
let roomsincecount = PduCount::Normal(*roomsince);
|
||||
|
||||
let mut timestamp: Option<_> = None;
|
||||
let mut invite_state = None;
|
||||
let (timeline_pdus, limited);
|
||||
let new_room_id: &RoomId = (*room_id).as_ref();
|
||||
if all_invited_rooms.clone().any(is_equal_to!(new_room_id)) {
|
||||
let Ok(invite_count) = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_invite_count(room_id, sender_user)
|
||||
.await
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if *roomsince >= invite_count {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: figure out a timestamp we can use for remote invites
|
||||
invite_state = services
|
||||
let invite_state = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.invite_state(sender_user, room_id)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
(timeline_pdus, limited) = (VecDeque::new(), true);
|
||||
} else {
|
||||
TimelinePdus { pdus: timeline_pdus, limited } = match load_timeline(
|
||||
services,
|
||||
sender_user,
|
||||
room_id,
|
||||
Some(roomsincecount),
|
||||
Some(PduCount::from(next_batch)),
|
||||
*timeline_limit,
|
||||
)
|
||||
.await
|
||||
{
|
||||
| Ok(value) => value,
|
||||
| Err(err) => {
|
||||
warn!("Encountered missing timeline in {}, error {}", room_id, err);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
rooms.insert(
|
||||
room_id.clone(),
|
||||
assign!(sync_events::v5::response::Room::new(), {
|
||||
initial: Some(roomsince == &0),
|
||||
invite_state,
|
||||
limited: true,
|
||||
}),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if all_knocked_rooms.clone().any(is_equal_to!(new_room_id)) {
|
||||
let Ok(knock_count) = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_knock_count(room_id, sender_user)
|
||||
.await
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if *roomsince >= knock_count {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Ok(knock_state) = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.knock_state(sender_user, room_id)
|
||||
.await
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
rooms.insert(
|
||||
room_id.clone(),
|
||||
assign!(sync_events::v5::response::Room::new(), {
|
||||
initial: Some(roomsince == &0),
|
||||
invite_state: Some(knock_state),
|
||||
limited: true,
|
||||
}),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if !services
|
||||
.rooms
|
||||
.state_cache
|
||||
.is_joined(sender_user, room_id)
|
||||
.await
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TimelinePdus { pdus: timeline_pdus, limited } = match load_timeline(
|
||||
services,
|
||||
sender_user,
|
||||
room_id,
|
||||
Some(roomsincecount),
|
||||
Some(PduCount::from(next_batch)),
|
||||
*timeline_limit,
|
||||
)
|
||||
.await
|
||||
{
|
||||
| Ok(value) => value,
|
||||
| Err(err) => {
|
||||
warn!("Encountered missing timeline in {}, error {}", room_id, err);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
|
||||
if body.extensions.account_data.enabled == Some(true) {
|
||||
response.extensions.account_data.rooms.insert(
|
||||
room_id.to_owned(),
|
||||
@@ -641,7 +722,6 @@ async fn process_rooms<'a, Rooms>(
|
||||
},
|
||||
initial: Some(roomsince == &0),
|
||||
is_dm: None,
|
||||
invite_state,
|
||||
unread_notifications: assign!(UnreadNotificationsCount::new(), {
|
||||
highlight_count: Some(
|
||||
services
|
||||
@@ -769,6 +849,15 @@ async fn collect_typing_events(
|
||||
|
||||
let mut typing_response = sync_events::v5::response::Typing::default();
|
||||
for (room_id, (_, _, roomsince)) in todo_rooms {
|
||||
if !services
|
||||
.rooms
|
||||
.state_cache
|
||||
.is_joined(sender_user, room_id)
|
||||
.await
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if services.rooms.typing.last_typing_update(room_id).await? <= *roomsince {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ pub fn build(router: Router<State>, state: State) -> Router<State> {
|
||||
.ruma_route(&client::get_relating_events_with_rel_type_route)
|
||||
.ruma_route(&client::get_relating_events_route)
|
||||
.ruma_route(&client::get_hierarchy_route)
|
||||
.ruma_route(&client::get_mutual_rooms_unstable_route)
|
||||
.ruma_route(&client::get_mutual_rooms_route)
|
||||
.ruma_route(&client::get_room_summary)
|
||||
.ruma_route(&client::get_suspended_status)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::{borrow::Borrow, iter::once};
|
||||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Error, Result, err, info, utils::stream::ReadyExt};
|
||||
use conduwuit::{Err, Event, Result, info, utils::stream::ReadyExt};
|
||||
use futures::StreamExt;
|
||||
use ruma::{RoomId, api::federation::authorization::get_event_authorization};
|
||||
use ruma::api::federation::authorization::get_event_authorization;
|
||||
|
||||
use super::AccessCheck;
|
||||
use crate::Ruma;
|
||||
@@ -48,25 +48,21 @@ pub(crate) async fn get_event_authorization_route(
|
||||
return Err!(Request(NotFound("This server is not participating in that room.")));
|
||||
}
|
||||
|
||||
let event = services
|
||||
// The event must be in the room we just authorised access to
|
||||
if !services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&body.event_id)
|
||||
.get_pdu(&body.event_id)
|
||||
.await
|
||||
.map_err(|_| err!(Request(NotFound("Event not found."))))?;
|
||||
|
||||
let room_id_str = event
|
||||
.get("room_id")
|
||||
.and_then(|val| val.as_str())
|
||||
.ok_or_else(|| Error::bad_database("Invalid event in database."))?;
|
||||
|
||||
let room_id = <&RoomId>::try_from(room_id_str)
|
||||
.map_err(|_| Error::bad_database("Invalid room_id in event in database."))?;
|
||||
.is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id)
|
||||
{
|
||||
return Err!(Request(NotFound("Event not found.")));
|
||||
}
|
||||
|
||||
let auth_chain = services
|
||||
.rooms
|
||||
.auth_chain
|
||||
.event_ids_iter(room_id, once(body.event_id.borrow()))
|
||||
.event_ids_iter(&body.room_id, once(body.event_id.borrow()))
|
||||
.ready_filter_map(Result::ok)
|
||||
.filter_map(|id| async move { services.rooms.timeline.get_pdu_json(&id).await.ok() })
|
||||
.then(|pdu| services.sending.convert_to_outgoing_federation_event(pdu))
|
||||
|
||||
+12
-1
@@ -1,7 +1,7 @@
|
||||
use std::{borrow::Borrow, iter::once};
|
||||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result, at, err, info, utils::IterStream};
|
||||
use conduwuit::{Err, Event, Result, at, err, info, utils::IterStream};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use ruma::{OwnedEventId, api::federation::event::get_room_state};
|
||||
|
||||
@@ -24,6 +24,17 @@ pub(crate) async fn get_room_state_route(
|
||||
.assert()
|
||||
.await?;
|
||||
|
||||
// The event must be in the room we just authorised access to
|
||||
if !services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu(&body.event_id)
|
||||
.await
|
||||
.is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id)
|
||||
{
|
||||
return Err!(Request(NotFound("Event not found.")));
|
||||
}
|
||||
|
||||
if services
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{borrow::Borrow, iter::once};
|
||||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result, at, err, info};
|
||||
use conduwuit::{Err, Event, Result, at, err, info};
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
use ruma::{OwnedEventId, api::federation::event::get_room_state_ids};
|
||||
|
||||
@@ -25,6 +25,17 @@ pub(crate) async fn get_room_state_ids_route(
|
||||
.assert()
|
||||
.await?;
|
||||
|
||||
// The event must be in the room we just authorised access to
|
||||
if !services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu(&body.event_id)
|
||||
.await
|
||||
.is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id)
|
||||
{
|
||||
return Err!(Request(NotFound("Event not found.")));
|
||||
}
|
||||
|
||||
if services
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
|
||||
@@ -34,6 +34,7 @@ pub fn unstable_features() -> BTreeMap<String, bool> {
|
||||
// query mutual rooms (https://github.com/matrix-org/matrix-spec-proposals/pull/2666)
|
||||
// Expected for spec v1.19
|
||||
("uk.half-shot.msc2666.query_mutual_rooms".to_owned(), true),
|
||||
("uk.half-shot.msc2666.query_mutual_rooms.stable".to_owned(), true),
|
||||
// Simplified Sliding sync (https://github.com/matrix-org/matrix-spec-proposals/pull/4186)
|
||||
// Expected for spec v1.19
|
||||
("org.matrix.simplified_msc3575".to_owned(), true),
|
||||
|
||||
+4
-1
@@ -35,7 +35,10 @@ systemd-units = { unit-name = "conduwuit", start = false, unit-scripts = "../../
|
||||
assets = [
|
||||
["../../pkg/debian/README.md", "usr/share/doc/conduwuit/README.Debian", "644"],
|
||||
["../../README.md", "usr/share/doc/conduwuit/", "644"],
|
||||
["../../target/release/conduwuit", "usr/bin/conduwuit", "755"],
|
||||
# cargo-deb only treats the exact prefix "target/release/" as the magic
|
||||
# path that resolves to the real build dir (e.g. target/<triple>/release
|
||||
# when cross-compiling); a ../../ prefix would be read as a literal path
|
||||
["target/release/conduwuit", "usr/bin/conduwuit", "755"],
|
||||
["../../conduwuit-example.toml", "etc/conduwuit/conduwuit.toml", "640"],
|
||||
]
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Err, Event, Result, debug, debug_error, debug_warn, defer, matrix::PartialPdu, trace,
|
||||
utils::time::jitter,
|
||||
};
|
||||
use futures::{FutureExt, StreamExt, future::try_join3};
|
||||
use futures::{FutureExt, StreamExt, future::try_join4};
|
||||
use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UserId};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
@@ -69,9 +69,13 @@ pub async fn handle_incoming_pdu<'a>(
|
||||
.and_then(|s| UserId::parse(s).ok())
|
||||
.is_some_and(|u| self.services.globals.user_is_local(&u));
|
||||
|
||||
let (room_exists, is_disabled, ()) = try_join3(
|
||||
let (room_exists, is_disabled, is_resident, ()) = try_join4(
|
||||
self.services.metadata.exists(room_id).map(Ok),
|
||||
self.services.metadata.is_disabled(room_id).map(Ok),
|
||||
self.services
|
||||
.state_cache
|
||||
.server_in_room(self.services.globals.server_name(), room_id)
|
||||
.map(Ok),
|
||||
self.acl_check(origin, room_id),
|
||||
)
|
||||
.await
|
||||
@@ -85,12 +89,20 @@ pub async fn handle_incoming_pdu<'a>(
|
||||
)));
|
||||
}
|
||||
|
||||
// If the room doesn't exist (we don't have the create event), there's nothing
|
||||
// we can do.
|
||||
if !room_exists {
|
||||
return Err!(Request(NotFound("Room is unknown to this server")));
|
||||
}
|
||||
// If the room does exist, but we aren't a resident of it, we might be
|
||||
// interested in an out-of-band membership (for example, an inviter rescinding
|
||||
// their invite).
|
||||
if !is_resident {
|
||||
if is_interesting_member_event {
|
||||
// TODO: handle interesting membership events where we aren't in
|
||||
// the room
|
||||
}
|
||||
return Err!(Request(NotFound("Room is unknown to this server")));
|
||||
return Err!(Request(NotFound("This server does not have any members this room")));
|
||||
}
|
||||
|
||||
// Fetch create event
|
||||
|
||||
@@ -104,24 +104,24 @@ pub(super) async fn upgrade_outlier_to_timeline_pdu(
|
||||
// Determine whether this PDU should be soft-failed.
|
||||
// If the auth check failed, invariably yes. Otherwise, only if the user isn't
|
||||
// allowed to redact the target event (if any).
|
||||
let mut should_soft_fail =
|
||||
match (passes_current_state, incoming_pdu.redacts_id(&room_version_rules)) {
|
||||
| (false, _) => true,
|
||||
| (true, None) => false,
|
||||
| (true, Some(redact_id)) => self
|
||||
.services
|
||||
let redaction_permitted =
|
||||
if let Some(redacted_id) = incoming_pdu.redacts_id(&room_version_rules) {
|
||||
self.services
|
||||
.state_accessor
|
||||
.user_can_redact(&redact_id, incoming_pdu.sender(), room_id, true)
|
||||
.user_can_redact(&redacted_id, incoming_pdu.sender(), room_id, true)
|
||||
.await
|
||||
.is_ok_and(is_true!()),
|
||||
.is_ok_and(is_true!())
|
||||
} else {
|
||||
true
|
||||
};
|
||||
let mut should_soft_fail = !redaction_permitted || !passes_current_state;
|
||||
|
||||
if !should_soft_fail {
|
||||
// Now we can perform check 7, which is ensuring the event passes policy server
|
||||
// checks.
|
||||
// We explicitly only do this if we aren't already going to soft-fail the event,
|
||||
// since the policy server refusing this event also soft-fails it.
|
||||
debug!(event_id = %incoming_pdu.event_id, "Checking policy server for event");
|
||||
debug!("Checking policy server for event");
|
||||
should_soft_fail = !self
|
||||
.policy_server_check_7(&incoming_pdu, &mut val, &room_version_rules)
|
||||
.await
|
||||
@@ -153,6 +153,12 @@ pub(super) async fn upgrade_outlier_to_timeline_pdu(
|
||||
should_soft_fail = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
%redaction_permitted,
|
||||
%passes_current_state,
|
||||
"Intending to soft-fail event (skipping further PDU checks)"
|
||||
);
|
||||
}
|
||||
|
||||
// The PDU has now passed all checks! We can now promote it (or soft-fail it if
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use conduwuit::{Err, Result, matrix::Event, pdu::PartialPdu};
|
||||
use conduwuit::{Err, Result, matrix::Event, pdu::PartialPdu, trace};
|
||||
use ruma::{
|
||||
EventId, RoomId, UserId,
|
||||
events::{
|
||||
@@ -46,6 +46,7 @@ pub async fn user_can_redact(
|
||||
let power_levels = self.get_room_power_levels(room_id).await;
|
||||
|
||||
if power_levels.user_can_redact_event_of_other(sender) {
|
||||
trace!(%sender, "Sender is allowed to redact other users' events");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -59,10 +60,12 @@ pub async fn user_can_redact(
|
||||
},
|
||||
| _ => false,
|
||||
};
|
||||
trace!(%is_own_event, "User can redact own event");
|
||||
|
||||
return Ok(is_own_event);
|
||||
}
|
||||
|
||||
trace!("User is not permitted to redact their own event nor others' events");
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,10 @@ pub async fn send_validation_email<Template: MessageTemplate>(
|
||||
// If a validation session already exists for this client secret, we can either
|
||||
// reuse it with a new token or return early because it's already valid.
|
||||
| Some(session) => {
|
||||
if session.email != recipient.email {
|
||||
return Err!(Request(InvalidParam("Wrong email for session.")));
|
||||
}
|
||||
|
||||
match session.validation_state {
|
||||
| ValidationState::Validated => {
|
||||
// If the existing session is already valid, don't send an email.
|
||||
@@ -134,7 +138,7 @@ pub async fn send_validation_email<Template: MessageTemplate>(
|
||||
},
|
||||
| ValidationState::Pending(ref mut token) => {
|
||||
// Check ratelimiting for the target address.
|
||||
if self.ratelimiter.check_key(&recipient.email).is_err() {
|
||||
if self.ratelimiter.check_key(&session.email).is_err() {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::LimitExceeded(LimitExceededErrorData::new()),
|
||||
"You're sending emails too fast, try again in a few minutes.",
|
||||
|
||||
Reference in New Issue
Block a user