Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aba95b20f3 | ||
|
|
9b57c89df6 | ||
|
|
34d3f74f36 | ||
|
|
11a21fc136 | ||
|
|
0183d003d0 | ||
|
|
f712455047 | ||
|
|
58ea081762 | ||
|
|
bffddbd487 | ||
|
|
41fef1da64 | ||
|
|
892a0525f2 | ||
|
|
1fc616320a | ||
|
|
14a178d783 | ||
|
|
339a26f56c | ||
|
|
ca724b6340 | ||
|
|
9bfc7b34b6 | ||
|
|
afa5d449c6 | ||
|
|
2fff720df3 | ||
|
|
da00f611e9 | ||
|
|
9fccbb014a | ||
|
|
109892b4b7 | ||
|
|
24a835647c | ||
|
|
c4bce1d0c7 | ||
|
|
9b63708685 | ||
|
|
86177faae7 | ||
|
|
2a749c1e99 | ||
|
|
d5d25fb064 | ||
|
|
8087a26a35 | ||
|
|
bbe16f8467 | ||
|
|
50f931a2fd | ||
|
|
1541b93f45 | ||
|
|
ccf501a420 |
@@ -14,6 +14,8 @@ docker-compose*
|
|||||||
# Git folder
|
# Git folder
|
||||||
.git
|
.git
|
||||||
.gitea
|
.gitea
|
||||||
|
.gitlab
|
||||||
|
.github
|
||||||
|
|
||||||
# Dot files
|
# Dot files
|
||||||
.env
|
.env
|
||||||
|
|||||||
+136
-199
@@ -9,7 +9,6 @@ variables:
|
|||||||
FF_USE_FASTZIP: 1
|
FF_USE_FASTZIP: 1
|
||||||
CACHE_COMPRESSION_LEVEL: fastest
|
CACHE_COMPRESSION_LEVEL: fastest
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# Cargo: Compiling for different architectures #
|
# Cargo: Compiling for different architectures #
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
@@ -20,7 +19,7 @@ variables:
|
|||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == "master"'
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
- if: '$CI_COMMIT_BRANCH == "next"'
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: "$CI_COMMIT_TAG"
|
||||||
interruptible: true
|
interruptible: true
|
||||||
image: "rust:latest"
|
image: "rust:latest"
|
||||||
tags: ["docker"]
|
tags: ["docker"]
|
||||||
@@ -28,258 +27,184 @@ variables:
|
|||||||
paths:
|
paths:
|
||||||
- cargohome
|
- cargohome
|
||||||
- target/
|
- target/
|
||||||
key: "build_cache-$TARGET-release"
|
key: "build_cache--$TARGET--$CI_COMMIT_BRANCH--release"
|
||||||
variables:
|
variables:
|
||||||
CARGO_PROFILE_RELEASE_LTO=true
|
CARGO_PROFILE_RELEASE_LTO: "true"
|
||||||
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1
|
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1"
|
||||||
before_script:
|
before_script:
|
||||||
- 'echo "Building for target $TARGET"'
|
- 'echo "Building for target $TARGET"'
|
||||||
- 'mkdir -p cargohome && CARGOHOME="cargohome"'
|
- 'mkdir -p cargohome && CARGOHOME="cargohome"'
|
||||||
- "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging
|
- "rustc --version && cargo --version && rustup show" # Print version info for debugging
|
||||||
- 'apt-get update -yqq'
|
|
||||||
- 'echo "Installing packages: $NEEDED_PACKAGES"'
|
|
||||||
- "apt-get install -yqq --no-install-recommends $NEEDED_PACKAGES"
|
|
||||||
- "rustup target add $TARGET"
|
- "rustup target add $TARGET"
|
||||||
script:
|
script:
|
||||||
- time cargo build --target $TARGET --release
|
- time cargo build --target $TARGET --release
|
||||||
- 'mv "target/$TARGET/release/conduit" "conduit-$TARGET"'
|
- 'cp "target/$TARGET/release/conduit" "conduit-$TARGET"'
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: never
|
expire_in: never
|
||||||
|
|
||||||
|
build:release:cargo:x86_64-unknown-linux-musl-with-debug:
|
||||||
build:release:cargo:x86_64-unknown-linux-gnu:
|
|
||||||
extends: .build-cargo-shared-settings
|
extends: .build-cargo-shared-settings
|
||||||
|
image: messense/rust-musl-cross:x86_64-musl
|
||||||
variables:
|
variables:
|
||||||
TARGET: "x86_64-unknown-linux-gnu"
|
CARGO_PROFILE_RELEASE_DEBUG: 2 # Enable debug info for flamegraph profiling
|
||||||
|
TARGET: "x86_64-unknown-linux-musl"
|
||||||
|
after_script:
|
||||||
|
- "mv ./conduit-x86_64-unknown-linux-musl ./conduit-x86_64-unknown-linux-musl-with-debug"
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "conduit-x86_64-unknown-linux-gnu"
|
name: "conduit-x86_64-unknown-linux-musl-with-debug"
|
||||||
paths:
|
paths:
|
||||||
- "conduit-x86_64-unknown-linux-gnu"
|
- "conduit-x86_64-unknown-linux-musl-with-debug"
|
||||||
expose_as: "Conduit for x86_64-unknown-linux-gnu"
|
expose_as: "Conduit for x86_64-unknown-linux-musl-with-debug"
|
||||||
|
|
||||||
build:release:cargo:armv7-unknown-linux-gnueabihf:
|
|
||||||
extends: .build-cargo-shared-settings
|
|
||||||
variables:
|
|
||||||
TARGET: "armv7-unknown-linux-gnueabihf"
|
|
||||||
NEEDED_PACKAGES: "build-essential gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross"
|
|
||||||
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
|
||||||
CC_armv7_unknown_linux_gnueabihf: arm-linux-gnueabihf-gcc
|
|
||||||
CXX_armv7_unknown_linux_gnueabihf: arm-linux-gnueabihf-g++
|
|
||||||
artifacts:
|
|
||||||
name: "conduit-armv7-unknown-linux-gnueabihf"
|
|
||||||
paths:
|
|
||||||
- "conduit-armv7-unknown-linux-gnueabihf"
|
|
||||||
expose_as: "Conduit for armv7-unknown-linux-gnueabihf"
|
|
||||||
|
|
||||||
build:release:cargo:aarch64-unknown-linux-gnu:
|
|
||||||
extends: .build-cargo-shared-settings
|
|
||||||
variables:
|
|
||||||
TARGET: "aarch64-unknown-linux-gnu"
|
|
||||||
NEEDED_PACKAGES: "build-essential gcc-10-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross"
|
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
|
||||||
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
|
|
||||||
CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
|
|
||||||
TARGET_CC: "/usr/bin/aarch64-linux-gnu-gcc-10"
|
|
||||||
TARGET_AR: "/usr/bin/aarch64-linux-gnu-gcc-ar-10"
|
|
||||||
artifacts:
|
|
||||||
name: "conduit-aarch64-unknown-linux-gnu"
|
|
||||||
paths:
|
|
||||||
- "conduit-aarch64-unknown-linux-gnu"
|
|
||||||
expose_as: "Conduit for aarch64-unknown-linux-gnu"
|
|
||||||
|
|
||||||
build:release:cargo:x86_64-unknown-linux-musl:
|
build:release:cargo:x86_64-unknown-linux-musl:
|
||||||
extends: .build-cargo-shared-settings
|
extends: .build-cargo-shared-settings
|
||||||
image: "rust:alpine"
|
image: messense/rust-musl-cross:x86_64-musl
|
||||||
variables:
|
variables:
|
||||||
TARGET: "x86_64-unknown-linux-musl"
|
TARGET: "x86_64-unknown-linux-musl"
|
||||||
before_script:
|
|
||||||
- 'echo "Building for target $TARGET"'
|
|
||||||
- 'mkdir -p cargohome && CARGOHOME="cargohome"'
|
|
||||||
- "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging
|
|
||||||
- "rustup target add $TARGET"
|
|
||||||
- "apk add libc-dev"
|
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "conduit-x86_64-unknown-linux-musl"
|
name: "conduit-x86_64-unknown-linux-musl"
|
||||||
paths:
|
paths:
|
||||||
- "conduit-x86_64-unknown-linux-musl"
|
- "conduit-x86_64-unknown-linux-musl"
|
||||||
expose_as: "Conduit for x86_64-unknown-linux-musl"
|
expose_as: "Conduit for x86_64-unknown-linux-musl"
|
||||||
|
|
||||||
|
build:release:cargo:arm-unknown-linux-musleabihf:
|
||||||
|
extends: .build-cargo-shared-settings
|
||||||
|
image: messense/rust-musl-cross:arm-musleabihf
|
||||||
|
variables:
|
||||||
|
TARGET: "arm-unknown-linux-musleabihf"
|
||||||
|
artifacts:
|
||||||
|
name: "conduit-arm-unknown-linux-musleabihf"
|
||||||
|
paths:
|
||||||
|
- "conduit-arm-unknown-linux-musleabihf"
|
||||||
|
expose_as: "Conduit for arm-unknown-linux-musleabihf"
|
||||||
|
|
||||||
|
build:release:cargo:armv7-unknown-linux-musleabihf:
|
||||||
|
extends: .build-cargo-shared-settings
|
||||||
|
image: messense/rust-musl-cross:armv7-musleabihf
|
||||||
|
variables:
|
||||||
|
TARGET: "armv7-unknown-linux-musleabihf"
|
||||||
|
artifacts:
|
||||||
|
name: "conduit-armv7-unknown-linux-musleabihf"
|
||||||
|
paths:
|
||||||
|
- "conduit-armv7-unknown-linux-musleabihf"
|
||||||
|
expose_as: "Conduit for armv7-unknown-linux-musleabihf"
|
||||||
|
|
||||||
|
build:release:cargo:aarch64-unknown-linux-musl:
|
||||||
|
extends: .build-cargo-shared-settings
|
||||||
|
image: messense/rust-musl-cross:aarch64-musl
|
||||||
|
variables:
|
||||||
|
TARGET: "aarch64-unknown-linux-musl"
|
||||||
|
artifacts:
|
||||||
|
name: "conduit-aarch64-unknown-linux-musl"
|
||||||
|
paths:
|
||||||
|
- "conduit-aarch64-unknown-linux-musl"
|
||||||
|
expose_as: "Conduit for aarch64-unknown-linux-musl"
|
||||||
|
|
||||||
.cargo-debug-shared-settings:
|
.cargo-debug-shared-settings:
|
||||||
extends: ".build-cargo-shared-settings"
|
extends: ".build-cargo-shared-settings"
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH'
|
- if: '$CI_COMMIT_BRANCH != "master"'
|
||||||
- if: '$CI_COMMIT_TAG'
|
|
||||||
cache:
|
cache:
|
||||||
key: "build_cache-$TARGET-debug"
|
key: "build_cache--$TARGET--$CI_COMMIT_BRANCH--debug"
|
||||||
script:
|
script:
|
||||||
- "time cargo build --target $TARGET"
|
- "time cargo build --target $TARGET"
|
||||||
- 'mv "target/$TARGET/debug/conduit" "conduit-debug-$TARGET"'
|
- 'mv "target/$TARGET/debug/conduit" "conduit-debug-$TARGET"'
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 4 weeks
|
expire_in: 4 weeks
|
||||||
|
|
||||||
build:debug:cargo:x86_64-unknown-linux-gnu:
|
|
||||||
extends: ".cargo-debug-shared-settings"
|
|
||||||
variables:
|
|
||||||
TARGET: "x86_64-unknown-linux-gnu"
|
|
||||||
artifacts:
|
|
||||||
name: "conduit-debug-x86_64-unknown-linux-gnu"
|
|
||||||
paths:
|
|
||||||
- "conduit-debug-x86_64-unknown-linux-gnu"
|
|
||||||
expose_as: "Conduit DEBUG for x86_64-unknown-linux-gnu"
|
|
||||||
|
|
||||||
build:debug:cargo:x86_64-unknown-linux-musl:
|
build:debug:cargo:x86_64-unknown-linux-musl:
|
||||||
extends: ".cargo-debug-shared-settings"
|
extends: ".cargo-debug-shared-settings"
|
||||||
image: "rust:alpine"
|
image: messense/rust-musl-cross:x86_64-musl
|
||||||
variables:
|
variables:
|
||||||
TARGET: "x86_64-unknown-linux-musl"
|
TARGET: "x86_64-unknown-linux-musl"
|
||||||
before_script:
|
|
||||||
- 'echo "Building for target $TARGET"'
|
|
||||||
- 'mkdir -p cargohome && CARGOHOME="cargohome"'
|
|
||||||
- "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging
|
|
||||||
- "rustup target add $TARGET"
|
|
||||||
- "apk add libc-dev"
|
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "conduit-debug-x86_64-unknown-linux-musl"
|
name: "conduit-debug-x86_64-unknown-linux-musl"
|
||||||
paths:
|
paths:
|
||||||
- "conduit-debug-x86_64-unknown-linux-musl"
|
- "conduit-debug-x86_64-unknown-linux-musl"
|
||||||
expose_as: "Conduit DEBUG for x86_64-unknown-linux-musl"
|
expose_as: "Conduit DEBUG for x86_64-unknown-linux-musl"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
|
||||||
# Cargo: Compiling deb packages for different architectures #
|
|
||||||
# --------------------------------------------------------------------- #
|
|
||||||
|
|
||||||
|
|
||||||
.build-cargo-deb-shared-settings:
|
|
||||||
stage: "build"
|
|
||||||
needs: [ ]
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
|
||||||
- if: '$CI_COMMIT_TAG'
|
|
||||||
interruptible: true
|
|
||||||
image: "rust:latest"
|
|
||||||
tags: ["docker"]
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- cargohome
|
|
||||||
- target/
|
|
||||||
key: "build_cache-deb-$TARGET"
|
|
||||||
before_script:
|
|
||||||
- 'echo "Building debian package for target $TARGET"'
|
|
||||||
- 'mkdir -p cargohome && CARGOHOME="cargohome"'
|
|
||||||
- "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging
|
|
||||||
- 'apt-get update -yqq'
|
|
||||||
- 'echo "Installing packages: $NEEDED_PACKAGES"'
|
|
||||||
- "apt-get install -yqq --no-install-recommends $NEEDED_PACKAGES"
|
|
||||||
- "rustup target add $TARGET"
|
|
||||||
- "cargo install cargo-deb"
|
|
||||||
script:
|
|
||||||
- time cargo deb --target $TARGET
|
|
||||||
- 'mv target/$TARGET/debian/*.deb "conduit-$TARGET.deb"'
|
|
||||||
|
|
||||||
build:cargo-deb:x86_64-unknown-linux-gnu:
|
|
||||||
extends: .build-cargo-deb-shared-settings
|
|
||||||
variables:
|
|
||||||
TARGET: "x86_64-unknown-linux-gnu"
|
|
||||||
NEEDED_PACKAGES: ""
|
|
||||||
artifacts:
|
|
||||||
name: "conduit-x86_64-unknown-linux-gnu.deb"
|
|
||||||
paths:
|
|
||||||
- "conduit-x86_64-unknown-linux-gnu.deb"
|
|
||||||
expose_as: "Debian Package x86_64"
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# Create and publish docker image #
|
# Create and publish docker image #
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
|
|
||||||
# Build a docker image by packaging up the x86_64-unknown-linux-musl binary into an alpine image
|
|
||||||
.docker-shared-settings:
|
.docker-shared-settings:
|
||||||
stage: "build docker image"
|
stage: "build docker image"
|
||||||
needs: []
|
image: jdrouet/docker-with-buildx:stable
|
||||||
interruptible: true
|
|
||||||
image:
|
|
||||||
name: "gcr.io/kaniko-project/executor:debug"
|
|
||||||
entrypoint: [""]
|
|
||||||
tags: ["docker"]
|
tags: ["docker"]
|
||||||
variables:
|
services:
|
||||||
# Configure Kaniko Caching: https://cloud.google.com/build/docs/kaniko-cache
|
- docker:dind
|
||||||
KANIKO_CACHE_ARGS: "--cache=true --cache-copy-layers=true --cache-ttl=120h --cache-repo $CI_REGISTRY_IMAGE/kaniko-ci-cache"
|
|
||||||
before_script:
|
|
||||||
- "mkdir -p /kaniko/.docker"
|
|
||||||
- 'echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"},\"$DOCKER_HUB\":{\"username\":\"$DOCKER_HUB_USER\",\"password\":\"$DOCKER_HUB_PASSWORD\"}}}" > /kaniko/.docker/config.json'
|
|
||||||
|
|
||||||
|
|
||||||
build:docker:next:
|
|
||||||
extends: .docker-shared-settings
|
|
||||||
needs:
|
needs:
|
||||||
- "build:release:cargo:x86_64-unknown-linux-musl"
|
- "build:release:cargo:x86_64-unknown-linux-musl"
|
||||||
|
- "build:release:cargo:arm-unknown-linux-musleabihf"
|
||||||
|
- "build:release:cargo:armv7-unknown-linux-musleabihf"
|
||||||
|
- "build:release:cargo:aarch64-unknown-linux-musl"
|
||||||
|
variables:
|
||||||
|
DOCKER_HOST: tcp://docker:2375/
|
||||||
|
DOCKER_TLS_CERTDIR: ""
|
||||||
|
DOCKER_DRIVER: overlay2
|
||||||
|
PLATFORMS: "linux/arm/v6,linux/arm/v7,linux/arm64,linux/amd64"
|
||||||
|
DOCKER_FILE: "docker/ci-binaries-packaging.Dockerfile"
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- docker_cache
|
||||||
|
key: "$CI_JOB_NAME"
|
||||||
|
before_script:
|
||||||
|
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||||
|
# Only log in to Dockerhub if the credentials are given:
|
||||||
|
- if [ -n "${DOCKER_HUB}" ]; then docker login -u "$DOCKER_HUB_USER" -p "$DOCKER_HUB_PASSWORD" "$DOCKER_HUB"; fi
|
||||||
script:
|
script:
|
||||||
|
# Prepare buildx to build multiarch stuff:
|
||||||
|
- docker context create 'ci-context'
|
||||||
|
- docker buildx create --name 'multiarch-builder' --use 'ci-context'
|
||||||
|
# Copy binaries to their docker arch path
|
||||||
|
- mkdir -p linux/ && mv ./conduit-x86_64-unknown-linux-musl linux/amd64
|
||||||
|
- mkdir -p linux/arm/ && mv ./conduit-arm-unknown-linux-musleabihf linux/arm/v6
|
||||||
|
- mkdir -p linux/arm/ && mv ./conduit-armv7-unknown-linux-musleabihf linux/arm/v7
|
||||||
|
- mv ./conduit-aarch64-unknown-linux-musl linux/arm64
|
||||||
|
- 'export CREATED=$(date -u +''%Y-%m-%dT%H:%M:%SZ'') && echo "Docker image creation date: $CREATED"'
|
||||||
|
# Build and push image:
|
||||||
- >
|
- >
|
||||||
/kaniko/executor
|
docker buildx build
|
||||||
$KANIKO_CACHE_ARGS
|
--pull
|
||||||
--force
|
--push
|
||||||
--context $CI_PROJECT_DIR
|
--cache-from=type=local,src=$CI_PROJECT_DIR/docker_cache
|
||||||
--build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
--cache-to=type=local,dest=$CI_PROJECT_DIR/docker_cache
|
||||||
|
--build-arg CREATED=$CREATED
|
||||||
--build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)
|
--build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)
|
||||||
--build-arg "GIT_REF=$CI_COMMIT_SHORT_SHA"
|
--build-arg "GIT_REF=$CI_COMMIT_SHORT_SHA"
|
||||||
--dockerfile "$CI_PROJECT_DIR/docker/ci-binaries-packaging.Dockerfile"
|
--platform "$PLATFORMS"
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:next"
|
--tag "$TAG"
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:next-alpine"
|
--tag "$TAG-alpine"
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:commit-$CI_COMMIT_SHORT_SHA"
|
--tag "$TAG-commit-$CI_COMMIT_SHORT_SHA"
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:next"
|
--file "$DOCKER_FILE" .
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:next-alpine"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:commit-$CI_COMMIT_SHORT_SHA"
|
docker:next:gitlab:
|
||||||
|
extends: .docker-shared-settings
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
- if: '$CI_COMMIT_BRANCH == "next"'
|
||||||
|
variables:
|
||||||
|
TAG: "$CI_REGISTRY_IMAGE/matrix-conduit:next"
|
||||||
|
|
||||||
|
docker:next:dockerhub:
|
||||||
|
extends: .docker-shared-settings
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "next" && $DOCKER_HUB'
|
||||||
|
variables:
|
||||||
|
TAG: "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:next"
|
||||||
|
|
||||||
build:docker:master:
|
docker:master:gitlab:
|
||||||
extends: .docker-shared-settings
|
extends: .docker-shared-settings
|
||||||
needs:
|
|
||||||
- "build:release:cargo:x86_64-unknown-linux-musl"
|
|
||||||
script:
|
|
||||||
- >
|
|
||||||
/kaniko/executor
|
|
||||||
$KANIKO_CACHE_ARGS
|
|
||||||
--context $CI_PROJECT_DIR
|
|
||||||
--build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
|
||||||
--build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)
|
|
||||||
--build-arg "GIT_REF=$CI_COMMIT_SHORT_SHA"
|
|
||||||
--dockerfile "$CI_PROJECT_DIR/docker/ci-binaries-packaging.Dockerfile"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:latest"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:latest-alpine"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest-alpine"
|
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == "master"'
|
||||||
|
variables:
|
||||||
|
TAG: "$CI_REGISTRY_IMAGE/matrix-conduit:latest"
|
||||||
|
|
||||||
|
docker:master:dockerhub:
|
||||||
build:docker:tags:
|
|
||||||
extends: .docker-shared-settings
|
extends: .docker-shared-settings
|
||||||
needs:
|
|
||||||
- "build:release:cargo:x86_64-unknown-linux-musl"
|
|
||||||
script:
|
|
||||||
- >
|
|
||||||
/kaniko/executor
|
|
||||||
$KANIKO_CACHE_ARGS
|
|
||||||
--context $CI_PROJECT_DIR
|
|
||||||
--build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
|
||||||
--build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)
|
|
||||||
--build-arg "GIT_REF=$CI_COMMIT_SHORT_SHA"
|
|
||||||
--dockerfile "$CI_PROJECT_DIR/docker/ci-binaries-packaging.Dockerfile"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:$CI_COMMIT_TAG"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:$CI_COMMIT_TAG-alpine"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:$CI_COMMIT_TAG"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:$CI_COMMIT_TAG-alpine"
|
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_BRANCH == "master" && $DOCKER_HUB'
|
||||||
|
variables:
|
||||||
|
TAG: "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest"
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# Run tests #
|
# Run tests #
|
||||||
@@ -301,13 +226,20 @@ test:cargo:
|
|||||||
before_script:
|
before_script:
|
||||||
- mkdir -p $CARGO_HOME && echo "using $CARGO_HOME to cache cargo deps"
|
- mkdir -p $CARGO_HOME && echo "using $CARGO_HOME to cache cargo deps"
|
||||||
- apt-get update -yqq
|
- apt-get update -yqq
|
||||||
- apt-get install -yqq --no-install-recommends build-essential libssl-dev pkg-config
|
- apt-get install -yqq --no-install-recommends build-essential libssl-dev pkg-config wget
|
||||||
- rustup component add clippy rustfmt
|
- rustup component add clippy rustfmt
|
||||||
|
- wget "https://faulty-storage.de/gitlab-report"
|
||||||
|
- chmod +x ./gitlab-report
|
||||||
script:
|
script:
|
||||||
- rustc --version && cargo --version # Print version info for debugging
|
- rustc --version && cargo --version # Print version info for debugging
|
||||||
- cargo fmt --all -- --check
|
- cargo fmt --all -- --check
|
||||||
- cargo test --workspace --verbose --locked
|
- "cargo test --color always --workspace --verbose --locked --no-fail-fast -- -Z unstable-options --format json | ./gitlab-report -p test > $CI_PROJECT_DIR/report.xml"
|
||||||
- cargo clippy
|
- "cargo clippy --color always --verbose --message-format=json | ./gitlab-report -p clippy > $CI_PROJECT_DIR/gl-code-quality-report.json"
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: report.xml
|
||||||
|
codequality: gl-code-quality-report.json
|
||||||
|
|
||||||
test:sytest:
|
test:sytest:
|
||||||
stage: "test"
|
stage: "test"
|
||||||
@@ -330,7 +262,7 @@ test:sytest:
|
|||||||
script:
|
script:
|
||||||
- "SYTEST_EXIT_CODE=0"
|
- "SYTEST_EXIT_CODE=0"
|
||||||
- "/bootstrap.sh conduit || SYTEST_EXIT_CODE=1"
|
- "/bootstrap.sh conduit || SYTEST_EXIT_CODE=1"
|
||||||
- "perl /sytest/tap-to-junit-xml.pl --puretap --input /logs/results.tap --output $CI_PROJECT_DIR/sytest.xml \"Sytest\" && cp /logs/results.tap $CI_PROJECT_DIR/results.tap"
|
- 'perl /sytest/tap-to-junit-xml.pl --puretap --input /logs/results.tap --output $CI_PROJECT_DIR/sytest.xml "Sytest" && cp /logs/results.tap $CI_PROJECT_DIR/results.tap'
|
||||||
- "exit $SYTEST_EXIT_CODE"
|
- "exit $SYTEST_EXIT_CODE"
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@@ -340,7 +272,6 @@ test:sytest:
|
|||||||
reports:
|
reports:
|
||||||
junit: "$CI_PROJECT_DIR/sytest.xml"
|
junit: "$CI_PROJECT_DIR/sytest.xml"
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# Store binaries as package so they have download urls #
|
# Store binaries as package so they have download urls #
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
@@ -348,25 +279,31 @@ test:sytest:
|
|||||||
publish:package:
|
publish:package:
|
||||||
stage: "upload artifacts"
|
stage: "upload artifacts"
|
||||||
needs:
|
needs:
|
||||||
- "build:release:cargo:x86_64-unknown-linux-gnu"
|
|
||||||
- "build:release:cargo:armv7-unknown-linux-gnueabihf"
|
|
||||||
- "build:release:cargo:aarch64-unknown-linux-gnu"
|
|
||||||
- "build:release:cargo:x86_64-unknown-linux-musl"
|
- "build:release:cargo:x86_64-unknown-linux-musl"
|
||||||
- "build:cargo-deb:x86_64-unknown-linux-gnu"
|
- "build:release:cargo:arm-unknown-linux-musleabihf"
|
||||||
|
- "build:release:cargo:armv7-unknown-linux-musleabihf"
|
||||||
|
- "build:release:cargo:aarch64-unknown-linux-musl"
|
||||||
|
# - "build:cargo-deb:x86_64-unknown-linux-gnu"
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == "master"'
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
- if: '$CI_COMMIT_BRANCH == "next"'
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: "$CI_COMMIT_TAG"
|
||||||
image: curlimages/curl:latest
|
image: curlimages/curl:latest
|
||||||
tags: ["docker"]
|
tags: ["docker"]
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: "none" # Don't need a clean copy of the code, we just operate on artifacts
|
GIT_STRATEGY: "none" # Don't need a clean copy of the code, we just operate on artifacts
|
||||||
script:
|
script:
|
||||||
- 'BASE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/conduit-${CI_COMMIT_REF_SLUG}/build-${CI_PIPELINE_ID}"'
|
- 'BASE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/conduit-${CI_COMMIT_REF_SLUG}/build-${CI_PIPELINE_ID}"'
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-x86_64-unknown-linux-gnu "${BASE_URL}/conduit-x86_64-unknown-linux-gnu"'
|
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-armv7-unknown-linux-gnueabihf "${BASE_URL}/conduit-armv7-unknown-linux-gnueabihf"'
|
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-aarch64-unknown-linux-gnu "${BASE_URL}/conduit-aarch64-unknown-linux-gnu"'
|
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-x86_64-unknown-linux-musl "${BASE_URL}/conduit-x86_64-unknown-linux-musl"'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-x86_64-unknown-linux-musl "${BASE_URL}/conduit-x86_64-unknown-linux-musl"'
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-x86_64-unknown-linux-gnu.deb "${BASE_URL}/conduit-x86_64-unknown-linux-gnu.deb"'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-arm-unknown-linux-musleabihf "${BASE_URL}/conduit-arm-unknown-linux-musleabihf"'
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-armv7-unknown-linux-musleabihf "${BASE_URL}/conduit-armv7-unknown-linux-musleabihf"'
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file conduit-aarch64-unknown-linux-musl "${BASE_URL}/conduit-aarch64-unknown-linux-musl"'
|
||||||
|
|
||||||
|
# Avoid duplicate pipelines
|
||||||
|
# See: https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||||
|
- if: "$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS"
|
||||||
|
when: never
|
||||||
|
- if: "$CI_COMMIT_BRANCH"
|
||||||
|
|||||||
Generated
+66
-32
@@ -245,6 +245,7 @@ dependencies = [
|
|||||||
"crossbeam",
|
"crossbeam",
|
||||||
"directories",
|
"directories",
|
||||||
"heed",
|
"heed",
|
||||||
|
"hmac",
|
||||||
"http",
|
"http",
|
||||||
"image",
|
"image",
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
@@ -266,6 +267,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
"sha-1",
|
||||||
"sled",
|
"sled",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
@@ -428,6 +430,16 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-mac"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@@ -897,6 +909,16 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-mac",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hostname"
|
name = "hostname"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -916,7 +938,7 @@ checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
"itoa",
|
"itoa 0.4.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -957,7 +979,7 @@ dependencies = [
|
|||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa 0.4.8",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.4.1",
|
"socket2 0.4.1",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1092,6 +1114,12 @@ version = "0.4.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@@ -1494,12 +1522,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "1.0.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pear"
|
name = "pear"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -1968,7 +1990,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -1989,7 +2011,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api"
|
name = "ruma-api"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"http",
|
"http",
|
||||||
@@ -2005,7 +2027,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api-macros"
|
name = "ruma-api-macros"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2016,7 +2038,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-appservice-api"
|
name = "ruma-appservice-api"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -2030,7 +2052,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2050,7 +2072,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2065,7 +2087,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.24.6"
|
version = "0.24.6"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2081,7 +2103,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events-macros"
|
name = "ruma-events-macros"
|
||||||
version = "0.24.6"
|
version = "0.24.6"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2092,7 +2114,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2107,9 +2129,8 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers"
|
name = "ruma-identifiers"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"paste",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"ruma-identifiers-macros",
|
"ruma-identifiers-macros",
|
||||||
@@ -2122,7 +2143,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-macros"
|
name = "ruma-identifiers-macros"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"ruma-identifiers-validation",
|
"ruma-identifiers-validation",
|
||||||
@@ -2132,7 +2153,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
@@ -2140,7 +2161,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identity-service-api"
|
name = "ruma-identity-service-api"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2153,7 +2174,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-push-gateway-api"
|
name = "ruma-push-gateway-api"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2168,11 +2189,11 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-serde"
|
name = "ruma-serde"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"itoa",
|
"itoa 0.4.8",
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-serde-macros",
|
"ruma-serde-macros",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2182,7 +2203,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-serde-macros"
|
name = "ruma-serde-macros"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2193,7 +2214,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
@@ -2210,7 +2231,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-state-res"
|
name = "ruma-state-res"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=44cfd0adbc83303c19aef590ad0d71647e19f197#44cfd0adbc83303c19aef590ad0d71647e19f197"
|
source = "git+https://github.com/ruma/ruma?rev=7cf3abbaf02995b03db74429090ca5af1cd71edc#7cf3abbaf02995b03db74429090ca5af1cd71edc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.10.1",
|
"itertools 0.10.1",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2389,11 +2410,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.67"
|
version = "1.0.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
|
checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa 1.0.1",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -2405,7 +2426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"itoa",
|
"itoa 0.4.8",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -2422,6 +2443,19 @@ dependencies = [
|
|||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-1"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|||||||
+7
-5
@@ -19,7 +19,7 @@ rocket = { version = "0.5.0-rc.1", features = ["tls"] } # Used to handle request
|
|||||||
|
|
||||||
# Used for matrix spec type definitions and helpers
|
# Used for matrix spec type definitions and helpers
|
||||||
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
ruma = { git = "https://github.com/ruma/ruma", rev = "58cdcae1f9a8f4824bcbec1de1bb13e659c66804", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
ruma = { git = "https://github.com/ruma/ruma", rev = "7cf3abbaf02995b03db74429090ca5af1cd71edc", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
|
|
||||||
@@ -36,11 +36,11 @@ http = "0.2.4"
|
|||||||
# Used to find data directory for default db path
|
# Used to find data directory for default db path
|
||||||
directories = "3.0.2"
|
directories = "3.0.2"
|
||||||
# Used for ruma wrapper
|
# Used for ruma wrapper
|
||||||
serde_json = { version = "1.0.67", features = ["raw_value"] }
|
serde_json = { version = "1.0.70", features = ["raw_value"] }
|
||||||
# Used for appservice registration files
|
# Used for appservice registration files
|
||||||
serde_yaml = "0.8.20"
|
serde_yaml = "0.8.20"
|
||||||
# Used for pdu definition
|
# Used for pdu definition
|
||||||
serde = "1.0.130"
|
serde = { version = "1.0.130", features = ["rc"] }
|
||||||
# Used for secure identifiers
|
# Used for secure identifiers
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
# Used to hash passwords
|
# Used to hash passwords
|
||||||
@@ -79,6 +79,9 @@ num_cpus = "1.13.0"
|
|||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true }
|
heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true }
|
||||||
thread_local = "1.1.3"
|
thread_local = "1.1.3"
|
||||||
|
# used for TURN server authentication
|
||||||
|
hmac = "0.11.0"
|
||||||
|
sha-1 = "0.9.8"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["conduit_bin", "backend_sqlite"]
|
default = ["conduit_bin", "backend_sqlite"]
|
||||||
@@ -120,13 +123,12 @@ maintainer-scripts = "debian/"
|
|||||||
systemd-units = { unit-name = "matrix-conduit" }
|
systemd-units = { unit-name = "matrix-conduit" }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
lto = 'thin'
|
lto = 'off'
|
||||||
incremental = true
|
incremental = true
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = 'thin'
|
lto = 'thin'
|
||||||
incremental = true
|
incremental = true
|
||||||
|
|
||||||
codegen-units=32
|
codegen-units=32
|
||||||
# If you want to make flamegraphs, enable debug info:
|
# If you want to make flamegraphs, enable debug info:
|
||||||
# debug = true
|
# debug = true
|
||||||
|
|||||||
@@ -2,25 +2,27 @@
|
|||||||
|
|
||||||
## Getting help
|
## Getting help
|
||||||
|
|
||||||
If you run into any problems while setting up Conduit, write an email to `timo@koesters.xyz`, ask us in `#conduit:matrix.org` or [open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new).
|
If you run into any problems while setting up Conduit, write an email to `timo@koesters.xyz`, ask us
|
||||||
|
in `#conduit:matrix.org` or [open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new).
|
||||||
|
|
||||||
## Installing Conduit
|
## Installing Conduit
|
||||||
|
|
||||||
|
Although you might be able to compile Conduit for Windows, we do recommend running it on a linux server. We therefore
|
||||||
|
only offer Linux binaries.
|
||||||
|
|
||||||
You may simply download the binary that fits your machine. Run `uname -m` to see what you need. Now copy the right url:
|
You may simply download the binary that fits your machine. Run `uname -m` to see what you need. Now copy the right url:
|
||||||
|
|
||||||
| CPU Architecture | GNU (Ubuntu, Debian, ArchLinux, ...) | MUSL (Alpine, ... ) |
|
| CPU Architecture | Download stable version |
|
||||||
| -------------------- | ------------------------------------- | ----------------------- |
|
| ------------------------------------------- | ------------------------------ |
|
||||||
| x84_64 / amd64 | [Download][x84_64-gnu] | [Download][x84_64-musl] |
|
| x84_64 / amd64 (Most servers and computers) | [Download][x84_64-musl-master] |
|
||||||
| armv7 (Raspberry Pi) | [Download][armv7-gnu] | - |
|
| armv6 | [Download][armv6-musl-master] |
|
||||||
| armv8 / aarch64 | [Download][armv8-gnu] | - |
|
| armv7 (e.g. Raspberry Pi by default) | [Download][armv7-musl-master] |
|
||||||
|
| armv8 / aarch64 | [Download][armv8-musl-master] |
|
||||||
|
|
||||||
[x84_64-gnu]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-x86_64-unknown-linux-gnu?job=build:release:cargo:x86_64-unknown-linux-gnu
|
[x84_64-musl-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-x86_64-unknown-linux-musl?job=build:release:cargo:x86_64-unknown-linux-musl
|
||||||
|
[armv6-musl-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-arm-unknown-linux-musleabihf?job=build:release:cargo:arm-unknown-linux-musleabihf
|
||||||
[x84_64-musl]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-x86_64-unknown-linux-musl?job=build:release:cargo:x86_64-unknown-linux-musl
|
[armv7-musl-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-armv7-unknown-linux-musleabihf?job=build:release:cargo:armv7-unknown-linux-musleabihf
|
||||||
|
[armv8-musl-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-aarch64-unknown-linux-musl?job=build:release:cargo:aarch64-unknown-linux-musl
|
||||||
[armv7-gnu]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-armv7-unknown-linux-gnueabihf?job=build:release:cargo:armv7-unknown-linux-gnueabihf
|
|
||||||
|
|
||||||
[armv8-gnu]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-aarch64-unknown-linux-gnu?job=build:release:cargo:aarch64-unknown-linux-gnu
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sudo wget -O /usr/local/bin/matrix-conduit <url>
|
$ sudo wget -O /usr/local/bin/matrix-conduit <url>
|
||||||
@@ -32,15 +34,15 @@ Alternatively, you may compile the binary yourself using
|
|||||||
```bash
|
```bash
|
||||||
$ cargo build --release
|
$ cargo build --release
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this currently requires Rust 1.50.
|
Note that this currently requires Rust 1.50.
|
||||||
|
|
||||||
If you want to cross compile Conduit to another architecture, read the [Cross-Compile Guide](CROSS_COMPILE.md).
|
If you want to cross compile Conduit to another architecture, read the [Cross-Compile Guide](CROSS_COMPILE.md).
|
||||||
|
|
||||||
|
|
||||||
## Adding a Conduit user
|
## Adding a Conduit user
|
||||||
|
|
||||||
While Conduit can run as any user it is usually better to use dedicated users for different services.
|
While Conduit can run as any user it is usually better to use dedicated users for different services. This also allows
|
||||||
This also allows you to make sure that the file permissions are correctly set up.
|
you to make sure that the file permissions are correctly set up.
|
||||||
|
|
||||||
In Debian you can use this command to create a Conduit user:
|
In Debian you can use this command to create a Conduit user:
|
||||||
|
|
||||||
@@ -50,9 +52,8 @@ sudo adduser --system conduit --no-create-home
|
|||||||
|
|
||||||
## Setting up a systemd service
|
## Setting up a systemd service
|
||||||
|
|
||||||
Now we'll set up a systemd service for Conduit, so it's easy to start/stop
|
Now we'll set up a systemd service for Conduit, so it's easy to start/stop Conduit and set it to autostart when your
|
||||||
Conduit and set it to autostart when your server reboots. Simply paste the
|
server reboots. Simply paste the default systemd service you can find below into
|
||||||
default systemd service you can find below into
|
|
||||||
`/etc/systemd/system/conduit.service`.
|
`/etc/systemd/system/conduit.service`.
|
||||||
|
|
||||||
```systemd
|
```systemd
|
||||||
@@ -77,10 +78,10 @@ Finally, run
|
|||||||
$ sudo systemctl daemon-reload
|
$ sudo systemctl daemon-reload
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Creating the Conduit configuration file
|
## Creating the Conduit configuration file
|
||||||
|
|
||||||
Now we need to create the Conduit's config file in `/etc/matrix-conduit/conduit.toml`. Paste this in **and take a moment to read it. You need to change at least the server name.**
|
Now we need to create the Conduit's config file in `/etc/matrix-conduit/conduit.toml`. Paste this in **and take a moment
|
||||||
|
to read it. You need to change at least the server name.**
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[global]
|
[global]
|
||||||
@@ -128,8 +129,8 @@ address = "127.0.0.1" # This makes sure Conduit can only be reached using the re
|
|||||||
|
|
||||||
## Setting the correct file permissions
|
## Setting the correct file permissions
|
||||||
|
|
||||||
As we are using a Conduit specific user we need to allow it to read the config.
|
As we are using a Conduit specific user we need to allow it to read the config. To do that you can run this command on
|
||||||
To do that you can run this command on Debian:
|
Debian:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo chown -R conduit:nogroup /etc/matrix-conduit
|
sudo chown -R conduit:nogroup /etc/matrix-conduit
|
||||||
@@ -142,7 +143,6 @@ sudo mkdir -p /var/lib/matrix-conduit/conduit_db
|
|||||||
sudo chown -R conduit:nogroup /var/lib/matrix-conduit/conduit_db
|
sudo chown -R conduit:nogroup /var/lib/matrix-conduit/conduit_db
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Setting up the Reverse Proxy
|
## Setting up the Reverse Proxy
|
||||||
|
|
||||||
This depends on whether you use Apache, Nginx or another web server.
|
This depends on whether you use Apache, Nginx or another web server.
|
||||||
@@ -171,11 +171,9 @@ ProxyPassReverse /_matrix/ http://127.0.0.1:6167/_matrix/
|
|||||||
$ sudo systemctl reload apache2
|
$ sudo systemctl reload apache2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Nginx
|
### Nginx
|
||||||
|
|
||||||
If you use Nginx and not Apache, add the following server section inside the
|
If you use Nginx and not Apache, add the following server section inside the http section of `/etc/nginx/nginx.conf`
|
||||||
http section of `/etc/nginx/nginx.conf`
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
@@ -198,13 +196,13 @@ server {
|
|||||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**You need to make some edits again.** When you are done, run
|
**You need to make some edits again.** When you are done, run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sudo systemctl reload nginx
|
$ sudo systemctl reload nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## SSL Certificate
|
## SSL Certificate
|
||||||
|
|
||||||
The easiest way to get an SSL certificate, if you don't have one already, is to install `certbot` and run this:
|
The easiest way to get an SSL certificate, if you don't have one already, is to install `certbot` and run this:
|
||||||
@@ -213,7 +211,6 @@ The easiest way to get an SSL certificate, if you don't have one already, is to
|
|||||||
$ sudo certbot -d your.server.name
|
$ sudo certbot -d your.server.name
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## You're done!
|
## You're done!
|
||||||
|
|
||||||
Now you can start Conduit with:
|
Now you can start Conduit with:
|
||||||
|
|||||||
+59
-75
@@ -1,75 +1,65 @@
|
|||||||
# Using multistage build:
|
# syntax=docker/dockerfile:1
|
||||||
# https://docs.docker.com/develop/develop-images/multistage-build/
|
FROM docker.io/rust:1.53-alpine AS builder
|
||||||
# https://whitfin.io/speeding-up-rust-docker-builds/
|
WORKDIR /usr/src/conduit
|
||||||
|
|
||||||
|
# Install required packages to build Conduit and it's dependencies
|
||||||
|
RUN apk add musl-dev
|
||||||
|
|
||||||
|
# == Build dependencies without our own code separately for caching ==
|
||||||
|
#
|
||||||
|
# Need a fake main.rs since Cargo refuses to build anything otherwise.
|
||||||
|
#
|
||||||
|
# See https://github.com/rust-lang/cargo/issues/2644 for a Cargo feature
|
||||||
|
# request that would allow just dependencies to be compiled, presumably
|
||||||
|
# regardless of whether source files are available.
|
||||||
|
RUN mkdir src && touch src/lib.rs && echo 'fn main() {}' > src/main.rs
|
||||||
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
RUN cargo build --release && rm -r src
|
||||||
|
|
||||||
|
# Copy over actual Conduit sources
|
||||||
|
COPY src src
|
||||||
|
|
||||||
|
# main.rs and lib.rs need their timestamp updated for this to work correctly since
|
||||||
|
# otherwise the build with the fake main.rs from above is newer than the
|
||||||
|
# source files (COPY preserves timestamps).
|
||||||
|
#
|
||||||
|
# Builds conduit and places the binary at /usr/src/conduit/target/release/conduit
|
||||||
|
RUN touch src/main.rs && touch src/lib.rs && cargo build --release
|
||||||
|
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
|
||||||
# Alpine build image to build Conduit's statically compiled binary
|
|
||||||
FROM alpine:3.14 as builder
|
|
||||||
|
|
||||||
# Install packages needed for building all crates
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
cargo \
|
|
||||||
openssl-dev
|
|
||||||
|
|
||||||
# Specifies if the local project is build or if Conduit gets build
|
# ---------------------------------------------------------------------------------------------------------------
|
||||||
# from the official git repository. Defaults to the git repo.
|
# Stuff below this line actually ends up in the resulting docker image
|
||||||
ARG LOCAL=false
|
# ---------------------------------------------------------------------------------------------------------------
|
||||||
# Specifies which revision/commit is build. Defaults to HEAD
|
FROM docker.io/alpine:3.15.0 AS runner
|
||||||
ARG GIT_REF=origin/master
|
|
||||||
|
|
||||||
# Copy project files from current folder
|
# Standard port on which Conduit launches.
|
||||||
COPY . .
|
# You still need to map the port when using the docker command or docker-compose.
|
||||||
# Build it from the copied local files or from the official git repository
|
|
||||||
RUN if [[ $LOCAL == "true" ]]; then \
|
|
||||||
mv ./docker/healthcheck.sh . ; \
|
|
||||||
echo "Building from local source..." ; \
|
|
||||||
cargo install --path . ; \
|
|
||||||
else \
|
|
||||||
echo "Building revision '${GIT_REF}' from online source..." ; \
|
|
||||||
cargo install --git "https://gitlab.com/famedly/conduit.git" --rev ${GIT_REF} ; \
|
|
||||||
echo "Loadings healthcheck script from online source..." ; \
|
|
||||||
wget "https://gitlab.com/famedly/conduit/-/raw/${GIT_REF#origin/}/docker/healthcheck.sh" ; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
########################## RUNTIME IMAGE ##########################
|
|
||||||
# Create new stage with a minimal image for the actual
|
|
||||||
# runtime image/container
|
|
||||||
FROM alpine:3.14
|
|
||||||
|
|
||||||
ARG CREATED
|
|
||||||
ARG VERSION
|
|
||||||
ARG GIT_REF=origin/master
|
|
||||||
|
|
||||||
ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml"
|
|
||||||
|
|
||||||
# Labels according to https://github.com/opencontainers/image-spec/blob/master/annotations.md
|
|
||||||
# including a custom label specifying the build command
|
|
||||||
LABEL org.opencontainers.image.created=${CREATED} \
|
|
||||||
org.opencontainers.image.authors="Conduit Contributors" \
|
|
||||||
org.opencontainers.image.title="Conduit" \
|
|
||||||
org.opencontainers.image.version=${VERSION} \
|
|
||||||
org.opencontainers.image.vendor="Conduit Contributors" \
|
|
||||||
org.opencontainers.image.description="A Matrix homeserver written in Rust" \
|
|
||||||
org.opencontainers.image.url="https://conduit.rs/" \
|
|
||||||
org.opencontainers.image.revision=${GIT_REF} \
|
|
||||||
org.opencontainers.image.source="https://gitlab.com/famedly/conduit.git" \
|
|
||||||
org.opencontainers.image.licenses="Apache-2.0" \
|
|
||||||
org.opencontainers.image.documentation="" \
|
|
||||||
org.opencontainers.image.ref.name="" \
|
|
||||||
org.label-schema.docker.build="docker build . -t matrixconduit/matrix-conduit:latest --build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)" \
|
|
||||||
maintainer="Weasy666"
|
|
||||||
|
|
||||||
# Standard port on which Conduit launches. You still need to map the port when using the docker command or docker-compose.
|
|
||||||
EXPOSE 6167
|
EXPOSE 6167
|
||||||
|
|
||||||
# Copy config files from context and the binary from
|
# Note from @jfowl: I would like to remove this in the future and just have the Docker version be configured with envs.
|
||||||
# the "builder" stage to the current stage into folder
|
ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml"
|
||||||
# /srv/conduit and create data folder for database
|
|
||||||
RUN mkdir -p /srv/conduit/.local/share/conduit
|
|
||||||
COPY --from=builder /root/.cargo/bin/conduit /srv/conduit/
|
|
||||||
COPY --from=builder ./healthcheck.sh /srv/conduit/
|
|
||||||
|
|
||||||
|
# Conduit needs:
|
||||||
|
# ca-certificates: for https
|
||||||
|
# libgcc: Apparently this is needed, even if I (@jfowl) don't know exactly why. But whatever, it's not that big.
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
ca-certificates \
|
||||||
|
libgcc
|
||||||
|
|
||||||
|
|
||||||
|
# Created directory for the database and media files
|
||||||
|
RUN mkdir -p /srv/conduit/.local/share/conduit
|
||||||
|
|
||||||
|
# Test if Conduit is still alive, uses the same endpoint as Element
|
||||||
|
COPY ./docker/healthcheck.sh /srv/conduit/healthcheck.sh
|
||||||
|
HEALTHCHECK --start-period=5s --interval=5s CMD ./healthcheck.sh
|
||||||
|
|
||||||
|
# Copy over the actual Conduit binary from the builder stage
|
||||||
|
COPY --from=builder /usr/src/conduit/target/release/conduit /srv/conduit/conduit
|
||||||
|
|
||||||
|
# Improve security: Don't run stuff as root, that does not need to run as root:
|
||||||
# Add www-data user and group with UID 82, as used by alpine
|
# Add www-data user and group with UID 82, as used by alpine
|
||||||
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install
|
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install
|
||||||
RUN set -x ; \
|
RUN set -x ; \
|
||||||
@@ -79,19 +69,13 @@ RUN set -x ; \
|
|||||||
|
|
||||||
# Change ownership of Conduit files to www-data user and group
|
# Change ownership of Conduit files to www-data user and group
|
||||||
RUN chown -cR www-data:www-data /srv/conduit
|
RUN chown -cR www-data:www-data /srv/conduit
|
||||||
|
RUN chmod +x /srv/conduit/healthcheck.sh
|
||||||
|
|
||||||
# Install packages needed to run Conduit
|
# Change user to www-data
|
||||||
RUN apk add --no-cache \
|
|
||||||
ca-certificates \
|
|
||||||
curl \
|
|
||||||
libgcc
|
|
||||||
|
|
||||||
# Test if Conduit is still alive, uses the same endpoint as Element
|
|
||||||
HEALTHCHECK --start-period=5s --interval=60s CMD ./healthcheck.sh
|
|
||||||
|
|
||||||
# Set user to www-data
|
|
||||||
USER www-data
|
USER www-data
|
||||||
# Set container home directory
|
# Set container home directory
|
||||||
WORKDIR /srv/conduit
|
WORKDIR /srv/conduit
|
||||||
# Run Conduit
|
|
||||||
|
# Run Conduit and print backtraces on panics
|
||||||
|
ENV RUST_BACKTRACE=1
|
||||||
ENTRYPOINT [ "/srv/conduit/conduit" ]
|
ENTRYPOINT [ "/srv/conduit/conduit" ]
|
||||||
+16
-27
@@ -2,38 +2,22 @@
|
|||||||
|
|
||||||
> **Note:** To run and use Conduit you should probably use it with a Domain or Subdomain behind a reverse proxy (like Nginx, Traefik, Apache, ...) with a Lets Encrypt certificate.
|
> **Note:** To run and use Conduit you should probably use it with a Domain or Subdomain behind a reverse proxy (like Nginx, Traefik, Apache, ...) with a Lets Encrypt certificate.
|
||||||
|
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
### Build & Dockerfile
|
### Build & Dockerfile
|
||||||
|
|
||||||
The Dockerfile provided by Conduit has two stages, each of which creates an image.
|
The Dockerfile provided by Conduit has two stages, each of which creates an image.
|
||||||
|
|
||||||
1. **Builder:** Builds the binary from local context or by cloning a git revision from the official repository.
|
1. **Builder:** Builds the binary from local context or by cloning a git revision from the official repository.
|
||||||
2. **Runtime:** Copies the built binary from **Builder** and sets up the runtime environment, like creating a volume to persist the database and applying the correct permissions.
|
2. **Runner:** Copies the built binary from **Builder** and sets up the runtime environment, like creating a volume to persist the database and applying the correct permissions.
|
||||||
|
|
||||||
The Dockerfile includes a few build arguments that should be supplied when building it.
|
|
||||||
|
|
||||||
``` Dockerfile
|
|
||||||
ARG LOCAL=false
|
|
||||||
ARG CREATED
|
|
||||||
ARG VERSION
|
|
||||||
ARG GIT_REF=origin/master
|
|
||||||
```
|
|
||||||
|
|
||||||
- **CREATED:** Date and time as string (date-time as defined by RFC 3339). Will be used to create the Open Container Initiative compliant label `org.opencontainers.image.created`. Supply by it like this `$(date -u +'%Y-%m-%dT%H:%M:%SZ')`
|
|
||||||
- **VERSION:** The SemVer version of Conduit, which is in the image. Will be used to create the Open Container Initiative compliant label `org.opencontainers.image.version`. If you have a `Cargo.toml` in your build context, you can get it with `$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)`
|
|
||||||
- **LOCAL:** *(Optional)* A boolean value, specifies if the local build context should be used, or if the official repository will be cloned. If not supplied with the build command, it will default to `false`.
|
|
||||||
- **GIT_REF:** *(Optional)* A git ref, like `HEAD` or a commit ID. The supplied ref will be used to create the Open Container Initiative compliant label `org.opencontainers.image.revision` and will be the ref that is cloned from the repository when not building from the local context. If not supplied with the build command, it will default to `origin/master`.
|
|
||||||
|
|
||||||
To build the image you can use the following command
|
To build the image you can use the following command
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build . -t matrixconduit/matrix-conduit:latest --build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)
|
docker build --tag matrixconduit/matrix-conduit:latest .
|
||||||
```
|
```
|
||||||
|
|
||||||
which also will tag the resulting image as `matrixconduit/matrix-conduit:latest`.
|
which also will tag the resulting image as `matrixconduit/matrix-conduit:latest`.
|
||||||
**Note:** it ommits the two optional `build-arg`s.
|
|
||||||
|
|
||||||
|
|
||||||
### Run
|
### Run
|
||||||
|
|
||||||
@@ -46,9 +30,13 @@ docker run -d -p 8448:6167 -v ~/conduit.toml:/srv/conduit/conduit.toml -v db:/sr
|
|||||||
or you can skip the build step and pull the image from one of the following registries:
|
or you can skip the build step and pull the image from one of the following registries:
|
||||||
|
|
||||||
| Registry | Image | Size |
|
| Registry | Image | Size |
|
||||||
| --------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
| --------------- | --------------------------------------------------------------- | --------------------- |
|
||||||
| Docker Hub | [matrixconduit/matrix-conduit:latest](https://hub.docker.com/r/matrixconduit/matrix-conduit) |  |
|
| Docker Hub | [matrixconduit/matrix-conduit:latest][dh] | ![Image Size][shield] |
|
||||||
| GitLab Registry | [registry.gitlab.com/famedly/conduit/conduit:latest](https://gitlab.com/famedly/conduit/container_registry/2134341) |  |
|
| GitLab Registry | [registry.gitlab.com/famedly/conduit/matrix-conduit:latest][gl] | ![Image Size][shield] |
|
||||||
|
|
||||||
|
[dh]: https://hub.docker.com/r/matrixconduit/matrix-conduit
|
||||||
|
[gl]: https://gitlab.com/famedly/conduit/container_registry/
|
||||||
|
[shield]: https://img.shields.io/docker/image-size/matrixconduit/matrix-conduit/latest
|
||||||
|
|
||||||
The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../conduit-example.toml).
|
The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../conduit-example.toml).
|
||||||
You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need
|
You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need
|
||||||
@@ -56,23 +44,20 @@ to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible
|
|||||||
|
|
||||||
If you just want to test Conduit for a short time, you can use the `--rm` flag, which will clean up everything related to your container after you stop it.
|
If you just want to test Conduit for a short time, you can use the `--rm` flag, which will clean up everything related to your container after you stop it.
|
||||||
|
|
||||||
|
|
||||||
## Docker-compose
|
## Docker-compose
|
||||||
|
|
||||||
If the docker command is not for you or your setup, you can also use one of the provided `docker-compose` files. Depending on your proxy setup, use the [`docker-compose.traefik.yml`](docker-compose.traefik.yml) and [`docker-compose.override.traefik.yml`](docker-compose.override.traefik.yml) for Traefik (don't forget to remove `.traefik` from the filenames) or the normal [`docker-compose.yml`](../docker-compose.yml) for every other reverse proxy. Additional info about deploying
|
If the docker command is not for you or your setup, you can also use one of the provided `docker-compose` files. Depending on your proxy setup, use the [`docker-compose.traefik.yml`](docker-compose.traefik.yml) and [`docker-compose.override.traefik.yml`](docker-compose.override.traefik.yml) for Traefik (don't forget to remove `.traefik` from the filenames) or the normal [`docker-compose.yml`](../docker-compose.yml) for every other reverse proxy. Additional info about deploying
|
||||||
Conduit can be found [here](../DEPLOY.md).
|
Conduit can be found [here](../DEPLOY.md).
|
||||||
|
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
To build the Conduit image with docker-compose, you first need to open and modify the `docker-compose.yml` file. There you need to comment the `image:` option and uncomment the `build:` option. Then call docker-compose with:
|
To build the Conduit image with docker-compose, you first need to open and modify the `docker-compose.yml` file. There you need to comment the `image:` option and uncomment the `build:` option. Then call docker-compose with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker-compose up
|
docker-compose up
|
||||||
```
|
```
|
||||||
|
|
||||||
This will also start the container right afterwards, so if want it to run in detached mode, you also should use the `-d` flag. For possible `build-args`, please take a look at the above `Build & Dockerfile` section.
|
This will also start the container right afterwards, so if want it to run in detached mode, you also should use the `-d` flag.
|
||||||
|
|
||||||
|
|
||||||
### Run
|
### Run
|
||||||
|
|
||||||
@@ -101,7 +86,9 @@ So...step by step:
|
|||||||
3. Create the `conduit.toml` config file, an example can be found [here](../conduit-example.toml), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars.
|
3. Create the `conduit.toml` config file, an example can be found [here](../conduit-example.toml), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars.
|
||||||
4. Uncomment the `element-web` service if you want to host your own Element Web Client and create a `element_config.json`.
|
4. Uncomment the `element-web` service if you want to host your own Element Web Client and create a `element_config.json`.
|
||||||
5. Create the files needed by the `well-known` service.
|
5. Create the files needed by the `well-known` service.
|
||||||
|
|
||||||
- `./nginx/matrix.conf` (relative to the compose file, you can change this, but then also need to change the volume mapping)
|
- `./nginx/matrix.conf` (relative to the compose file, you can change this, but then also need to change the volume mapping)
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
server_name <SUBDOMAIN>.<DOMAIN>;
|
server_name <SUBDOMAIN>.<DOMAIN>;
|
||||||
@@ -114,6 +101,7 @@ So...step by step:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `./nginx/www/.well-known/matrix/client` (relative to the compose file, you can change this, but then also need to change the volume mapping)
|
- `./nginx/www/.well-known/matrix/client` (relative to the compose file, you can change this, but then also need to change the volume mapping)
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -128,5 +116,6 @@ So...step by step:
|
|||||||
"m.server": "<SUBDOMAIN>.<DOMAIN>:443"
|
"m.server": "<SUBDOMAIN>.<DOMAIN>:443"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Run `docker-compose up -d`
|
6. Run `docker-compose up -d`
|
||||||
7. Connect to your homeserver with your preferred client and create a user. You should do this immediatly after starting Conduit, because the first created user is the admin.
|
7. Connect to your homeserver with your preferred client and create a user. You should do this immediatly after starting Conduit, because the first created user is the admin.
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
# ---------------------------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------------------------
|
||||||
# This Dockerfile is intended to be built as part of Conduit's CI pipeline.
|
# This Dockerfile is intended to be built as part of Conduit's CI pipeline.
|
||||||
# It does not build Conduit in Docker, but just copies the matching build artifact from the build job.
|
# It does not build Conduit in Docker, but just copies the matching build artifact from the build jobs.
|
||||||
# As a consequence, this is not a multiarch capable image. It always expects and packages a x86_64 binary.
|
|
||||||
#
|
#
|
||||||
# It is mostly based on the normal Conduit Dockerfile, but adjusted in a few places to maximise caching.
|
# It is mostly based on the normal Conduit Dockerfile, but adjusted in a few places to maximise caching.
|
||||||
# Credit's for the original Dockerfile: Weasy666.
|
# Credit's for the original Dockerfile: Weasy666.
|
||||||
# ---------------------------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
FROM alpine:3.14
|
FROM docker.io/alpine:3.15.0 AS runner
|
||||||
|
|
||||||
# Install packages needed to run Conduit
|
# Standard port on which Conduit launches.
|
||||||
|
# You still need to map the port when using the docker command or docker-compose.
|
||||||
|
EXPOSE 6167
|
||||||
|
|
||||||
|
# Note from @jfowl: I would like to remove this in the future and just have the Docker version be configured with envs.
|
||||||
|
ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml"
|
||||||
|
|
||||||
|
# Conduit needs:
|
||||||
|
# ca-certificates: for https
|
||||||
|
# libgcc: Apparently this is needed, even if I (@jfowl) don't know exactly why. But whatever, it's not that big.
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
|
||||||
libgcc
|
libgcc
|
||||||
|
|
||||||
|
|
||||||
ARG CREATED
|
ARG CREATED
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ARG GIT_REF
|
ARG GIT_REF
|
||||||
|
|
||||||
ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml"
|
|
||||||
|
|
||||||
# Labels according to https://github.com/opencontainers/image-spec/blob/master/annotations.md
|
# Labels according to https://github.com/opencontainers/image-spec/blob/master/annotations.md
|
||||||
# including a custom label specifying the build command
|
# including a custom label specifying the build command
|
||||||
LABEL org.opencontainers.image.created=${CREATED} \
|
LABEL org.opencontainers.image.created=${CREATED} \
|
||||||
@@ -33,19 +39,24 @@ LABEL org.opencontainers.image.created=${CREATED} \
|
|||||||
org.opencontainers.image.revision=${GIT_REF} \
|
org.opencontainers.image.revision=${GIT_REF} \
|
||||||
org.opencontainers.image.source="https://gitlab.com/famedly/conduit.git" \
|
org.opencontainers.image.source="https://gitlab.com/famedly/conduit.git" \
|
||||||
org.opencontainers.image.licenses="Apache-2.0" \
|
org.opencontainers.image.licenses="Apache-2.0" \
|
||||||
org.opencontainers.image.documentation="" \
|
org.opencontainers.image.documentation="https://gitlab.com/famedly/conduit" \
|
||||||
org.opencontainers.image.ref.name=""
|
org.opencontainers.image.ref.name=""
|
||||||
|
|
||||||
# Standard port on which Conduit launches. You still need to map the port when using the docker command or docker-compose.
|
# Created directory for the database and media files
|
||||||
EXPOSE 6167
|
|
||||||
|
|
||||||
# create data folder for database
|
|
||||||
RUN mkdir -p /srv/conduit/.local/share/conduit
|
RUN mkdir -p /srv/conduit/.local/share/conduit
|
||||||
|
|
||||||
# Copy the Conduit binary into the image at the latest possible moment to maximise caching:
|
# Test if Conduit is still alive, uses the same endpoint as Element
|
||||||
COPY ./conduit-x86_64-unknown-linux-musl /srv/conduit/conduit
|
COPY ./docker/healthcheck.sh /srv/conduit/healthcheck.sh
|
||||||
COPY ./docker/healthcheck.sh /srv/conduit/
|
HEALTHCHECK --start-period=5s --interval=5s CMD ./healthcheck.sh
|
||||||
|
|
||||||
|
|
||||||
|
# Depending on the target platform (e.g. "linux/arm/v7", "linux/arm64/v8", or "linux/amd64")
|
||||||
|
# copy the matching binary into this docker image
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
COPY ./$TARGETPLATFORM /srv/conduit/conduit
|
||||||
|
|
||||||
|
|
||||||
|
# Improve security: Don't run stuff as root, that does not need to run as root:
|
||||||
# Add www-data user and group with UID 82, as used by alpine
|
# Add www-data user and group with UID 82, as used by alpine
|
||||||
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install
|
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install
|
||||||
RUN set -x ; \
|
RUN set -x ; \
|
||||||
@@ -57,13 +68,11 @@ RUN set -x ; \
|
|||||||
RUN chown -cR www-data:www-data /srv/conduit
|
RUN chown -cR www-data:www-data /srv/conduit
|
||||||
RUN chmod +x /srv/conduit/healthcheck.sh
|
RUN chmod +x /srv/conduit/healthcheck.sh
|
||||||
|
|
||||||
|
# Change user to www-data
|
||||||
# Test if Conduit is still alive, uses the same endpoint as Element
|
|
||||||
HEALTHCHECK --start-period=5s --interval=60s CMD ./healthcheck.sh
|
|
||||||
|
|
||||||
# Set user to www-data
|
|
||||||
USER www-data
|
USER www-data
|
||||||
# Set container home directory
|
# Set container home directory
|
||||||
WORKDIR /srv/conduit
|
WORKDIR /srv/conduit
|
||||||
# Run Conduit
|
|
||||||
|
# Run Conduit and print backtraces on panics
|
||||||
|
ENV RUST_BACKTRACE=1
|
||||||
ENTRYPOINT [ "/srv/conduit/conduit" ]
|
ENTRYPOINT [ "/srv/conduit/conduit" ]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fi
|
|||||||
|
|
||||||
# The actual health check.
|
# The actual health check.
|
||||||
# We try to first get a response on HTTP and when that fails on HTTPS and when that fails, we exit with code 1.
|
# We try to first get a response on HTTP and when that fails on HTTPS and when that fails, we exit with code 1.
|
||||||
# TODO: Change this to a single curl call. Do we have a config value that we can check for that?
|
# TODO: Change this to a single wget call. Do we have a config value that we can check for that?
|
||||||
curl --fail -s "http://localhost:${CONDUIT_PORT}/_matrix/client/versions" || \
|
wget --no-verbose --tries=1 --spider "http://localhost:${CONDUIT_PORT}/_matrix/client/versions" || \
|
||||||
curl -k --fail -s "https://localhost:${CONDUIT_PORT}/_matrix/client/versions" || \
|
wget --no-verbose --tries=1 --spider "https://localhost:${CONDUIT_PORT}/_matrix/client/versions" || \
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
use std::{
|
use std::{collections::BTreeMap, convert::TryInto, sync::Arc};
|
||||||
collections::BTreeMap,
|
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH};
|
use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH};
|
||||||
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
|
||||||
@@ -11,10 +7,9 @@ use ruma::{
|
|||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::{
|
r0::{
|
||||||
account::{
|
account::{
|
||||||
change_password, deactivate, get_username_availability, register, whoami,
|
change_password, deactivate, get_3pids, get_username_availability, register,
|
||||||
ThirdPartyIdRemovalStatus,
|
whoami, ThirdPartyIdRemovalStatus,
|
||||||
},
|
},
|
||||||
contact::get_contacts,
|
|
||||||
uiaa::{AuthFlow, AuthType, UiaaInfo},
|
uiaa::{AuthFlow, AuthType, UiaaInfo},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -282,7 +277,7 @@ pub async fn register_route(
|
|||||||
let mut content = RoomCreateEventContent::new(conduit_user.clone());
|
let mut content = RoomCreateEventContent::new(conduit_user.clone());
|
||||||
content.federate = true;
|
content.federate = true;
|
||||||
content.predecessor = None;
|
content.predecessor = None;
|
||||||
content.room_version = RoomVersionId::Version6;
|
content.room_version = RoomVersionId::V6;
|
||||||
|
|
||||||
// 1. The room create event
|
// 1. The room create event
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
@@ -311,6 +306,7 @@ pub async fn register_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
@@ -397,8 +393,7 @@ pub async fn register_route(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 6. Events implied by name and topic
|
// 6. Events implied by name and topic
|
||||||
let room_name =
|
let room_name = RoomName::parse(format!("{} Admin Room", db.globals.server_name()))
|
||||||
Box::<RoomName>::try_from(format!("{} Admin Room", db.globals.server_name()))
|
|
||||||
.expect("Room name is valid");
|
.expect("Room name is valid");
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
PduBuilder {
|
PduBuilder {
|
||||||
@@ -433,7 +428,7 @@ pub async fn register_route(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Room alias
|
// Room alias
|
||||||
let alias: RoomAliasId = format!("#admins:{}", db.globals.server_name())
|
let alias: Box<RoomAliasId> = format!("#admins:{}", db.globals.server_name())
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("#admins:server_name is a valid alias name");
|
.expect("#admins:server_name is a valid alias name");
|
||||||
|
|
||||||
@@ -469,6 +464,7 @@ pub async fn register_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
@@ -491,6 +487,7 @@ pub async fn register_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
@@ -707,6 +704,7 @@ pub async fn deactivate_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mutex_state = Arc::clone(
|
let mutex_state = Arc::clone(
|
||||||
@@ -757,9 +755,9 @@ pub async fn deactivate_route(
|
|||||||
get("/_matrix/client/r0/account/3pid", data = "<body>")
|
get("/_matrix/client/r0/account/3pid", data = "<body>")
|
||||||
)]
|
)]
|
||||||
pub async fn third_party_route(
|
pub async fn third_party_route(
|
||||||
body: Ruma<get_contacts::Request>,
|
body: Ruma<get_3pids::Request>,
|
||||||
) -> ConduitResult<get_contacts::Response> {
|
) -> ConduitResult<get_3pids::Response> {
|
||||||
let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_contacts::Response::new(Vec::new()).into())
|
Ok(get_3pids::Response::new(Vec::new()).into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ pub async fn get_capabilities_route(
|
|||||||
_body: Ruma<get_capabilities::Request>,
|
_body: Ruma<get_capabilities::Request>,
|
||||||
) -> ConduitResult<get_capabilities::Response> {
|
) -> ConduitResult<get_capabilities::Response> {
|
||||||
let mut available = BTreeMap::new();
|
let mut available = BTreeMap::new();
|
||||||
available.insert(RoomVersionId::Version5, RoomVersionStability::Stable);
|
available.insert(RoomVersionId::V5, RoomVersionStability::Stable);
|
||||||
available.insert(RoomVersionId::Version6, RoomVersionStability::Stable);
|
available.insert(RoomVersionId::V6, RoomVersionStability::Stable);
|
||||||
|
|
||||||
let mut capabilities = Capabilities::new();
|
let mut capabilities = Capabilities::new();
|
||||||
capabilities.room_versions = RoomVersionsCapability {
|
capabilities.room_versions = RoomVersionsCapability {
|
||||||
default: RoomVersionId::Version6,
|
default: RoomVersionId::V6,
|
||||||
available,
|
available,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
|||||||
other_server,
|
other_server,
|
||||||
federation::directory::get_public_rooms_filtered::v1::Request {
|
federation::directory::get_public_rooms_filtered::v1::Request {
|
||||||
limit,
|
limit,
|
||||||
since: since.as_deref(),
|
since,
|
||||||
filter: Filter {
|
filter: Filter {
|
||||||
generic_search_term: filter.generic_search_term.as_deref(),
|
generic_search_term: filter.generic_search_term.as_deref(),
|
||||||
},
|
},
|
||||||
|
|||||||
+38
-29
@@ -15,7 +15,7 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
federation,
|
federation,
|
||||||
},
|
},
|
||||||
encryption::UnsignedDeviceInfo,
|
serde::Raw,
|
||||||
DeviceId, DeviceKeyAlgorithm, UserId,
|
DeviceId, DeviceKeyAlgorithm, UserId,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@@ -42,16 +42,9 @@ pub async fn upload_keys_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");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if let Some(one_time_keys) = &body.one_time_keys {
|
for (key_key, key_value) in &body.one_time_keys {
|
||||||
for (key_key, key_value) in one_time_keys {
|
db.users
|
||||||
db.users.add_one_time_key(
|
.add_one_time_key(sender_user, sender_device, key_key, key_value, &db.globals)?;
|
||||||
sender_user,
|
|
||||||
sender_device,
|
|
||||||
key_key,
|
|
||||||
key_value,
|
|
||||||
&db.globals,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(device_keys) = &body.device_keys {
|
if let Some(device_keys) = &body.device_keys {
|
||||||
@@ -316,7 +309,7 @@ pub async fn get_key_changes_route(
|
|||||||
|
|
||||||
pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
||||||
sender_user: Option<&UserId>,
|
sender_user: Option<&UserId>,
|
||||||
device_keys_input: &BTreeMap<UserId, Vec<Box<DeviceId>>>,
|
device_keys_input: &BTreeMap<Box<UserId>, Vec<Box<DeviceId>>>,
|
||||||
allowed_signatures: F,
|
allowed_signatures: F,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<get_keys::Response> {
|
) -> Result<get_keys::Response> {
|
||||||
@@ -328,6 +321,8 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
let mut get_over_federation = HashMap::new();
|
let mut get_over_federation = HashMap::new();
|
||||||
|
|
||||||
for (user_id, device_ids) in device_keys_input {
|
for (user_id, device_ids) in device_keys_input {
|
||||||
|
let user_id: &UserId = &**user_id;
|
||||||
|
|
||||||
if user_id.server_name() != db.globals.server_name() {
|
if user_id.server_name() != db.globals.server_name() {
|
||||||
get_over_federation
|
get_over_federation
|
||||||
.entry(user_id.server_name())
|
.entry(user_id.server_name())
|
||||||
@@ -348,18 +343,16 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
Error::bad_database("all_device_keys contained nonexistent device.")
|
Error::bad_database("all_device_keys contained nonexistent device.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
keys.unsigned = UnsignedDeviceInfo {
|
add_unsigned_device_display_name(&mut keys, metadata)
|
||||||
device_display_name: metadata.display_name,
|
.map_err(|_| Error::bad_database("invalid device keys in database"))?;
|
||||||
};
|
|
||||||
|
|
||||||
container.insert(device_id, keys);
|
container.insert(device_id, keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
device_keys.insert(user_id.clone(), container);
|
device_keys.insert(user_id.to_owned(), container);
|
||||||
} else {
|
} else {
|
||||||
for device_id in device_ids {
|
for device_id in device_ids {
|
||||||
let mut container = BTreeMap::new();
|
let mut container = BTreeMap::new();
|
||||||
if let Some(mut keys) = db.users.get_device_keys(&user_id.clone(), device_id)? {
|
if let Some(mut keys) = db.users.get_device_keys(user_id, device_id)? {
|
||||||
let metadata = db.users.get_device_metadata(user_id, device_id)?.ok_or(
|
let metadata = db.users.get_device_metadata(user_id, device_id)?.ok_or(
|
||||||
Error::BadRequest(
|
Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
@@ -367,28 +360,26 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
keys.unsigned = UnsignedDeviceInfo {
|
add_unsigned_device_display_name(&mut keys, metadata)
|
||||||
device_display_name: metadata.display_name,
|
.map_err(|_| Error::bad_database("invalid device keys in database"))?;
|
||||||
};
|
container.insert(device_id.to_owned(), keys);
|
||||||
|
|
||||||
container.insert(device_id.clone(), keys);
|
|
||||||
}
|
}
|
||||||
device_keys.insert(user_id.clone(), container);
|
device_keys.insert(user_id.to_owned(), container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(master_key) = db.users.get_master_key(user_id, &allowed_signatures)? {
|
if let Some(master_key) = db.users.get_master_key(user_id, &allowed_signatures)? {
|
||||||
master_keys.insert(user_id.clone(), master_key);
|
master_keys.insert(user_id.to_owned(), master_key);
|
||||||
}
|
}
|
||||||
if let Some(self_signing_key) = db
|
if let Some(self_signing_key) = db
|
||||||
.users
|
.users
|
||||||
.get_self_signing_key(user_id, &allowed_signatures)?
|
.get_self_signing_key(user_id, &allowed_signatures)?
|
||||||
{
|
{
|
||||||
self_signing_keys.insert(user_id.clone(), self_signing_key);
|
self_signing_keys.insert(user_id.to_owned(), self_signing_key);
|
||||||
}
|
}
|
||||||
if Some(user_id) == sender_user {
|
if Some(user_id) == sender_user {
|
||||||
if let Some(user_signing_key) = db.users.get_user_signing_key(user_id)? {
|
if let Some(user_signing_key) = db.users.get_user_signing_key(user_id)? {
|
||||||
user_signing_keys.insert(user_id.clone(), user_signing_key);
|
user_signing_keys.insert(user_id.to_owned(), user_signing_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,7 +391,7 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
.map(|(server, vec)| async move {
|
.map(|(server, vec)| async move {
|
||||||
let mut device_keys_input_fed = BTreeMap::new();
|
let mut device_keys_input_fed = BTreeMap::new();
|
||||||
for (user_id, keys) in vec {
|
for (user_id, keys) in vec {
|
||||||
device_keys_input_fed.insert(user_id.clone(), keys.clone());
|
device_keys_input_fed.insert(user_id.to_owned(), keys.clone());
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
server,
|
server,
|
||||||
@@ -439,8 +430,26 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_unsigned_device_display_name(
|
||||||
|
keys: &mut Raw<ruma::encryption::DeviceKeys>,
|
||||||
|
metadata: ruma::api::client::r0::device::Device,
|
||||||
|
) -> serde_json::Result<()> {
|
||||||
|
if let Some(display_name) = metadata.display_name {
|
||||||
|
let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?;
|
||||||
|
|
||||||
|
let unsigned = object.entry("unsigned").or_insert_with(|| json!({}));
|
||||||
|
if let serde_json::Value::Object(unsigned_object) = unsigned {
|
||||||
|
unsigned_object.insert("device_display_name".to_owned(), display_name.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
*keys = Raw::from_json(serde_json::value::to_raw_value(&object)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn claim_keys_helper(
|
pub(crate) async fn claim_keys_helper(
|
||||||
one_time_keys_input: &BTreeMap<UserId, BTreeMap<Box<DeviceId>, DeviceKeyAlgorithm>>,
|
one_time_keys_input: &BTreeMap<Box<UserId>, BTreeMap<Box<DeviceId>, DeviceKeyAlgorithm>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<claim_keys::Response> {
|
) -> Result<claim_keys::Response> {
|
||||||
let mut one_time_keys = BTreeMap::new();
|
let mut one_time_keys = BTreeMap::new();
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
|
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
|
iter,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
@@ -64,7 +65,7 @@ pub async fn join_room_by_id_route(
|
|||||||
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
||||||
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
||||||
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
||||||
.filter_map(|sender| UserId::try_from(sender).ok())
|
.filter_map(|sender| UserId::parse(sender).ok())
|
||||||
.map(|user| user.server_name().to_owned())
|
.map(|user| user.server_name().to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ pub async fn join_room_by_id_route(
|
|||||||
|
|
||||||
let ret = join_room_by_id_helper(
|
let ret = join_room_by_id_helper(
|
||||||
&db,
|
&db,
|
||||||
body.sender_user.as_ref(),
|
body.sender_user.as_deref(),
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&servers,
|
&servers,
|
||||||
body.third_party_signed.as_ref(),
|
body.third_party_signed.as_ref(),
|
||||||
@@ -99,9 +100,10 @@ pub async fn join_room_by_id_or_alias_route(
|
|||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<join_room_by_id_or_alias::Request<'_>>,
|
body: Ruma<join_room_by_id_or_alias::Request<'_>>,
|
||||||
) -> ConduitResult<join_room_by_id_or_alias::Response> {
|
) -> ConduitResult<join_room_by_id_or_alias::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_deref().expect("user is authenticated");
|
||||||
|
let body = body.body;
|
||||||
|
|
||||||
let (servers, room_id) = match RoomId::try_from(body.room_id_or_alias.clone()) {
|
let (servers, room_id) = match Box::<RoomId>::try_from(body.room_id_or_alias) {
|
||||||
Ok(room_id) => {
|
Ok(room_id) => {
|
||||||
let mut servers: HashSet<_> = db
|
let mut servers: HashSet<_> = db
|
||||||
.rooms
|
.rooms
|
||||||
@@ -111,7 +113,7 @@ pub async fn join_room_by_id_or_alias_route(
|
|||||||
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
||||||
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
||||||
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
||||||
.filter_map(|sender| UserId::try_from(sender).ok())
|
.filter_map(|sender| UserId::parse(sender).ok())
|
||||||
.map(|user| user.server_name().to_owned())
|
.map(|user| user.server_name().to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -127,7 +129,7 @@ pub async fn join_room_by_id_or_alias_route(
|
|||||||
|
|
||||||
let join_room_response = join_room_by_id_helper(
|
let join_room_response = join_room_by_id_helper(
|
||||||
&db,
|
&db,
|
||||||
body.sender_user.as_ref(),
|
Some(sender_user),
|
||||||
&room_id,
|
&room_id,
|
||||||
&servers,
|
&servers,
|
||||||
body.third_party_signed.as_ref(),
|
body.third_party_signed.as_ref(),
|
||||||
@@ -284,6 +286,7 @@ pub async fn ban_user_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(&body.user_id)?,
|
blurhash: db.users.blurhash(&body.user_id)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
}),
|
}),
|
||||||
|event| {
|
|event| {
|
||||||
serde_json::from_str(event.content.get())
|
serde_json::from_str(event.content.get())
|
||||||
@@ -531,7 +534,7 @@ async fn join_room_by_id_helper(
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
@@ -551,7 +554,7 @@ async fn join_room_by_id_helper(
|
|||||||
federation::membership::create_join_event_template::v1::Request {
|
federation::membership::create_join_event_template::v1::Request {
|
||||||
room_id,
|
room_id,
|
||||||
user_id: sender_user,
|
user_id: sender_user,
|
||||||
ver: &[RoomVersionId::Version5, RoomVersionId::Version6],
|
ver: &[RoomVersionId::V5, RoomVersionId::V6],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -567,8 +570,7 @@ async fn join_room_by_id_helper(
|
|||||||
|
|
||||||
let room_version = match make_join_response.room_version {
|
let room_version = match make_join_response.room_version {
|
||||||
Some(room_version)
|
Some(room_version)
|
||||||
if room_version == RoomVersionId::Version5
|
if room_version == RoomVersionId::V5 || room_version == RoomVersionId::V6 =>
|
||||||
|| room_version == RoomVersionId::Version6 =>
|
|
||||||
{
|
{
|
||||||
room_version
|
room_version
|
||||||
}
|
}
|
||||||
@@ -603,6 +605,7 @@ async fn join_room_by_id_helper(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
);
|
);
|
||||||
@@ -620,11 +623,12 @@ async fn join_room_by_id_helper(
|
|||||||
.expect("event is valid, we just created it");
|
.expect("event is valid, we just created it");
|
||||||
|
|
||||||
// Generate event id
|
// Generate event id
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&join_event_stub, &room_version)
|
ruma::signatures::reference_hash(&join_event_stub, &room_version)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
))
|
);
|
||||||
|
let event_id = <&EventId>::try_from(event_id.as_str())
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
|
|
||||||
// Add event_id back
|
// Add event_id back
|
||||||
@@ -643,7 +647,7 @@ async fn join_room_by_id_helper(
|
|||||||
remote_server,
|
remote_server,
|
||||||
federation::membership::create_join_event::v2::Request {
|
federation::membership::create_join_event::v2::Request {
|
||||||
room_id,
|
room_id,
|
||||||
event_id: &event_id,
|
event_id,
|
||||||
pdu: &PduEvent::convert_to_outgoing_federation_event(join_event.clone()),
|
pdu: &PduEvent::convert_to_outgoing_federation_event(join_event.clone()),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -651,7 +655,7 @@ async fn join_room_by_id_helper(
|
|||||||
|
|
||||||
db.rooms.get_or_create_shortroomid(room_id, &db.globals)?;
|
db.rooms.get_or_create_shortroomid(room_id, &db.globals)?;
|
||||||
|
|
||||||
let pdu = PduEvent::from_id_val(&event_id, join_event.clone())
|
let pdu = PduEvent::from_id_val(event_id, join_event.clone())
|
||||||
.map_err(|_| Error::BadServerResponse("Invalid join event PDU."))?;
|
.map_err(|_| Error::BadServerResponse("Invalid join event PDU."))?;
|
||||||
|
|
||||||
let mut state = HashMap::new();
|
let mut state = HashMap::new();
|
||||||
@@ -739,7 +743,7 @@ async fn join_room_by_id_helper(
|
|||||||
db.rooms.append_pdu(
|
db.rooms.append_pdu(
|
||||||
&pdu,
|
&pdu,
|
||||||
utils::to_canonical_object(&pdu).expect("Pdu is valid canonical object"),
|
utils::to_canonical_object(&pdu).expect("Pdu is valid canonical object"),
|
||||||
&[pdu.event_id.clone()],
|
iter::once(&*pdu.event_id),
|
||||||
db,
|
db,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -755,6 +759,7 @@ async fn join_room_by_id_helper(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
@@ -776,7 +781,7 @@ async fn join_room_by_id_helper(
|
|||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(join_room_by_id::Response::new(room_id.clone()).into())
|
Ok(join_room_by_id::Response::new(room_id.to_owned()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_and_add_event_id(
|
fn validate_and_add_event_id(
|
||||||
@@ -784,12 +789,12 @@ fn validate_and_add_event_id(
|
|||||||
room_version: &RoomVersionId,
|
room_version: &RoomVersionId,
|
||||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<(EventId, CanonicalJsonObject)> {
|
) -> Result<(Box<EventId>, CanonicalJsonObject)> {
|
||||||
let mut value: CanonicalJsonObject = serde_json::from_str(pdu.get()).map_err(|e| {
|
let mut value: CanonicalJsonObject = serde_json::from_str(pdu.get()).map_err(|e| {
|
||||||
error!("Invalid PDU in server response: {:?}: {:?}", pdu, e);
|
error!("Invalid PDU in server response: {:?}: {:?}", pdu, e);
|
||||||
Error::BadServerResponse("Invalid PDU in server response")
|
Error::BadServerResponse("Invalid PDU in server response")
|
||||||
})?;
|
})?;
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::parse(format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&value, room_version)
|
ruma::signatures::reference_hash(&value, room_version)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
@@ -856,7 +861,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
@@ -892,9 +897,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
|
|
||||||
// If there was no create event yet, assume we are creating a version 6 room right now
|
// If there was no create event yet, assume we are creating a version 6 room right now
|
||||||
let room_version_id = create_event_content
|
let room_version_id = create_event_content
|
||||||
.map_or(RoomVersionId::Version6, |create_event| {
|
.map_or(RoomVersionId::V6, |create_event| create_event.room_version);
|
||||||
create_event.room_version
|
|
||||||
});
|
|
||||||
let room_version =
|
let room_version =
|
||||||
RoomVersion::new(&room_version_id).expect("room version is supported");
|
RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||||
|
|
||||||
@@ -906,6 +909,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("member event is valid value");
|
.expect("member event is valid value");
|
||||||
|
|
||||||
@@ -934,14 +938,14 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
||||||
unsigned.insert(
|
unsigned.insert(
|
||||||
"prev_sender".to_owned(),
|
"prev_sender".to_owned(),
|
||||||
serde_json::from_str(prev_pdu.sender.as_str()).expect("UserId is valid string"),
|
to_raw_value(&prev_pdu.sender).expect("UserId is valid"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pdu = PduEvent {
|
let pdu = PduEvent {
|
||||||
event_id: ruma::event_id!("$thiswillbefilledinlater"),
|
event_id: ruma::event_id!("$thiswillbefilledinlater").into(),
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.to_owned(),
|
||||||
sender: sender_user.clone(),
|
sender: sender_user.to_owned(),
|
||||||
origin_server_ts: utils::millis_since_unix_epoch()
|
origin_server_ts: utils::millis_since_unix_epoch()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("time is valid"),
|
.expect("time is valid"),
|
||||||
@@ -1014,11 +1018,12 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Generate event id
|
// Generate event id
|
||||||
let expected_event_id = EventId::try_from(&*format!(
|
let expected_event_id = format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&pdu_json, &room_version_id)
|
ruma::signatures::reference_hash(&pdu_json, &room_version_id)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
))
|
);
|
||||||
|
let expected_event_id = <&EventId>::try_from(expected_event_id.as_str())
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
|
|
||||||
let response = db
|
let response = db
|
||||||
@@ -1028,7 +1033,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
user_id.server_name(),
|
user_id.server_name(),
|
||||||
create_invite::v2::Request {
|
create_invite::v2::Request {
|
||||||
room_id,
|
room_id,
|
||||||
event_id: &expected_event_id,
|
event_id: expected_event_id,
|
||||||
room_version: &room_version_id,
|
room_version: &room_version_id,
|
||||||
event: &PduEvent::convert_to_outgoing_federation_event(pdu_json.clone()),
|
event: &PduEvent::convert_to_outgoing_federation_event(pdu_json.clone()),
|
||||||
invite_room_state: &invite_room_state,
|
invite_room_state: &invite_room_state,
|
||||||
@@ -1100,7 +1105,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
@@ -1116,6 +1121,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(user_id)?,
|
blurhash: db.users.blurhash(user_id)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
|
|||||||
@@ -5,13 +5,8 @@ use ruma::{
|
|||||||
r0::message::{get_message_events, send_message_event},
|
r0::message::{get_message_events, send_message_event},
|
||||||
},
|
},
|
||||||
events::EventType,
|
events::EventType,
|
||||||
EventId,
|
|
||||||
};
|
|
||||||
use std::{
|
|
||||||
collections::BTreeMap,
|
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
};
|
||||||
|
use std::{collections::BTreeMap, convert::TryInto, sync::Arc};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
use rocket::{get, put};
|
use rocket::{get, put};
|
||||||
@@ -67,10 +62,9 @@ pub async fn send_message_event_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let event_id = EventId::try_from(
|
let event_id = utils::string_from_bytes(&response)
|
||||||
utils::string_from_bytes(&response)
|
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?
|
||||||
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?,
|
.try_into()
|
||||||
)
|
|
||||||
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
|
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
|
||||||
return Ok(send_message_event::Response { event_id }.into());
|
return Ok(send_message_event::Response { event_id }.into());
|
||||||
}
|
}
|
||||||
@@ -104,7 +98,7 @@ pub async fn send_message_event_route(
|
|||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(send_message_event::Response::new(event_id).into())
|
Ok(send_message_event::Response::new((*event_id).to_owned()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/messages`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/messages`
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ mod profile;
|
|||||||
mod push;
|
mod push;
|
||||||
mod read_marker;
|
mod read_marker;
|
||||||
mod redact;
|
mod redact;
|
||||||
|
mod report;
|
||||||
mod room;
|
mod room;
|
||||||
mod search;
|
mod search;
|
||||||
mod session;
|
mod session;
|
||||||
@@ -47,6 +48,7 @@ pub use profile::*;
|
|||||||
pub use push::*;
|
pub use push::*;
|
||||||
pub use read_marker::*;
|
pub use read_marker::*;
|
||||||
pub use redact::*;
|
pub use redact::*;
|
||||||
|
pub use report::*;
|
||||||
pub use room::*;
|
pub use room::*;
|
||||||
pub use search::*;
|
pub use search::*;
|
||||||
pub use session::*;
|
pub use session::*;
|
||||||
|
|||||||
@@ -105,15 +105,15 @@ pub async fn get_pushrule_route(
|
|||||||
/// Creates a single specified push rule for this user.
|
/// Creates a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "conduit_bin",
|
feature = "conduit_bin",
|
||||||
put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<req>")
|
put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<body>")
|
||||||
)]
|
)]
|
||||||
#[tracing::instrument(skip(db, req))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_pushrule_route(
|
pub async fn set_pushrule_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
req: Ruma<set_pushrule::Request<'_>>,
|
body: Ruma<set_pushrule::Request<'_>>,
|
||||||
) -> ConduitResult<set_pushrule::Response> {
|
) -> ConduitResult<set_pushrule::Response> {
|
||||||
let sender_user = req.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let body = req.body;
|
let body = body.body;
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub async fn redact_event_route(
|
|||||||
body: Ruma<redact_event::Request<'_>>,
|
body: Ruma<redact_event::Request<'_>>,
|
||||||
) -> ConduitResult<redact_event::Response> {
|
) -> ConduitResult<redact_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
let body = body.body;
|
||||||
|
|
||||||
let mutex_state = Arc::clone(
|
let mutex_state = Arc::clone(
|
||||||
db.globals
|
db.globals
|
||||||
@@ -45,7 +46,7 @@ pub async fn redact_event_route(
|
|||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
state_key: None,
|
state_key: None,
|
||||||
redacts: Some(body.event_id.clone()),
|
redacts: Some(body.event_id.into()),
|
||||||
},
|
},
|
||||||
sender_user,
|
sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
@@ -57,5 +58,6 @@ pub async fn redact_event_route(
|
|||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
|
let event_id = (*event_id).to_owned();
|
||||||
Ok(redact_event::Response { event_id }.into())
|
Ok(redact_event::Response { event_id }.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
use crate::{
|
||||||
|
database::{admin::AdminCommand, DatabaseGuard},
|
||||||
|
ConduitResult, Error, Ruma,
|
||||||
|
};
|
||||||
|
use ruma::{
|
||||||
|
api::client::{error::ErrorKind, r0::room::report_content},
|
||||||
|
events::room::message,
|
||||||
|
int,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "conduit_bin")]
|
||||||
|
use rocket::{http::RawStr, post};
|
||||||
|
|
||||||
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/report/{eventId}`
|
||||||
|
///
|
||||||
|
/// Reports an inappropriate event to homeserver admins
|
||||||
|
///
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "conduit_bin",
|
||||||
|
post("/_matrix/client/r0/rooms/<_>/report/<_>", data = "<body>")
|
||||||
|
)]
|
||||||
|
#[tracing::instrument(skip(db, body))]
|
||||||
|
pub async fn report_event_route(
|
||||||
|
db: DatabaseGuard,
|
||||||
|
body: Ruma<report_content::Request<'_>>,
|
||||||
|
) -> ConduitResult<report_content::Response> {
|
||||||
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
let pdu = match db.rooms.get_pdu(&body.event_id)? {
|
||||||
|
Some(pdu) => pdu,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Invalid Event ID",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if body.score > int!(0) || body.score < int!(-100) {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Invalid score, must be within 0 to -100",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
if body.reason.chars().count() > 250 {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Reason too long, should be 250 characters or fewer",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
db.admin.send(AdminCommand::SendMessage(
|
||||||
|
message::RoomMessageEventContent::text_html(
|
||||||
|
format!(
|
||||||
|
"Report received from: {}\n\n\
|
||||||
|
Event ID: {}\n\
|
||||||
|
Room ID: {}\n\
|
||||||
|
Sent By: {}\n\n\
|
||||||
|
Report Score: {}\n\
|
||||||
|
Report Reason: {}",
|
||||||
|
sender_user, pdu.event_id, pdu.room_id, pdu.sender, body.score, body.reason
|
||||||
|
),
|
||||||
|
format!(
|
||||||
|
"<details><summary>Report received from: <a href=\"https://matrix.to/#/{0}\">{0}\
|
||||||
|
</a></summary><ul><li>Event Info<ul><li>Event ID: <code>{1}</code>\
|
||||||
|
<a href=\"https://matrix.to/#/{2}/{1}\">🔗</a></li><li>Room ID: <code>{2}</code>\
|
||||||
|
</li><li>Sent By: <a href=\"https://matrix.to/#/{3}\">{3}</a></li></ul></li><li>\
|
||||||
|
Report Info<ul><li>Report Score: {4}</li><li>Report Reason: {5}</li></ul></li>\
|
||||||
|
</ul></details>",
|
||||||
|
sender_user,
|
||||||
|
pdu.event_id,
|
||||||
|
pdu.room_id,
|
||||||
|
pdu.sender,
|
||||||
|
body.score,
|
||||||
|
RawStr::new(&body.reason).html_escape()
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
db.flush()?;
|
||||||
|
|
||||||
|
Ok(report_content::Response {}.into())
|
||||||
|
}
|
||||||
+106
-33
@@ -22,11 +22,12 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
EventType,
|
EventType,
|
||||||
},
|
},
|
||||||
serde::JsonObject,
|
int,
|
||||||
|
serde::{CanonicalJsonObject, JsonObject},
|
||||||
RoomAliasId, RoomId, RoomVersionId,
|
RoomAliasId, RoomId, RoomVersionId,
|
||||||
};
|
};
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::{json, value::to_raw_value};
|
||||||
use std::{cmp::max, collections::BTreeMap, convert::TryFrom, sync::Arc};
|
use std::{cmp::max, collections::BTreeMap, convert::TryInto, sync::Arc};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
@@ -83,14 +84,16 @@ pub async fn create_room_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let alias: Option<RoomAliasId> =
|
let alias: Option<Box<RoomAliasId>> =
|
||||||
body.room_alias_name
|
body.room_alias_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(Ok(None), |localpart| {
|
.map_or(Ok(None), |localpart| {
|
||||||
// TODO: Check for invalid characters and maximum length
|
// TODO: Check for invalid characters and maximum length
|
||||||
let alias =
|
let alias =
|
||||||
RoomAliasId::try_from(format!("#{}:{}", localpart, db.globals.server_name()))
|
RoomAliasId::parse(format!("#{}:{}", localpart, db.globals.server_name()))
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias.")
|
||||||
|
})?;
|
||||||
|
|
||||||
if db.rooms.id_from_alias(&alias)?.is_some() {
|
if db.rooms.id_from_alias(&alias)?.is_some() {
|
||||||
Err(Error::BadRequest(
|
Err(Error::BadRequest(
|
||||||
@@ -102,12 +105,9 @@ pub async fn create_room_route(
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut content = RoomCreateEventContent::new(sender_user.clone());
|
let room_version = match body.room_version.clone() {
|
||||||
content.federate = body.creation_content.federate;
|
|
||||||
content.predecessor = body.creation_content.predecessor.clone();
|
|
||||||
content.room_version = match body.room_version.clone() {
|
|
||||||
Some(room_version) => {
|
Some(room_version) => {
|
||||||
if room_version == RoomVersionId::Version5 || room_version == RoomVersionId::Version6 {
|
if room_version == RoomVersionId::V5 || room_version == RoomVersionId::V6 {
|
||||||
room_version
|
room_version
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
@@ -116,9 +116,59 @@ pub async fn create_room_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => RoomVersionId::Version6,
|
None => RoomVersionId::V6,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let content = match &body.creation_content {
|
||||||
|
Some(content) => {
|
||||||
|
let mut content = content
|
||||||
|
.deserialize_as::<CanonicalJsonObject>()
|
||||||
|
.expect("Invalid creation content");
|
||||||
|
content.insert(
|
||||||
|
"creator".into(),
|
||||||
|
json!(&sender_user).try_into().map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
content.insert(
|
||||||
|
"room_version".into(),
|
||||||
|
json!(room_version.as_str()).try_into().map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
content
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut content = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
|
to_raw_value(&RoomCreateEventContent::new(sender_user.clone()))
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))?
|
||||||
|
.get(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
content.insert(
|
||||||
|
"room_version".into(),
|
||||||
|
json!(room_version.as_str()).try_into().map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
|
||||||
|
})?,
|
||||||
|
);
|
||||||
|
content
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Validate creation content
|
||||||
|
let de_result = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
|
to_raw_value(&content)
|
||||||
|
.expect("Invalid creation content")
|
||||||
|
.get(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if de_result.is_err() {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::BadJson,
|
||||||
|
"Invalid creation content",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// 1. The room create event
|
// 1. The room create event
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
PduBuilder {
|
PduBuilder {
|
||||||
@@ -146,6 +196,7 @@ pub async fn create_room_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
@@ -171,11 +222,11 @@ pub async fn create_room_route(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut users = BTreeMap::new();
|
let mut users = BTreeMap::new();
|
||||||
users.insert(sender_user.clone(), 100.into());
|
users.insert(sender_user.clone(), int!(100));
|
||||||
|
|
||||||
if preset == create_room::RoomPreset::TrustedPrivateChat {
|
if preset == create_room::RoomPreset::TrustedPrivateChat {
|
||||||
for invite_ in &body.invite {
|
for invite_ in &body.invite {
|
||||||
users.insert(invite_.clone(), 100.into());
|
users.insert(invite_.clone(), int!(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +268,7 @@ pub async fn create_room_route(
|
|||||||
PduBuilder {
|
PduBuilder {
|
||||||
event_type: EventType::RoomCanonicalAlias,
|
event_type: EventType::RoomCanonicalAlias,
|
||||||
content: to_raw_value(&RoomCanonicalAliasEventContent {
|
content: to_raw_value(&RoomCanonicalAliasEventContent {
|
||||||
alias: Some(room_alias_id.clone()),
|
alias: Some(room_alias_id.to_owned()),
|
||||||
alt_aliases: vec![],
|
alt_aliases: vec![],
|
||||||
})
|
})
|
||||||
.expect("We checked that alias earlier, it must be fine"),
|
.expect("We checked that alias earlier, it must be fine"),
|
||||||
@@ -432,7 +483,7 @@ pub async fn get_room_aliases_route(
|
|||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/upgrade`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade`
|
||||||
///
|
///
|
||||||
/// Upgrades the room.
|
/// Upgrades the room.
|
||||||
///
|
///
|
||||||
@@ -453,10 +504,7 @@ pub async fn upgrade_room_route(
|
|||||||
) -> ConduitResult<upgrade_room::Response> {
|
) -> ConduitResult<upgrade_room::Response> {
|
||||||
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 !matches!(
|
if !matches!(body.new_version, RoomVersionId::V5 | RoomVersionId::V6) {
|
||||||
body.new_version,
|
|
||||||
RoomVersionId::Version5 | RoomVersionId::Version6
|
|
||||||
) {
|
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::UnsupportedRoomVersion,
|
ErrorKind::UnsupportedRoomVersion,
|
||||||
"This server does not support that room version.",
|
"This server does not support that room version.",
|
||||||
@@ -510,28 +558,55 @@ pub async fn upgrade_room_route(
|
|||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
// Get the old room federations status
|
// Get the old room creation event
|
||||||
let federate = serde_json::from_str::<RoomCreateEventContent>(
|
let mut create_event_content = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
db.rooms
|
db.rooms
|
||||||
.room_state_get(&body.room_id, &EventType::RoomCreate, "")?
|
.room_state_get(&body.room_id, &EventType::RoomCreate, "")?
|
||||||
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
|
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
|
||||||
.content
|
.content
|
||||||
.get(),
|
.get(),
|
||||||
)
|
)
|
||||||
.map_err(|_| Error::bad_database("Invalid room event in database."))?
|
.map_err(|_| Error::bad_database("Invalid room event in database."))?;
|
||||||
.federate;
|
|
||||||
|
|
||||||
// Use the m.room.tombstone event as the predecessor
|
// Use the m.room.tombstone event as the predecessor
|
||||||
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
||||||
body.room_id.clone(),
|
body.room_id.clone(),
|
||||||
tombstone_event_id,
|
(*tombstone_event_id).to_owned(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Send a m.room.create event containing a predecessor field and the applicable room_version
|
// Send a m.room.create event containing a predecessor field and the applicable room_version
|
||||||
let mut create_event_content = RoomCreateEventContent::new(sender_user.clone());
|
create_event_content.insert(
|
||||||
create_event_content.federate = federate;
|
"creator".into(),
|
||||||
create_event_content.room_version = body.new_version.clone();
|
json!(&sender_user)
|
||||||
create_event_content.predecessor = predecessor;
|
.try_into()
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
|
||||||
|
);
|
||||||
|
create_event_content.insert(
|
||||||
|
"room_version".into(),
|
||||||
|
json!(&body.new_version)
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
|
||||||
|
);
|
||||||
|
create_event_content.insert(
|
||||||
|
"predecessor".into(),
|
||||||
|
json!(predecessor)
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Validate creation event content
|
||||||
|
let de_result = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
|
to_raw_value(&create_event_content)
|
||||||
|
.expect("Error forming creation event")
|
||||||
|
.get(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if de_result.is_err() {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::BadJson,
|
||||||
|
"Error forming creation event",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
db.rooms.build_and_append_pdu(
|
db.rooms.build_and_append_pdu(
|
||||||
PduBuilder {
|
PduBuilder {
|
||||||
@@ -560,6 +635,7 @@ pub async fn upgrade_room_route(
|
|||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
unsigned: None,
|
unsigned: None,
|
||||||
@@ -624,10 +700,7 @@ pub async fn upgrade_room_route(
|
|||||||
.map_err(|_| Error::bad_database("Invalid room event in database."))?;
|
.map_err(|_| Error::bad_database("Invalid room event in database."))?;
|
||||||
|
|
||||||
// Setting events_default and invite to the greater of 50 and users_default + 1
|
// Setting events_default and invite to the greater of 50 and users_default + 1
|
||||||
let new_level = max(
|
let new_level = max(int!(50), power_levels_event_content.users_default + int!(1));
|
||||||
50.into(),
|
|
||||||
power_levels_event_content.users_default + 1.into(),
|
|
||||||
);
|
|
||||||
power_levels_event_content.events_default = new_level;
|
power_levels_event_content.events_default = new_level;
|
||||||
power_levels_event_content.invite = new_level;
|
power_levels_event_content.invite = new_level;
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ pub async fn send_state_event_for_key_route(
|
|||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
|
let event_id = (*event_id).to_owned();
|
||||||
Ok(send_state_event::Response { event_id }.into())
|
Ok(send_state_event::Response { event_id }.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@ pub async fn send_state_event_for_empty_key_route(
|
|||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
|
let event_id = (*event_id).to_owned();
|
||||||
Ok(send_state_event::Response { event_id }.into())
|
Ok(send_state_event::Response { event_id }.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +269,7 @@ async fn send_state_event_for_key_helper(
|
|||||||
event_type: EventType,
|
event_type: EventType,
|
||||||
json: &Raw<AnyStateEventContent>,
|
json: &Raw<AnyStateEventContent>,
|
||||||
state_key: String,
|
state_key: String,
|
||||||
) -> Result<EventId> {
|
) -> Result<Arc<EventId>> {
|
||||||
let sender_user = sender;
|
let sender_user = sender;
|
||||||
|
|
||||||
// TODO: Review this check, error if event is unparsable, use event type, allow alias if it
|
// TODO: Review this check, error if event is unparsable, use event type, allow alias if it
|
||||||
@@ -303,7 +305,7 @@ async fn send_state_event_for_key_helper(
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use ruma::{
|
|||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
|
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::TryInto,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@@ -61,8 +61,9 @@ pub async fn sync_events_route(
|
|||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<sync_events::Request<'_>>,
|
body: Ruma<sync_events::Request<'_>>,
|
||||||
) -> Result<RumaResponse<sync_events::Response>, RumaResponse<UiaaResponse>> {
|
) -> Result<RumaResponse<sync_events::Response>, RumaResponse<UiaaResponse>> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.expect("user is authenticated");
|
||||||
|
let body = body.body;
|
||||||
|
|
||||||
let arc_db = Arc::new(db);
|
let arc_db = Arc::new(db);
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ pub async fn sync_events_route(
|
|||||||
|
|
||||||
async fn sync_helper_wrapper(
|
async fn sync_helper_wrapper(
|
||||||
db: Arc<DatabaseGuard>,
|
db: Arc<DatabaseGuard>,
|
||||||
sender_user: UserId,
|
sender_user: Box<UserId>,
|
||||||
sender_device: Box<DeviceId>,
|
sender_device: Box<DeviceId>,
|
||||||
since: Option<String>,
|
since: Option<String>,
|
||||||
full_state: bool,
|
full_state: bool,
|
||||||
@@ -176,7 +177,7 @@ async fn sync_helper_wrapper(
|
|||||||
|
|
||||||
async fn sync_helper(
|
async fn sync_helper(
|
||||||
db: Arc<DatabaseGuard>,
|
db: Arc<DatabaseGuard>,
|
||||||
sender_user: UserId,
|
sender_user: Box<UserId>,
|
||||||
sender_device: Box<DeviceId>,
|
sender_device: Box<DeviceId>,
|
||||||
since: Option<String>,
|
since: Option<String>,
|
||||||
full_state: bool,
|
full_state: bool,
|
||||||
@@ -296,7 +297,7 @@ async fn sync_helper(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(state_key) = &pdu.state_key {
|
if let Some(state_key) = &pdu.state_key {
|
||||||
let user_id = UserId::try_from(state_key.clone()).map_err(|_| {
|
let user_id = UserId::parse(state_key.clone()).map_err(|_| {
|
||||||
Error::bad_database("Invalid UserId in member PDU.")
|
Error::bad_database("Invalid UserId in member PDU.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -424,7 +425,7 @@ async fn sync_helper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(state_key) = &state_event.state_key {
|
if let Some(state_key) = &state_event.state_key {
|
||||||
let user_id = UserId::try_from(state_key.clone())
|
let user_id = UserId::parse(state_key.clone())
|
||||||
.map_err(|_| Error::bad_database("Invalid UserId in member PDU."))?;
|
.map_err(|_| Error::bad_database("Invalid UserId in member PDU."))?;
|
||||||
|
|
||||||
if user_id == sender_user {
|
if user_id == sender_user {
|
||||||
@@ -761,6 +762,8 @@ async fn sync_helper(
|
|||||||
.users
|
.users
|
||||||
.get_to_device_events(&sender_user, &sender_device)?,
|
.get_to_device_events(&sender_user, &sender_device)?,
|
||||||
},
|
},
|
||||||
|
// Fallback keys are not yet supported
|
||||||
|
device_unused_fallback_key_types: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Retry the endpoint instead of returning (waiting for #118)
|
// TODO: Retry the endpoint instead of returning (waiting for #118)
|
||||||
@@ -793,7 +796,7 @@ fn share_encrypted_room(
|
|||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
Ok(db
|
Ok(db
|
||||||
.rooms
|
.rooms
|
||||||
.get_shared_rooms(vec![sender_user.clone(), user_id.clone()])?
|
.get_shared_rooms(vec![sender_user.to_owned(), user_id.to_owned()])?
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.filter(|room_id| room_id != ignore_room)
|
.filter(|room_id| room_id != ignore_room)
|
||||||
.filter_map(|other_room_id| {
|
.filter_map(|other_room_id| {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
use crate::ConduitResult;
|
use crate::{database::DatabaseGuard, ConduitResult, Ruma};
|
||||||
|
use hmac::{Hmac, Mac, NewMac};
|
||||||
use ruma::api::client::r0::voip::get_turn_server_info;
|
use ruma::api::client::r0::voip::get_turn_server_info;
|
||||||
use std::time::Duration;
|
use ruma::SecondsSinceUnixEpoch;
|
||||||
|
use sha1::Sha1;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
|
type HmacSha1 = Hmac<Sha1>;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
use rocket::get;
|
use rocket::get;
|
||||||
@@ -8,14 +13,46 @@ use rocket::get;
|
|||||||
/// # `GET /_matrix/client/r0/voip/turnServer`
|
/// # `GET /_matrix/client/r0/voip/turnServer`
|
||||||
///
|
///
|
||||||
/// TODO: Returns information about the recommended turn server.
|
/// TODO: Returns information about the recommended turn server.
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/voip/turnServer"))]
|
#[cfg_attr(
|
||||||
#[tracing::instrument]
|
feature = "conduit_bin",
|
||||||
pub async fn turn_server_route() -> ConduitResult<get_turn_server_info::Response> {
|
get("/_matrix/client/r0/voip/turnServer", data = "<body>")
|
||||||
|
)]
|
||||||
|
#[tracing::instrument(skip(body, db))]
|
||||||
|
pub async fn turn_server_route(
|
||||||
|
body: Ruma<get_turn_server_info::Request>,
|
||||||
|
db: DatabaseGuard,
|
||||||
|
) -> ConduitResult<get_turn_server_info::Response> {
|
||||||
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
let turn_secret = db.globals.turn_secret();
|
||||||
|
|
||||||
|
let (username, password) = if !turn_secret.is_empty() {
|
||||||
|
let expiry = SecondsSinceUnixEpoch::from_system_time(
|
||||||
|
SystemTime::now() + Duration::from_secs(db.globals.turn_ttl()),
|
||||||
|
)
|
||||||
|
.expect("time is valid");
|
||||||
|
|
||||||
|
let username: String = format!("{}:{}", expiry.get(), sender_user);
|
||||||
|
|
||||||
|
let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes())
|
||||||
|
.expect("HMAC can take key of any size");
|
||||||
|
mac.update(username.as_bytes());
|
||||||
|
|
||||||
|
let password: String = base64::encode_config(mac.finalize().into_bytes(), base64::STANDARD);
|
||||||
|
|
||||||
|
(username, password)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
db.globals.turn_username().clone(),
|
||||||
|
db.globals.turn_password().clone(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
Ok(get_turn_server_info::Response {
|
Ok(get_turn_server_info::Response {
|
||||||
username: "".to_owned(),
|
username,
|
||||||
password: "".to_owned(),
|
password,
|
||||||
uris: Vec::new(),
|
uris: db.globals.turn_uris().to_vec(),
|
||||||
ttl: Duration::from_secs(60 * 60 * 24),
|
ttl: Duration::from_secs(db.globals.turn_ttl()),
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-11
@@ -74,6 +74,16 @@ pub struct Config {
|
|||||||
trusted_servers: Vec<Box<ServerName>>,
|
trusted_servers: Vec<Box<ServerName>>,
|
||||||
#[serde(default = "default_log")]
|
#[serde(default = "default_log")]
|
||||||
pub log: String,
|
pub log: String,
|
||||||
|
#[serde(default)]
|
||||||
|
turn_username: String,
|
||||||
|
#[serde(default)]
|
||||||
|
turn_password: String,
|
||||||
|
#[serde(default = "Vec::new")]
|
||||||
|
turn_uris: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
turn_secret: String,
|
||||||
|
#[serde(default = "default_turn_ttl")]
|
||||||
|
turn_ttl: u64,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
catchall: BTreeMap<String, IgnoredAny>,
|
catchall: BTreeMap<String, IgnoredAny>,
|
||||||
@@ -131,6 +141,10 @@ fn default_log() -> String {
|
|||||||
"info,state_res=warn,rocket=off,_=off,sled=off".to_owned()
|
"info,state_res=warn,rocket=off,_=off,sled=off".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_turn_ttl() -> u64 {
|
||||||
|
60 * 60 * 24
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sled")]
|
#[cfg(feature = "sled")]
|
||||||
pub type Engine = abstraction::sled::Engine;
|
pub type Engine = abstraction::sled::Engine;
|
||||||
|
|
||||||
@@ -462,10 +476,9 @@ impl Database {
|
|||||||
if db.globals.database_version()? < 6 {
|
if db.globals.database_version()? < 6 {
|
||||||
// Set room member count
|
// Set room member count
|
||||||
for (roomid, _) in db.rooms.roomid_shortstatehash.iter() {
|
for (roomid, _) in db.rooms.roomid_shortstatehash.iter() {
|
||||||
let room_id =
|
let string = utils::string_from_bytes(&roomid).unwrap();
|
||||||
RoomId::try_from(utils::string_from_bytes(&roomid).unwrap()).unwrap();
|
let room_id = <&RoomId>::try_from(string.as_str()).unwrap();
|
||||||
|
db.rooms.update_joined_count(room_id, &db)?;
|
||||||
db.rooms.update_joined_count(&room_id, &db)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.globals.bump_database_version(6)?;
|
db.globals.bump_database_version(6)?;
|
||||||
@@ -475,7 +488,7 @@ impl Database {
|
|||||||
|
|
||||||
if db.globals.database_version()? < 7 {
|
if db.globals.database_version()? < 7 {
|
||||||
// Upgrade state store
|
// Upgrade state store
|
||||||
let mut last_roomstates: HashMap<RoomId, u64> = HashMap::new();
|
let mut last_roomstates: HashMap<Box<RoomId>, u64> = HashMap::new();
|
||||||
let mut current_sstatehash: Option<u64> = None;
|
let mut current_sstatehash: Option<u64> = None;
|
||||||
let mut current_room = None;
|
let mut current_room = None;
|
||||||
let mut current_state = HashSet::new();
|
let mut current_state = HashSet::new();
|
||||||
@@ -556,7 +569,7 @@ impl Database {
|
|||||||
if let Some(current_sstatehash) = current_sstatehash {
|
if let Some(current_sstatehash) = current_sstatehash {
|
||||||
handle_state(
|
handle_state(
|
||||||
current_sstatehash,
|
current_sstatehash,
|
||||||
current_room.as_ref().unwrap(),
|
current_room.as_deref().unwrap(),
|
||||||
current_state,
|
current_state,
|
||||||
&mut last_roomstates,
|
&mut last_roomstates,
|
||||||
)?;
|
)?;
|
||||||
@@ -572,10 +585,9 @@ impl Database {
|
|||||||
.get(&seventid)
|
.get(&seventid)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let event_id =
|
let string = utils::string_from_bytes(&event_id).unwrap();
|
||||||
EventId::try_from(utils::string_from_bytes(&event_id).unwrap())
|
let event_id = <&EventId>::try_from(string.as_str()).unwrap();
|
||||||
.unwrap();
|
let pdu = db.rooms.get_pdu(event_id).unwrap().unwrap();
|
||||||
let pdu = db.rooms.get_pdu(&event_id).unwrap().unwrap();
|
|
||||||
|
|
||||||
if Some(&pdu.room_id) != current_room.as_ref() {
|
if Some(&pdu.room_id) != current_room.as_ref() {
|
||||||
current_room = Some(pdu.room_id.clone());
|
current_room = Some(pdu.room_id.clone());
|
||||||
@@ -590,7 +602,7 @@ impl Database {
|
|||||||
if let Some(current_sstatehash) = current_sstatehash {
|
if let Some(current_sstatehash) = current_sstatehash {
|
||||||
handle_state(
|
handle_state(
|
||||||
current_sstatehash,
|
current_sstatehash,
|
||||||
current_room.as_ref().unwrap(),
|
current_room.as_deref().unwrap(),
|
||||||
current_state,
|
current_state,
|
||||||
&mut last_roomstates,
|
&mut last_roomstates,
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
use std::{
|
use std::{convert::TryInto, sync::Arc};
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{pdu::PduBuilder, Database};
|
use crate::{pdu::PduBuilder, Database};
|
||||||
use rocket::futures::{channel::mpsc, stream::StreamExt};
|
use rocket::futures::{channel::mpsc, stream::StreamExt};
|
||||||
@@ -36,14 +33,14 @@ impl Admin {
|
|||||||
|
|
||||||
let guard = db.read().await;
|
let guard = db.read().await;
|
||||||
|
|
||||||
let conduit_user =
|
let conduit_user = UserId::parse(format!("@conduit:{}", guard.globals.server_name()))
|
||||||
UserId::try_from(format!("@conduit:{}", guard.globals.server_name()))
|
|
||||||
.expect("@conduit:server_name is valid");
|
.expect("@conduit:server_name is valid");
|
||||||
|
|
||||||
let conduit_room = guard
|
let conduit_room = guard
|
||||||
.rooms
|
.rooms
|
||||||
.id_from_alias(
|
.id_from_alias(
|
||||||
&format!("#admins:{}", guard.globals.server_name())
|
format!("#admins:{}", guard.globals.server_name())
|
||||||
|
.as_str()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("#admins:server_name is a valid room alias"),
|
.expect("#admins:server_name is a valid room alias"),
|
||||||
)
|
)
|
||||||
|
|||||||
+27
-7
@@ -40,13 +40,13 @@ pub struct Globals {
|
|||||||
dns_resolver: TokioAsyncResolver,
|
dns_resolver: TokioAsyncResolver,
|
||||||
jwt_decoding_key: Option<jsonwebtoken::DecodingKey<'static>>,
|
jwt_decoding_key: Option<jsonwebtoken::DecodingKey<'static>>,
|
||||||
pub(super) server_signingkeys: Arc<dyn Tree>,
|
pub(super) server_signingkeys: Arc<dyn Tree>,
|
||||||
pub bad_event_ratelimiter: Arc<RwLock<HashMap<EventId, RateLimitState>>>,
|
pub bad_event_ratelimiter: Arc<RwLock<HashMap<Box<EventId>, RateLimitState>>>,
|
||||||
pub bad_signature_ratelimiter: Arc<RwLock<HashMap<Vec<String>, RateLimitState>>>,
|
pub bad_signature_ratelimiter: Arc<RwLock<HashMap<Vec<String>, RateLimitState>>>,
|
||||||
pub servername_ratelimiter: Arc<RwLock<HashMap<Box<ServerName>, Arc<Semaphore>>>>,
|
pub servername_ratelimiter: Arc<RwLock<HashMap<Box<ServerName>, Arc<Semaphore>>>>,
|
||||||
pub sync_receivers: RwLock<HashMap<(UserId, Box<DeviceId>), SyncHandle>>,
|
pub sync_receivers: RwLock<HashMap<(Box<UserId>, Box<DeviceId>), SyncHandle>>,
|
||||||
pub roomid_mutex_insert: RwLock<HashMap<RoomId, Arc<Mutex<()>>>>,
|
pub roomid_mutex_insert: RwLock<HashMap<Box<RoomId>, Arc<Mutex<()>>>>,
|
||||||
pub roomid_mutex_state: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>,
|
pub roomid_mutex_state: RwLock<HashMap<Box<RoomId>, Arc<TokioMutex<()>>>>,
|
||||||
pub roomid_mutex_federation: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>, // this lock will be held longer
|
pub roomid_mutex_federation: RwLock<HashMap<Box<RoomId>, Arc<TokioMutex<()>>>>, // this lock will be held longer
|
||||||
pub rotate: RotationHandler,
|
pub rotate: RotationHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +226,26 @@ impl Globals {
|
|||||||
self.jwt_decoding_key.as_ref()
|
self.jwt_decoding_key.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn turn_password(&self) -> &String {
|
||||||
|
&self.config.turn_password
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turn_ttl(&self) -> u64 {
|
||||||
|
self.config.turn_ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turn_uris(&self) -> &[String] {
|
||||||
|
&self.config.turn_uris
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turn_username(&self) -> &String {
|
||||||
|
&self.config.turn_username
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turn_secret(&self) -> &String {
|
||||||
|
&self.config.turn_secret
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: the key valid until timestamp is only honored in room version > 4
|
/// TODO: the key valid until timestamp is only honored in room version > 4
|
||||||
/// Remove the outdated keys and insert the new ones.
|
/// Remove the outdated keys and insert the new ones.
|
||||||
///
|
///
|
||||||
@@ -234,7 +254,7 @@ impl Globals {
|
|||||||
&self,
|
&self,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
new_keys: ServerSigningKeys,
|
new_keys: ServerSigningKeys,
|
||||||
) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
|
) -> Result<BTreeMap<Box<ServerSigningKeyId>, VerifyKey>> {
|
||||||
// Not atomic, but this is not critical
|
// Not atomic, but this is not critical
|
||||||
let signingkeys = self.server_signingkeys.get(origin.as_bytes())?;
|
let signingkeys = self.server_signingkeys.get(origin.as_bytes())?;
|
||||||
|
|
||||||
@@ -273,7 +293,7 @@ impl Globals {
|
|||||||
pub fn signing_keys_for(
|
pub fn signing_keys_for(
|
||||||
&self,
|
&self,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
|
) -> Result<BTreeMap<Box<ServerSigningKeyId>, VerifyKey>> {
|
||||||
let signingkeys = self
|
let signingkeys = self
|
||||||
.server_signingkeys
|
.server_signingkeys
|
||||||
.get(origin.as_bytes())?
|
.get(origin.as_bytes())?
|
||||||
|
|||||||
+42
-27
@@ -4,9 +4,11 @@ use ruma::{
|
|||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::backup::{BackupAlgorithm, KeyBackupData, RoomKeyBackup},
|
r0::backup::{BackupAlgorithm, KeyBackupData, RoomKeyBackup},
|
||||||
},
|
},
|
||||||
|
serde::Raw,
|
||||||
RoomId, UserId,
|
RoomId, UserId,
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeMap, convert::TryFrom, sync::Arc};
|
use serde_json::json;
|
||||||
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use super::abstraction::Tree;
|
use super::abstraction::Tree;
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ impl KeyBackups {
|
|||||||
pub fn create_backup(
|
pub fn create_backup(
|
||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
backup_metadata: &BackupAlgorithm,
|
backup_metadata: &Raw<BackupAlgorithm>,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let version = globals.next_count()?.to_string();
|
let version = globals.next_count()?.to_string();
|
||||||
@@ -59,7 +61,7 @@ impl KeyBackups {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
version: &str,
|
version: &str,
|
||||||
backup_metadata: &BackupAlgorithm,
|
backup_metadata: &Raw<BackupAlgorithm>,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
@@ -73,12 +75,8 @@ impl KeyBackups {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backupid_algorithm.insert(
|
self.backupid_algorithm
|
||||||
&key,
|
.insert(&key, backup_metadata.json().get().as_bytes())?;
|
||||||
serde_json::to_string(backup_metadata)
|
|
||||||
.expect("BackupAlgorithm::to_string always works")
|
|
||||||
.as_bytes(),
|
|
||||||
)?;
|
|
||||||
self.backupid_etag
|
self.backupid_etag
|
||||||
.insert(&key, &globals.next_count()?.to_be_bytes())?;
|
.insert(&key, &globals.next_count()?.to_be_bytes())?;
|
||||||
Ok(version.to_owned())
|
Ok(version.to_owned())
|
||||||
@@ -105,7 +103,10 @@ impl KeyBackups {
|
|||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_latest_backup(&self, user_id: &UserId) -> Result<Option<(String, BackupAlgorithm)>> {
|
pub fn get_latest_backup(
|
||||||
|
&self,
|
||||||
|
user_id: &UserId,
|
||||||
|
) -> Result<Option<(String, Raw<BackupAlgorithm>)>> {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
let mut last_possible_key = prefix.clone();
|
let mut last_possible_key = prefix.clone();
|
||||||
@@ -133,7 +134,11 @@ impl KeyBackups {
|
|||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_backup(&self, user_id: &UserId, version: &str) -> Result<Option<BackupAlgorithm>> {
|
pub fn get_backup(
|
||||||
|
&self,
|
||||||
|
user_id: &UserId,
|
||||||
|
version: &str,
|
||||||
|
) -> Result<Option<Raw<BackupAlgorithm>>> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(version.as_bytes());
|
key.extend_from_slice(version.as_bytes());
|
||||||
@@ -152,7 +157,7 @@ impl KeyBackups {
|
|||||||
version: &str,
|
version: &str,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
session_id: &str,
|
session_id: &str,
|
||||||
key_data: &KeyBackupData,
|
key_data: &Raw<KeyBackupData>,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
@@ -174,10 +179,8 @@ impl KeyBackups {
|
|||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(session_id.as_bytes());
|
key.extend_from_slice(session_id.as_bytes());
|
||||||
|
|
||||||
self.backupkeyid_backup.insert(
|
self.backupkeyid_backup
|
||||||
&key,
|
.insert(&key, key_data.json().get().as_bytes())?;
|
||||||
&serde_json::to_vec(&key_data).expect("KeyBackupData::to_vec always works"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -209,13 +212,13 @@ impl KeyBackups {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
version: &str,
|
version: &str,
|
||||||
) -> Result<BTreeMap<RoomId, RoomKeyBackup>> {
|
) -> Result<BTreeMap<Box<RoomId>, Raw<RoomKeyBackup>>> {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
prefix.extend_from_slice(version.as_bytes());
|
prefix.extend_from_slice(version.as_bytes());
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
let mut rooms = BTreeMap::<RoomId, RoomKeyBackup>::new();
|
let mut rooms = BTreeMap::<Box<RoomId>, Raw<RoomKeyBackup>>::new();
|
||||||
|
|
||||||
for result in self
|
for result in self
|
||||||
.backupkeyid_backup
|
.backupkeyid_backup
|
||||||
@@ -231,7 +234,7 @@ impl KeyBackups {
|
|||||||
Error::bad_database("backupkeyid_backup session_id is invalid.")
|
Error::bad_database("backupkeyid_backup session_id is invalid.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::parse(
|
||||||
utils::string_from_bytes(parts.next().ok_or_else(|| {
|
utils::string_from_bytes(parts.next().ok_or_else(|| {
|
||||||
Error::bad_database("backupkeyid_backup key is invalid.")
|
Error::bad_database("backupkeyid_backup key is invalid.")
|
||||||
})?)
|
})?)
|
||||||
@@ -241,7 +244,7 @@ impl KeyBackups {
|
|||||||
Error::bad_database("backupkeyid_backup room_id is invalid room id.")
|
Error::bad_database("backupkeyid_backup room_id is invalid room id.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let key_data = serde_json::from_slice(&value).map_err(|_| {
|
let key_data: serde_json::Value = serde_json::from_slice(&value).map_err(|_| {
|
||||||
Error::bad_database("KeyBackupData in backupkeyid_backup is invalid.")
|
Error::bad_database("KeyBackupData in backupkeyid_backup is invalid.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -249,13 +252,25 @@ impl KeyBackups {
|
|||||||
})
|
})
|
||||||
{
|
{
|
||||||
let (room_id, session_id, key_data) = result?;
|
let (room_id, session_id, key_data) = result?;
|
||||||
rooms
|
let room_key_backup = rooms.entry(room_id).or_insert_with(|| {
|
||||||
.entry(room_id)
|
Raw::new(&RoomKeyBackup {
|
||||||
.or_insert_with(|| RoomKeyBackup {
|
|
||||||
sessions: BTreeMap::new(),
|
sessions: BTreeMap::new(),
|
||||||
})
|
})
|
||||||
.sessions
|
.expect("RoomKeyBackup serialization")
|
||||||
.insert(session_id, key_data);
|
});
|
||||||
|
|
||||||
|
let mut object = room_key_backup
|
||||||
|
.deserialize_as::<serde_json::Map<String, serde_json::Value>>()
|
||||||
|
.map_err(|_| Error::bad_database("RoomKeyBackup is not an object"))?;
|
||||||
|
|
||||||
|
let sessions = object.entry("session").or_insert_with(|| json!({}));
|
||||||
|
if let serde_json::Value::Object(unsigned_object) = sessions {
|
||||||
|
unsigned_object.insert(session_id, key_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
*room_key_backup = Raw::from_json(
|
||||||
|
serde_json::value::to_raw_value(&object).expect("Value => RawValue serialization"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(rooms)
|
Ok(rooms)
|
||||||
@@ -266,7 +281,7 @@ impl KeyBackups {
|
|||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
version: &str,
|
version: &str,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> Result<BTreeMap<String, KeyBackupData>> {
|
) -> Result<BTreeMap<String, Raw<KeyBackupData>>> {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
prefix.extend_from_slice(version.as_bytes());
|
prefix.extend_from_slice(version.as_bytes());
|
||||||
@@ -304,7 +319,7 @@ impl KeyBackups {
|
|||||||
version: &str,
|
version: &str,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
session_id: &str,
|
session_id: &str,
|
||||||
) -> Result<Option<KeyBackupData>> {
|
) -> Result<Option<Raw<KeyBackupData>>> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(version.as_bytes());
|
key.extend_from_slice(version.as_bytes());
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ pub fn get_actions<'a>(
|
|||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<&'a [Action]> {
|
) -> Result<&'a [Action]> {
|
||||||
let ctx = PushConditionRoomCtx {
|
let ctx = PushConditionRoomCtx {
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.to_owned(),
|
||||||
member_count: 10_u32.into(), // TODO: get member count efficiently
|
member_count: 10_u32.into(), // TODO: get member count efficiently
|
||||||
user_display_name: db
|
user_display_name: db
|
||||||
.users
|
.users
|
||||||
@@ -277,7 +277,7 @@ async fn send_notice(
|
|||||||
let mut data_minus_url = pusher.data.clone();
|
let mut data_minus_url = pusher.data.clone();
|
||||||
// The url must be stripped off according to spec
|
// The url must be stripped off according to spec
|
||||||
data_minus_url.url = None;
|
data_minus_url.url = None;
|
||||||
device.data = Some(data_minus_url);
|
device.data = data_minus_url;
|
||||||
|
|
||||||
// Tweaks are only added if the format is NOT event_id_only
|
// Tweaks are only added if the format is NOT event_id_only
|
||||||
if !event_id_only {
|
if !event_id_only {
|
||||||
|
|||||||
+78
-73
@@ -36,6 +36,8 @@ use std::{
|
|||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
|
fmt::Debug,
|
||||||
|
iter,
|
||||||
mem::size_of,
|
mem::size_of,
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, Mutex, RwLock},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
@@ -107,14 +109,14 @@ pub struct Rooms {
|
|||||||
/// RoomId + EventId -> Parent PDU EventId.
|
/// RoomId + EventId -> Parent PDU EventId.
|
||||||
pub(super) referencedevents: Arc<dyn Tree>,
|
pub(super) referencedevents: Arc<dyn Tree>,
|
||||||
|
|
||||||
pub(super) pdu_cache: Mutex<LruCache<EventId, Arc<PduEvent>>>,
|
pub(super) pdu_cache: Mutex<LruCache<Box<EventId>, Arc<PduEvent>>>,
|
||||||
pub(super) shorteventid_cache: Mutex<LruCache<u64, Arc<EventId>>>,
|
pub(super) shorteventid_cache: Mutex<LruCache<u64, Arc<EventId>>>,
|
||||||
pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
|
pub(super) auth_chain_cache: Mutex<LruCache<Vec<u64>, Arc<HashSet<u64>>>>,
|
||||||
pub(super) eventidshort_cache: Mutex<LruCache<EventId, u64>>,
|
pub(super) eventidshort_cache: Mutex<LruCache<Box<EventId>, u64>>,
|
||||||
pub(super) statekeyshort_cache: Mutex<LruCache<(EventType, String), u64>>,
|
pub(super) statekeyshort_cache: Mutex<LruCache<(EventType, String), u64>>,
|
||||||
pub(super) shortstatekey_cache: Mutex<LruCache<u64, (EventType, String)>>,
|
pub(super) shortstatekey_cache: Mutex<LruCache<u64, (EventType, String)>>,
|
||||||
pub(super) our_real_users_cache: RwLock<HashMap<RoomId, Arc<HashSet<UserId>>>>,
|
pub(super) our_real_users_cache: RwLock<HashMap<Box<RoomId>, Arc<HashSet<Box<UserId>>>>>,
|
||||||
pub(super) appservice_in_room_cache: RwLock<HashMap<RoomId, HashMap<String, bool>>>,
|
pub(super) appservice_in_room_cache: RwLock<HashMap<Box<RoomId>, HashMap<String, bool>>>,
|
||||||
pub(super) stateinfo_cache: Mutex<
|
pub(super) stateinfo_cache: Mutex<
|
||||||
LruCache<
|
LruCache<
|
||||||
u64,
|
u64,
|
||||||
@@ -434,7 +436,7 @@ impl Rooms {
|
|||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_id = match UserId::try_from(state_key) {
|
let user_id = match UserId::parse(state_key) {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
@@ -742,7 +744,7 @@ impl Rooms {
|
|||||||
self.eventidshort_cache
|
self.eventidshort_cache
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(event_id.clone(), short);
|
.insert(event_id.to_owned(), short);
|
||||||
|
|
||||||
Ok(short)
|
Ok(short)
|
||||||
}
|
}
|
||||||
@@ -871,12 +873,10 @@ impl Rooms {
|
|||||||
.get(&shorteventid.to_be_bytes())?
|
.get(&shorteventid.to_be_bytes())?
|
||||||
.ok_or_else(|| Error::bad_database("Shorteventid does not exist"))?;
|
.ok_or_else(|| Error::bad_database("Shorteventid does not exist"))?;
|
||||||
|
|
||||||
let event_id = Arc::new(
|
let event_id = EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
EventId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
|
|
||||||
Error::bad_database("EventID in shorteventid_eventid is invalid unicode.")
|
Error::bad_database("EventID in shorteventid_eventid is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?,
|
.map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?;
|
||||||
);
|
|
||||||
|
|
||||||
self.shorteventid_cache
|
self.shorteventid_cache
|
||||||
.lock()
|
.lock()
|
||||||
@@ -1112,7 +1112,7 @@ impl Rooms {
|
|||||||
self.pdu_cache
|
self.pdu_cache
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(event_id.clone(), Arc::clone(&pdu));
|
.insert(event_id.to_owned(), Arc::clone(&pdu));
|
||||||
Ok(Some(pdu))
|
Ok(Some(pdu))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -1162,14 +1162,14 @@ impl Rooms {
|
|||||||
|
|
||||||
/// Returns the leaf pdus of a room.
|
/// Returns the leaf pdus of a room.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<HashSet<EventId>> {
|
pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>> {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.roomid_pduleaves
|
self.roomid_pduleaves
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(_, bytes)| {
|
.map(|(_, bytes)| {
|
||||||
EventId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
|
EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("EventID in roomid_pduleaves is invalid unicode.")
|
Error::bad_database("EventID in roomid_pduleaves is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))
|
.map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))
|
||||||
@@ -1178,7 +1178,7 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self, room_id, event_ids))]
|
#[tracing::instrument(skip(self, room_id, event_ids))]
|
||||||
pub fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[EventId]) -> Result<()> {
|
pub fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()> {
|
||||||
for prev in event_ids {
|
for prev in event_ids {
|
||||||
let mut key = room_id.as_bytes().to_vec();
|
let mut key = room_id.as_bytes().to_vec();
|
||||||
key.extend_from_slice(prev.as_bytes());
|
key.extend_from_slice(prev.as_bytes());
|
||||||
@@ -1193,7 +1193,11 @@ impl Rooms {
|
|||||||
/// The provided `event_ids` become the new leaves, this allows a room to have multiple
|
/// The provided `event_ids` become the new leaves, this allows a room to have multiple
|
||||||
/// `prev_events`.
|
/// `prev_events`.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn replace_pdu_leaves(&self, room_id: &RoomId, event_ids: &[EventId]) -> Result<()> {
|
pub fn replace_pdu_leaves<'a>(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
event_ids: impl IntoIterator<Item = &'a EventId> + Debug,
|
||||||
|
) -> Result<()> {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
@@ -1257,11 +1261,11 @@ impl Rooms {
|
|||||||
///
|
///
|
||||||
/// Returns pdu id
|
/// Returns pdu id
|
||||||
#[tracing::instrument(skip(self, pdu, pdu_json, leaves, db))]
|
#[tracing::instrument(skip(self, pdu, pdu_json, leaves, db))]
|
||||||
pub fn append_pdu(
|
pub fn append_pdu<'a>(
|
||||||
&self,
|
&self,
|
||||||
pdu: &PduEvent,
|
pdu: &PduEvent,
|
||||||
mut pdu_json: CanonicalJsonObject,
|
mut pdu_json: CanonicalJsonObject,
|
||||||
leaves: &[EventId],
|
leaves: impl IntoIterator<Item = &'a EventId> + Debug,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let shortroomid = self.get_shortroomid(&pdu.room_id)?.expect("room exists");
|
let shortroomid = self.get_shortroomid(&pdu.room_id)?.expect("room exists");
|
||||||
@@ -1420,7 +1424,7 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the state_key fails
|
// if the state_key fails
|
||||||
let target_user_id = UserId::try_from(state_key.clone())
|
let target_user_id = UserId::parse(state_key.clone())
|
||||||
.expect("This state_key was previously validated");
|
.expect("This state_key was previously validated");
|
||||||
|
|
||||||
let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
|
let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
|
||||||
@@ -1476,8 +1480,9 @@ impl Rooms {
|
|||||||
if body.starts_with(&format!("@conduit:{}: ", db.globals.server_name()))
|
if body.starts_with(&format!("@conduit:{}: ", db.globals.server_name()))
|
||||||
&& self
|
&& self
|
||||||
.id_from_alias(
|
.id_from_alias(
|
||||||
&format!("#admins:{}", db.globals.server_name())
|
<&RoomAliasId>::try_from(
|
||||||
.try_into()
|
format!("#admins:{}", db.globals.server_name()).as_str(),
|
||||||
|
)
|
||||||
.expect("#admins:server_name is a valid room alias"),
|
.expect("#admins:server_name is a valid room alias"),
|
||||||
)?
|
)?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1528,7 +1533,7 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
"get_auth_chain" => {
|
"get_auth_chain" => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let Ok(event_id) = EventId::try_from(args[0]) {
|
if let Ok(event_id) = EventId::parse_arc(args[0]) {
|
||||||
if let Some(event) = db.rooms.get_pdu_json(&event_id)? {
|
if let Some(event) = db.rooms.get_pdu_json(&event_id)? {
|
||||||
let room_id_str = event
|
let room_id_str = event
|
||||||
.get("room_id")
|
.get("room_id")
|
||||||
@@ -1539,12 +1544,12 @@ impl Rooms {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let room_id = RoomId::try_from(room_id_str)
|
let room_id = <&RoomId>::try_from(room_id_str)
|
||||||
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let count = server_server::get_auth_chain(
|
let count = server_server::get_auth_chain(
|
||||||
&room_id,
|
room_id,
|
||||||
vec![Arc::new(event_id)],
|
vec![event_id],
|
||||||
db,
|
db,
|
||||||
)?
|
)?
|
||||||
.count();
|
.count();
|
||||||
@@ -1567,12 +1572,12 @@ impl Rooms {
|
|||||||
let string = body[1..body.len() - 1].join("\n");
|
let string = body[1..body.len() - 1].join("\n");
|
||||||
match serde_json::from_str(&string) {
|
match serde_json::from_str(&string) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::parse(format!(
|
||||||
"${}",
|
"${}",
|
||||||
// Anything higher than version3 behaves the same
|
// Anything higher than version3 behaves the same
|
||||||
ruma::signatures::reference_hash(
|
ruma::signatures::reference_hash(
|
||||||
&value,
|
&value,
|
||||||
&RoomVersionId::Version6
|
&RoomVersionId::V6
|
||||||
)
|
)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
))
|
))
|
||||||
@@ -1622,7 +1627,7 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
"get_pdu" => {
|
"get_pdu" => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let Ok(event_id) = EventId::try_from(args[0]) {
|
if let Ok(event_id) = EventId::parse(args[0]) {
|
||||||
let mut outlier = false;
|
let mut outlier = false;
|
||||||
let mut pdu_json =
|
let mut pdu_json =
|
||||||
db.rooms.get_non_outlier_pdu_json(&event_id)?;
|
db.rooms.get_non_outlier_pdu_json(&event_id)?;
|
||||||
@@ -1948,7 +1953,7 @@ impl Rooms {
|
|||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
|
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
|
||||||
) -> Result<EventId> {
|
) -> Result<Arc<EventId>> {
|
||||||
let PduBuilder {
|
let PduBuilder {
|
||||||
event_type,
|
event_type,
|
||||||
content,
|
content,
|
||||||
@@ -1985,9 +1990,7 @@ impl Rooms {
|
|||||||
|
|
||||||
// If there was no create event yet, assume we are creating a version 6 room right now
|
// If there was no create event yet, assume we are creating a version 6 room right now
|
||||||
let room_version_id = create_event_content
|
let room_version_id = create_event_content
|
||||||
.map_or(RoomVersionId::Version6, |create_event| {
|
.map_or(RoomVersionId::V6, |create_event| create_event.room_version);
|
||||||
create_event.room_version
|
|
||||||
});
|
|
||||||
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||||
|
|
||||||
let auth_events =
|
let auth_events =
|
||||||
@@ -2016,9 +2019,9 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut pdu = PduEvent {
|
let mut pdu = PduEvent {
|
||||||
event_id: ruma::event_id!("$thiswillbefilledinlater"),
|
event_id: ruma::event_id!("$thiswillbefilledinlater").into(),
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.to_owned(),
|
||||||
sender: sender.clone(),
|
sender: sender.to_owned(),
|
||||||
origin_server_ts: utils::millis_since_unix_epoch()
|
origin_server_ts: utils::millis_since_unix_epoch()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("time is valid"),
|
.expect("time is valid"),
|
||||||
@@ -2083,7 +2086,7 @@ impl Rooms {
|
|||||||
.expect("event is valid, we just created it");
|
.expect("event is valid, we just created it");
|
||||||
|
|
||||||
// Generate event id
|
// Generate event id
|
||||||
pdu.event_id = EventId::try_from(&*format!(
|
pdu.event_id = EventId::parse_arc(format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&pdu_json, &room_version_id)
|
ruma::signatures::reference_hash(&pdu_json, &room_version_id)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
@@ -2107,7 +2110,7 @@ impl Rooms {
|
|||||||
pdu_json,
|
pdu_json,
|
||||||
// Since this PDU references all pdu_leaves we can update the leaves
|
// Since this PDU references all pdu_leaves we can update the leaves
|
||||||
// of the room
|
// of the room
|
||||||
&[pdu.event_id.clone()],
|
iter::once(&*pdu.event_id),
|
||||||
db,
|
db,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -2206,7 +2209,7 @@ impl Rooms {
|
|||||||
let mut first_pdu_id = prefix.clone();
|
let mut first_pdu_id = prefix.clone();
|
||||||
first_pdu_id.extend_from_slice(&(since + 1).to_be_bytes());
|
first_pdu_id.extend_from_slice(&(since + 1).to_be_bytes());
|
||||||
|
|
||||||
let user_id = user_id.clone();
|
let user_id = user_id.to_owned();
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.pduid_pdu
|
.pduid_pdu
|
||||||
@@ -2243,7 +2246,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let current: &[u8] = ¤t;
|
let current: &[u8] = ¤t;
|
||||||
|
|
||||||
let user_id = user_id.clone();
|
let user_id = user_id.to_owned();
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.pduid_pdu
|
.pduid_pdu
|
||||||
@@ -2280,7 +2283,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let current: &[u8] = ¤t;
|
let current: &[u8] = ¤t;
|
||||||
|
|
||||||
let user_id = user_id.clone();
|
let user_id = user_id.to_owned();
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.pduid_pdu
|
.pduid_pdu
|
||||||
@@ -2412,7 +2415,7 @@ impl Rooms {
|
|||||||
|
|
||||||
for room_ids in direct_event.content.0.values_mut() {
|
for room_ids in direct_event.content.0.values_mut() {
|
||||||
if room_ids.iter().any(|r| r == &predecessor.room_id) {
|
if room_ids.iter().any(|r| r == &predecessor.room_id) {
|
||||||
room_ids.push(room_id.clone());
|
room_ids.push(room_id.to_owned());
|
||||||
room_ids_updated = true;
|
room_ids_updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2451,7 +2454,11 @@ impl Rooms {
|
|||||||
EventType::IgnoredUserList,
|
EventType::IgnoredUserList,
|
||||||
)?
|
)?
|
||||||
.map_or(false, |ignored| {
|
.map_or(false, |ignored| {
|
||||||
ignored.content.ignored_users.contains(sender)
|
ignored
|
||||||
|
.content
|
||||||
|
.ignored_users
|
||||||
|
.iter()
|
||||||
|
.any(|user| user == sender)
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_ignored {
|
if is_ignored {
|
||||||
@@ -2537,7 +2544,7 @@ impl Rooms {
|
|||||||
self.our_real_users_cache
|
self.our_real_users_cache
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(room_id.clone(), Arc::new(real_users));
|
.insert(room_id.to_owned(), Arc::new(real_users));
|
||||||
|
|
||||||
for old_joined_server in self.room_servers(room_id).filter_map(|r| r.ok()) {
|
for old_joined_server in self.room_servers(room_id).filter_map(|r| r.ok()) {
|
||||||
if !joined_servers.remove(&old_joined_server) {
|
if !joined_servers.remove(&old_joined_server) {
|
||||||
@@ -2582,7 +2589,7 @@ impl Rooms {
|
|||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<Arc<HashSet<UserId>>> {
|
) -> Result<Arc<HashSet<Box<UserId>>>> {
|
||||||
let maybe = self
|
let maybe = self
|
||||||
.our_real_users_cache
|
.our_real_users_cache
|
||||||
.read()
|
.read()
|
||||||
@@ -2650,7 +2657,7 @@ impl Rooms {
|
|||||||
self.appservice_in_room_cache
|
self.appservice_in_room_cache
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(appservice.0.clone(), in_room);
|
.insert(appservice.0.clone(), in_room);
|
||||||
|
|
||||||
@@ -2694,7 +2701,7 @@ impl Rooms {
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
@@ -2754,7 +2761,7 @@ impl Rooms {
|
|||||||
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
.filter_map(|event| serde_json::from_str(event.json().get()).ok())
|
||||||
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
.filter_map(|event: serde_json::Value| event.get("sender").cloned())
|
||||||
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
.filter_map(|sender| sender.as_str().map(|s| s.to_owned()))
|
||||||
.filter_map(|sender| UserId::try_from(sender).ok())
|
.filter_map(|sender| UserId::parse(sender).ok())
|
||||||
.map(|user| user.server_name().to_owned())
|
.map(|user| user.server_name().to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -2778,9 +2785,7 @@ impl Rooms {
|
|||||||
let (make_leave_response, remote_server) = make_leave_response_and_server?;
|
let (make_leave_response, remote_server) = make_leave_response_and_server?;
|
||||||
|
|
||||||
let room_version_id = match make_leave_response.room_version {
|
let room_version_id = match make_leave_response.room_version {
|
||||||
Some(version)
|
Some(version) if version == RoomVersionId::V5 || version == RoomVersionId::V6 => {
|
||||||
if version == RoomVersionId::Version5 || version == RoomVersionId::Version6 =>
|
|
||||||
{
|
|
||||||
version
|
version
|
||||||
}
|
}
|
||||||
_ => return Err(Error::BadServerResponse("Room version is not supported")),
|
_ => return Err(Error::BadServerResponse("Room version is not supported")),
|
||||||
@@ -2817,7 +2822,7 @@ impl Rooms {
|
|||||||
.expect("event is valid, we just created it");
|
.expect("event is valid, we just created it");
|
||||||
|
|
||||||
// Generate event id
|
// Generate event id
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::parse(format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&leave_event_stub, &room_version_id)
|
ruma::signatures::reference_hash(&leave_event_stub, &room_version_id)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
@@ -2902,11 +2907,11 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn id_from_alias(&self, alias: &RoomAliasId) -> Result<Option<RoomId>> {
|
pub fn id_from_alias(&self, alias: &RoomAliasId) -> Result<Option<Box<RoomId>>> {
|
||||||
self.alias_roomid
|
self.alias_roomid
|
||||||
.get(alias.alias().as_bytes())?
|
.get(alias.alias().as_bytes())?
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
RoomId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
|
RoomId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("Room ID in alias_roomid is invalid unicode.")
|
Error::bad_database("Room ID in alias_roomid is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid."))
|
.map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid."))
|
||||||
@@ -2918,7 +2923,7 @@ impl Rooms {
|
|||||||
pub fn room_aliases<'a>(
|
pub fn room_aliases<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> impl Iterator<Item = Result<RoomAliasId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<RoomAliasId>>> + 'a {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
@@ -2947,9 +2952,9 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn public_rooms(&self) -> impl Iterator<Item = Result<RoomId>> + '_ {
|
pub fn public_rooms(&self) -> impl Iterator<Item = Result<Box<RoomId>>> + '_ {
|
||||||
self.publicroomids.iter().map(|(bytes, _)| {
|
self.publicroomids.iter().map(|(bytes, _)| {
|
||||||
RoomId::try_from(
|
RoomId::parse(
|
||||||
utils::string_from_bytes(&bytes).map_err(|_| {
|
utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("Room ID in publicroomids is invalid unicode.")
|
Error::bad_database("Room ID in publicroomids is invalid unicode.")
|
||||||
})?,
|
})?,
|
||||||
@@ -3009,8 +3014,8 @@ impl Rooms {
|
|||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn get_shared_rooms<'a>(
|
pub fn get_shared_rooms<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
users: Vec<UserId>,
|
users: Vec<Box<UserId>>,
|
||||||
) -> Result<impl Iterator<Item = Result<RoomId>> + 'a> {
|
) -> Result<impl Iterator<Item = Result<Box<RoomId>>> + 'a> {
|
||||||
let iterators = users.into_iter().map(move |user_id| {
|
let iterators = users.into_iter().map(move |user_id| {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
@@ -3037,7 +3042,7 @@ impl Rooms {
|
|||||||
Ok(utils::common_elements(iterators, Ord::cmp)
|
Ok(utils::common_elements(iterators, Ord::cmp)
|
||||||
.expect("users is not empty")
|
.expect("users is not empty")
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
RoomId::try_from(utils::string_from_bytes(&*bytes).map_err(|_| {
|
RoomId::parse(utils::string_from_bytes(&*bytes).map_err(|_| {
|
||||||
Error::bad_database("Invalid RoomId bytes in userroomid_joined")
|
Error::bad_database("Invalid RoomId bytes in userroomid_joined")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("Invalid RoomId in userroomid_joined."))
|
.map_err(|_| Error::bad_database("Invalid RoomId in userroomid_joined."))
|
||||||
@@ -3054,7 +3059,7 @@ impl Rooms {
|
|||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
|
self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
|
||||||
Box::<ServerName>::try_from(
|
ServerName::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3082,12 +3087,12 @@ impl Rooms {
|
|||||||
pub fn server_rooms<'a>(
|
pub fn server_rooms<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
server: &ServerName,
|
server: &ServerName,
|
||||||
) -> impl Iterator<Item = Result<RoomId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<RoomId>>> + 'a {
|
||||||
let mut prefix = server.as_bytes().to_vec();
|
let mut prefix = server.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
|
self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
|
||||||
RoomId::try_from(
|
RoomId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3104,12 +3109,12 @@ impl Rooms {
|
|||||||
pub fn room_members<'a>(
|
pub fn room_members<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> impl Iterator<Item = Result<UserId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
|
self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3150,14 +3155,14 @@ impl Rooms {
|
|||||||
pub fn room_useroncejoined<'a>(
|
pub fn room_useroncejoined<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> impl Iterator<Item = Result<UserId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.roomuseroncejoinedids
|
self.roomuseroncejoinedids
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3176,14 +3181,14 @@ impl Rooms {
|
|||||||
pub fn room_members_invited<'a>(
|
pub fn room_members_invited<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> impl Iterator<Item = Result<UserId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.roomuserid_invitecount
|
self.roomuserid_invitecount
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3232,11 +3237,11 @@ impl Rooms {
|
|||||||
pub fn rooms_joined<'a>(
|
pub fn rooms_joined<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
) -> impl Iterator<Item = Result<RoomId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<RoomId>>> + 'a {
|
||||||
self.userroomid_joined
|
self.userroomid_joined
|
||||||
.scan_prefix(user_id.as_bytes().to_vec())
|
.scan_prefix(user_id.as_bytes().to_vec())
|
||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
RoomId::try_from(
|
RoomId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3255,14 +3260,14 @@ impl Rooms {
|
|||||||
pub fn rooms_invited<'a>(
|
pub fn rooms_invited<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
) -> impl Iterator<Item = Result<(RoomId, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a {
|
) -> impl Iterator<Item = Result<(Box<RoomId>, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.userroomid_invitestate
|
self.userroomid_invitestate
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(key, state)| {
|
.map(|(key, state)| {
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
@@ -3328,14 +3333,14 @@ impl Rooms {
|
|||||||
pub fn rooms_left<'a>(
|
pub fn rooms_left<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
) -> impl Iterator<Item = Result<(RoomId, Vec<Raw<AnySyncStateEvent>>)>> + 'a {
|
) -> impl Iterator<Item = Result<(Box<RoomId>, Vec<Raw<AnySyncStateEvent>>)>> + 'a {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
self.userroomid_leftstate
|
self.userroomid_leftstate
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(key, state)| {
|
.map(|(key, state)| {
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
|
|||||||
+18
-17
@@ -11,7 +11,7 @@ use ruma::{
|
|||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::TryInto,
|
||||||
mem,
|
mem,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
@@ -76,8 +76,13 @@ impl RoomEdus {
|
|||||||
&'a self,
|
&'a self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
since: u64,
|
since: u64,
|
||||||
) -> impl Iterator<Item = Result<(UserId, u64, Raw<ruma::events::AnySyncEphemeralRoomEvent>)>> + 'a
|
) -> impl Iterator<
|
||||||
{
|
Item = Result<(
|
||||||
|
Box<UserId>,
|
||||||
|
u64,
|
||||||
|
Raw<ruma::events::AnySyncEphemeralRoomEvent>,
|
||||||
|
)>,
|
||||||
|
> + 'a {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
let prefix2 = prefix.clone();
|
let prefix2 = prefix.clone();
|
||||||
@@ -92,7 +97,7 @@ impl RoomEdus {
|
|||||||
let count =
|
let count =
|
||||||
utils::u64_from_bytes(&k[prefix.len()..prefix.len() + mem::size_of::<u64>()])
|
utils::u64_from_bytes(&k[prefix.len()..prefix.len() + mem::size_of::<u64>()])
|
||||||
.map_err(|_| Error::bad_database("Invalid readreceiptid count in db."))?;
|
.map_err(|_| Error::bad_database("Invalid readreceiptid count in db."))?;
|
||||||
let user_id = UserId::try_from(
|
let user_id = UserId::parse(
|
||||||
utils::string_from_bytes(&k[prefix.len() + mem::size_of::<u64>() + 1..])
|
utils::string_from_bytes(&k[prefix.len() + mem::size_of::<u64>() + 1..])
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::bad_database("Invalid readreceiptid userid bytes in db.")
|
Error::bad_database("Invalid readreceiptid userid bytes in db.")
|
||||||
@@ -305,17 +310,13 @@ impl RoomEdus {
|
|||||||
|
|
||||||
let mut user_ids = HashSet::new();
|
let mut user_ids = HashSet::new();
|
||||||
|
|
||||||
for user_id in self
|
for (_, user_id) in self.typingid_userid.scan_prefix(prefix) {
|
||||||
.typingid_userid
|
let user_id = UserId::parse(utils::string_from_bytes(&user_id).map_err(|_| {
|
||||||
.scan_prefix(prefix)
|
|
||||||
.map(|(_, user_id)| {
|
|
||||||
UserId::try_from(utils::string_from_bytes(&user_id).map_err(|_| {
|
|
||||||
Error::bad_database("User ID in typingid_userid is invalid unicode.")
|
Error::bad_database("User ID in typingid_userid is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("User ID in typingid_userid is invalid."))
|
.map_err(|_| Error::bad_database("User ID in typingid_userid is invalid."))?;
|
||||||
})
|
|
||||||
{
|
user_ids.insert(user_id);
|
||||||
user_ids.insert(user_id?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SyncEphemeralRoomEvent {
|
Ok(SyncEphemeralRoomEvent {
|
||||||
@@ -449,7 +450,7 @@ impl RoomEdus {
|
|||||||
{
|
{
|
||||||
// Send new presence events to set the user offline
|
// Send new presence events to set the user offline
|
||||||
let count = globals.next_count()?.to_be_bytes();
|
let count = globals.next_count()?.to_be_bytes();
|
||||||
let user_id = utils::string_from_bytes(&user_id_bytes)
|
let user_id: Box<_> = utils::string_from_bytes(&user_id_bytes)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::bad_database("Invalid UserId bytes in userid_lastpresenceupdate.")
|
Error::bad_database("Invalid UserId bytes in userid_lastpresenceupdate.")
|
||||||
})?
|
})?
|
||||||
@@ -475,7 +476,7 @@ impl RoomEdus {
|
|||||||
presence: PresenceState::Offline,
|
presence: PresenceState::Offline,
|
||||||
status_msg: None,
|
status_msg: None,
|
||||||
},
|
},
|
||||||
sender: user_id.clone(),
|
sender: user_id.to_owned(),
|
||||||
})
|
})
|
||||||
.expect("PresenceEvent can be serialized"),
|
.expect("PresenceEvent can be serialized"),
|
||||||
)?;
|
)?;
|
||||||
@@ -498,7 +499,7 @@ impl RoomEdus {
|
|||||||
since: u64,
|
since: u64,
|
||||||
_rooms: &super::Rooms,
|
_rooms: &super::Rooms,
|
||||||
_globals: &super::super::globals::Globals,
|
_globals: &super::super::globals::Globals,
|
||||||
) -> Result<HashMap<UserId, PresenceEvent>> {
|
) -> Result<HashMap<Box<UserId>, PresenceEvent>> {
|
||||||
//self.presence_maintain(rooms, globals)?;
|
//self.presence_maintain(rooms, globals)?;
|
||||||
|
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
@@ -513,7 +514,7 @@ impl RoomEdus {
|
|||||||
.iter_from(&*first_possible_edu, false)
|
.iter_from(&*first_possible_edu, false)
|
||||||
.take_while(|(key, _)| key.starts_with(&prefix))
|
.take_while(|(key, _)| key.starts_with(&prefix))
|
||||||
{
|
{
|
||||||
let user_id = UserId::try_from(
|
let user_id = UserId::parse(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::TryInto,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
@@ -397,7 +397,7 @@ impl Sending {
|
|||||||
// Because synapse resyncs, we can just insert dummy data
|
// Because synapse resyncs, we can just insert dummy data
|
||||||
let edu = Edu::DeviceListUpdate(DeviceListUpdateContent {
|
let edu = Edu::DeviceListUpdate(DeviceListUpdateContent {
|
||||||
user_id,
|
user_id,
|
||||||
device_id: device_id!("dummy"),
|
device_id: device_id!("dummy").to_owned(),
|
||||||
device_display_name: Some("Dummy".to_owned()),
|
device_display_name: Some("Dummy".to_owned()),
|
||||||
stream_id: uint!(1),
|
stream_id: uint!(1),
|
||||||
prev_id: Vec::new(),
|
prev_id: Vec::new(),
|
||||||
@@ -583,8 +583,7 @@ impl Sending {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let userid =
|
let userid = UserId::parse(utils::string_from_bytes(user).map_err(|_| {
|
||||||
UserId::try_from(utils::string_from_bytes(user).map_err(|_| {
|
|
||||||
(
|
(
|
||||||
kind.clone(),
|
kind.clone(),
|
||||||
Error::bad_database("Invalid push user string in db."),
|
Error::bad_database("Invalid push user string in db."),
|
||||||
@@ -732,7 +731,7 @@ impl Sending {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
(
|
(
|
||||||
OutgoingKind::Appservice(Box::<ServerName>::try_from(server).map_err(|_| {
|
OutgoingKind::Appservice(ServerName::parse(server).map_err(|_| {
|
||||||
Error::bad_database("Invalid server string in server_currenttransaction")
|
Error::bad_database("Invalid server string in server_currenttransaction")
|
||||||
})?),
|
})?),
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
@@ -771,7 +770,7 @@ impl Sending {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
(
|
(
|
||||||
OutgoingKind::Normal(Box::<ServerName>::try_from(server).map_err(|_| {
|
OutgoingKind::Normal(ServerName::parse(server).map_err(|_| {
|
||||||
Error::bad_database("Invalid server string in server_currenttransaction")
|
Error::bad_database("Invalid server string in server_currenttransaction")
|
||||||
})?),
|
})?),
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
|
|||||||
+95
-62
@@ -8,7 +8,12 @@ use ruma::{
|
|||||||
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt,
|
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt,
|
||||||
UserId,
|
UserId,
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeMap, convert::TryFrom, mem, sync::Arc};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
convert::{TryFrom, TryInto},
|
||||||
|
mem,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use super::abstraction::Tree;
|
use super::abstraction::Tree;
|
||||||
@@ -62,12 +67,11 @@ impl Users {
|
|||||||
rooms: &super::rooms::Rooms,
|
rooms: &super::rooms::Rooms,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let admin_room_alias_id =
|
let admin_room_alias_id = RoomAliasId::parse(format!("#admins:{}", globals.server_name()))
|
||||||
RoomAliasId::try_from(format!("#admins:{}", globals.server_name()))
|
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
||||||
let admin_room_id = rooms.id_from_alias(&admin_room_alias_id)?.unwrap();
|
let admin_room_id = rooms.id_from_alias(&admin_room_alias_id)?.unwrap();
|
||||||
|
|
||||||
Ok(rooms.is_joined(user_id, &admin_room_id)?)
|
rooms.is_joined(user_id, &admin_room_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new user account on this homeserver.
|
/// Create a new user account on this homeserver.
|
||||||
@@ -85,7 +89,7 @@ impl Users {
|
|||||||
|
|
||||||
/// Find out which user an access token belongs to.
|
/// Find out which user an access token belongs to.
|
||||||
#[tracing::instrument(skip(self, token))]
|
#[tracing::instrument(skip(self, token))]
|
||||||
pub fn find_from_token(&self, token: &str) -> Result<Option<(UserId, String)>> {
|
pub fn find_from_token(&self, token: &str) -> Result<Option<(Box<UserId>, String)>> {
|
||||||
self.token_userdeviceid
|
self.token_userdeviceid
|
||||||
.get(token.as_bytes())?
|
.get(token.as_bytes())?
|
||||||
.map_or(Ok(None), |bytes| {
|
.map_or(Ok(None), |bytes| {
|
||||||
@@ -98,7 +102,7 @@ impl Users {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Some((
|
Ok(Some((
|
||||||
UserId::try_from(utils::string_from_bytes(user_bytes).map_err(|_| {
|
UserId::parse(utils::string_from_bytes(user_bytes).map_err(|_| {
|
||||||
Error::bad_database("User ID in token_userdeviceid is invalid unicode.")
|
Error::bad_database("User ID in token_userdeviceid is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@@ -113,9 +117,9 @@ impl Users {
|
|||||||
|
|
||||||
/// Returns an iterator over all users on this homeserver.
|
/// Returns an iterator over all users on this homeserver.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = Result<UserId>> + '_ {
|
pub fn iter(&self) -> impl Iterator<Item = Result<Box<UserId>>> + '_ {
|
||||||
self.userid_password.iter().map(|(bytes, _)| {
|
self.userid_password.iter().map(|(bytes, _)| {
|
||||||
UserId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
|
UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("User ID in userid_password is invalid unicode.")
|
Error::bad_database("User ID in userid_password is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("User ID in userid_password is invalid."))
|
.map_err(|_| Error::bad_database("User ID in userid_password is invalid."))
|
||||||
@@ -181,20 +185,21 @@ impl Users {
|
|||||||
|
|
||||||
/// Get the avatar_url of a user.
|
/// Get the avatar_url of a user.
|
||||||
#[tracing::instrument(skip(self, user_id))]
|
#[tracing::instrument(skip(self, user_id))]
|
||||||
pub fn avatar_url(&self, user_id: &UserId) -> Result<Option<MxcUri>> {
|
pub fn avatar_url(&self, user_id: &UserId) -> Result<Option<Box<MxcUri>>> {
|
||||||
self.userid_avatarurl
|
self.userid_avatarurl
|
||||||
.get(user_id.as_bytes())?
|
.get(user_id.as_bytes())?
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
let s = utils::string_from_bytes(&bytes)
|
let s = utils::string_from_bytes(&bytes)
|
||||||
.map_err(|_| Error::bad_database("Avatar URL in db is invalid."))?;
|
.map_err(|_| Error::bad_database("Avatar URL in db is invalid."))?;
|
||||||
MxcUri::try_from(s).map_err(|_| Error::bad_database("Avatar URL in db is invalid."))
|
s.try_into()
|
||||||
|
.map_err(|_| Error::bad_database("Avatar URL in db is invalid."))
|
||||||
})
|
})
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a new avatar_url or removes it if avatar_url is None.
|
/// Sets a new avatar_url or removes it if avatar_url is None.
|
||||||
#[tracing::instrument(skip(self, user_id, avatar_url))]
|
#[tracing::instrument(skip(self, user_id, avatar_url))]
|
||||||
pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<MxcUri>) -> Result<()> {
|
pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<Box<MxcUri>>) -> Result<()> {
|
||||||
if let Some(avatar_url) = avatar_url {
|
if let Some(avatar_url) = avatar_url {
|
||||||
self.userid_avatarurl
|
self.userid_avatarurl
|
||||||
.insert(user_id.as_bytes(), avatar_url.to_string().as_bytes())?;
|
.insert(user_id.as_bytes(), avatar_url.to_string().as_bytes())?;
|
||||||
@@ -359,7 +364,7 @@ impl Users {
|
|||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
device_id: &DeviceId,
|
device_id: &DeviceId,
|
||||||
one_time_key_key: &DeviceKeyId,
|
one_time_key_key: &DeviceKeyId,
|
||||||
one_time_key_value: &OneTimeKey,
|
one_time_key_value: &Raw<OneTimeKey>,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
@@ -409,7 +414,7 @@ impl Users {
|
|||||||
device_id: &DeviceId,
|
device_id: &DeviceId,
|
||||||
key_algorithm: &DeviceKeyAlgorithm,
|
key_algorithm: &DeviceKeyAlgorithm,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<Option<(DeviceKeyId, OneTimeKey)>> {
|
) -> Result<Option<(Box<DeviceKeyId>, Raw<OneTimeKey>)>> {
|
||||||
let mut prefix = user_id.as_bytes().to_vec();
|
let mut prefix = user_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
prefix.extend_from_slice(device_id.as_bytes());
|
prefix.extend_from_slice(device_id.as_bytes());
|
||||||
@@ -459,7 +464,7 @@ impl Users {
|
|||||||
.scan_prefix(userdeviceid)
|
.scan_prefix(userdeviceid)
|
||||||
.map(|(bytes, _)| {
|
.map(|(bytes, _)| {
|
||||||
Ok::<_, Error>(
|
Ok::<_, Error>(
|
||||||
serde_json::from_slice::<DeviceKeyId>(
|
serde_json::from_slice::<Box<DeviceKeyId>>(
|
||||||
&*bytes.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
|
&*bytes.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
|
||||||
Error::bad_database("OneTimeKey ID in db is invalid.")
|
Error::bad_database("OneTimeKey ID in db is invalid.")
|
||||||
})?,
|
})?,
|
||||||
@@ -480,7 +485,7 @@ impl Users {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
device_id: &DeviceId,
|
device_id: &DeviceId,
|
||||||
device_keys: &DeviceKeys,
|
device_keys: &Raw<DeviceKeys>,
|
||||||
rooms: &super::rooms::Rooms,
|
rooms: &super::rooms::Rooms,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -509,9 +514,9 @@ impl Users {
|
|||||||
pub fn add_cross_signing_keys(
|
pub fn add_cross_signing_keys(
|
||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
master_key: &CrossSigningKey,
|
master_key: &Raw<CrossSigningKey>,
|
||||||
self_signing_key: &Option<CrossSigningKey>,
|
self_signing_key: &Option<Raw<CrossSigningKey>>,
|
||||||
user_signing_key: &Option<CrossSigningKey>,
|
user_signing_key: &Option<Raw<CrossSigningKey>>,
|
||||||
rooms: &super::rooms::Rooms,
|
rooms: &super::rooms::Rooms,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -521,7 +526,12 @@ impl Users {
|
|||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
// Master key
|
// Master key
|
||||||
let mut master_key_ids = master_key.keys.values();
|
let master_key_map = master_key
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid master key"))?
|
||||||
|
.keys;
|
||||||
|
let mut master_key_ids = master_key_map.values();
|
||||||
|
|
||||||
let master_key_id = master_key_ids.next().ok_or(Error::BadRequest(
|
let master_key_id = master_key_ids.next().ok_or(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Master key contained no key.",
|
"Master key contained no key.",
|
||||||
@@ -537,17 +547,21 @@ impl Users {
|
|||||||
let mut master_key_key = prefix.clone();
|
let mut master_key_key = prefix.clone();
|
||||||
master_key_key.extend_from_slice(master_key_id.as_bytes());
|
master_key_key.extend_from_slice(master_key_id.as_bytes());
|
||||||
|
|
||||||
self.keyid_key.insert(
|
self.keyid_key
|
||||||
&master_key_key,
|
.insert(&master_key_key, master_key.json().get().as_bytes())?;
|
||||||
&serde_json::to_vec(&master_key).expect("CrossSigningKey::to_vec always works"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.userid_masterkeyid
|
self.userid_masterkeyid
|
||||||
.insert(user_id.as_bytes(), &master_key_key)?;
|
.insert(user_id.as_bytes(), &master_key_key)?;
|
||||||
|
|
||||||
// Self-signing key
|
// Self-signing key
|
||||||
if let Some(self_signing_key) = self_signing_key {
|
if let Some(self_signing_key) = self_signing_key {
|
||||||
let mut self_signing_key_ids = self_signing_key.keys.values();
|
let self_signing_key_map = self_signing_key
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid self signing key")
|
||||||
|
})?
|
||||||
|
.keys;
|
||||||
|
let mut self_signing_key_ids = self_signing_key_map.values();
|
||||||
let self_signing_key_id = self_signing_key_ids.next().ok_or(Error::BadRequest(
|
let self_signing_key_id = self_signing_key_ids.next().ok_or(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Self signing key contained no key.",
|
"Self signing key contained no key.",
|
||||||
@@ -565,8 +579,7 @@ impl Users {
|
|||||||
|
|
||||||
self.keyid_key.insert(
|
self.keyid_key.insert(
|
||||||
&self_signing_key_key,
|
&self_signing_key_key,
|
||||||
&serde_json::to_vec(&self_signing_key)
|
self_signing_key.json().get().as_bytes(),
|
||||||
.expect("CrossSigningKey::to_vec always works"),
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.userid_selfsigningkeyid
|
self.userid_selfsigningkeyid
|
||||||
@@ -575,7 +588,13 @@ impl Users {
|
|||||||
|
|
||||||
// User-signing key
|
// User-signing key
|
||||||
if let Some(user_signing_key) = user_signing_key {
|
if let Some(user_signing_key) = user_signing_key {
|
||||||
let mut user_signing_key_ids = user_signing_key.keys.values();
|
let user_signing_key_map = user_signing_key
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid user signing key")
|
||||||
|
})?
|
||||||
|
.keys;
|
||||||
|
let mut user_signing_key_ids = user_signing_key_map.values();
|
||||||
let user_signing_key_id = user_signing_key_ids.next().ok_or(Error::BadRequest(
|
let user_signing_key_id = user_signing_key_ids.next().ok_or(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"User signing key contained no key.",
|
"User signing key contained no key.",
|
||||||
@@ -593,8 +612,7 @@ impl Users {
|
|||||||
|
|
||||||
self.keyid_key.insert(
|
self.keyid_key.insert(
|
||||||
&user_signing_key_key,
|
&user_signing_key_key,
|
||||||
&serde_json::to_vec(&user_signing_key)
|
user_signing_key.json().get().as_bytes(),
|
||||||
.expect("CrossSigningKey::to_vec always works"),
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.userid_usersigningkeyid
|
self.userid_usersigningkeyid
|
||||||
@@ -632,7 +650,7 @@ impl Users {
|
|||||||
.ok_or_else(|| Error::bad_database("key in keyid_key has no signatures field."))?
|
.ok_or_else(|| Error::bad_database("key in keyid_key has no signatures field."))?
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.ok_or_else(|| Error::bad_database("key in keyid_key has invalid signatures field."))?
|
.ok_or_else(|| Error::bad_database("key in keyid_key has invalid signatures field."))?
|
||||||
.entry(sender_id.clone())
|
.entry(sender_id.to_owned())
|
||||||
.or_insert_with(|| serde_json::Map::new().into());
|
.or_insert_with(|| serde_json::Map::new().into());
|
||||||
|
|
||||||
signatures
|
signatures
|
||||||
@@ -657,7 +675,7 @@ impl Users {
|
|||||||
user_or_room_id: &str,
|
user_or_room_id: &str,
|
||||||
from: u64,
|
from: u64,
|
||||||
to: Option<u64>,
|
to: Option<u64>,
|
||||||
) -> impl Iterator<Item = Result<UserId>> + 'a {
|
) -> impl Iterator<Item = Result<Box<UserId>>> + 'a {
|
||||||
let mut prefix = user_or_room_id.as_bytes().to_vec();
|
let mut prefix = user_or_room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
@@ -683,7 +701,7 @@ impl Users {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|(_, bytes)| {
|
.map(|(_, bytes)| {
|
||||||
UserId::try_from(utils::string_from_bytes(&bytes).map_err(|_| {
|
UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("User ID in devicekeychangeid_userid is invalid unicode.")
|
Error::bad_database("User ID in devicekeychangeid_userid is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("User ID in devicekeychangeid_userid is invalid."))
|
.map_err(|_| Error::bad_database("User ID in devicekeychangeid_userid is invalid."))
|
||||||
@@ -727,7 +745,7 @@ impl Users {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
device_id: &DeviceId,
|
device_id: &DeviceId,
|
||||||
) -> Result<Option<DeviceKeys>> {
|
) -> Result<Option<Raw<DeviceKeys>>> {
|
||||||
let mut key = user_id.as_bytes().to_vec();
|
let mut key = user_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(device_id.as_bytes());
|
key.extend_from_slice(device_id.as_bytes());
|
||||||
@@ -744,25 +762,19 @@ impl Users {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
allowed_signatures: F,
|
allowed_signatures: F,
|
||||||
) -> Result<Option<CrossSigningKey>> {
|
) -> Result<Option<Raw<CrossSigningKey>>> {
|
||||||
self.userid_masterkeyid
|
self.userid_masterkeyid
|
||||||
.get(user_id.as_bytes())?
|
.get(user_id.as_bytes())?
|
||||||
.map_or(Ok(None), |key| {
|
.map_or(Ok(None), |key| {
|
||||||
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
|
||||||
let mut cross_signing_key = serde_json::from_slice::<CrossSigningKey>(&bytes)
|
let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes)
|
||||||
.map_err(|_| {
|
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?;
|
||||||
Error::bad_database("CrossSigningKey in db is invalid.")
|
clean_signatures(&mut cross_signing_key, user_id, allowed_signatures)?;
|
||||||
})?;
|
|
||||||
|
|
||||||
// A user is not allowed to see signatures from users other than himself and
|
Ok(Some(Raw::from_json(
|
||||||
// the target user
|
serde_json::value::to_raw_value(&cross_signing_key)
|
||||||
cross_signing_key.signatures = cross_signing_key
|
.expect("Value to RawValue serialization"),
|
||||||
.signatures
|
)))
|
||||||
.into_iter()
|
|
||||||
.filter(|(user, _)| allowed_signatures(user))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(Some(cross_signing_key))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -772,31 +784,25 @@ impl Users {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
allowed_signatures: F,
|
allowed_signatures: F,
|
||||||
) -> Result<Option<CrossSigningKey>> {
|
) -> Result<Option<Raw<CrossSigningKey>>> {
|
||||||
self.userid_selfsigningkeyid
|
self.userid_selfsigningkeyid
|
||||||
.get(user_id.as_bytes())?
|
.get(user_id.as_bytes())?
|
||||||
.map_or(Ok(None), |key| {
|
.map_or(Ok(None), |key| {
|
||||||
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
|
||||||
let mut cross_signing_key = serde_json::from_slice::<CrossSigningKey>(&bytes)
|
let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes)
|
||||||
.map_err(|_| {
|
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?;
|
||||||
Error::bad_database("CrossSigningKey in db is invalid.")
|
clean_signatures(&mut cross_signing_key, user_id, allowed_signatures)?;
|
||||||
})?;
|
|
||||||
|
|
||||||
// A user is not allowed to see signatures from users other than himself and
|
Ok(Some(Raw::from_json(
|
||||||
// the target user
|
serde_json::value::to_raw_value(&cross_signing_key)
|
||||||
cross_signing_key.signatures = cross_signing_key
|
.expect("Value to RawValue serialization"),
|
||||||
.signatures
|
)))
|
||||||
.into_iter()
|
|
||||||
.filter(|(user, _)| user == user_id || allowed_signatures(user))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(Some(cross_signing_key))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self, user_id))]
|
#[tracing::instrument(skip(self, user_id))]
|
||||||
pub fn get_user_signing_key(&self, user_id: &UserId) -> Result<Option<CrossSigningKey>> {
|
pub fn get_user_signing_key(&self, user_id: &UserId) -> Result<Option<Raw<CrossSigningKey>>> {
|
||||||
self.userid_usersigningkeyid
|
self.userid_usersigningkeyid
|
||||||
.get(user_id.as_bytes())?
|
.get(user_id.as_bytes())?
|
||||||
.map_or(Ok(None), |key| {
|
.map_or(Ok(None), |key| {
|
||||||
@@ -991,3 +997,30 @@ impl Users {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure that a user only sees signatures from themselves and the target user
|
||||||
|
fn clean_signatures<F: Fn(&UserId) -> bool>(
|
||||||
|
cross_signing_key: &mut serde_json::Value,
|
||||||
|
user_id: &UserId,
|
||||||
|
allowed_signatures: F,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if let Some(signatures) = cross_signing_key
|
||||||
|
.get_mut("signatures")
|
||||||
|
.and_then(|v| v.as_object_mut())
|
||||||
|
{
|
||||||
|
// Don't allocate for the full size of the current signatures, but require
|
||||||
|
// at most one resize if nothing is dropped
|
||||||
|
let new_capacity = signatures.len() / 2;
|
||||||
|
for (user, signature) in
|
||||||
|
mem::replace(signatures, serde_json::Map::with_capacity(new_capacity))
|
||||||
|
{
|
||||||
|
let id = <&UserId>::try_from(user.as_str())
|
||||||
|
.map_err(|_| Error::bad_database("Invalid user ID in database."))?;
|
||||||
|
if id == user_id || allowed_signatures(id) {
|
||||||
|
signatures.insert(user, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ fn setup_rocket(config: Figment, data: Arc<RwLock<Database>>) -> rocket::Rocket<
|
|||||||
client_server::create_typing_event_route,
|
client_server::create_typing_event_route,
|
||||||
client_server::create_room_route,
|
client_server::create_room_route,
|
||||||
client_server::redact_event_route,
|
client_server::redact_event_route,
|
||||||
|
client_server::report_event_route,
|
||||||
client_server::create_alias_route,
|
client_server::create_alias_route,
|
||||||
client_server::delete_alias_route,
|
client_server::delete_alias_route,
|
||||||
client_server::get_alias_route,
|
client_server::get_alias_route,
|
||||||
|
|||||||
+19
-16
@@ -13,7 +13,7 @@ use serde_json::{
|
|||||||
json,
|
json,
|
||||||
value::{to_raw_value, RawValue as RawJsonValue},
|
value::{to_raw_value, RawValue as RawJsonValue},
|
||||||
};
|
};
|
||||||
use std::{cmp::Ordering, collections::BTreeMap, convert::TryFrom};
|
use std::{cmp::Ordering, collections::BTreeMap, convert::TryInto, sync::Arc};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
/// Content hashes of a PDU.
|
/// Content hashes of a PDU.
|
||||||
@@ -25,20 +25,20 @@ pub struct EventHash {
|
|||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize, Debug)]
|
#[derive(Clone, Deserialize, Serialize, Debug)]
|
||||||
pub struct PduEvent {
|
pub struct PduEvent {
|
||||||
pub event_id: EventId,
|
pub event_id: Arc<EventId>,
|
||||||
pub room_id: RoomId,
|
pub room_id: Box<RoomId>,
|
||||||
pub sender: UserId,
|
pub sender: Box<UserId>,
|
||||||
pub origin_server_ts: UInt,
|
pub origin_server_ts: UInt,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub kind: EventType,
|
pub kind: EventType,
|
||||||
pub content: Box<RawJsonValue>,
|
pub content: Box<RawJsonValue>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub state_key: Option<String>,
|
pub state_key: Option<String>,
|
||||||
pub prev_events: Vec<EventId>,
|
pub prev_events: Vec<Arc<EventId>>,
|
||||||
pub depth: UInt,
|
pub depth: UInt,
|
||||||
pub auth_events: Vec<EventId>,
|
pub auth_events: Vec<Arc<EventId>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub redacts: Option<EventId>,
|
pub redacts: Option<Arc<EventId>>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub unsigned: Option<Box<RawJsonValue>>,
|
pub unsigned: Option<Box<RawJsonValue>>,
|
||||||
pub hashes: EventHash,
|
pub hashes: EventHash,
|
||||||
@@ -266,7 +266,9 @@ impl PduEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl state_res::Event for PduEvent {
|
impl state_res::Event for PduEvent {
|
||||||
fn event_id(&self) -> &EventId {
|
type Id = Arc<EventId>;
|
||||||
|
|
||||||
|
fn event_id(&self) -> &Self::Id {
|
||||||
&self.event_id
|
&self.event_id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,15 +296,15 @@ impl state_res::Event for PduEvent {
|
|||||||
self.state_key.as_deref()
|
self.state_key.as_deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
|
fn prev_events(&self) -> Box<dyn DoubleEndedIterator<Item = &Self::Id> + '_> {
|
||||||
Box::new(self.prev_events.iter())
|
Box::new(self.prev_events.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auth_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
|
fn auth_events(&self) -> Box<dyn DoubleEndedIterator<Item = &Self::Id> + '_> {
|
||||||
Box::new(self.auth_events.iter())
|
Box::new(self.auth_events.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redacts(&self) -> Option<&EventId> {
|
fn redacts(&self) -> Option<&Self::Id> {
|
||||||
self.redacts.as_ref()
|
self.redacts.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,18 +333,19 @@ impl Ord for PduEvent {
|
|||||||
/// Returns a tuple of the new `EventId` and the PDU as a `BTreeMap<String, CanonicalJsonValue>`.
|
/// Returns a tuple of the new `EventId` and the PDU as a `BTreeMap<String, CanonicalJsonValue>`.
|
||||||
pub(crate) fn gen_event_id_canonical_json(
|
pub(crate) fn gen_event_id_canonical_json(
|
||||||
pdu: &RawJsonValue,
|
pdu: &RawJsonValue,
|
||||||
) -> crate::Result<(EventId, CanonicalJsonObject)> {
|
) -> crate::Result<(Box<EventId>, CanonicalJsonObject)> {
|
||||||
let value = serde_json::from_str(pdu.get()).map_err(|e| {
|
let value = serde_json::from_str(pdu.get()).map_err(|e| {
|
||||||
warn!("Error parsing incoming event {:?}: {:?}", pdu, e);
|
warn!("Error parsing incoming event {:?}: {:?}", pdu, e);
|
||||||
Error::BadServerResponse("Invalid PDU in server response")
|
Error::BadServerResponse("Invalid PDU in server response")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = format!(
|
||||||
"${}",
|
"${}",
|
||||||
// Anything higher than version3 behaves the same
|
// Anything higher than version3 behaves the same
|
||||||
ruma::signatures::reference_hash(&value, &RoomVersionId::Version6)
|
ruma::signatures::reference_hash(&value, &RoomVersionId::V6)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
))
|
)
|
||||||
|
.try_into()
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
|
|
||||||
Ok((event_id, value))
|
Ok((event_id, value))
|
||||||
@@ -356,7 +359,7 @@ pub struct PduBuilder {
|
|||||||
pub content: Box<RawJsonValue>,
|
pub content: Box<RawJsonValue>,
|
||||||
pub unsigned: Option<BTreeMap<String, serde_json::Value>>,
|
pub unsigned: Option<BTreeMap<String, serde_json::Value>>,
|
||||||
pub state_key: Option<String>,
|
pub state_key: Option<String>,
|
||||||
pub redacts: Option<EventId>,
|
pub redacts: Option<Arc<EventId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Direct conversion prevents loss of the empty `state_key` that ruma requires.
|
/// Direct conversion prevents loss of the empty `state_key` that ruma requires.
|
||||||
|
|||||||
+4
-6
@@ -20,7 +20,6 @@ use {
|
|||||||
},
|
},
|
||||||
ruma::api::{AuthScheme, IncomingRequest},
|
ruma::api::{AuthScheme, IncomingRequest},
|
||||||
std::collections::BTreeMap,
|
std::collections::BTreeMap,
|
||||||
std::convert::TryFrom,
|
|
||||||
std::io::Cursor,
|
std::io::Cursor,
|
||||||
tracing::{debug, warn},
|
tracing::{debug, warn},
|
||||||
};
|
};
|
||||||
@@ -29,7 +28,7 @@ use {
|
|||||||
/// first.
|
/// first.
|
||||||
pub struct Ruma<T: Outgoing> {
|
pub struct Ruma<T: Outgoing> {
|
||||||
pub body: T::Incoming,
|
pub body: T::Incoming,
|
||||||
pub sender_user: Option<UserId>,
|
pub sender_user: Option<Box<UserId>>,
|
||||||
pub sender_device: Option<Box<DeviceId>>,
|
pub sender_device: Option<Box<DeviceId>>,
|
||||||
pub sender_servername: Option<Box<ServerName>>,
|
pub sender_servername: Option<Box<ServerName>>,
|
||||||
// This is None when body is not a valid string
|
// This is None when body is not a valid string
|
||||||
@@ -86,7 +85,7 @@ where
|
|||||||
registration
|
registration
|
||||||
.get("as_token")
|
.get("as_token")
|
||||||
.and_then(|as_token| as_token.as_str())
|
.and_then(|as_token| as_token.as_str())
|
||||||
.map_or(false, |as_token| token.as_deref() == Some(as_token))
|
.map_or(false, |as_token| token == Some(as_token))
|
||||||
}) {
|
}) {
|
||||||
match metadata.authentication {
|
match metadata.authentication {
|
||||||
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
||||||
@@ -103,8 +102,7 @@ where
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
},
|
},
|
||||||
|string| {
|
|string| {
|
||||||
UserId::try_from(string.expect("parsing to string always works"))
|
UserId::parse(string.expect("parsing to string always works")).unwrap()
|
||||||
.unwrap()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -171,7 +169,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let origin = match Box::<ServerName>::try_from(origin_str) {
|
let origin = match ServerName::parse(origin_str) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
_ => {
|
_ => {
|
||||||
warn!(
|
warn!(
|
||||||
|
|||||||
+72
-103
@@ -64,6 +64,7 @@ use std::{
|
|||||||
future::Future,
|
future::Future,
|
||||||
mem,
|
mem,
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
|
ops::Deref,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::{Arc, RwLock, RwLockWriteGuard},
|
sync::{Arc, RwLock, RwLockWriteGuard},
|
||||||
time::{Duration, Instant, SystemTime},
|
time::{Duration, Instant, SystemTime},
|
||||||
@@ -396,10 +397,7 @@ async fn find_actual_destination(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(port) = force_port {
|
if let Some(port) = force_port {
|
||||||
FedDest::Named(
|
FedDest::Named(delegated_hostname, format!(":{}", port))
|
||||||
delegated_hostname,
|
|
||||||
format!(":{}", port.to_string()),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
add_port_to_hostname(&delegated_hostname)
|
add_port_to_hostname(&delegated_hostname)
|
||||||
}
|
}
|
||||||
@@ -432,10 +430,7 @@ async fn find_actual_destination(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(port) = force_port {
|
if let Some(port) = force_port {
|
||||||
FedDest::Named(
|
FedDest::Named(hostname.clone(), format!(":{}", port))
|
||||||
hostname.clone(),
|
|
||||||
format!(":{}", port.to_string()),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
add_port_to_hostname(&hostname)
|
add_port_to_hostname(&hostname)
|
||||||
}
|
}
|
||||||
@@ -550,11 +545,10 @@ pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> {
|
|||||||
return Json("Federation is disabled.".to_owned());
|
return Json("Federation is disabled.".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut verify_keys = BTreeMap::new();
|
let mut verify_keys: BTreeMap<Box<ServerSigningKeyId>, VerifyKey> = BTreeMap::new();
|
||||||
verify_keys.insert(
|
verify_keys.insert(
|
||||||
ServerSigningKeyId::try_from(
|
format!("ed25519:{}", db.globals.keypair().version())
|
||||||
format!("ed25519:{}", db.globals.keypair().version()).as_str(),
|
.try_into()
|
||||||
)
|
|
||||||
.expect("found invalid server signing keys in DB"),
|
.expect("found invalid server signing keys in DB"),
|
||||||
VerifyKey {
|
VerifyKey {
|
||||||
key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD),
|
key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD),
|
||||||
@@ -736,7 +730,7 @@ pub async fn send_transaction_message_route(
|
|||||||
// 0. Check the server is in the room
|
// 0. Check the server is in the room
|
||||||
let room_id = match value
|
let room_id = match value
|
||||||
.get("room_id")
|
.get("room_id")
|
||||||
.and_then(|id| RoomId::try_from(id.as_str()?).ok())
|
.and_then(|id| RoomId::parse(id.as_str()?).ok())
|
||||||
{
|
{
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => {
|
None => {
|
||||||
@@ -1001,14 +995,9 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 9. Fetch any missing prev events doing all checks listed here starting at 1. These are timeline events
|
// 9. Fetch any missing prev events doing all checks listed here starting at 1. These are timeline events
|
||||||
let mut graph = HashMap::new();
|
let mut graph: HashMap<Arc<EventId>, _> = HashMap::new();
|
||||||
let mut eventid_info = HashMap::new();
|
let mut eventid_info = HashMap::new();
|
||||||
let mut todo_outlier_stack: Vec<_> = incoming_pdu
|
let mut todo_outlier_stack: Vec<Arc<EventId>> = incoming_pdu.prev_events.clone();
|
||||||
.prev_events
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(Arc::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut amount = 0;
|
let mut amount = 0;
|
||||||
|
|
||||||
@@ -1027,7 +1016,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
if amount > 100 {
|
if amount > 100 {
|
||||||
// Max limit reached
|
// Max limit reached
|
||||||
warn!("Max prev event limit reached!");
|
warn!("Max prev event limit reached!");
|
||||||
graph.insert((*prev_event_id).clone(), HashSet::new());
|
graph.insert(prev_event_id.clone(), HashSet::new());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,27 +1027,27 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
amount += 1;
|
amount += 1;
|
||||||
for prev_prev in &pdu.prev_events {
|
for prev_prev in &pdu.prev_events {
|
||||||
if !graph.contains_key(prev_prev) {
|
if !graph.contains_key(prev_prev) {
|
||||||
todo_outlier_stack.push(dbg!(Arc::new(prev_prev.clone())));
|
todo_outlier_stack.push(dbg!(prev_prev.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.insert(
|
graph.insert(
|
||||||
(*prev_event_id).clone(),
|
prev_event_id.clone(),
|
||||||
pdu.prev_events.iter().cloned().collect(),
|
pdu.prev_events.iter().cloned().collect(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Time based check failed
|
// Time based check failed
|
||||||
graph.insert((*prev_event_id).clone(), HashSet::new());
|
graph.insert(prev_event_id.clone(), HashSet::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
eventid_info.insert(prev_event_id.clone(), (pdu, json));
|
eventid_info.insert(prev_event_id.clone(), (pdu, json));
|
||||||
} else {
|
} else {
|
||||||
// Get json failed
|
// Get json failed
|
||||||
graph.insert((*prev_event_id).clone(), HashSet::new());
|
graph.insert(prev_event_id.clone(), HashSet::new());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fetch and handle failed
|
// Fetch and handle failed
|
||||||
graph.insert((*prev_event_id).clone(), HashSet::new());
|
graph.insert(prev_event_id.clone(), HashSet::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,7 +1063,6 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
.get(event_id)
|
.get(event_id)
|
||||||
.map_or_else(|| uint!(0), |info| info.0.origin_server_ts),
|
.map_or_else(|| uint!(0), |info| info.0.origin_server_ts),
|
||||||
),
|
),
|
||||||
ruma::event_id!("$notimportant"),
|
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.map_err(|_| "Error sorting prev events".to_owned())?;
|
.map_err(|_| "Error sorting prev events".to_owned())?;
|
||||||
@@ -1084,7 +1072,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
if errors >= 5 {
|
if errors >= 5 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((pdu, json)) = eventid_info.remove(&prev_id) {
|
if let Some((pdu, json)) = eventid_info.remove(&*prev_id) {
|
||||||
if pdu.origin_server_ts < first_pdu_in_room.origin_server_ts {
|
if pdu.origin_server_ts < first_pdu_in_room.origin_server_ts {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1200,8 +1188,7 @@ fn handle_outlier_pdu<'a>(
|
|||||||
&incoming_pdu
|
&incoming_pdu
|
||||||
.auth_events
|
.auth_events
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.map(|x| Arc::from(&**x))
|
||||||
.map(Arc::new)
|
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
create_event,
|
create_event,
|
||||||
room_id,
|
room_id,
|
||||||
@@ -1331,7 +1318,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
let mut state_at_incoming_event = None;
|
let mut state_at_incoming_event = None;
|
||||||
|
|
||||||
if incoming_pdu.prev_events.len() == 1 {
|
if incoming_pdu.prev_events.len() == 1 {
|
||||||
let prev_event = &incoming_pdu.prev_events[0];
|
let prev_event = &*incoming_pdu.prev_events[0];
|
||||||
let prev_event_sstatehash = db
|
let prev_event_sstatehash = db
|
||||||
.rooms
|
.rooms
|
||||||
.pdu_shortstatehash(prev_event)
|
.pdu_shortstatehash(prev_event)
|
||||||
@@ -1353,7 +1340,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.get_or_create_shortstatekey(&prev_pdu.kind, state_key, &db.globals)
|
.get_or_create_shortstatekey(&prev_pdu.kind, state_key, &db.globals)
|
||||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||||
|
|
||||||
state.insert(shortstatekey, Arc::new(prev_event.clone()));
|
state.insert(shortstatekey, Arc::from(prev_event));
|
||||||
// Now it's the state after the pdu
|
// Now it's the state after the pdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1397,7 +1384,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.rooms
|
.rooms
|
||||||
.get_or_create_shortstatekey(&prev_event.kind, state_key, &db.globals)
|
.get_or_create_shortstatekey(&prev_event.kind, state_key, &db.globals)
|
||||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||||
leaf_state.insert(shortstatekey, Arc::new(prev_event.event_id.clone()));
|
leaf_state.insert(shortstatekey, Arc::from(&*prev_event.event_id));
|
||||||
// Now it's the state after the pdu
|
// Now it's the state after the pdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1410,14 +1397,13 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.get_statekey_from_short(k)
|
.get_statekey_from_short(k)
|
||||||
.map_err(|_| "Failed to get_statekey_from_short.".to_owned())?;
|
.map_err(|_| "Failed to get_statekey_from_short.".to_owned())?;
|
||||||
|
|
||||||
state.insert(k, (*id).clone());
|
state.insert(k, id.clone());
|
||||||
starting_events.push(id);
|
starting_events.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
auth_chain_sets.push(
|
auth_chain_sets.push(
|
||||||
get_auth_chain(room_id, starting_events, db)
|
get_auth_chain(room_id, starting_events, db)
|
||||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||||
.map(|event_id| (*event_id).clone())
|
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1444,7 +1430,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.rooms
|
.rooms
|
||||||
.get_or_create_shortstatekey(&event_type, &state_key, &db.globals)
|
.get_or_create_shortstatekey(&event_type, &state_key, &db.globals)
|
||||||
.map_err(|_| "Failed to get_or_create_shortstatekey".to_owned())?;
|
.map_err(|_| "Failed to get_or_create_shortstatekey".to_owned())?;
|
||||||
Ok((shortstatekey, Arc::new(event_id)))
|
Ok((shortstatekey, event_id))
|
||||||
})
|
})
|
||||||
.collect::<Result<_, String>>()?,
|
.collect::<Result<_, String>>()?,
|
||||||
),
|
),
|
||||||
@@ -1479,8 +1465,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
origin,
|
origin,
|
||||||
&res.pdu_ids
|
&res.pdu_ids
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.map(|x| Arc::from(&**x))
|
||||||
.map(Arc::new)
|
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
create_event,
|
create_event,
|
||||||
room_id,
|
room_id,
|
||||||
@@ -1488,7 +1473,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut state = BTreeMap::new();
|
let mut state: BTreeMap<_, Arc<EventId>> = BTreeMap::new();
|
||||||
for (pdu, _) in state_vec {
|
for (pdu, _) in state_vec {
|
||||||
let state_key = pdu
|
let state_key = pdu
|
||||||
.state_key
|
.state_key
|
||||||
@@ -1502,7 +1487,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
|
|
||||||
match state.entry(shortstatekey) {
|
match state.entry(shortstatekey) {
|
||||||
btree_map::Entry::Vacant(v) => {
|
btree_map::Entry::Vacant(v) => {
|
||||||
v.insert(Arc::new(pdu.event_id.clone()));
|
v.insert(Arc::from(&*pdu.event_id));
|
||||||
}
|
}
|
||||||
btree_map::Entry::Occupied(_) => return Err(
|
btree_map::Entry::Occupied(_) => return Err(
|
||||||
"State event's type and state_key combination exists multiple times."
|
"State event's type and state_key combination exists multiple times."
|
||||||
@@ -1577,7 +1562,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.roomid_mutex_state
|
.roomid_mutex_state
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
@@ -1647,7 +1632,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
db,
|
db,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
val,
|
val,
|
||||||
extremities,
|
extremities.iter().map(Deref::deref),
|
||||||
state_ids_compressed,
|
state_ids_compressed,
|
||||||
soft_fail,
|
soft_fail,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -1715,7 +1700,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.rooms
|
.rooms
|
||||||
.get_or_create_shortstatekey(&leaf_pdu.kind, state_key, &db.globals)
|
.get_or_create_shortstatekey(&leaf_pdu.kind, state_key, &db.globals)
|
||||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||||
leaf_state.insert(shortstatekey, Arc::new(leaf_pdu.event_id.clone()));
|
leaf_state.insert(shortstatekey, Arc::from(&*leaf_pdu.event_id));
|
||||||
// Now it's the state after the pdu
|
// Now it's the state after the pdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1730,7 +1715,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.get_or_create_shortstatekey(&incoming_pdu.kind, state_key, &db.globals)
|
.get_or_create_shortstatekey(&incoming_pdu.kind, state_key, &db.globals)
|
||||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||||
|
|
||||||
state_after.insert(shortstatekey, Arc::new(incoming_pdu.event_id.clone()));
|
state_after.insert(shortstatekey, Arc::from(&*incoming_pdu.event_id));
|
||||||
}
|
}
|
||||||
fork_states.push(state_after);
|
fork_states.push(state_after);
|
||||||
|
|
||||||
@@ -1762,7 +1747,6 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||||
.map(|event_id| (*event_id).clone())
|
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1771,11 +1755,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|map| {
|
.map(|map| {
|
||||||
map.into_iter()
|
map.into_iter()
|
||||||
.map(|(k, id)| {
|
.map(|(k, id)| db.rooms.get_statekey_from_short(k).map(|k| (k, id)))
|
||||||
db.rooms
|
|
||||||
.get_statekey_from_short(k)
|
|
||||||
.map(|k| (k, (*id).clone()))
|
|
||||||
})
|
|
||||||
.collect::<Result<StateMap<_>>>()
|
.collect::<Result<StateMap<_>>>()
|
||||||
})
|
})
|
||||||
.collect::<Result<_>>()
|
.collect::<Result<_>>()
|
||||||
@@ -1832,7 +1812,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
db,
|
db,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
val,
|
val,
|
||||||
extremities,
|
extremities.iter().map(Deref::deref),
|
||||||
state_ids_compressed,
|
state_ids_compressed,
|
||||||
soft_fail,
|
soft_fail,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -1874,7 +1854,8 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
|
|
||||||
let mut pdus = vec![];
|
let mut pdus = vec![];
|
||||||
for id in events {
|
for id in events {
|
||||||
if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(id) {
|
if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(&**id)
|
||||||
|
{
|
||||||
// Exponential backoff
|
// Exponential backoff
|
||||||
let mut min_elapsed_duration = Duration::from_secs(5 * 60) * (*tries) * (*tries);
|
let mut min_elapsed_duration = Duration::from_secs(5 * 60) * (*tries) * (*tries);
|
||||||
if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) {
|
if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) {
|
||||||
@@ -1914,7 +1895,7 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
match crate::pdu::gen_event_id_canonical_json(&res.pdu) {
|
match crate::pdu::gen_event_id_canonical_json(&res.pdu) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
back_off((**id).clone());
|
back_off((**id).to_owned());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1939,14 +1920,14 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
Ok((pdu, json)) => (pdu, Some(json)),
|
Ok((pdu, json)) => (pdu, Some(json)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Authentication of event {} failed: {:?}", id, e);
|
warn!("Authentication of event {} failed: {:?}", id, e);
|
||||||
back_off((**id).clone());
|
back_off((**id).to_owned());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Failed to fetch event: {}", id);
|
warn!("Failed to fetch event: {}", id);
|
||||||
back_off((**id).clone());
|
back_off((**id).to_owned());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2124,11 +2105,11 @@ pub(crate) async fn fetch_signing_keys(
|
|||||||
/// Append the incoming event setting the state snapshot to the state from the
|
/// Append the incoming event setting the state snapshot to the state from the
|
||||||
/// server that sent the event.
|
/// server that sent the event.
|
||||||
#[tracing::instrument(skip(db, pdu, pdu_json, new_room_leaves, state_ids_compressed, _mutex_lock))]
|
#[tracing::instrument(skip(db, pdu, pdu_json, new_room_leaves, state_ids_compressed, _mutex_lock))]
|
||||||
fn append_incoming_pdu(
|
fn append_incoming_pdu<'a>(
|
||||||
db: &Database,
|
db: &Database,
|
||||||
pdu: &PduEvent,
|
pdu: &PduEvent,
|
||||||
pdu_json: CanonicalJsonObject,
|
pdu_json: CanonicalJsonObject,
|
||||||
new_room_leaves: HashSet<EventId>,
|
new_room_leaves: impl IntoIterator<Item = &'a EventId> + Clone + Debug,
|
||||||
state_ids_compressed: HashSet<CompressedStateEvent>,
|
state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||||
soft_fail: bool,
|
soft_fail: bool,
|
||||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
|
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room mutex
|
||||||
@@ -2145,19 +2126,11 @@ fn append_incoming_pdu(
|
|||||||
if soft_fail {
|
if soft_fail {
|
||||||
db.rooms
|
db.rooms
|
||||||
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||||
db.rooms.replace_pdu_leaves(
|
db.rooms.replace_pdu_leaves(&pdu.room_id, new_room_leaves)?;
|
||||||
&pdu.room_id,
|
|
||||||
&new_room_leaves.into_iter().collect::<Vec<_>>(),
|
|
||||||
)?;
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pdu_id = db.rooms.append_pdu(
|
let pdu_id = db.rooms.append_pdu(pdu, pdu_json, new_room_leaves, db)?;
|
||||||
pdu,
|
|
||||||
pdu_json,
|
|
||||||
&new_room_leaves.into_iter().collect::<Vec<_>>(),
|
|
||||||
db,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
for appservice in db.appservice.all()? {
|
for appservice in db.appservice.all()? {
|
||||||
if db.rooms.appservice_in_room(&pdu.room_id, &appservice, db)? {
|
if db.rooms.appservice_in_room(&pdu.room_id, &appservice, db)? {
|
||||||
@@ -2298,13 +2271,13 @@ fn get_auth_chain_inner(
|
|||||||
event_id: &EventId,
|
event_id: &EventId,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<HashSet<u64>> {
|
) -> Result<HashSet<u64>> {
|
||||||
let mut todo = vec![event_id.clone()];
|
let mut todo = vec![Arc::from(event_id)];
|
||||||
let mut found = HashSet::new();
|
let mut found = HashSet::new();
|
||||||
|
|
||||||
while let Some(event_id) = todo.pop() {
|
while let Some(event_id) = todo.pop() {
|
||||||
match db.rooms.get_pdu(&event_id) {
|
match db.rooms.get_pdu(&event_id) {
|
||||||
Ok(Some(pdu)) => {
|
Ok(Some(pdu)) => {
|
||||||
if &pdu.room_id != room_id {
|
if pdu.room_id != room_id {
|
||||||
return Err(Error::BadRequest(ErrorKind::Forbidden, "Evil event in db"));
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Evil event in db"));
|
||||||
}
|
}
|
||||||
for auth_event in &pdu.auth_events {
|
for auth_event in &pdu.auth_events {
|
||||||
@@ -2363,10 +2336,10 @@ pub fn get_event_route(
|
|||||||
.and_then(|val| val.as_str())
|
.and_then(|val| val.as_str())
|
||||||
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
||||||
|
|
||||||
let room_id = RoomId::try_from(room_id_str)
|
let room_id = <&RoomId>::try_from(room_id_str)
|
||||||
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
||||||
|
|
||||||
if !db.rooms.server_in_room(sender_servername, &room_id)? {
|
if !db.rooms.server_in_room(sender_servername, room_id)? {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2417,7 +2390,7 @@ pub fn get_missing_events_route(
|
|||||||
.and_then(|val| val.as_str())
|
.and_then(|val| val.as_str())
|
||||||
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
||||||
|
|
||||||
let event_room_id = RoomId::try_from(room_id_str)
|
let event_room_id = <&RoomId>::try_from(room_id_str)
|
||||||
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
||||||
|
|
||||||
if event_room_id != body.room_id {
|
if event_room_id != body.room_id {
|
||||||
@@ -2436,7 +2409,7 @@ pub fn get_missing_events_route(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
queued_events.extend_from_slice(
|
queued_events.extend_from_slice(
|
||||||
&serde_json::from_value::<Vec<EventId>>(
|
&serde_json::from_value::<Vec<Box<EventId>>>(
|
||||||
serde_json::to_value(pdu.get("prev_events").cloned().ok_or_else(|| {
|
serde_json::to_value(pdu.get("prev_events").cloned().ok_or_else(|| {
|
||||||
Error::bad_database("Event in db has no prev_events field.")
|
Error::bad_database("Event in db has no prev_events field.")
|
||||||
})?)
|
})?)
|
||||||
@@ -2485,14 +2458,14 @@ pub fn get_event_authorization_route(
|
|||||||
.and_then(|val| val.as_str())
|
.and_then(|val| val.as_str())
|
||||||
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?;
|
||||||
|
|
||||||
let room_id = RoomId::try_from(room_id_str)
|
let room_id = <&RoomId>::try_from(room_id_str)
|
||||||
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?;
|
||||||
|
|
||||||
if !db.rooms.server_in_room(sender_servername, &room_id)? {
|
if !db.rooms.server_in_room(sender_servername, room_id)? {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
let auth_chain_ids = get_auth_chain(&room_id, vec![Arc::new(body.event_id.clone())], &db)?;
|
let auth_chain_ids = get_auth_chain(room_id, vec![Arc::from(&*body.event_id)], &db)?;
|
||||||
|
|
||||||
Ok(get_event_authorization::v1::Response {
|
Ok(get_event_authorization::v1::Response {
|
||||||
auth_chain: auth_chain_ids
|
auth_chain: auth_chain_ids
|
||||||
@@ -2550,7 +2523,7 @@ pub fn get_room_state_route(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?;
|
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::from(&*body.event_id)], &db)?;
|
||||||
|
|
||||||
Ok(get_room_state::v1::Response {
|
Ok(get_room_state::v1::Response {
|
||||||
auth_chain: auth_chain_ids
|
auth_chain: auth_chain_ids
|
||||||
@@ -2606,13 +2579,13 @@ pub fn get_room_state_ids_route(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_full_ids(shortstatehash)?
|
.state_full_ids(shortstatehash)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, id)| (*id).clone())
|
.map(|(_, id)| (*id).to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?;
|
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::from(&*body.event_id)], &db)?;
|
||||||
|
|
||||||
Ok(get_room_state_ids::v1::Response {
|
Ok(get_room_state_ids::v1::Response {
|
||||||
auth_chain_ids: auth_chain_ids.map(|id| (*id).clone()).collect(),
|
auth_chain_ids: auth_chain_ids.map(|id| (*id).to_owned()).collect(),
|
||||||
pdu_ids,
|
pdu_ids,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
@@ -2671,9 +2644,8 @@ pub fn create_join_event_template_route(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If there was no create event yet, assume we are creating a version 6 room right now
|
// If there was no create event yet, assume we are creating a version 6 room right now
|
||||||
let room_version_id = create_event_content.map_or(RoomVersionId::Version6, |create_event| {
|
let room_version_id =
|
||||||
create_event.room_version
|
create_event_content.map_or(RoomVersionId::V6, |create_event| create_event.room_version);
|
||||||
});
|
|
||||||
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||||
|
|
||||||
if !body.ver.contains(&room_version_id) {
|
if !body.ver.contains(&room_version_id) {
|
||||||
@@ -2693,6 +2665,7 @@ pub fn create_join_event_template_route(
|
|||||||
membership: MembershipState::Join,
|
membership: MembershipState::Join,
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
reason: None,
|
reason: None,
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
})
|
})
|
||||||
.expect("member event is valid value");
|
.expect("member event is valid value");
|
||||||
|
|
||||||
@@ -2721,12 +2694,12 @@ pub fn create_join_event_template_route(
|
|||||||
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
||||||
unsigned.insert(
|
unsigned.insert(
|
||||||
"prev_sender".to_owned(),
|
"prev_sender".to_owned(),
|
||||||
serde_json::from_str(prev_pdu.sender.as_str()).expect("UserId is valid string"),
|
to_raw_value(&prev_pdu.sender).expect("UserId is valid"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pdu = PduEvent {
|
let pdu = PduEvent {
|
||||||
event_id: ruma::event_id!("$thiswillbefilledinlater"),
|
event_id: ruma::event_id!("$thiswillbefilledinlater").into(),
|
||||||
room_id: body.room_id.clone(),
|
room_id: body.room_id.clone(),
|
||||||
sender: body.user_id.clone(),
|
sender: body.user_id.clone(),
|
||||||
origin_server_ts: utils::millis_since_unix_epoch()
|
origin_server_ts: utils::millis_since_unix_epoch()
|
||||||
@@ -2838,7 +2811,7 @@ async fn create_join_event(
|
|||||||
.roomid_mutex_federation
|
.roomid_mutex_federation
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.entry(room_id.clone())
|
.entry(room_id.to_owned())
|
||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let mutex_lock = mutex.lock().await;
|
let mutex_lock = mutex.lock().await;
|
||||||
@@ -2937,8 +2910,7 @@ pub async fn create_invite_route(
|
|||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if body.room_version != RoomVersionId::Version5 && body.room_version != RoomVersionId::Version6
|
if body.room_version != RoomVersionId::V5 && body.room_version != RoomVersionId::V6 {
|
||||||
{
|
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion {
|
ErrorKind::IncompatibleRoomVersion {
|
||||||
room_version: body.room_version.clone(),
|
room_version: body.room_version.clone(),
|
||||||
@@ -2959,7 +2931,7 @@ pub async fn create_invite_route(
|
|||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Failed to sign event."))?;
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Failed to sign event."))?;
|
||||||
|
|
||||||
// Generate event id
|
// Generate event id
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::parse(format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&signed_event, &body.room_version)
|
ruma::signatures::reference_hash(&signed_event, &body.room_version)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
@@ -2972,7 +2944,7 @@ pub async fn create_invite_route(
|
|||||||
CanonicalJsonValue::String(event_id.into()),
|
CanonicalJsonValue::String(event_id.into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sender = serde_json::from_value(
|
let sender: Box<_> = serde_json::from_value(
|
||||||
signed_event
|
signed_event
|
||||||
.get("sender")
|
.get("sender")
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
@@ -2984,7 +2956,7 @@ pub async fn create_invite_route(
|
|||||||
)
|
)
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "sender is not a user id."))?;
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "sender is not a user id."))?;
|
||||||
|
|
||||||
let invited_user = serde_json::from_value(
|
let invited_user: Box<_> = serde_json::from_value(
|
||||||
signed_event
|
signed_event
|
||||||
.get("state_key")
|
.get("state_key")
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
@@ -3235,7 +3207,7 @@ pub(crate) async fn fetch_required_signing_keys(
|
|||||||
|
|
||||||
let fetch_res = fetch_signing_keys(
|
let fetch_res = fetch_signing_keys(
|
||||||
db,
|
db,
|
||||||
&Box::<ServerName>::try_from(&**signature_server).map_err(|_| {
|
signature_server.as_str().try_into().map_err(|_| {
|
||||||
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
||||||
})?,
|
})?,
|
||||||
signature_ids,
|
signature_ids,
|
||||||
@@ -3263,7 +3235,7 @@ pub(crate) async fn fetch_required_signing_keys(
|
|||||||
// the PDUs and either cache the key or add it to the list that needs to be retrieved.
|
// the PDUs and either cache the key or add it to the list that needs to be retrieved.
|
||||||
fn get_server_keys_from_cache(
|
fn get_server_keys_from_cache(
|
||||||
pdu: &RawJsonValue,
|
pdu: &RawJsonValue,
|
||||||
servers: &mut BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>>,
|
servers: &mut BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>>,
|
||||||
room_version: &RoomVersionId,
|
room_version: &RoomVersionId,
|
||||||
pub_key_map: &mut RwLockWriteGuard<'_, BTreeMap<String, BTreeMap<String, String>>>,
|
pub_key_map: &mut RwLockWriteGuard<'_, BTreeMap<String, BTreeMap<String, String>>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
@@ -3273,11 +3245,12 @@ fn get_server_keys_from_cache(
|
|||||||
Error::BadServerResponse("Invalid PDU in server response")
|
Error::BadServerResponse("Invalid PDU in server response")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = format!(
|
||||||
"${}",
|
"${}",
|
||||||
ruma::signatures::reference_hash(&value, room_version)
|
ruma::signatures::reference_hash(&value, room_version)
|
||||||
.expect("ruma can calculate reference hashes")
|
.expect("ruma can calculate reference hashes")
|
||||||
))
|
);
|
||||||
|
let event_id = <&EventId>::try_from(event_id.as_str())
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
|
|
||||||
if let Some((time, tries)) = db
|
if let Some((time, tries)) = db
|
||||||
@@ -3285,7 +3258,7 @@ fn get_server_keys_from_cache(
|
|||||||
.bad_event_ratelimiter
|
.bad_event_ratelimiter
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&event_id)
|
.get(event_id)
|
||||||
{
|
{
|
||||||
// Exponential backoff
|
// Exponential backoff
|
||||||
let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries);
|
let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries);
|
||||||
@@ -3319,7 +3292,7 @@ fn get_server_keys_from_cache(
|
|||||||
let contains_all_ids =
|
let contains_all_ids =
|
||||||
|keys: &BTreeMap<String, String>| signature_ids.iter().all(|id| keys.contains_key(id));
|
|keys: &BTreeMap<String, String>| signature_ids.iter().all(|id| keys.contains_key(id));
|
||||||
|
|
||||||
let origin = &Box::<ServerName>::try_from(&**signature_server).map_err(|_| {
|
let origin = <&ServerName>::try_from(signature_server.as_str()).map_err(|_| {
|
||||||
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -3338,7 +3311,7 @@ fn get_server_keys_from_cache(
|
|||||||
|
|
||||||
if !contains_all_ids(&result) {
|
if !contains_all_ids(&result) {
|
||||||
trace!("Signing key not loaded for {}", origin);
|
trace!("Signing key not loaded for {}", origin);
|
||||||
servers.insert(origin.clone(), BTreeMap::new());
|
servers.insert(origin.to_owned(), BTreeMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub_key_map.insert(origin.to_string(), result);
|
pub_key_map.insert(origin.to_string(), result);
|
||||||
@@ -3353,7 +3326,7 @@ pub(crate) async fn fetch_join_signing_keys(
|
|||||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut servers: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>> =
|
let mut servers: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>> =
|
||||||
BTreeMap::new();
|
BTreeMap::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -3387,10 +3360,6 @@ pub(crate) async fn fetch_join_signing_keys(
|
|||||||
server,
|
server,
|
||||||
get_remote_server_keys_batch::v2::Request {
|
get_remote_server_keys_batch::v2::Request {
|
||||||
server_keys: servers.clone(),
|
server_keys: servers.clone(),
|
||||||
minimum_valid_until_ts: MilliSecondsSinceUnixEpoch::from_system_time(
|
|
||||||
SystemTime::now() + Duration::from_secs(60),
|
|
||||||
)
|
|
||||||
.expect("time is valid"),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in New Issue
Block a user