Compare commits
94
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f500565079 | ||
|
|
3b5853043f | ||
|
|
5536bfdca5 | ||
|
|
3357bbec1e | ||
|
|
102ff574ea | ||
|
|
2770ce2cf6 | ||
|
|
7cd7f1923f | ||
|
|
43d693ca19 | ||
|
|
875b345a5f | ||
|
|
17adf096e9 | ||
|
|
487601a249 | ||
|
|
27788af022 | ||
|
|
4b39d7cb64 | ||
|
|
c53d79e287 | ||
|
|
984ad5ecd6 | ||
|
|
b546a5bf15 | ||
|
|
a87519fb71 | ||
|
|
9c3f1a9272 | ||
|
|
8518d59a0b | ||
|
|
4e68c22457 | ||
|
|
73d876643c | ||
|
|
22779c21d3 | ||
|
|
8c584887c9 | ||
|
|
33738dbbc2 | ||
|
|
a6bb9bbe68 | ||
|
|
b9eb39a9c6 | ||
|
|
364820aae4 | ||
|
|
ec38411620 | ||
|
|
9ec8b7f2b3 | ||
|
|
a08ea15695 | ||
|
|
49dd3567c6 | ||
|
|
69df9a0145 | ||
|
|
d0d47675d8 | ||
|
|
bd4ea14a29 | ||
|
|
9033cc86aa | ||
|
|
1b25e78e3a | ||
|
|
d57c19802d | ||
|
|
9ded40e983 | ||
|
|
a469ca0461 | ||
|
|
632a1343eb | ||
|
|
00c9ad12bd | ||
|
|
1601027605 | ||
|
|
afca61fe7c | ||
|
|
9bff276fa9 | ||
|
|
19b89ab91f | ||
|
|
0330d3e270 | ||
|
|
a1e8a99db5 | ||
|
|
33172a70e6 | ||
|
|
1b56a7bbfd | ||
|
|
d485eb5a24 | ||
|
|
41d07be97b | ||
|
|
bef4fe50ce | ||
|
|
9152b877a7 | ||
|
|
9f8c45c763 | ||
|
|
5800e9b797 | ||
|
|
5aa56b92ee | ||
|
|
dd87066546 | ||
|
|
30b309b708 | ||
|
|
d5695fb9fe | ||
|
|
81e056417c | ||
|
|
72dd95f500 | ||
|
|
b6e755f67e | ||
|
|
4f8cf3bed4 | ||
|
|
b3ea6adc9c | ||
|
|
6d83954c40 | ||
|
|
667ffb4239 | ||
|
|
48494c9464 | ||
|
|
2ef23b213a | ||
|
|
33481ec062 | ||
|
|
3b78e43a18 | ||
|
|
4956fb9fba | ||
|
|
b09499c2df | ||
|
|
46d8a46e1f | ||
|
|
bf7e019a68 | ||
|
|
75ba8bb565 | ||
|
|
0823506d05 | ||
|
|
2c3bee34a0 | ||
|
|
a4310f840e | ||
|
|
5bd5b41c70 | ||
|
|
f9a2edc0dd | ||
|
|
ecd1e45a44 | ||
|
|
1d46569929 | ||
|
|
1e3a8ca35d | ||
|
|
0cb22996be | ||
|
|
38effda799 | ||
|
|
3cf0145bc5 | ||
|
|
3eabaa2a95 | ||
|
|
31f60ad6fd | ||
|
|
41dd620d74 | ||
|
|
9410d3ef9c | ||
|
|
665aee11c0 | ||
|
|
5173d0deb5 | ||
|
|
c2c6a8673e | ||
|
|
096e0971f1 |
+35
-73
@@ -3,7 +3,6 @@ stages:
|
|||||||
- build docker image
|
- build docker image
|
||||||
- test
|
- test
|
||||||
- upload artifacts
|
- upload artifacts
|
||||||
- publish
|
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
@@ -19,8 +18,7 @@ variables:
|
|||||||
stage: "build"
|
stage: "build"
|
||||||
needs: []
|
needs: []
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_TAG'
|
||||||
interruptible: true
|
interruptible: true
|
||||||
image: "rust:latest"
|
image: "rust:latest"
|
||||||
@@ -44,8 +42,6 @@ variables:
|
|||||||
script:
|
script:
|
||||||
- time cargo build --target $TARGET --release
|
- time cargo build --target $TARGET --release
|
||||||
- 'mv "target/$TARGET/release/conduit" "conduit-$TARGET"'
|
- 'mv "target/$TARGET/release/conduit" "conduit-$TARGET"'
|
||||||
artifacts:
|
|
||||||
expire_in: never
|
|
||||||
|
|
||||||
|
|
||||||
build:release:cargo:x86_64-unknown-linux-gnu:
|
build:release:cargo:x86_64-unknown-linux-gnu:
|
||||||
@@ -117,8 +113,6 @@ build:release:cargo:x86_64-unknown-linux-musl:
|
|||||||
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:
|
|
||||||
expire_in: 4 weeks
|
|
||||||
|
|
||||||
build:debug:cargo:x86_64-unknown-linux-gnu:
|
build:debug:cargo:x86_64-unknown-linux-gnu:
|
||||||
extends: ".cargo-debug-shared-settings"
|
extends: ".cargo-debug-shared-settings"
|
||||||
@@ -158,8 +152,7 @@ build:debug:cargo:x86_64-unknown-linux-musl:
|
|||||||
stage: "build"
|
stage: "build"
|
||||||
needs: [ ]
|
needs: [ ]
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_TAG'
|
||||||
interruptible: true
|
interruptible: true
|
||||||
image: "rust:latest"
|
image: "rust:latest"
|
||||||
@@ -194,11 +187,11 @@ build:cargo-deb:x86_64-unknown-linux-gnu:
|
|||||||
expose_as: "Debian Package x86_64"
|
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: []
|
needs: []
|
||||||
@@ -215,30 +208,8 @@ build:cargo-deb:x86_64-unknown-linux-gnu:
|
|||||||
- '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'
|
- '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:
|
# Build a docker image by packaging up the x86_64-unknown-linux-musl binary into an alpine image
|
||||||
extends: .docker-shared-settings
|
build:docker:main:
|
||||||
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:next"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:next-alpine"
|
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:commit-$CI_COMMIT_SHORT_SHA"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:next"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:next-alpine"
|
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:commit-$CI_COMMIT_SHORT_SHA"
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "next"'
|
|
||||||
|
|
||||||
|
|
||||||
build:docker:master:
|
|
||||||
extends: .docker-shared-settings
|
extends: .docker-shared-settings
|
||||||
needs:
|
needs:
|
||||||
- "build:release:cargo:x86_64-unknown-linux-musl"
|
- "build:release:cargo:x86_64-unknown-linux-musl"
|
||||||
@@ -252,31 +223,13 @@ build:docker:master:
|
|||||||
--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"
|
--dockerfile "$CI_PROJECT_DIR/docker/ci-binaries-packaging.Dockerfile"
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:latest"
|
--destination "$CI_REGISTRY_IMAGE/conduit:latest"
|
||||||
--destination "$CI_REGISTRY_IMAGE/conduit:latest-alpine"
|
--destination "$CI_REGISTRY_IMAGE/conduit:alpine"
|
||||||
|
--destination "$CI_REGISTRY_IMAGE/conduit:commit-$CI_COMMIT_SHORT_SHA"
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest"
|
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest"
|
||||||
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:latest-alpine"
|
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:alpine"
|
||||||
rules:
|
--destination "$DOCKER_HUB_IMAGE/matrixconduit/matrix-conduit:commit-$CI_COMMIT_SHORT_SHA"
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
|
||||||
|
|
||||||
|
|
||||||
build:docker:tags:
|
|
||||||
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_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_TAG'
|
||||||
|
|
||||||
|
|
||||||
@@ -341,6 +294,30 @@ test:sytest:
|
|||||||
junit: "$CI_PROJECT_DIR/sytest.xml"
|
junit: "$CI_PROJECT_DIR/sytest.xml"
|
||||||
|
|
||||||
|
|
||||||
|
test:register:element-web-stable:
|
||||||
|
stage: "test"
|
||||||
|
needs:
|
||||||
|
- "build:debug:cargo:x86_64-unknown-linux-gnu"
|
||||||
|
image: "buildkite/puppeteer:latest"
|
||||||
|
tags: [ "docker" ]
|
||||||
|
interruptible: true
|
||||||
|
script:
|
||||||
|
- "CONDUIT_CONFIG=tests/test-config.toml ./conduit-debug-x86_64-unknown-linux-gnu > conduit.log &"
|
||||||
|
- "cd tests/client-element-web/"
|
||||||
|
- "npm install puppeteer"
|
||||||
|
- "node test-element-web-registration.js \"https://app.element.io/\" \"http://localhost:6167\""
|
||||||
|
- "killall --regexp \"conduit\""
|
||||||
|
- "cd ../.."
|
||||||
|
- "cat conduit.log"
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- "tests/client-element-web/*.png"
|
||||||
|
- "*.log"
|
||||||
|
expire_in: 1 week
|
||||||
|
when: always
|
||||||
|
retry: 1
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# Store binaries as package so they have download urls #
|
# Store binaries as package so they have download urls #
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
@@ -354,8 +331,7 @@ publish:package:
|
|||||||
- "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:cargo-deb:x86_64-unknown-linux-gnu"
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
- 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"]
|
||||||
@@ -370,17 +346,3 @@ publish:package:
|
|||||||
- '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-x86_64-unknown-linux-gnu.deb "${BASE_URL}/conduit-x86_64-unknown-linux-gnu.deb"'
|
||||||
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: "publish"
|
|
||||||
image:
|
|
||||||
name: "squidfunk/mkdocs-material"
|
|
||||||
entrypoint: [""]
|
|
||||||
tags: ["docker"]
|
|
||||||
needs: []
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
|
||||||
script:
|
|
||||||
- "mkdocs build --site-dir public"
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- "public"
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Setting up Appservices
|
||||||
|
|
||||||
|
## Getting help
|
||||||
|
|
||||||
|
If you run into any problems while setting up an Appservice, 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).
|
||||||
|
|
||||||
|
## Tested appservices
|
||||||
|
|
||||||
|
Here are some appservices we tested and that work with Conduit:
|
||||||
|
- matrix-appservice-discord
|
||||||
|
- mautrix-hangouts
|
||||||
|
- mautrix-telegram
|
||||||
|
|
||||||
|
## Set up the appservice
|
||||||
|
|
||||||
|
Follow whatever instructions are given by the appservice. This usually includes
|
||||||
|
downloading, changing its config (setting domain, homeserver url, port etc.)
|
||||||
|
and later starting it.
|
||||||
|
|
||||||
|
At some point the appservice guide should ask you to add a registration yaml
|
||||||
|
file to the homeserver. In Synapse you would do this by adding the path to the
|
||||||
|
homeserver.yaml, but in Conduit you can do this from within Matrix:
|
||||||
|
|
||||||
|
First, go into the #admins room of your homeserver. The first person that
|
||||||
|
registered on the homeserver automatically joins it. Then send a message into
|
||||||
|
the room like this:
|
||||||
|
|
||||||
|
@conduit:your.server.name: register_appservice
|
||||||
|
```
|
||||||
|
paste
|
||||||
|
the
|
||||||
|
contents
|
||||||
|
of
|
||||||
|
the
|
||||||
|
yaml
|
||||||
|
registration
|
||||||
|
here
|
||||||
|
```
|
||||||
|
|
||||||
|
You can confirm it worked by sending a message like this:
|
||||||
|
`@conduit:your.server.name: list_appservices`
|
||||||
|
|
||||||
|
The @conduit bot should answer with `Appservices (1): your-bridge`
|
||||||
|
|
||||||
|
Then you are done. Conduit will send messages to the appservices and the
|
||||||
|
appservice can send requests to the homeserver. You don't need to restart
|
||||||
|
Conduit, but if it doesn't work, restarting while the appservice is running
|
||||||
|
could help.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Install docker:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt install docker
|
||||||
|
$ sudo usermod -aG docker $USER
|
||||||
|
$ exec sudo su -l $USER
|
||||||
|
$ sudo systemctl start docker
|
||||||
|
$ cargo install cross
|
||||||
|
$ cross build --release --target armv7-unknown-linux-musleabihf
|
||||||
|
```
|
||||||
|
The cross-compiled binary is at target/armv7-unknown-linux-musleabihf/release/conduit
|
||||||
Generated
+91
-25
@@ -1,7 +1,5 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler32"
|
name = "adler32"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -253,6 +251,7 @@ dependencies = [
|
|||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
"opentelemetry-jaeger",
|
"opentelemetry-jaeger",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"pretty_env_logger",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@@ -273,6 +272,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-flame",
|
"tracing-flame",
|
||||||
|
"tracing-opentelemetry",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"trust-dns-resolver",
|
"trust-dns-resolver",
|
||||||
"webpki 0.22.0",
|
"webpki 0.22.0",
|
||||||
@@ -325,9 +325,9 @@ checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.1"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
|
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -590,6 +590,19 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -942,6 +955,15 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
|
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||||
|
dependencies = [
|
||||||
|
"quick-error",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.12"
|
version = "0.14.12"
|
||||||
@@ -1607,6 +1629,16 @@ version = "0.2.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_env_logger"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -1968,7 +2000,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -1989,7 +2021,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api"
|
name = "ruma-api"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"http",
|
"http",
|
||||||
@@ -2005,7 +2037,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-api-macros"
|
name = "ruma-api-macros"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2016,7 +2048,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -2030,7 +2062,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2050,7 +2082,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2065,7 +2097,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.24.5"
|
version = "0.24.5"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2081,7 +2113,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events-macros"
|
name = "ruma-events-macros"
|
||||||
version = "0.24.5"
|
version = "0.24.5"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2092,7 +2124,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2107,7 +2139,7 @@ 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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"paste",
|
"paste",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
@@ -2121,7 +2153,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"ruma-identifiers-validation",
|
"ruma-identifiers-validation",
|
||||||
@@ -2131,12 +2163,15 @@ 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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2149,7 +2184,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
@@ -2164,7 +2199,7 @@ 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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
@@ -2178,7 +2213,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2189,7 +2224,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=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
@@ -2205,8 +2240,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-state-res"
|
name = "ruma-state-res"
|
||||||
version = "0.4.1"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/ruma/ruma?rev=a6a1224652912a957b09f136ec5da2686be6e0e2#a6a1224652912a957b09f136ec5da2686be6e0e2"
|
source = "git+https://github.com/ruma/ruma?rev=5e574319f4e19d03898471e9792bdf5f89d94b26#5e574319f4e19d03898471e9792bdf5f89d94b26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.10.1",
|
"itertools 0.10.1",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -2426,9 +2461,9 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.6"
|
version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3"
|
checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
@@ -2671,6 +2706,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.28"
|
version = "1.0.28"
|
||||||
@@ -2932,6 +2976,19 @@ dependencies = [
|
|||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-opentelemetry"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "599f388ecb26b28d9c1b2e4437ae019a7b336018b45ed911458cd9ebf91129f6"
|
||||||
|
dependencies = [
|
||||||
|
"opentelemetry",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-serde"
|
name = "tracing-serde"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -3273,6 +3330,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|||||||
+3
-1
@@ -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 = "a6a1224652912a957b09f136ec5da2686be6e0e2", 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 = "5e574319f4e19d03898471e9792bdf5f89d94b26", 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"] }
|
||||||
|
|
||||||
@@ -68,9 +68,11 @@ jsonwebtoken = "7.2.0"
|
|||||||
# Performance measurements
|
# Performance measurements
|
||||||
tracing = { version = "0.1.26", features = ["release_max_level_warn"] }
|
tracing = { version = "0.1.26", features = ["release_max_level_warn"] }
|
||||||
tracing-subscriber = "0.2.20"
|
tracing-subscriber = "0.2.20"
|
||||||
|
tracing-opentelemetry = "0.15.0"
|
||||||
tracing-flame = "0.1.0"
|
tracing-flame = "0.1.0"
|
||||||
opentelemetry = { version = "0.16.0", features = ["rt-tokio"] }
|
opentelemetry = { version = "0.16.0", features = ["rt-tokio"] }
|
||||||
opentelemetry-jaeger = { version = "0.15.0", features = ["rt-tokio"] }
|
opentelemetry-jaeger = { version = "0.15.0", features = ["rt-tokio"] }
|
||||||
|
pretty_env_logger = "0.4.0"
|
||||||
lru-cache = "0.1.2"
|
lru-cache = "0.1.2"
|
||||||
rusqlite = { version = "0.25.3", optional = true, features = ["bundled"] }
|
rusqlite = { version = "0.25.3", optional = true, features = ["bundled"] }
|
||||||
parking_lot = { version = "0.11.2", optional = true }
|
parking_lot = { version = "0.11.2", optional = true }
|
||||||
|
|||||||
@@ -162,6 +162,9 @@ AllowEncodedSlashes NoDecode
|
|||||||
ProxyPass /_matrix/ http://127.0.0.1:6167/_matrix/ nocanon
|
ProxyPass /_matrix/ http://127.0.0.1:6167/_matrix/ nocanon
|
||||||
ProxyPassReverse /_matrix/ http://127.0.0.1:6167/_matrix/
|
ProxyPassReverse /_matrix/ http://127.0.0.1:6167/_matrix/
|
||||||
|
|
||||||
|
Include /etc/letsencrypt/options-ssl-apache.conf
|
||||||
|
SSLCertificateFile /etc/letsencrypt/live/your.server.name/fullchain.pem # EDIT THIS
|
||||||
|
SSLCertificateKeyFile /etc/letsencrypt/live/your.server.name/privkey.pem # EDIT THIS
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -50,17 +50,6 @@ If you want to connect an Appservice to Conduit, take a look at [APPSERVICES.md]
|
|||||||
3. Fork the repo and work on the issue. #conduit:nordgedanken.dev is happy to help :)
|
3. Fork the repo and work on the issue. #conduit:nordgedanken.dev is happy to help :)
|
||||||
4. Submit a MR
|
4. Submit a MR
|
||||||
|
|
||||||
|
|
||||||
#### Thanks to
|
|
||||||
|
|
||||||
Thanks to Famedly, Prototype Fund (DLR and German BMBF) and all other individuals for financially supporting this project.
|
|
||||||
|
|
||||||
Thanks to the contributors to Conduit and all libraries we use, for example:
|
|
||||||
|
|
||||||
- Ruma: A clean library for the Matrix Spec in Rust
|
|
||||||
- Rocket: A flexible web framework
|
|
||||||
|
|
||||||
|
|
||||||
#### Donate
|
#### Donate
|
||||||
|
|
||||||
Liberapay: <https://liberapay.com/timokoesters/>\
|
Liberapay: <https://liberapay.com/timokoesters/>\
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
[book]
|
|
||||||
title = "Conduit Docs"
|
|
||||||
author = "The Conduit contributors"
|
|
||||||
description = "Conduit is a simple, fast and reliable chat server for the Matrix protocol"
|
|
||||||
language = "en"
|
|
||||||
src = "docs"
|
|
||||||
|
|
||||||
[rust]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[build]
|
|
||||||
build-dir = "public"
|
|
||||||
create-missing = true
|
|
||||||
|
|
||||||
[output.html.search]
|
|
||||||
limit-results = 15
|
|
||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
- "traefik.http.routers.to-conduit.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.to-conduit.tls.certresolver=letsencrypt"
|
||||||
- "traefik.http.routers.to-conduit.middlewares=cors-headers@docker"
|
- "traefik.http.routers.to-conduit.middlewares=cors-headers@docker"
|
||||||
|
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowOriginList=*"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowOrigin=*"
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS"
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ services:
|
|||||||
- "traefik.http.routers.to-matrix-wellknown.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.to-matrix-wellknown.tls.certresolver=letsencrypt"
|
||||||
- "traefik.http.routers.to-matrix-wellknown.middlewares=cors-headers@docker"
|
- "traefik.http.routers.to-matrix-wellknown.middlewares=cors-headers@docker"
|
||||||
|
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowOriginList=*"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowOrigin=*"
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowHeaders=Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
||||||
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS"
|
- "traefik.http.middlewares.cors-headers.headers.accessControlAllowMethods=GET, POST, PUT, DELETE, OPTIONS"
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
# Summary
|
|
||||||
|
|
||||||
[Home](index.md)
|
|
||||||
|
|
||||||
- [Installation](installation.md)
|
|
||||||
- [Prerequisites](installation/prerequisites.md)
|
|
||||||
- [From Binaries](installation/manual.md)
|
|
||||||
- [From Packages](installation/packages.md)
|
|
||||||
- [With Docker](installation/docker.md)
|
|
||||||
- [Configuration](configuration.md)
|
|
||||||
- [Config options](configuration/configuration.md)
|
|
||||||
- [Appservices](configuration/appservices.md)
|
|
||||||
- [Contribute](contribute.md)
|
|
||||||
- [Basics](development/basics.md)
|
|
||||||
- [Cross compilation](development/cross-compilation.md)
|
|
||||||
- [Tests & CI](development/tests-ci.md)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Configuration
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Configuring Conduit
|
|
||||||
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
# Configuring Conduit
|
|
||||||
|
|
||||||
Conduit can be configured via a config file (conventionally called Conduit.toml) or environment variables. If a config
|
|
||||||
file exists and environment variables are set, environment variables overwrite config options.
|
|
||||||
|
|
||||||
You absolutely need to set the environment variable `CONDUIT_CONFIG_FILE` to either point to a config file (
|
|
||||||
e.g. `CONDUIT_CONFIG_FILE=/etc/conduit/Conduit.toml`) or to an empty string (`CONDUIT_CONFIG_FILE=''`) if you want to
|
|
||||||
configure Conduit with just environment variables.
|
|
||||||
|
|
||||||
## Mandatory config options
|
|
||||||
|
|
||||||
Mandatory variables must be configured in order for Conduit to run properly.
|
|
||||||
|
|
||||||
### Server Name
|
|
||||||
|
|
||||||
- Config file key: `server_name`
|
|
||||||
- Envirnoment variable: `CONDUIT_SERVER_NAME`
|
|
||||||
- Default value: _None, you will need to choose your own._
|
|
||||||
|
|
||||||
The server_name is the name of this server. It is used as a suffix for user and room ids. Example: If you set it
|
|
||||||
to `conduit.rs`, your usernames will look like `@somebody:conduit.rs`.
|
|
||||||
|
|
||||||
The Conduit server needs to be reachable at https://your.server.name/ on port 443 (client-server) and 8448 (
|
|
||||||
server-server) OR you can create /.well-known files to redirect requests. See
|
|
||||||
the [Client-Server specs](https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client) and
|
|
||||||
the [Server-Server specs](https://matrix.org/docs/spec/server_server/r0.1.4#get-well-known-matrix-server) for more
|
|
||||||
information.
|
|
||||||
|
|
||||||
### Database Path
|
|
||||||
|
|
||||||
- Config file key: `database_path`
|
|
||||||
- Envirnoment variable: `CONDUIT_DATABASE_PATH`
|
|
||||||
- Default value: _None, but many people like to use `/var/lib/conduit/`_.
|
|
||||||
|
|
||||||
A **directory** where Conduit stores its database and media files. This directory must exist, have enough free space and
|
|
||||||
be readable and writable by the user Conduit is running as.
|
|
||||||
|
|
||||||
What does _enough free space_ mean? It heavily on the amount of messages your Conduit server will see and the amount and
|
|
||||||
size of media files users on your Conduit server send. As a rule of thumb, you should have at least 10 GB of free space
|
|
||||||
left. You should be comfortable for quite some time with 50 GB.
|
|
||||||
|
|
||||||
### TCP Port
|
|
||||||
|
|
||||||
- Config file key: `port`
|
|
||||||
- Environment variable: `CONDUIT_PORT`
|
|
||||||
- Default value: _None, but many people like to use `6167`_.
|
|
||||||
|
|
||||||
The TCP port Conduit will listen on for connections. The port needs to be free (no other program is listeing on it).
|
|
||||||
|
|
||||||
Conduit does currently (2021-09) not offer HTTPS by itself. Only unencrypted HTTP requests will be accepted on this
|
|
||||||
port. Unless you know what you are doing, this port should not be exposed to the internet. Instead, use a reverse proxy
|
|
||||||
capable of doing TLS to offer your Conduit server to the internet via HTTPS. See [TODO] for example configurations.
|
|
||||||
|
|
||||||
## Optional configuration options
|
|
||||||
|
|
||||||
These config options come with defaults and don't need to be configured for Conduit to run. That said, you should still
|
|
||||||
check them to make sure that your Conduit server behaves like you want it to do.
|
|
||||||
|
|
||||||
### Maximum request size
|
|
||||||
|
|
||||||
- Config file key: `max_request_size`
|
|
||||||
- Environment variable: `CONDUIT_MAX_REQUEST_SIZE`
|
|
||||||
- Default value: `20_000_000` (~= 20 MB)
|
|
||||||
|
|
||||||
The maximum size in bytes for incoming requests to Conduit. You can use underscores to improve readability.
|
|
||||||
|
|
||||||
This will effectively limit the size for images, videos and other files users on your Conduit server can send.
|
|
||||||
|
|
||||||
### Allow Registration?
|
|
||||||
|
|
||||||
- Config file key: `allow_registration`
|
|
||||||
- Environment variable: `CONDUIT_ALLOW_REGISTRATION`
|
|
||||||
- Default value: `true`
|
|
||||||
- Possible values: `true`, `false`
|
|
||||||
|
|
||||||
It this is set to `false`, no new users can register accounts on your Conduit server. Already registered users will not
|
|
||||||
be affected from this setting and can continue to user your server.
|
|
||||||
|
|
||||||
The first user to ever register on your Conduit server will be considered the admin account and is automatically invited
|
|
||||||
into the admin room.
|
|
||||||
|
|
||||||
### Allow Encryption?
|
|
||||||
|
|
||||||
- Config file key: `allow_encryption`
|
|
||||||
- Environment variable: `CONDUIT_ALLOW_ENCRYPTION`
|
|
||||||
- Default value: `true`
|
|
||||||
- Possible values: `true`, `false`
|
|
||||||
|
|
||||||
If this is set to `false`, Conduit disables the ability for users to create encrypted chats. Existing encrypted chats
|
|
||||||
may continue to work.
|
|
||||||
|
|
||||||
### Allow federation?
|
|
||||||
|
|
||||||
- Config file key: `allow_federation`
|
|
||||||
- Environment variable: `CONDUIT_ALLOW_FEDERATION`
|
|
||||||
- Default value: `false`
|
|
||||||
- Possible values: `true`, `false`
|
|
||||||
|
|
||||||
Federation means that users from different Matrix servers can chat with each other. E.g. `@mathew:matrix.org` can chat
|
|
||||||
with `@timo:conduit.rs`.
|
|
||||||
|
|
||||||
If this option is set to `false`, users on your Conduit server can only talk with other users on your Conduit server.
|
|
||||||
|
|
||||||
Federation with other servers needs to happen over HTTPS, so make sure you have set up a reverse proxy.
|
|
||||||
|
|
||||||
### Jaeger Tracing
|
|
||||||
|
|
||||||
- Config file key: `allow_jaeger`
|
|
||||||
- Environment variable: `CONDUIT_ALLOW_JAEGER`
|
|
||||||
- Default value: `false`
|
|
||||||
- Possible values: `true`, `false`
|
|
||||||
|
|
||||||
Enable Jaeger to support monitoring and troubleshooting through Jaeger.
|
|
||||||
|
|
||||||
If you don't know what Jaeger is, you can safely leave this set to `false`.
|
|
||||||
|
|
||||||
### Trusted servers
|
|
||||||
|
|
||||||
- Config file key: `trusted_servers`
|
|
||||||
- Environment variable: `CONDUIT_TRUSTED_SERVERS`
|
|
||||||
- Default value: `[]`
|
|
||||||
- Possible values: JSON-Array of server domains, e.g. `["matrix.org"]` or `["matrix.org", "conduit.rs"]`.
|
|
||||||
|
|
||||||
Matrix servers have so-called "server keys", which authenticate messages from their users. Because your Conduit server
|
|
||||||
might not know the server keys from every server it encounters, it can ask a _trusted server_ for them. This speeds
|
|
||||||
things up for rooms with people from a lot of different servers.
|
|
||||||
|
|
||||||
You should only set this to include trustworthy servers. Most people consider a good default to be `["matrix.org"]`.
|
|
||||||
|
|
||||||
Only relevant if you have federation enabled.
|
|
||||||
|
|
||||||
### Limit amount of concurrent requests
|
|
||||||
|
|
||||||
- Config file key: `max_concurrent_requests`
|
|
||||||
- Environment variable: `CONDUIT_MAX_CONCURRENT_REQUESTS`
|
|
||||||
- Default value: `100`
|
|
||||||
- Suggested values: `1` - `1000` (u16)
|
|
||||||
|
|
||||||
How many requests Conduit can make at the same time. This affects federation with other Matrix servers, push
|
|
||||||
notifications and app_services.
|
|
||||||
|
|
||||||
// TODO Timo: When does it make sense to change this?
|
|
||||||
|
|
||||||
### Configure logging
|
|
||||||
|
|
||||||
- Config file key: `log`
|
|
||||||
- Environment variable: `CONDUIT_LOG`
|
|
||||||
- Default value: `info,state_res=warn,rocket=off,_=off,sled=off`
|
|
||||||
|
|
||||||
Configures which kind of messages Conduit logs.
|
|
||||||
|
|
||||||
> // TODO: Better and more thorough explanation
|
|
||||||
|
|
||||||
### Worker threads
|
|
||||||
|
|
||||||
- Config file key: `workers`
|
|
||||||
- Environment variable: `CONDUIT_WORKERS`
|
|
||||||
- Default value: cpu core count * 2
|
|
||||||
- Possible values: // TODO
|
|
||||||
|
|
||||||
> // TODO: Which thing exactly threads? What not?
|
|
||||||
|
|
||||||
### Listening address
|
|
||||||
|
|
||||||
- Config file key: `address`
|
|
||||||
- Environment variable: `CONDUIT_ADDRESS`
|
|
||||||
- Default value: `127.0.0.1`
|
|
||||||
- Possible values: Valid IP addresses.
|
|
||||||
|
|
||||||
Which IP address conduit is listening on. 127.0.0.1 means that Conduit can only be accessed from the same server or
|
|
||||||
through a reverse proxy on that server. If you want it to be accessible from any network interface (which you should
|
|
||||||
not, because other matrix servers should talk to your Conduit via a reverse proxy and not directly), you can set it
|
|
||||||
to `0.0.0.0`.
|
|
||||||
|
|
||||||
### Database cache capacity
|
|
||||||
|
|
||||||
- Config file key: `db_cache_capacity_mb`
|
|
||||||
- Environment variable: `CONDUIT_DB_CACHE_CAPACITY_MB`
|
|
||||||
- Default value: `200`
|
|
||||||
- Possible values: `true`, `false`
|
|
||||||
|
|
||||||
The total amount of memory (RAM) that the database cache will be able to use.
|
|
||||||
|
|
||||||
> // TODO: this needs clearification: In RAM or on disk and for what exactly?
|
|
||||||
|
|
||||||
### PDU cache capacity
|
|
||||||
|
|
||||||
- Config file key: `pdu_cache_capacity`
|
|
||||||
- Environment variable: `CONDUIT_PDU_CACHE_CAPACITY`
|
|
||||||
- Default value: `100_000`
|
|
||||||
- Suggested values: `1_000` - `1_000_000` (u32)
|
|
||||||
|
|
||||||
The total capacity (read: number of items) the pdu cache can hold in memory. Setting this to a lower number may slow
|
|
||||||
Conduit down, as it must fetch more data from the database. Increasing it will mean that Conduit will start to use more
|
|
||||||
memory as the cache slowly fills up.
|
|
||||||
|
|
||||||
### SQLite WAL clean interval
|
|
||||||
|
|
||||||
- Config file key: `sqlite_wal_clean_second_interval`
|
|
||||||
- Environment variable: `CONDUIT_SQLITE_WAL_CLEAN_SECOND_INTERVAL`
|
|
||||||
- Default value: `60` (every 60 seconds)
|
|
||||||
- Suggested values: `1` - `3600` (u32)
|
|
||||||
|
|
||||||
How often the WAL file should be cleaned up. The WAL file will be written to until cleaned up, after which it restarts
|
|
||||||
writing from the beginning.
|
|
||||||
|
|
||||||
The file's size will correspond to how long it could write to it in one go. (e.g. if conduit writes 100MB of data to the
|
|
||||||
database inbetween that period, the file will grow to 100MB). You can read more about that in
|
|
||||||
the [SQLite Docs](https://www.sqlite.org/draft/wal.html).
|
|
||||||
|
|
||||||
Reducing this down too much can offset the benefits of using a WAL at all. However, having this too high can result in a
|
|
||||||
large WAL file.
|
|
||||||
|
|
||||||
Only relevant when using SQLite as the database.
|
|
||||||
|
|
||||||
### Still undocumented config options
|
|
||||||
|
|
||||||
- `tracing_flame`
|
|
||||||
- `proxy`
|
|
||||||
- `jwt_secret`
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Contribute
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Basics
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Cross compilation
|
|
||||||
|
|
||||||
Install docker:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install docker
|
|
||||||
sudo usermod -aG docker $USER
|
|
||||||
exec sudo su -l $USER
|
|
||||||
sudo systemctl start docker
|
|
||||||
cargo install cross
|
|
||||||
cross build --release --target armv7-unknown-linux-musleabihf
|
|
||||||
```
|
|
||||||
The cross-compiled binary is at target/armv7-unknown-linux-musleabihf/release/conduit
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Tests & CI
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# Conduit
|
|
||||||
|
|
||||||
Conduit is a simple, fast and reliable chat server for the [Matrix] protocol written in [Rust].
|
|
||||||
|
|
||||||
-----
|
|
||||||
> Note: This project is work-in-progress. Do *not* rely on it yet.
|
|
||||||
|
|
||||||
## What is Matrix?
|
|
||||||
|
|
||||||
[Matrix] is an open network for secure and decentralized
|
|
||||||
communication. It allows you to chat with friends even if they are using
|
|
||||||
another servers and client. You can even use bridges to communicate with users
|
|
||||||
outside of Matrix, like a community on Discord or your family on Hangouts.
|
|
||||||
|
|
||||||
## Why Conduit?
|
|
||||||
|
|
||||||
Conduit is an open-source server implementation of the [Matrix
|
|
||||||
Specification] with a focus on easy setup and low
|
|
||||||
system requirements, making it very easy to set up.
|
|
||||||
|
|
||||||
Other server implementations try to be extremely scalable, which makes sense if
|
|
||||||
the goal is to support millions of users on a single instance, but makes
|
|
||||||
smaller deployments a lot more inefficient. Conduit tries to keep it simple but
|
|
||||||
takes full advantage of that, for example by using an in-memory database for
|
|
||||||
[huge performance gains](https://github.com/timokoesters/romeo-and-juliet-benchmark).
|
|
||||||
|
|
||||||
The future for Conduit in peer-to-peer Matrix (every client contains a server)
|
|
||||||
is also bright.
|
|
||||||
|
|
||||||
Conduit tries to be reliable by using the Rust programming language and paying
|
|
||||||
close attention to error handling to make sure that evil clients, misbehaving
|
|
||||||
servers or even a partially broken database will not cause the whole server to
|
|
||||||
stop working.
|
|
||||||
|
|
||||||
## Chat with us!
|
|
||||||
|
|
||||||
We have a room on Matrix: [#conduit:matrix.org](https://matrix.to/#/#conduit:matrix.org)
|
|
||||||
|
|
||||||
You can also contact us using:
|
|
||||||
- Matrix: [@timo:koesters.xyz](https://matrix.to/#/@timo:koesters.xyz)
|
|
||||||
- Email: [conduit@koesters.xyz](mailto:conduit@koesters.xyz)
|
|
||||||
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
Liberapay: <https://liberapay.com/timokoesters/>\
|
|
||||||
Bitcoin: `bc1qnnykf986tw49ur7wx9rpw2tevpsztvar5x8w4n`
|
|
||||||
|
|
||||||
|
|
||||||
[Matrix]: https://matrix.org/
|
|
||||||
[Rust]: https://rust-lang.org
|
|
||||||
[Matrix Specification]: https://matrix.org/docs/spec
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Installation
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
:::warning Test
|
|
||||||
:::
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Distribution packages
|
|
||||||
|
|
||||||
## Debian / Ubuntu
|
|
||||||
|
|
||||||
[@paul:luon.net](https://matrix.to/#/@paul:luon.net) plans to package Conduit for Debian as soon as it reaches 1.0.
|
|
||||||
Until it is available in the official repos, you can install the development version of it manually:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt-get install ca-certificates
|
|
||||||
wget --https-only -O /tmp/conduit.deb https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/conduit-x86_64-unknown-linux-gnu.deb?job=build:cargo-deb:x86_64-unknown-linux-gnu
|
|
||||||
sudo dpkg -i /tmp/conduit.deb
|
|
||||||
```
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Prerequisites for running Conduit
|
|
||||||
|
|
||||||
You'll need:
|
|
||||||
|
|
||||||
- A domain. Commonly cost about $10/year.
|
|
||||||
- A Linux server with a stable internet connection, at least 500 MB of RAM and some disk space for messages and
|
|
||||||
attachments. Commonly start at $5/month.
|
|
||||||
- Some basic knowledge about using a shell, SSH and configuring and protecting a server.
|
|
||||||
|
|
||||||
|
|
||||||
## A word of caution:
|
|
||||||
|
|
||||||
Don't underestimate the toll of administrating your own server.
|
|
||||||
Conduit can't protect your conversations if your server gets compromised or deleted.
|
|
||||||
|
|
||||||
Make sure that you got:
|
|
||||||
|
|
||||||
- Automatic security updates
|
|
||||||
- On Ubuntu/Debian: Set up unattended-upgrades
|
|
||||||
- On RHEL/CentOS: Have a look at yum-cron
|
|
||||||
- A firewall blocking all but the needed incoming ports
|
|
||||||
- ufw is an easy interface for the linux firewall
|
|
||||||
- Protection against automatic attacks
|
|
||||||
- fail2ban scans logs and bans IPs which try to brute force their way into your server.
|
|
||||||
- Disable ssh login for root and switch from password to key based authentication.
|
|
||||||
- Automated backups
|
|
||||||
- Most VPS hosting companies offer whole server backups for a small fee.
|
|
||||||
- Or run your own backup with something like borg.
|
|
||||||
- A way to get notified if your disk fills up.
|
|
||||||
- If you send too much cat videos to your friends, Conduit might at some point become unable to
|
|
||||||
store any important messages.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# About Matrix Homeservers
|
|
||||||
|
|
||||||
Matrix homeservers manage its users chats. Every Matrix username includes the homserver it belongs to:
|
|
||||||
`@alice:matrix.org` means that the `matrix.org` homeserver hosts a user called `@alice`.
|
|
||||||
Every time someone chats with Alice, the `matrix.org` homeserver stores these messages.
|
|
||||||
When `@alice:matrix.org` talks with `@adelaide:matrix.org`, that's easy. Both users use the same server.
|
|
||||||
|
|
||||||
But how can `@bob:vector.tld`, who uses the `vector.tld` homeserver, exchange messages with `@alice:matrix.org`?
|
|
||||||
This is where it get's a bit more complicated.
|
|
||||||
|
|
||||||
## Matrix Homeserver discovery
|
|
||||||
|
|
||||||
The Matrix specification specifies multiple ways how servers can discover and then talk to each other.
|
|
||||||
Let's look at the most common one:
|
|
||||||
|
|
||||||
### .well-known files
|
|
||||||
|
|
||||||
At first, the only information a server has about a user (e.g. `@bob:vector.tld`) is its homeserver name: `vector.tld`.
|
|
||||||
It then makes a HTTP GET request to `https://vector.tld/.well-known/matrix/server`.
|
|
||||||
In the ideal case, this file contains a content like this:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"m.server": "matrix.vector.tld:443"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This translates to: The matrix homeserver software for users with a username ending on `vector.tld`
|
|
||||||
can be found at the address `matrix.vector.tld` at port 443 (which is the common port for HTTPS).
|
|
||||||
|
|
||||||
The homeserver on it's quest to find `@bob:vector.tld` now contacts `matrix.vector.tld:443` and is then
|
|
||||||
able to exchange chat messages with it.
|
|
||||||
|
|
||||||
|
|
||||||
### Why so complicated?
|
|
||||||
|
|
||||||
Organizations often don't want to run their Matrix server on the same machine that hosts their website,
|
|
||||||
but `@foo:matrix.evil.corp` usernames are ugly and everyone wants to be `@foo:evil.corp`.
|
|
||||||
|
|
||||||
To solve that problem, Matrix implements this extra step via a .well-known file or a DNS entry.
|
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
site_name: Conduit Docs
|
|
||||||
site_description: Conduit is a simple, fast and reliable chat server for the Matrix protocol
|
|
||||||
theme:
|
|
||||||
name: material
|
|
||||||
repo_url: https://gitlab.com/famedly/conduit
|
|
||||||
nav:
|
|
||||||
- Home: index.md
|
|
||||||
- Installation:
|
|
||||||
- Prerequisites: installation/prerequisites.md
|
|
||||||
- Distribution Packages: installation/packages.md
|
|
||||||
- Manual: installation/manual.md
|
|
||||||
- Docker: installation/docker.md
|
|
||||||
- Configuration:
|
|
||||||
- Conduit.toml: configuration/conduit.toml.md
|
|
||||||
- Appservices: configuration/appservices.md
|
|
||||||
- Development:
|
|
||||||
- Basics: development/basics.md
|
|
||||||
- Cross compilation: development/cross-compilation.md
|
|
||||||
- Tests & CI: development/tests-ci.md
|
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ where
|
|||||||
let hs_token = registration.get("hs_token").unwrap().as_str().unwrap();
|
let hs_token = registration.get("hs_token").unwrap().as_str().unwrap();
|
||||||
|
|
||||||
let mut http_request = request
|
let mut http_request = request
|
||||||
.try_into_http_request::<BytesMut>(destination, SendAccessToken::IfRequired(""))
|
.try_into_http_request::<BytesMut>(&destination, SendAccessToken::IfRequired(""))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|body| body.freeze());
|
.map(|body| body.freeze());
|
||||||
|
|
||||||
|
|||||||
@@ -572,7 +572,7 @@ pub async fn change_password_route(
|
|||||||
|
|
||||||
if let Some(auth) = &body.auth {
|
if let Some(auth) = &body.auth {
|
||||||
let (worked, uiaainfo) = db.uiaa.try_auth(
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
sender_user,
|
&sender_user,
|
||||||
sender_device,
|
sender_device,
|
||||||
auth,
|
auth,
|
||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
@@ -586,24 +586,24 @@ pub async fn change_password_route(
|
|||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
db.uiaa
|
db.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
}
|
}
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
.set_password(sender_user, Some(&body.new_password))?;
|
.set_password(&sender_user, Some(&body.new_password))?;
|
||||||
|
|
||||||
if body.logout_devices {
|
if body.logout_devices {
|
||||||
// Logout all devices except the current one
|
// Logout all devices except the current one
|
||||||
for id in db
|
for id in db
|
||||||
.users
|
.users
|
||||||
.all_device_ids(sender_user)
|
.all_device_ids(&sender_user)
|
||||||
.filter_map(|id| id.ok())
|
.filter_map(|id| id.ok())
|
||||||
.filter(|id| id != sender_device)
|
.filter(|id| id != sender_device)
|
||||||
{
|
{
|
||||||
db.users.remove_device(sender_user, &id)?;
|
db.users.remove_device(&sender_user, &id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,8 +664,8 @@ pub async fn deactivate_route(
|
|||||||
|
|
||||||
if let Some(auth) = &body.auth {
|
if let Some(auth) = &body.auth {
|
||||||
let (worked, uiaainfo) = db.uiaa.try_auth(
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
sender_user,
|
&sender_user,
|
||||||
sender_device,
|
&sender_device,
|
||||||
auth,
|
auth,
|
||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
&db.users,
|
&db.users,
|
||||||
@@ -678,7 +678,7 @@ pub async fn deactivate_route(
|
|||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
db.uiaa
|
db.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
@@ -688,10 +688,10 @@ pub async fn deactivate_route(
|
|||||||
// TODO: work over federation invites
|
// TODO: work over federation invites
|
||||||
let all_rooms = db
|
let all_rooms = db
|
||||||
.rooms
|
.rooms
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(&sender_user)
|
||||||
.chain(
|
.chain(
|
||||||
db.rooms
|
db.rooms
|
||||||
.rooms_invited(sender_user)
|
.rooms_invited(&sender_user)
|
||||||
.map(|t| t.map(|(r, _)| r)),
|
.map(|t| t.map(|(r, _)| r)),
|
||||||
)
|
)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@@ -726,7 +726,7 @@ pub async fn deactivate_route(
|
|||||||
state_key: Some(sender_user.to_string()),
|
state_key: Some(sender_user.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -734,7 +734,7 @@ pub async fn deactivate_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove devices and mark account as deactivated
|
// Remove devices and mark account as deactivated
|
||||||
db.users.deactivate_account(sender_user)?;
|
db.users.deactivate_account(&sender_user)?;
|
||||||
|
|
||||||
info!("{} deactivated their account", sender_user);
|
info!("{} deactivated their account", sender_user);
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ pub(crate) async fn get_alias_helper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut room_id = None;
|
let mut room_id = None;
|
||||||
match db.rooms.id_from_alias(room_alias)? {
|
match db.rooms.id_from_alias(&room_alias)? {
|
||||||
Some(r) => room_id = Some(r),
|
Some(r) => room_id = Some(r),
|
||||||
None => {
|
None => {
|
||||||
for (_id, registration) in db.appservice.all()? {
|
for (_id, registration) in db.appservice.all()? {
|
||||||
@@ -140,7 +140,7 @@ pub(crate) async fn get_alias_helper(
|
|||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
room_id = Some(db.rooms.id_from_alias(room_alias)?.ok_or_else(|| {
|
room_id = Some(db.rooms.id_from_alias(&room_alias)?.ok_or_else(|| {
|
||||||
Error::bad_config("Appservice lied to us. Room does not exist.")
|
Error::bad_config("Appservice lied to us. Room does not exist.")
|
||||||
})?);
|
})?);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+20
-19
@@ -27,7 +27,7 @@ pub async fn create_backup_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 version = db
|
let version = db
|
||||||
.key_backups
|
.key_backups
|
||||||
.create_backup(sender_user, &body.algorithm, &db.globals)?;
|
.create_backup(&sender_user, &body.algorithm, &db.globals)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ pub async fn update_backup_route(
|
|||||||
) -> ConduitResult<update_backup::Response> {
|
) -> ConduitResult<update_backup::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");
|
||||||
db.key_backups
|
db.key_backups
|
||||||
.update_backup(sender_user, &body.version, &body.algorithm, &db.globals)?;
|
.update_backup(&sender_user, &body.version, &body.algorithm, &db.globals)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ pub async fn get_latest_backup_route(
|
|||||||
|
|
||||||
let (version, algorithm) =
|
let (version, algorithm) =
|
||||||
db.key_backups
|
db.key_backups
|
||||||
.get_latest_backup(sender_user)?
|
.get_latest_backup(&sender_user)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"Key backup does not exist.",
|
"Key backup does not exist.",
|
||||||
@@ -101,7 +101,7 @@ pub async fn get_backup_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 algorithm = db
|
let algorithm = db
|
||||||
.key_backups
|
.key_backups
|
||||||
.get_backup(sender_user, &body.version)?
|
.get_backup(&sender_user, &body.version)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"Key backup does not exist.",
|
"Key backup does not exist.",
|
||||||
@@ -132,7 +132,7 @@ pub async fn delete_backup_route(
|
|||||||
) -> ConduitResult<delete_backup::Response> {
|
) -> ConduitResult<delete_backup::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");
|
||||||
|
|
||||||
db.key_backups.delete_backup(sender_user, &body.version)?;
|
db.key_backups.delete_backup(&sender_user, &body.version)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -172,11 +172,11 @@ pub async fn add_backup_keys_route(
|
|||||||
for (room_id, room) in &body.rooms {
|
for (room_id, room) in &body.rooms {
|
||||||
for (session_id, key_data) in &room.sessions {
|
for (session_id, key_data) in &room.sessions {
|
||||||
db.key_backups.add_key(
|
db.key_backups.add_key(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.version,
|
&body.version,
|
||||||
room_id,
|
&room_id,
|
||||||
session_id,
|
&session_id,
|
||||||
key_data,
|
&key_data,
|
||||||
&db.globals,
|
&db.globals,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
@@ -223,11 +223,11 @@ pub async fn add_backup_key_sessions_route(
|
|||||||
|
|
||||||
for (session_id, key_data) in &body.sessions {
|
for (session_id, key_data) in &body.sessions {
|
||||||
db.key_backups.add_key(
|
db.key_backups.add_key(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.version,
|
&body.version,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
session_id,
|
&session_id,
|
||||||
key_data,
|
&key_data,
|
||||||
&db.globals,
|
&db.globals,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ pub async fn add_backup_key_session_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
db.key_backups.add_key(
|
db.key_backups.add_key(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.version,
|
&body.version,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&body.session_id,
|
&body.session_id,
|
||||||
@@ -303,7 +303,7 @@ pub async fn get_backup_keys_route(
|
|||||||
) -> ConduitResult<get_backup_keys::Response> {
|
) -> ConduitResult<get_backup_keys::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 rooms = db.key_backups.get_all(sender_user, &body.version)?;
|
let rooms = db.key_backups.get_all(&sender_user, &body.version)?;
|
||||||
|
|
||||||
Ok(get_backup_keys::Response { rooms }.into())
|
Ok(get_backup_keys::Response { rooms }.into())
|
||||||
}
|
}
|
||||||
@@ -324,7 +324,7 @@ pub async fn get_backup_key_sessions_route(
|
|||||||
|
|
||||||
let sessions = db
|
let sessions = db
|
||||||
.key_backups
|
.key_backups
|
||||||
.get_room(sender_user, &body.version, &body.room_id)?;
|
.get_room(&sender_user, &body.version, &body.room_id)?;
|
||||||
|
|
||||||
Ok(get_backup_key_sessions::Response { sessions }.into())
|
Ok(get_backup_key_sessions::Response { sessions }.into())
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ pub async fn get_backup_key_session_route(
|
|||||||
|
|
||||||
let key_data = db
|
let key_data = db
|
||||||
.key_backups
|
.key_backups
|
||||||
.get_session(sender_user, &body.version, &body.room_id, &body.session_id)?
|
.get_session(&sender_user, &body.version, &body.room_id, &body.session_id)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"Backup key not found for this user's session.",
|
"Backup key not found for this user's session.",
|
||||||
@@ -368,7 +368,8 @@ pub async fn delete_backup_keys_route(
|
|||||||
) -> ConduitResult<delete_backup_keys::Response> {
|
) -> ConduitResult<delete_backup_keys::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");
|
||||||
|
|
||||||
db.key_backups.delete_all_keys(sender_user, &body.version)?;
|
db.key_backups
|
||||||
|
.delete_all_keys(&sender_user, &body.version)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -394,7 +395,7 @@ pub async fn delete_backup_key_sessions_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");
|
||||||
|
|
||||||
db.key_backups
|
db.key_backups
|
||||||
.delete_room_keys(sender_user, &body.version, &body.room_id)?;
|
.delete_room_keys(&sender_user, &body.version, &body.room_id)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -420,7 +421,7 @@ pub async fn delete_backup_key_session_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");
|
||||||
|
|
||||||
db.key_backups
|
db.key_backups
|
||||||
.delete_room_key(sender_user, &body.version, &body.room_id, &body.session_id)?;
|
.delete_room_key(&sender_user, &body.version, &body.room_id, &body.session_id)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{ConduitResult, Ruma};
|
use crate::ConduitResult;
|
||||||
|
use crate::Ruma;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::r0::capabilities::{
|
api::client::r0::capabilities::{
|
||||||
get_capabilities, Capabilities, RoomVersionStability, RoomVersionsCapability,
|
get_capabilities, Capabilities, RoomVersionStability, RoomVersionsCapability,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub async fn get_context_route(
|
|||||||
|
|
||||||
let events_before = db
|
let events_before = db
|
||||||
.rooms
|
.rooms
|
||||||
.pdus_until(sender_user, &body.room_id, base_token)?
|
.pdus_until(&sender_user, &body.room_id, base_token)?
|
||||||
.take(
|
.take(
|
||||||
u32::try_from(body.limit).map_err(|_| {
|
u32::try_from(body.limit).map_err(|_| {
|
||||||
Error::BadRequest(ErrorKind::InvalidParam, "Limit value is invalid.")
|
Error::BadRequest(ErrorKind::InvalidParam, "Limit value is invalid.")
|
||||||
@@ -72,7 +72,7 @@ pub async fn get_context_route(
|
|||||||
|
|
||||||
let events_after = db
|
let events_after = db
|
||||||
.rooms
|
.rooms
|
||||||
.pdus_after(sender_user, &body.room_id, base_token)?
|
.pdus_after(&sender_user, &body.room_id, base_token)?
|
||||||
.take(
|
.take(
|
||||||
u32::try_from(body.limit).map_err(|_| {
|
u32::try_from(body.limit).map_err(|_| {
|
||||||
Error::BadRequest(ErrorKind::InvalidParam, "Limit value is invalid.")
|
Error::BadRequest(ErrorKind::InvalidParam, "Limit value is invalid.")
|
||||||
|
|||||||
+11
-11
@@ -50,7 +50,7 @@ pub async fn get_device_route(
|
|||||||
|
|
||||||
let device = db
|
let device = db
|
||||||
.users
|
.users
|
||||||
.get_device_metadata(sender_user, &body.body.device_id)?
|
.get_device_metadata(&sender_user, &body.body.device_id)?
|
||||||
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
||||||
|
|
||||||
Ok(get_device::Response { device }.into())
|
Ok(get_device::Response { device }.into())
|
||||||
@@ -72,13 +72,13 @@ pub async fn update_device_route(
|
|||||||
|
|
||||||
let mut device = db
|
let mut device = db
|
||||||
.users
|
.users
|
||||||
.get_device_metadata(sender_user, &body.device_id)?
|
.get_device_metadata(&sender_user, &body.device_id)?
|
||||||
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
||||||
|
|
||||||
device.display_name = body.display_name.clone();
|
device.display_name = body.display_name.clone();
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
.update_device_metadata(sender_user, &body.device_id, &device)?;
|
.update_device_metadata(&sender_user, &body.device_id, &device)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -119,8 +119,8 @@ pub async fn delete_device_route(
|
|||||||
|
|
||||||
if let Some(auth) = &body.auth {
|
if let Some(auth) = &body.auth {
|
||||||
let (worked, uiaainfo) = db.uiaa.try_auth(
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
sender_user,
|
&sender_user,
|
||||||
sender_device,
|
&sender_device,
|
||||||
auth,
|
auth,
|
||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
&db.users,
|
&db.users,
|
||||||
@@ -133,13 +133,13 @@ pub async fn delete_device_route(
|
|||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
db.uiaa
|
db.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
}
|
}
|
||||||
|
|
||||||
db.users.remove_device(sender_user, &body.device_id)?;
|
db.users.remove_device(&sender_user, &body.device_id)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -182,8 +182,8 @@ pub async fn delete_devices_route(
|
|||||||
|
|
||||||
if let Some(auth) = &body.auth {
|
if let Some(auth) = &body.auth {
|
||||||
let (worked, uiaainfo) = db.uiaa.try_auth(
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
sender_user,
|
&sender_user,
|
||||||
sender_device,
|
&sender_device,
|
||||||
auth,
|
auth,
|
||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
&db.users,
|
&db.users,
|
||||||
@@ -196,14 +196,14 @@ pub async fn delete_devices_route(
|
|||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
db.uiaa
|
db.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
}
|
}
|
||||||
|
|
||||||
for device_id in &body.devices {
|
for device_id in &body.devices {
|
||||||
db.users.remove_device(sender_user, device_id)?
|
db.users.remove_device(&sender_user, &device_id)?
|
||||||
}
|
}
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|||||||
@@ -158,8 +158,8 @@ pub async fn upload_signing_keys_route(
|
|||||||
|
|
||||||
if let Some(auth) = &body.auth {
|
if let Some(auth) = &body.auth {
|
||||||
let (worked, uiaainfo) = db.uiaa.try_auth(
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
sender_user,
|
&sender_user,
|
||||||
sender_device,
|
&sender_device,
|
||||||
auth,
|
auth,
|
||||||
&uiaainfo,
|
&uiaainfo,
|
||||||
&db.users,
|
&db.users,
|
||||||
@@ -172,7 +172,7 @@ pub async fn upload_signing_keys_route(
|
|||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
db.uiaa
|
db.uiaa
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
@@ -181,7 +181,7 @@ pub async fn upload_signing_keys_route(
|
|||||||
if let Some(master_key) = &body.master_key {
|
if let Some(master_key) = &body.master_key {
|
||||||
db.users.add_cross_signing_keys(
|
db.users.add_cross_signing_keys(
|
||||||
sender_user,
|
sender_user,
|
||||||
master_key,
|
&master_key,
|
||||||
&body.self_signing_key,
|
&body.self_signing_key,
|
||||||
&body.user_signing_key,
|
&body.user_signing_key,
|
||||||
&db.rooms,
|
&db.rooms,
|
||||||
@@ -242,10 +242,10 @@ pub async fn upload_signatures_route(
|
|||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
db.users.sign_key(
|
db.users.sign_key(
|
||||||
user_id,
|
&user_id,
|
||||||
key_id,
|
&key_id,
|
||||||
signature,
|
signature,
|
||||||
sender_user,
|
&sender_user,
|
||||||
&db.rooms,
|
&db.rooms,
|
||||||
&db.globals,
|
&db.globals,
|
||||||
)?;
|
)?;
|
||||||
@@ -359,8 +359,8 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
|||||||
} 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.clone(), &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,
|
||||||
"Tried to get keys for nonexistent device.",
|
"Tried to get keys for nonexistent device.",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
database::{media::FileMeta, DatabaseGuard},
|
database::media::FileMeta, database::DatabaseGuard, utils, ConduitResult, Error, Ruma,
|
||||||
utils, ConduitResult, Error, Ruma,
|
|
||||||
};
|
};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ pub async fn join_room_by_id_route(
|
|||||||
|
|
||||||
let mut servers = db
|
let mut servers = db
|
||||||
.rooms
|
.rooms
|
||||||
.invite_state(sender_user, &body.room_id)?
|
.invite_state(&sender_user, &body.room_id)?
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|event| {
|
.filter_map(|event| {
|
||||||
@@ -105,7 +105,7 @@ pub async fn join_room_by_id_or_alias_route(
|
|||||||
Ok(room_id) => {
|
Ok(room_id) => {
|
||||||
let mut servers = db
|
let mut servers = db
|
||||||
.rooms
|
.rooms
|
||||||
.invite_state(sender_user, &room_id)?
|
.invite_state(&sender_user, &room_id)?
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|event| {
|
.filter_map(|event| {
|
||||||
@@ -243,7 +243,7 @@ pub async fn kick_user_route(
|
|||||||
state_key: Some(body.user_id.to_string()),
|
state_key: Some(body.user_id.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -319,7 +319,7 @@ pub async fn ban_user_route(
|
|||||||
state_key: Some(body.user_id.to_string()),
|
state_key: Some(body.user_id.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -384,7 +384,7 @@ pub async fn unban_user_route(
|
|||||||
state_key: Some(body.user_id.to_string()),
|
state_key: Some(body.user_id.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -416,7 +416,7 @@ pub async fn forget_room_route(
|
|||||||
) -> ConduitResult<forget_room::Response> {
|
) -> ConduitResult<forget_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");
|
||||||
|
|
||||||
db.rooms.forget(&body.room_id, sender_user)?;
|
db.rooms.forget(&body.room_id, &sender_user)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ pub async fn joined_rooms_route(
|
|||||||
Ok(joined_rooms::Response {
|
Ok(joined_rooms::Response {
|
||||||
joined_rooms: db
|
joined_rooms: db
|
||||||
.rooms
|
.rooms
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(&sender_user)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
@@ -500,7 +500,7 @@ pub async fn joined_members_route(
|
|||||||
) -> ConduitResult<joined_members::Response> {
|
) -> ConduitResult<joined_members::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 !db.rooms.is_joined(sender_user, &body.room_id)? {
|
if !db.rooms.is_joined(&sender_user, &body.room_id)? {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::Forbidden,
|
ErrorKind::Forbidden,
|
||||||
"You aren't a member of the room.",
|
"You aren't a member of the room.",
|
||||||
@@ -545,7 +545,7 @@ async fn join_room_by_id_helper(
|
|||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
// Ask a remote server if we don't have this room
|
// Ask a remote server if we don't have this room
|
||||||
if !db.rooms.exists(room_id)? && room_id.server_name() != db.globals.server_name() {
|
if !db.rooms.exists(&room_id)? && room_id.server_name() != db.globals.server_name() {
|
||||||
let mut make_join_response_and_server = Err(Error::BadServerResponse(
|
let mut make_join_response_and_server = Err(Error::BadServerResponse(
|
||||||
"No server available to assist in joining.",
|
"No server available to assist in joining.",
|
||||||
));
|
));
|
||||||
@@ -606,11 +606,11 @@ async fn join_room_by_id_helper(
|
|||||||
"content".to_owned(),
|
"content".to_owned(),
|
||||||
to_canonical_value(member::MemberEventContent {
|
to_canonical_value(member::MemberEventContent {
|
||||||
membership: member::MembershipState::Join,
|
membership: member::MembershipState::Join,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
is_direct: None,
|
is_direct: None,
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(&sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
@@ -658,7 +658,7 @@ async fn join_room_by_id_helper(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
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."))?;
|
||||||
@@ -670,7 +670,7 @@ async fn join_room_by_id_helper(
|
|||||||
&send_join_response,
|
&send_join_response,
|
||||||
&room_version,
|
&room_version,
|
||||||
&pub_key_map,
|
&pub_key_map,
|
||||||
db,
|
&db,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ async fn join_room_by_id_helper(
|
|||||||
.room_state
|
.room_state
|
||||||
.state
|
.state
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pdu| validate_and_add_event_id(pdu, &room_version, &pub_key_map, db))
|
.map(|pdu| validate_and_add_event_id(pdu, &room_version, &pub_key_map, &db))
|
||||||
{
|
{
|
||||||
let (event_id, value) = match result {
|
let (event_id, value) = match result {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
@@ -724,14 +724,14 @@ async fn join_room_by_id_helper(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, id)| db.rooms.compress_state_event(k, &id, &db.globals))
|
.map(|(k, id)| db.rooms.compress_state_event(k, &id, &db.globals))
|
||||||
.collect::<Result<HashSet<_>>>()?,
|
.collect::<Result<HashSet<_>>>()?,
|
||||||
db,
|
&db,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for result in send_join_response
|
for result in send_join_response
|
||||||
.room_state
|
.room_state
|
||||||
.auth_chain
|
.auth_chain
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pdu| validate_and_add_event_id(pdu, &room_version, &pub_key_map, db))
|
.map(|pdu| validate_and_add_event_id(pdu, &room_version, &pub_key_map, &db))
|
||||||
{
|
{
|
||||||
let (event_id, value) = match result {
|
let (event_id, value) = match result {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
@@ -754,15 +754,15 @@ async fn join_room_by_id_helper(
|
|||||||
|
|
||||||
// We set the room state after inserting the pdu, so that we never have a moment in time
|
// We set the room state after inserting the pdu, so that we never have a moment in time
|
||||||
// where events in the current room state do not exist
|
// where events in the current room state do not exist
|
||||||
db.rooms.set_room_state(room_id, statehashid)?;
|
db.rooms.set_room_state(&room_id, statehashid)?;
|
||||||
} else {
|
} else {
|
||||||
let event = member::MemberEventContent {
|
let event = member::MemberEventContent {
|
||||||
membership: member::MembershipState::Join,
|
membership: member::MembershipState::Join,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
is_direct: None,
|
is_direct: None,
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(&sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -774,9 +774,9 @@ async fn join_room_by_id_helper(
|
|||||||
state_key: Some(sender_user.to_string()),
|
state_key: Some(sender_user.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
room_id,
|
&room_id,
|
||||||
db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@@ -800,7 +800,7 @@ fn validate_and_add_event_id(
|
|||||||
})?;
|
})?;
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::try_from(&*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")
|
||||||
))
|
))
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
@@ -927,7 +927,7 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
let auth_events = db.rooms.get_auth_events(
|
let auth_events = db.rooms.get_auth_events(
|
||||||
room_id,
|
room_id,
|
||||||
&kind,
|
&kind,
|
||||||
sender_user,
|
&sender_user,
|
||||||
Some(&state_key),
|
Some(&state_key),
|
||||||
&content,
|
&content,
|
||||||
)?;
|
)?;
|
||||||
@@ -976,10 +976,10 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
|
|
||||||
let auth_check = state_res::auth_check(
|
let auth_check = state_res::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&pdu,
|
&Arc::new(pdu.clone()),
|
||||||
create_prev_event,
|
create_prev_event,
|
||||||
None::<PduEvent>, // TODO: third_party_invite
|
None, // TODO: third_party_invite
|
||||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
|k, s| auth_events.get(&(k.clone(), s.to_owned())).map(Arc::clone),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("{:?}", e);
|
error!("{:?}", e);
|
||||||
@@ -1074,10 +1074,10 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
let pdu_id = server_server::handle_incoming_pdu(
|
let pdu_id = server_server::handle_incoming_pdu(
|
||||||
&origin,
|
&origin,
|
||||||
&event_id,
|
&event_id,
|
||||||
room_id,
|
&room_id,
|
||||||
value,
|
value,
|
||||||
true,
|
true,
|
||||||
db,
|
&db,
|
||||||
&pub_key_map,
|
&pub_key_map,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -1119,11 +1119,11 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
event_type: EventType::RoomMember,
|
event_type: EventType::RoomMember,
|
||||||
content: serde_json::to_value(member::MemberEventContent {
|
content: serde_json::to_value(member::MemberEventContent {
|
||||||
membership: member::MembershipState::Invite,
|
membership: member::MembershipState::Invite,
|
||||||
displayname: db.users.displayname(user_id)?,
|
displayname: db.users.displayname(&user_id)?,
|
||||||
avatar_url: db.users.avatar_url(user_id)?,
|
avatar_url: db.users.avatar_url(&user_id)?,
|
||||||
is_direct: Some(is_direct),
|
is_direct: Some(is_direct),
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(user_id)?,
|
blurhash: db.users.blurhash(&user_id)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
@@ -1131,9 +1131,9 @@ pub(crate) async fn invite_helper<'a>(
|
|||||||
state_key: Some(user_id.to_string()),
|
state_key: Some(user_id.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
room_id,
|
room_id,
|
||||||
db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ pub async fn send_message_event_route(
|
|||||||
state_key: None,
|
state_key: None,
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -141,7 +141,7 @@ pub async fn get_message_events_route(
|
|||||||
get_message_events::Direction::Forward => {
|
get_message_events::Direction::Forward => {
|
||||||
let events_after = db
|
let events_after = db
|
||||||
.rooms
|
.rooms
|
||||||
.pdus_after(sender_user, &body.room_id, from)?
|
.pdus_after(&sender_user, &body.room_id, from)?
|
||||||
.take(limit)
|
.take(limit)
|
||||||
.filter_map(|r| r.ok()) // Filter out buggy events
|
.filter_map(|r| r.ok()) // Filter out buggy events
|
||||||
.filter_map(|(pdu_id, pdu)| {
|
.filter_map(|(pdu_id, pdu)| {
|
||||||
@@ -171,7 +171,7 @@ pub async fn get_message_events_route(
|
|||||||
get_message_events::Direction::Backward => {
|
get_message_events::Direction::Backward => {
|
||||||
let events_before = db
|
let events_before = db
|
||||||
.rooms
|
.rooms
|
||||||
.pdus_until(sender_user, &body.room_id, from)?
|
.pdus_until(&sender_user, &body.room_id, from)?
|
||||||
.take(limit)
|
.take(limit)
|
||||||
.filter_map(|r| r.ok()) // Filter out buggy events
|
.filter_map(|r| r.ok()) // Filter out buggy events
|
||||||
.filter_map(|(pdu_id, pdu)| {
|
.filter_map(|(pdu_id, pdu)| {
|
||||||
|
|||||||
@@ -19,17 +19,17 @@ pub async fn set_presence_route(
|
|||||||
) -> ConduitResult<set_presence::Response> {
|
) -> ConduitResult<set_presence::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");
|
||||||
|
|
||||||
for room_id in db.rooms.rooms_joined(sender_user) {
|
for room_id in db.rooms.rooms_joined(&sender_user) {
|
||||||
let room_id = room_id?;
|
let room_id = room_id?;
|
||||||
|
|
||||||
db.rooms.edus.update_presence(
|
db.rooms.edus.update_presence(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
ruma::events::presence::PresenceEvent {
|
ruma::events::presence::PresenceEvent {
|
||||||
content: ruma::events::presence::PresenceEventContent {
|
content: ruma::events::presence::PresenceEventContent {
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
currently_active: None,
|
currently_active: None,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
last_active_ago: Some(
|
last_active_ago: Some(
|
||||||
utils::millis_since_unix_epoch()
|
utils::millis_since_unix_epoch()
|
||||||
.try_into()
|
.try_into()
|
||||||
@@ -76,7 +76,7 @@ pub async fn get_presence_route(
|
|||||||
if let Some(presence) = db
|
if let Some(presence) = db
|
||||||
.rooms
|
.rooms
|
||||||
.edus
|
.edus
|
||||||
.get_last_presence_event(sender_user, &room_id)?
|
.get_last_presence_event(&sender_user, &room_id)?
|
||||||
{
|
{
|
||||||
presence_event = Some(presence);
|
presence_event = Some(presence);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ pub async fn set_displayname_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");
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
.set_displayname(sender_user, body.displayname.clone())?;
|
.set_displayname(&sender_user, body.displayname.clone())?;
|
||||||
|
|
||||||
// Send a new membership event and presence update into all joined rooms
|
// Send a new membership event and presence update into all joined rooms
|
||||||
let all_rooms_joined: Vec<_> = db
|
let all_rooms_joined: Vec<_> = db
|
||||||
.rooms
|
.rooms
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(&sender_user)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.map(|room_id| {
|
.map(|room_id| {
|
||||||
Ok::<_, Error>((
|
Ok::<_, Error>((
|
||||||
@@ -89,19 +89,19 @@ pub async fn set_displayname_route(
|
|||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
let _ = db
|
let _ =
|
||||||
.rooms
|
db.rooms
|
||||||
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &db, &state_lock);
|
.build_and_append_pdu(pdu_builder, &sender_user, &room_id, &db, &state_lock);
|
||||||
|
|
||||||
// Presence update
|
// Presence update
|
||||||
db.rooms.edus.update_presence(
|
db.rooms.edus.update_presence(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
ruma::events::presence::PresenceEvent {
|
ruma::events::presence::PresenceEvent {
|
||||||
content: ruma::events::presence::PresenceEventContent {
|
content: ruma::events::presence::PresenceEventContent {
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
currently_active: None,
|
currently_active: None,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
last_active_ago: Some(
|
last_active_ago: Some(
|
||||||
utils::millis_since_unix_epoch()
|
utils::millis_since_unix_epoch()
|
||||||
.try_into()
|
.try_into()
|
||||||
@@ -177,14 +177,14 @@ pub async fn set_avatar_url_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");
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
.set_avatar_url(sender_user, body.avatar_url.clone())?;
|
.set_avatar_url(&sender_user, body.avatar_url.clone())?;
|
||||||
|
|
||||||
db.users.set_blurhash(sender_user, body.blurhash.clone())?;
|
db.users.set_blurhash(&sender_user, body.blurhash.clone())?;
|
||||||
|
|
||||||
// Send a new membership event and presence update into all joined rooms
|
// Send a new membership event and presence update into all joined rooms
|
||||||
let all_joined_rooms: Vec<_> = db
|
let all_joined_rooms: Vec<_> = db
|
||||||
.rooms
|
.rooms
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(&sender_user)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.map(|room_id| {
|
.map(|room_id| {
|
||||||
Ok::<_, Error>((
|
Ok::<_, Error>((
|
||||||
@@ -234,19 +234,19 @@ pub async fn set_avatar_url_route(
|
|||||||
);
|
);
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
let _ = db
|
let _ =
|
||||||
.rooms
|
db.rooms
|
||||||
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &db, &state_lock);
|
.build_and_append_pdu(pdu_builder, &sender_user, &room_id, &db, &state_lock);
|
||||||
|
|
||||||
// Presence update
|
// Presence update
|
||||||
db.rooms.edus.update_presence(
|
db.rooms.edus.update_presence(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
ruma::events::presence::PresenceEvent {
|
ruma::events::presence::PresenceEvent {
|
||||||
content: ruma::events::presence::PresenceEventContent {
|
content: ruma::events::presence::PresenceEventContent {
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
currently_active: None,
|
currently_active: None,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
last_active_ago: Some(
|
last_active_ago: Some(
|
||||||
utils::millis_since_unix_epoch()
|
utils::millis_since_unix_epoch()
|
||||||
.try_into()
|
.try_into()
|
||||||
|
|||||||
+36
-16
@@ -31,7 +31,7 @@ pub async fn get_pushrules_all_route(
|
|||||||
|
|
||||||
let event = db
|
let event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -59,7 +59,7 @@ pub async fn get_pushrule_route(
|
|||||||
|
|
||||||
let event = db
|
let event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -124,7 +124,7 @@ pub async fn set_pushrule_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -193,8 +193,13 @@ pub async fn set_pushrule_route(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.account_data
|
db.account_data.update(
|
||||||
.update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
|
None,
|
||||||
|
&sender_user,
|
||||||
|
EventType::PushRules,
|
||||||
|
&event,
|
||||||
|
&db.globals,
|
||||||
|
)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -224,7 +229,7 @@ pub async fn get_pushrule_actions_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -286,7 +291,7 @@ pub async fn set_pushrule_actions_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -327,8 +332,13 @@ pub async fn set_pushrule_actions_route(
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
db.account_data
|
db.account_data.update(
|
||||||
.update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
|
None,
|
||||||
|
&sender_user,
|
||||||
|
EventType::PushRules,
|
||||||
|
&event,
|
||||||
|
&db.globals,
|
||||||
|
)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -358,7 +368,7 @@ pub async fn get_pushrule_enabled_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -422,7 +432,7 @@ pub async fn set_pushrule_enabled_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<ruma::events::push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<ruma::events::push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -468,8 +478,13 @@ pub async fn set_pushrule_enabled_route(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.account_data
|
db.account_data.update(
|
||||||
.update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
|
None,
|
||||||
|
&sender_user,
|
||||||
|
EventType::PushRules,
|
||||||
|
&event,
|
||||||
|
&db.globals,
|
||||||
|
)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -499,7 +514,7 @@ pub async fn delete_pushrule_route(
|
|||||||
|
|
||||||
let mut event = db
|
let mut event = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, sender_user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &sender_user, EventType::PushRules)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"PushRules event not found.",
|
"PushRules event not found.",
|
||||||
@@ -535,8 +550,13 @@ pub async fn delete_pushrule_route(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.account_data
|
db.account_data.update(
|
||||||
.update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
|
None,
|
||||||
|
&sender_user,
|
||||||
|
EventType::PushRules,
|
||||||
|
&event,
|
||||||
|
&db.globals,
|
||||||
|
)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub async fn set_read_marker_route(
|
|||||||
};
|
};
|
||||||
db.account_data.update(
|
db.account_data.update(
|
||||||
Some(&body.room_id),
|
Some(&body.room_id),
|
||||||
sender_user,
|
&sender_user,
|
||||||
EventType::FullyRead,
|
EventType::FullyRead,
|
||||||
&fully_read_event,
|
&fully_read_event,
|
||||||
&db.globals,
|
&db.globals,
|
||||||
@@ -46,7 +46,7 @@ pub async fn set_read_marker_route(
|
|||||||
if let Some(event) = &body.read_receipt {
|
if let Some(event) = &body.read_receipt {
|
||||||
db.rooms.edus.private_read_set(
|
db.rooms.edus.private_read_set(
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
sender_user,
|
&sender_user,
|
||||||
db.rooms.get_pdu_count(event)?.ok_or(Error::BadRequest(
|
db.rooms.get_pdu_count(event)?.ok_or(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Event does not exist.",
|
"Event does not exist.",
|
||||||
@@ -54,7 +54,7 @@ pub async fn set_read_marker_route(
|
|||||||
&db.globals,
|
&db.globals,
|
||||||
)?;
|
)?;
|
||||||
db.rooms
|
db.rooms
|
||||||
.reset_notification_counts(sender_user, &body.room_id)?;
|
.reset_notification_counts(&sender_user, &body.room_id)?;
|
||||||
|
|
||||||
let mut user_receipts = BTreeMap::new();
|
let mut user_receipts = BTreeMap::new();
|
||||||
user_receipts.insert(
|
user_receipts.insert(
|
||||||
@@ -71,7 +71,7 @@ pub async fn set_read_marker_route(
|
|||||||
receipt_content.insert(event.to_owned(), receipts);
|
receipt_content.insert(event.to_owned(), receipts);
|
||||||
|
|
||||||
db.rooms.edus.readreceipt_update(
|
db.rooms.edus.readreceipt_update(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
AnyEphemeralRoomEvent::Receipt(ruma::events::receipt::ReceiptEvent {
|
AnyEphemeralRoomEvent::Receipt(ruma::events::receipt::ReceiptEvent {
|
||||||
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
||||||
@@ -102,7 +102,7 @@ pub async fn create_receipt_route(
|
|||||||
|
|
||||||
db.rooms.edus.private_read_set(
|
db.rooms.edus.private_read_set(
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
sender_user,
|
&sender_user,
|
||||||
db.rooms
|
db.rooms
|
||||||
.get_pdu_count(&body.event_id)?
|
.get_pdu_count(&body.event_id)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
@@ -112,7 +112,7 @@ pub async fn create_receipt_route(
|
|||||||
&db.globals,
|
&db.globals,
|
||||||
)?;
|
)?;
|
||||||
db.rooms
|
db.rooms
|
||||||
.reset_notification_counts(sender_user, &body.room_id)?;
|
.reset_notification_counts(&sender_user, &body.room_id)?;
|
||||||
|
|
||||||
let mut user_receipts = BTreeMap::new();
|
let mut user_receipts = BTreeMap::new();
|
||||||
user_receipts.insert(
|
user_receipts.insert(
|
||||||
@@ -128,7 +128,7 @@ pub async fn create_receipt_route(
|
|||||||
receipt_content.insert(body.event_id.to_owned(), receipts);
|
receipt_content.insert(body.event_id.to_owned(), receipts);
|
||||||
|
|
||||||
db.rooms.edus.readreceipt_update(
|
db.rooms.edus.readreceipt_update(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
AnyEphemeralRoomEvent::Receipt(ruma::events::receipt::ReceiptEvent {
|
AnyEphemeralRoomEvent::Receipt(ruma::events::receipt::ReceiptEvent {
|
||||||
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ pub async fn redact_event_route(
|
|||||||
state_key: None,
|
state_key: None,
|
||||||
redacts: Some(body.event_id.clone()),
|
redacts: Some(body.event_id.clone()),
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
|
|||||||
+16
-16
@@ -106,7 +106,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -118,11 +118,11 @@ pub async fn create_room_route(
|
|||||||
event_type: EventType::RoomMember,
|
event_type: EventType::RoomMember,
|
||||||
content: serde_json::to_value(member::MemberEventContent {
|
content: serde_json::to_value(member::MemberEventContent {
|
||||||
membership: member::MembershipState::Join,
|
membership: member::MembershipState::Join,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
is_direct: Some(body.is_direct),
|
is_direct: Some(body.is_direct),
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(&sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
@@ -130,7 +130,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some(sender_user.to_string()),
|
state_key: Some(sender_user.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -185,7 +185,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -207,7 +207,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -235,7 +235,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -253,7 +253,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -279,7 +279,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -298,7 +298,7 @@ pub async fn create_room_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
db.rooms
|
db.rooms
|
||||||
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &db, &state_lock)?;
|
.build_and_append_pdu(pdu_builder, &sender_user, &room_id, &db, &state_lock)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Events implied by name and topic
|
// 7. Events implied by name and topic
|
||||||
@@ -312,7 +312,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -331,7 +331,7 @@ pub async fn create_room_route(
|
|||||||
state_key: Some("".to_owned()),
|
state_key: Some("".to_owned()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -551,11 +551,11 @@ pub async fn upgrade_room_route(
|
|||||||
event_type: EventType::RoomMember,
|
event_type: EventType::RoomMember,
|
||||||
content: serde_json::to_value(member::MemberEventContent {
|
content: serde_json::to_value(member::MemberEventContent {
|
||||||
membership: member::MembershipState::Join,
|
membership: member::MembershipState::Join,
|
||||||
displayname: db.users.displayname(sender_user)?,
|
displayname: db.users.displayname(&sender_user)?,
|
||||||
avatar_url: db.users.avatar_url(sender_user)?,
|
avatar_url: db.users.avatar_url(&sender_user)?,
|
||||||
is_direct: None,
|
is_direct: None,
|
||||||
third_party_invite: None,
|
third_party_invite: None,
|
||||||
blurhash: db.users.blurhash(sender_user)?,
|
blurhash: db.users.blurhash(&sender_user)?,
|
||||||
reason: None,
|
reason: None,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub async fn search_events_route(
|
|||||||
|
|
||||||
let room_ids = filter.rooms.clone().unwrap_or_else(|| {
|
let room_ids = filter.rooms.clone().unwrap_or_else(|| {
|
||||||
db.rooms
|
db.rooms
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(&sender_user)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
@@ -88,7 +88,7 @@ pub async fn search_events_route(
|
|||||||
rank: None,
|
rank: None,
|
||||||
result: db
|
result: db
|
||||||
.rooms
|
.rooms
|
||||||
.get_pdu_from_id(result)?
|
.get_pdu_from_id(&result)?
|
||||||
.map(|pdu| pdu.to_room_event()),
|
.map(|pdu| pdu.to_room_event()),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ pub async fn login_route(
|
|||||||
login::IncomingLoginInfo::Token { token } => {
|
login::IncomingLoginInfo::Token { token } => {
|
||||||
if let Some(jwt_decoding_key) = db.globals.jwt_decoding_key() {
|
if let Some(jwt_decoding_key) = db.globals.jwt_decoding_key() {
|
||||||
let token = jsonwebtoken::decode::<Claims>(
|
let token = jsonwebtoken::decode::<Claims>(
|
||||||
token,
|
&token,
|
||||||
jwt_decoding_key,
|
&jwt_decoding_key,
|
||||||
&jsonwebtoken::Validation::default(),
|
&jsonwebtoken::Validation::default(),
|
||||||
)
|
)
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Token is invalid."))?;
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Token is invalid."))?;
|
||||||
@@ -179,7 +179,7 @@ pub async fn logout_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");
|
||||||
|
|
||||||
db.users.remove_device(sender_user, sender_device)?;
|
db.users.remove_device(&sender_user, sender_device)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ pub async fn logout_all_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");
|
||||||
|
|
||||||
for device_id in db.users.all_device_ids(sender_user).flatten() {
|
for device_id in db.users.all_device_ids(sender_user).flatten() {
|
||||||
db.users.remove_device(sender_user, &device_id)?;
|
db.users.remove_device(&sender_user, &device_id)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|||||||
@@ -308,9 +308,9 @@ async fn send_state_event_for_key_helper(
|
|||||||
state_key: Some(state_key),
|
state_key: Some(state_key),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
&sender_user,
|
||||||
room_id,
|
&room_id,
|
||||||
db,
|
&db,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ pub async fn send_event_to_device_route(
|
|||||||
match target_device_id_maybe {
|
match target_device_id_maybe {
|
||||||
DeviceIdOrAllDevices::DeviceId(target_device_id) => db.users.add_to_device_event(
|
DeviceIdOrAllDevices::DeviceId(target_device_id) => db.users.add_to_device_event(
|
||||||
sender_user,
|
sender_user,
|
||||||
target_user_id,
|
&target_user_id,
|
||||||
target_device_id,
|
&target_device_id,
|
||||||
&body.event_type,
|
&body.event_type,
|
||||||
event.deserialize_as().map_err(|_| {
|
event.deserialize_as().map_err(|_| {
|
||||||
Error::BadRequest(ErrorKind::InvalidParam, "Event is invalid")
|
Error::BadRequest(ErrorKind::InvalidParam, "Event is invalid")
|
||||||
@@ -78,10 +78,10 @@ pub async fn send_event_to_device_route(
|
|||||||
)?,
|
)?,
|
||||||
|
|
||||||
DeviceIdOrAllDevices::AllDevices => {
|
DeviceIdOrAllDevices::AllDevices => {
|
||||||
for target_device_id in db.users.all_device_ids(target_user_id) {
|
for target_device_id in db.users.all_device_ids(&target_user_id) {
|
||||||
db.users.add_to_device_event(
|
db.users.add_to_device_event(
|
||||||
sender_user,
|
sender_user,
|
||||||
target_user_id,
|
&target_user_id,
|
||||||
&target_device_id?,
|
&target_device_id?,
|
||||||
&body.event_type,
|
&body.event_type,
|
||||||
event.deserialize_as().map_err(|_| {
|
event.deserialize_as().map_err(|_| {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ pub fn create_typing_event_route(
|
|||||||
|
|
||||||
if let Typing::Yes(duration) = body.state {
|
if let Typing::Yes(duration) = body.state {
|
||||||
db.rooms.edus.typing_add(
|
db.rooms.edus.typing_add(
|
||||||
sender_user,
|
&sender_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
duration.as_millis() as u64 + utils::millis_since_unix_epoch(),
|
duration.as_millis() as u64 + utils::millis_since_unix_epoch(),
|
||||||
&db.globals,
|
&db.globals,
|
||||||
@@ -29,7 +29,7 @@ pub fn create_typing_event_route(
|
|||||||
} else {
|
} else {
|
||||||
db.rooms
|
db.rooms
|
||||||
.edus
|
.edus
|
||||||
.typing_remove(sender_user, &body.room_id, &db.globals)?;
|
.typing_remove(&sender_user, &body.room_id, &db.globals)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(create_typing_event::Response {}.into())
|
Ok(create_typing_event::Response {}.into())
|
||||||
|
|||||||
+8
-22
@@ -196,14 +196,9 @@ impl Database {
|
|||||||
|
|
||||||
/// Load an existing database or create a new one.
|
/// Load an existing database or create a new one.
|
||||||
pub async fn load_or_create(config: &Config) -> Result<Arc<TokioRwLock<Self>>> {
|
pub async fn load_or_create(config: &Config) -> Result<Arc<TokioRwLock<Self>>> {
|
||||||
Self::check_sled_or_sqlite_db(config)?;
|
Self::check_sled_or_sqlite_db(&config)?;
|
||||||
|
|
||||||
if !Path::new(&config.database_path).exists() {
|
let builder = Engine::open(&config)?;
|
||||||
std::fs::create_dir_all(&config.database_path)
|
|
||||||
.map_err(|_| Error::BadConfig("Database folder doesn't exists and couldn't be created (e.g. due to missing permissions). Please create the database folder yourself."))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let builder = Engine::open(config)?;
|
|
||||||
|
|
||||||
if config.max_request_size < 1024 {
|
if config.max_request_size < 1024 {
|
||||||
eprintln!("ERROR: Max request size is less than 1KB. Please increase it.");
|
eprintln!("ERROR: Max request size is less than 1KB. Please increase it.");
|
||||||
@@ -618,7 +613,7 @@ impl Database {
|
|||||||
let short_room_id = db
|
let short_room_id = db
|
||||||
.rooms
|
.rooms
|
||||||
.roomid_shortroomid
|
.roomid_shortroomid
|
||||||
.get(room_id)
|
.get(&room_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.expect("shortroomid should exist");
|
.expect("shortroomid should exist");
|
||||||
|
|
||||||
@@ -641,7 +636,7 @@ impl Database {
|
|||||||
let short_room_id = db
|
let short_room_id = db
|
||||||
.rooms
|
.rooms
|
||||||
.roomid_shortroomid
|
.roomid_shortroomid
|
||||||
.get(room_id)
|
.get(&room_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.expect("shortroomid should exist");
|
.expect("shortroomid should exist");
|
||||||
|
|
||||||
@@ -677,7 +672,7 @@ impl Database {
|
|||||||
let short_room_id = db
|
let short_room_id = db
|
||||||
.rooms
|
.rooms
|
||||||
.roomid_shortroomid
|
.roomid_shortroomid
|
||||||
.get(room_id)
|
.get(&room_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.expect("shortroomid should exist");
|
.expect("shortroomid should exist");
|
||||||
let mut new_key = short_room_id;
|
let mut new_key = short_room_id;
|
||||||
@@ -757,7 +752,7 @@ impl Database {
|
|||||||
|
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
{
|
{
|
||||||
Self::start_wal_clean_task(Arc::clone(&db), config).await;
|
Self::start_wal_clean_task(Arc::clone(&db), &config).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(db)
|
Ok(db)
|
||||||
@@ -815,21 +810,12 @@ impl Database {
|
|||||||
|
|
||||||
// Events for rooms we are in
|
// Events for rooms we are in
|
||||||
for room_id in self.rooms.rooms_joined(user_id).filter_map(|r| r.ok()) {
|
for room_id in self.rooms.rooms_joined(user_id).filter_map(|r| r.ok()) {
|
||||||
let short_roomid = self
|
|
||||||
.rooms
|
|
||||||
.get_shortroomid(&room_id)
|
|
||||||
.ok()
|
|
||||||
.flatten()
|
|
||||||
.expect("room exists")
|
|
||||||
.to_be_bytes()
|
|
||||||
.to_vec();
|
|
||||||
|
|
||||||
let roomid_bytes = room_id.as_bytes().to_vec();
|
let roomid_bytes = room_id.as_bytes().to_vec();
|
||||||
let mut roomid_prefix = roomid_bytes.clone();
|
let mut roomid_prefix = roomid_bytes.clone();
|
||||||
roomid_prefix.push(0xff);
|
roomid_prefix.push(0xff);
|
||||||
|
|
||||||
// PDUs
|
// PDUs
|
||||||
futures.push(self.rooms.pduid_pdu.watch_prefix(&short_roomid));
|
futures.push(self.rooms.pduid_pdu.watch_prefix(&roomid_prefix));
|
||||||
|
|
||||||
// EDUs
|
// EDUs
|
||||||
futures.push(
|
futures.push(
|
||||||
@@ -964,7 +950,7 @@ impl<'r> FromRequest<'r> for DatabaseGuard {
|
|||||||
async fn from_request(req: &'r Request<'_>) -> rocket::request::Outcome<Self, ()> {
|
async fn from_request(req: &'r Request<'_>) -> rocket::request::Outcome<Self, ()> {
|
||||||
let db = try_outcome!(req.guard::<&State<Arc<TokioRwLock<Database>>>>().await);
|
let db = try_outcome!(req.guard::<&State<Arc<TokioRwLock<Database>>>>().await);
|
||||||
|
|
||||||
Ok(DatabaseGuard(Arc::clone(db).read_owned().await)).or_forward(())
|
Ok(DatabaseGuard(Arc::clone(&db).read_owned().await)).or_forward(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ use parking_lot::{Mutex, MutexGuard, RwLock};
|
|||||||
use rusqlite::{Connection, DatabaseName::Main, OptionalExtension};
|
use rusqlite::{Connection, DatabaseName::Main, OptionalExtension};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map, HashMap},
|
collections::HashMap,
|
||||||
future::Future,
|
future::Future,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use thread_local::ThreadLocal;
|
use thread_local::ThreadLocal;
|
||||||
use tokio::sync::watch;
|
use tokio::sync::oneshot::Sender;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@@ -56,7 +56,7 @@ impl Engine {
|
|||||||
conn.pragma_update(Some(Main), "journal_mode", &"WAL")?;
|
conn.pragma_update(Some(Main), "journal_mode", &"WAL")?;
|
||||||
conn.pragma_update(Some(Main), "synchronous", &"NORMAL")?;
|
conn.pragma_update(Some(Main), "synchronous", &"NORMAL")?;
|
||||||
conn.pragma_update(Some(Main), "cache_size", &(-i64::from(cache_size_kb)))?;
|
conn.pragma_update(Some(Main), "cache_size", &(-i64::from(cache_size_kb)))?;
|
||||||
conn.pragma_update(Some(Main), "wal_autocheckpoint", &0)?;
|
conn.pragma_update(Some(Main), "wal_autocheckpoint", &2000)?;
|
||||||
|
|
||||||
Ok(conn)
|
Ok(conn)
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ impl Engine {
|
|||||||
|
|
||||||
pub fn flush_wal(self: &Arc<Self>) -> Result<()> {
|
pub fn flush_wal(self: &Arc<Self>) -> Result<()> {
|
||||||
self.write_lock()
|
self.write_lock()
|
||||||
.pragma_update(Some(Main), "wal_checkpoint", &"RESTART")?;
|
.pragma_update(Some(Main), "wal_checkpoint", &"TRUNCATE")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ impl DatabaseEngine for Engine {
|
|||||||
pub struct SqliteTable {
|
pub struct SqliteTable {
|
||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
name: String,
|
name: String,
|
||||||
watchers: RwLock<HashMap<Vec<u8>, (watch::Sender<()>, watch::Receiver<()>)>>,
|
watchers: RwLock<HashMap<Vec<u8>, Vec<Sender<()>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type TupleOfBytes = (Vec<u8>, Vec<u8>);
|
type TupleOfBytes = (Vec<u8>, Vec<u8>);
|
||||||
@@ -192,7 +192,7 @@ impl SqliteTable {
|
|||||||
impl Tree for SqliteTable {
|
impl Tree for SqliteTable {
|
||||||
#[tracing::instrument(skip(self, key))]
|
#[tracing::instrument(skip(self, key))]
|
||||||
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
|
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
|
||||||
self.get_with_guard(self.engine.read_lock(), key)
|
self.get_with_guard(&self.engine.read_lock(), key)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self, key, value))]
|
#[tracing::instrument(skip(self, key, value))]
|
||||||
@@ -215,8 +215,10 @@ impl Tree for SqliteTable {
|
|||||||
if !triggered.is_empty() {
|
if !triggered.is_empty() {
|
||||||
let mut watchers = self.watchers.write();
|
let mut watchers = self.watchers.write();
|
||||||
for prefix in triggered {
|
for prefix in triggered {
|
||||||
if let Some(tx) = watchers.remove(prefix) {
|
if let Some(txs) = watchers.remove(prefix) {
|
||||||
let _ = tx.0.send(());
|
for tx in txs {
|
||||||
|
let _ = tx.send(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -273,7 +275,7 @@ impl Tree for SqliteTable {
|
|||||||
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = TupleOfBytes> + 'a> {
|
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = TupleOfBytes> + 'a> {
|
||||||
let guard = self.engine.read_lock_iterator();
|
let guard = self.engine.read_lock_iterator();
|
||||||
|
|
||||||
self.iter_with_guard(guard)
|
self.iter_with_guard(&guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self, from, backwards))]
|
#[tracing::instrument(skip(self, from, backwards))]
|
||||||
@@ -365,18 +367,17 @@ impl Tree for SqliteTable {
|
|||||||
|
|
||||||
#[tracing::instrument(skip(self, prefix))]
|
#[tracing::instrument(skip(self, prefix))]
|
||||||
fn watch_prefix<'a>(&'a self, prefix: &[u8]) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
fn watch_prefix<'a>(&'a self, prefix: &[u8]) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||||
let mut rx = match self.watchers.write().entry(prefix.to_vec()) {
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||||
hash_map::Entry::Occupied(o) => o.get().1.clone(),
|
|
||||||
hash_map::Entry::Vacant(v) => {
|
self.watchers
|
||||||
let (tx, rx) = tokio::sync::watch::channel(());
|
.write()
|
||||||
v.insert((tx, rx.clone()));
|
.entry(prefix.to_vec())
|
||||||
rx
|
.or_default()
|
||||||
}
|
.push(tx);
|
||||||
};
|
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// Tx is never destroyed
|
// Tx is never destroyed
|
||||||
rx.changed().await.unwrap();
|
rx.await.unwrap();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ impl AccountData {
|
|||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
prefix.extend_from_slice(user_id.as_bytes());
|
prefix.extend_from_slice(&user_id.as_bytes());
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
let mut roomuserdataid = prefix.clone();
|
let mut roomuserdataid = prefix.clone();
|
||||||
roomuserdataid.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
roomuserdataid.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
||||||
roomuserdataid.push(0xff);
|
roomuserdataid.push(0xff);
|
||||||
roomuserdataid.extend_from_slice(event_type.as_bytes());
|
roomuserdataid.extend_from_slice(&event_type.as_bytes());
|
||||||
|
|
||||||
let mut key = prefix;
|
let mut key = prefix;
|
||||||
key.extend_from_slice(event_type.as_bytes());
|
key.extend_from_slice(event_type.as_bytes());
|
||||||
@@ -83,7 +83,7 @@ impl AccountData {
|
|||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(user_id.as_bytes());
|
key.extend_from_slice(&user_id.as_bytes());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(kind.as_ref().as_bytes());
|
key.extend_from_slice(kind.as_ref().as_bytes());
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ impl AccountData {
|
|||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
prefix.extend_from_slice(user_id.as_bytes());
|
prefix.extend_from_slice(&user_id.as_bytes());
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
// Skip the data that's exactly at since, because we sent that last time
|
// Skip the data that's exactly at since, because we sent that last time
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ impl Globals {
|
|||||||
.map(|key| (version, key))
|
.map(|key| (version, key))
|
||||||
})
|
})
|
||||||
.and_then(|(version, key)| {
|
.and_then(|(version, key)| {
|
||||||
ruma::signatures::Ed25519KeyPair::from_der(key, version)
|
ruma::signatures::Ed25519KeyPair::from_der(&key, version)
|
||||||
.map_err(|_| Error::bad_database("Private or public keys are invalid."))
|
.map_err(|_| Error::bad_database("Private or public keys are invalid."))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -27,7 +27,7 @@ impl KeyBackups {
|
|||||||
|
|
||||||
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());
|
||||||
|
|
||||||
self.backupid_algorithm.insert(
|
self.backupid_algorithm.insert(
|
||||||
&key,
|
&key,
|
||||||
@@ -41,7 +41,7 @@ impl KeyBackups {
|
|||||||
pub fn delete_backup(&self, user_id: &UserId, version: &str) -> Result<()> {
|
pub fn delete_backup(&self, user_id: &UserId, version: &str) -> Result<()> {
|
||||||
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());
|
||||||
|
|
||||||
self.backupid_algorithm.remove(&key)?;
|
self.backupid_algorithm.remove(&key)?;
|
||||||
self.backupid_etag.remove(&key)?;
|
self.backupid_etag.remove(&key)?;
|
||||||
@@ -64,7 +64,7 @@ impl KeyBackups {
|
|||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
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());
|
||||||
|
|
||||||
if self.backupid_algorithm.get(&key)?.is_none() {
|
if self.backupid_algorithm.get(&key)?.is_none() {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
@@ -75,7 +75,7 @@ impl KeyBackups {
|
|||||||
|
|
||||||
self.backupid_algorithm.insert(
|
self.backupid_algorithm.insert(
|
||||||
&key,
|
&key,
|
||||||
serde_json::to_string(backup_metadata)
|
&serde_json::to_string(backup_metadata)
|
||||||
.expect("BackupAlgorithm::to_string always works")
|
.expect("BackupAlgorithm::to_string always works")
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
)?;
|
)?;
|
||||||
@@ -192,7 +192,7 @@ impl KeyBackups {
|
|||||||
pub fn get_etag(&self, user_id: &UserId, version: &str) -> Result<String> {
|
pub fn get_etag(&self, user_id: &UserId, version: &str) -> Result<String> {
|
||||||
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());
|
||||||
|
|
||||||
Ok(utils::u64_from_bytes(
|
Ok(utils::u64_from_bytes(
|
||||||
&self
|
&self
|
||||||
@@ -223,7 +223,7 @@ impl KeyBackups {
|
|||||||
let mut parts = key.rsplit(|&b| b == 0xff);
|
let mut parts = key.rsplit(|&b| b == 0xff);
|
||||||
|
|
||||||
let session_id =
|
let session_id =
|
||||||
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.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@@ -231,7 +231,7 @@ impl KeyBackups {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::try_from(
|
||||||
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.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("backupkeyid_backup room_id is invalid."))?,
|
.map_err(|_| Error::bad_database("backupkeyid_backup room_id is invalid."))?,
|
||||||
@@ -280,7 +280,7 @@ impl KeyBackups {
|
|||||||
let mut parts = key.rsplit(|&b| b == 0xff);
|
let mut parts = key.rsplit(|&b| b == 0xff);
|
||||||
|
|
||||||
let session_id =
|
let session_id =
|
||||||
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.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@@ -325,7 +325,7 @@ impl KeyBackups {
|
|||||||
pub fn delete_all_keys(&self, user_id: &UserId, version: &str) -> Result<()> {
|
pub fn delete_all_keys(&self, user_id: &UserId, version: &str) -> Result<()> {
|
||||||
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());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
|
|
||||||
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
||||||
@@ -343,9 +343,9 @@ impl KeyBackups {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
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());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(room_id.as_bytes());
|
key.extend_from_slice(&room_id.as_bytes());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
|
|
||||||
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
||||||
@@ -364,11 +364,11 @@ impl KeyBackups {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
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());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(room_id.as_bytes());
|
key.extend_from_slice(&room_id.as_bytes());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(session_id.as_bytes());
|
key.extend_from_slice(&session_id.as_bytes());
|
||||||
|
|
||||||
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
for (outdated_key, _) in self.backupkeyid_backup.scan_prefix(key) {
|
||||||
self.backupkeyid_backup.remove(&outdated_key)?;
|
self.backupkeyid_backup.remove(&outdated_key)?;
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ use image::{imageops::FilterType, GenericImageView};
|
|||||||
use super::abstraction::Tree;
|
use super::abstraction::Tree;
|
||||||
use crate::{utils, Error, Result};
|
use crate::{utils, Error, Result};
|
||||||
use std::{mem, sync::Arc};
|
use std::{mem, sync::Arc};
|
||||||
use tokio::{
|
use tokio::{fs::File, io::AsyncReadExt, io::AsyncWriteExt};
|
||||||
fs::File,
|
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct FileMeta {
|
pub struct FileMeta {
|
||||||
pub content_disposition: Option<String>,
|
pub content_disposition: Option<String>,
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ pub fn get_actions<'a>(
|
|||||||
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
|
||||||
.displayname(user)?
|
.displayname(&user)?
|
||||||
.unwrap_or_else(|| user.localpart().to_owned()),
|
.unwrap_or_else(|| user.localpart().to_owned()),
|
||||||
users_power_levels: power_levels.users.clone(),
|
users_power_levels: power_levels.users.clone(),
|
||||||
default_power_level: power_levels.users_default,
|
default_power_level: power_levels.users_default,
|
||||||
@@ -302,7 +302,7 @@ async fn send_notice(
|
|||||||
if event_id_only {
|
if event_id_only {
|
||||||
send_request(
|
send_request(
|
||||||
&db.globals,
|
&db.globals,
|
||||||
url,
|
&url,
|
||||||
send_event_notification::v1::Request::new(notifi),
|
send_event_notification::v1::Request::new(notifi),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -332,7 +332,7 @@ async fn send_notice(
|
|||||||
|
|
||||||
send_request(
|
send_request(
|
||||||
&db.globals,
|
&db.globals,
|
||||||
url,
|
&url,
|
||||||
send_event_notification::v1::Request::new(notifi),
|
send_event_notification::v1::Request::new(notifi),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
+94
-82
@@ -97,8 +97,8 @@ pub struct Rooms {
|
|||||||
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<EventId, Arc<PduEvent>>>,
|
||||||
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) shorteventid_cache: Mutex<LruCache<u64, EventId>>,
|
||||||
pub(super) eventidshort_cache: Mutex<LruCache<EventId, u64>>,
|
pub(super) eventidshort_cache: Mutex<LruCache<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)>>,
|
||||||
@@ -121,7 +121,7 @@ impl Rooms {
|
|||||||
/// Builds a StateMap by iterating over all keys that start
|
/// Builds a StateMap by iterating over all keys that start
|
||||||
/// with state_hash, this gives the full state for the given state_hash.
|
/// with state_hash, this gives the full state for the given state_hash.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn state_full_ids(&self, shortstatehash: u64) -> Result<BTreeMap<u64, Arc<EventId>>> {
|
pub fn state_full_ids(&self, shortstatehash: u64) -> Result<BTreeMap<u64, EventId>> {
|
||||||
let full_state = self
|
let full_state = self
|
||||||
.load_shortstatehash_info(shortstatehash)?
|
.load_shortstatehash_info(shortstatehash)?
|
||||||
.pop()
|
.pop()
|
||||||
@@ -172,7 +172,7 @@ impl Rooms {
|
|||||||
shortstatehash: u64,
|
shortstatehash: u64,
|
||||||
event_type: &EventType,
|
event_type: &EventType,
|
||||||
state_key: &str,
|
state_key: &str,
|
||||||
) -> Result<Option<Arc<EventId>>> {
|
) -> Result<Option<EventId>> {
|
||||||
let shortstatekey = match self.get_shortstatekey(event_type, state_key)? {
|
let shortstatekey = match self.get_shortstatekey(event_type, state_key)? {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
@@ -252,7 +252,12 @@ impl Rooms {
|
|||||||
return Ok(HashMap::new());
|
return Ok(HashMap::new());
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_events = state_res::auth_types_for_event(kind, sender, state_key, content);
|
let auth_events = state_res::auth_types_for_event(
|
||||||
|
kind,
|
||||||
|
sender,
|
||||||
|
state_key.map(|s| s.to_string()),
|
||||||
|
content.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let mut sauthevents = auth_events
|
let mut sauthevents = auth_events
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -339,7 +344,7 @@ impl Rooms {
|
|||||||
new_state_ids_compressed: HashSet<CompressedStateEvent>,
|
new_state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let previous_shortstatehash = self.current_shortstatehash(room_id)?;
|
let previous_shortstatehash = self.current_shortstatehash(&room_id)?;
|
||||||
|
|
||||||
let state_hash = self.calculate_hash(
|
let state_hash = self.calculate_hash(
|
||||||
&new_state_ids_compressed
|
&new_state_ids_compressed
|
||||||
@@ -424,7 +429,7 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_joined_count(room_id, db)?;
|
self.update_joined_count(room_id, &db)?;
|
||||||
|
|
||||||
self.roomid_shortstatehash
|
self.roomid_shortstatehash
|
||||||
.insert(room_id.as_bytes(), &new_shortstatehash.to_be_bytes())?;
|
.insert(room_id.as_bytes(), &new_shortstatehash.to_be_bytes())?;
|
||||||
@@ -522,7 +527,7 @@ impl Rooms {
|
|||||||
pub fn parse_compressed_state_event(
|
pub fn parse_compressed_state_event(
|
||||||
&self,
|
&self,
|
||||||
compressed_event: CompressedStateEvent,
|
compressed_event: CompressedStateEvent,
|
||||||
) -> Result<(u64, Arc<EventId>)> {
|
) -> Result<(u64, EventId)> {
|
||||||
Ok((
|
Ok((
|
||||||
utils::u64_from_bytes(&compressed_event[0..size_of::<u64>()])
|
utils::u64_from_bytes(&compressed_event[0..size_of::<u64>()])
|
||||||
.expect("bytes have right length"),
|
.expect("bytes have right length"),
|
||||||
@@ -704,7 +709,7 @@ impl Rooms {
|
|||||||
event_id: &EventId,
|
event_id: &EventId,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<u64> {
|
) -> Result<u64> {
|
||||||
if let Some(short) = self.eventidshort_cache.lock().unwrap().get_mut(event_id) {
|
if let Some(short) = self.eventidshort_cache.lock().unwrap().get_mut(&event_id) {
|
||||||
return Ok(*short);
|
return Ok(*short);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,7 +737,7 @@ impl Rooms {
|
|||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
pub fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||||
self.roomid_shortroomid
|
self.roomid_shortroomid
|
||||||
.get(room_id.as_bytes())?
|
.get(&room_id.as_bytes())?
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
utils::u64_from_bytes(&bytes)
|
utils::u64_from_bytes(&bytes)
|
||||||
.map_err(|_| Error::bad_database("Invalid shortroomid in db."))
|
.map_err(|_| Error::bad_database("Invalid shortroomid in db."))
|
||||||
@@ -757,7 +762,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let mut statekey = event_type.as_ref().as_bytes().to_vec();
|
let mut statekey = event_type.as_ref().as_bytes().to_vec();
|
||||||
statekey.push(0xff);
|
statekey.push(0xff);
|
||||||
statekey.extend_from_slice(state_key.as_bytes());
|
statekey.extend_from_slice(&state_key.as_bytes());
|
||||||
|
|
||||||
let short = self
|
let short = self
|
||||||
.statekey_shortstatekey
|
.statekey_shortstatekey
|
||||||
@@ -784,13 +789,13 @@ impl Rooms {
|
|||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<u64> {
|
) -> Result<u64> {
|
||||||
Ok(match self.roomid_shortroomid.get(room_id.as_bytes())? {
|
Ok(match self.roomid_shortroomid.get(&room_id.as_bytes())? {
|
||||||
Some(short) => utils::u64_from_bytes(&short)
|
Some(short) => utils::u64_from_bytes(&short)
|
||||||
.map_err(|_| Error::bad_database("Invalid shortroomid in db."))?,
|
.map_err(|_| Error::bad_database("Invalid shortroomid in db."))?,
|
||||||
None => {
|
None => {
|
||||||
let short = globals.next_count()?;
|
let short = globals.next_count()?;
|
||||||
self.roomid_shortroomid
|
self.roomid_shortroomid
|
||||||
.insert(room_id.as_bytes(), &short.to_be_bytes())?;
|
.insert(&room_id.as_bytes(), &short.to_be_bytes())?;
|
||||||
short
|
short
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -814,7 +819,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let mut statekey = event_type.as_ref().as_bytes().to_vec();
|
let mut statekey = event_type.as_ref().as_bytes().to_vec();
|
||||||
statekey.push(0xff);
|
statekey.push(0xff);
|
||||||
statekey.extend_from_slice(state_key.as_bytes());
|
statekey.extend_from_slice(&state_key.as_bytes());
|
||||||
|
|
||||||
let short = match self.statekey_shortstatekey.get(&statekey)? {
|
let short = match self.statekey_shortstatekey.get(&statekey)? {
|
||||||
Some(shortstatekey) => utils::u64_from_bytes(&shortstatekey)
|
Some(shortstatekey) => utils::u64_from_bytes(&shortstatekey)
|
||||||
@@ -838,14 +843,14 @@ impl Rooms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>> {
|
pub fn get_eventid_from_short(&self, shorteventid: u64) -> Result<EventId> {
|
||||||
if let Some(id) = self
|
if let Some(id) = self
|
||||||
.shorteventid_cache
|
.shorteventid_cache
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_mut(&shorteventid)
|
.get_mut(&shorteventid)
|
||||||
{
|
{
|
||||||
return Ok(Arc::clone(id));
|
return Ok(id.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = self
|
let bytes = self
|
||||||
@@ -853,17 +858,15 @@ 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::try_from(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()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(shorteventid, Arc::clone(&event_id));
|
.insert(shorteventid, event_id.clone());
|
||||||
|
|
||||||
Ok(event_id)
|
Ok(event_id)
|
||||||
}
|
}
|
||||||
@@ -891,12 +894,12 @@ impl Rooms {
|
|||||||
.ok_or_else(|| Error::bad_database("Invalid statekey in shortstatekey_statekey."))?;
|
.ok_or_else(|| Error::bad_database("Invalid statekey in shortstatekey_statekey."))?;
|
||||||
|
|
||||||
let event_type =
|
let event_type =
|
||||||
EventType::try_from(utils::string_from_bytes(eventtype_bytes).map_err(|_| {
|
EventType::try_from(utils::string_from_bytes(&eventtype_bytes).map_err(|_| {
|
||||||
Error::bad_database("Event type in shortstatekey_statekey is invalid unicode.")
|
Error::bad_database("Event type in shortstatekey_statekey is invalid unicode.")
|
||||||
})?)
|
})?)
|
||||||
.map_err(|_| Error::bad_database("Event type in shortstatekey_statekey is invalid."))?;
|
.map_err(|_| Error::bad_database("Event type in shortstatekey_statekey is invalid."))?;
|
||||||
|
|
||||||
let state_key = utils::string_from_bytes(statekey_bytes).map_err(|_| {
|
let state_key = utils::string_from_bytes(&statekey_bytes).map_err(|_| {
|
||||||
Error::bad_database("Statekey in shortstatekey_statekey is invalid unicode.")
|
Error::bad_database("Statekey in shortstatekey_statekey is invalid unicode.")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -930,7 +933,7 @@ impl Rooms {
|
|||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
event_type: &EventType,
|
event_type: &EventType,
|
||||||
state_key: &str,
|
state_key: &str,
|
||||||
) -> Result<Option<Arc<EventId>>> {
|
) -> Result<Option<EventId>> {
|
||||||
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
||||||
self.state_get_id(current_shortstatehash, event_type, state_key)
|
self.state_get_id(current_shortstatehash, event_type, state_key)
|
||||||
} else {
|
} else {
|
||||||
@@ -956,8 +959,10 @@ impl Rooms {
|
|||||||
/// Returns the `count` of this pdu's id.
|
/// Returns the `count` of this pdu's id.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn pdu_count(&self, pdu_id: &[u8]) -> Result<u64> {
|
pub fn pdu_count(&self, pdu_id: &[u8]) -> Result<u64> {
|
||||||
utils::u64_from_bytes(&pdu_id[pdu_id.len() - size_of::<u64>()..])
|
Ok(
|
||||||
.map_err(|_| Error::bad_database("PDU has invalid count bytes."))
|
utils::u64_from_bytes(&pdu_id[pdu_id.len() - size_of::<u64>()..])
|
||||||
|
.map_err(|_| Error::bad_database("PDU has invalid count bytes."))?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `count` of this pdu's id.
|
/// Returns the `count` of this pdu's id.
|
||||||
@@ -1074,7 +1079,7 @@ impl Rooms {
|
|||||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
||||||
if let Some(p) = self.pdu_cache.lock().unwrap().get_mut(event_id) {
|
if let Some(p) = self.pdu_cache.lock().unwrap().get_mut(&event_id) {
|
||||||
return Ok(Some(Arc::clone(p)));
|
return Ok(Some(Arc::clone(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1136,9 +1141,9 @@ impl Rooms {
|
|||||||
/// Removes a pdu and creates a new one with the same id.
|
/// Removes a pdu and creates a new one with the same id.
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
fn replace_pdu(&self, pdu_id: &[u8], pdu: &PduEvent) -> Result<()> {
|
fn replace_pdu(&self, pdu_id: &[u8], pdu: &PduEvent) -> Result<()> {
|
||||||
if self.pduid_pdu.get(pdu_id)?.is_some() {
|
if self.pduid_pdu.get(&pdu_id)?.is_some() {
|
||||||
self.pduid_pdu.insert(
|
self.pduid_pdu.insert(
|
||||||
pdu_id,
|
&pdu_id,
|
||||||
&serde_json::to_vec(pdu).expect("PduEvent::to_vec always works"),
|
&serde_json::to_vec(pdu).expect("PduEvent::to_vec always works"),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1223,20 +1228,20 @@ impl Rooms {
|
|||||||
#[tracing::instrument(skip(self, pdu))]
|
#[tracing::instrument(skip(self, pdu))]
|
||||||
pub fn add_pdu_outlier(&self, event_id: &EventId, pdu: &CanonicalJsonObject) -> Result<()> {
|
pub fn add_pdu_outlier(&self, event_id: &EventId, pdu: &CanonicalJsonObject) -> Result<()> {
|
||||||
self.eventid_outlierpdu.insert(
|
self.eventid_outlierpdu.insert(
|
||||||
event_id.as_bytes(),
|
&event_id.as_bytes(),
|
||||||
&serde_json::to_vec(&pdu).expect("CanonicalJsonObject is valid"),
|
&serde_json::to_vec(&pdu).expect("CanonicalJsonObject is valid"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn mark_event_soft_failed(&self, event_id: &EventId) -> Result<()> {
|
pub fn mark_event_soft_failed(&self, event_id: &EventId) -> Result<()> {
|
||||||
self.softfailedeventids.insert(event_id.as_bytes(), &[])
|
self.softfailedeventids.insert(&event_id.as_bytes(), &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn is_event_soft_failed(&self, event_id: &EventId) -> Result<bool> {
|
pub fn is_event_soft_failed(&self, event_id: &EventId) -> Result<bool> {
|
||||||
self.softfailedeventids
|
self.softfailedeventids
|
||||||
.get(event_id.as_bytes())
|
.get(&event_id.as_bytes())
|
||||||
.map(|o| o.is_some())
|
.map(|o| o.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1266,7 +1271,7 @@ impl Rooms {
|
|||||||
{
|
{
|
||||||
if let Some(shortstatehash) = self.pdu_shortstatehash(&pdu.event_id).unwrap() {
|
if let Some(shortstatehash) = self.pdu_shortstatehash(&pdu.event_id).unwrap() {
|
||||||
if let Some(prev_state) = self
|
if let Some(prev_state) = self
|
||||||
.state_get(shortstatehash, &pdu.kind, state_key)
|
.state_get(shortstatehash, &pdu.kind, &state_key)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
unsigned.insert(
|
unsigned.insert(
|
||||||
@@ -1348,15 +1353,15 @@ impl Rooms {
|
|||||||
|
|
||||||
let rules_for_user = db
|
let rules_for_user = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<push_rules::PushRulesEvent>(None, user, EventType::PushRules)?
|
.get::<push_rules::PushRulesEvent>(None, &user, EventType::PushRules)?
|
||||||
.map(|ev| ev.content.global)
|
.map(|ev| ev.content.global)
|
||||||
.unwrap_or_else(|| push::Ruleset::server_default(user));
|
.unwrap_or_else(|| push::Ruleset::server_default(&user));
|
||||||
|
|
||||||
let mut highlight = false;
|
let mut highlight = false;
|
||||||
let mut notify = false;
|
let mut notify = false;
|
||||||
|
|
||||||
for action in pusher::get_actions(
|
for action in pusher::get_actions(
|
||||||
user,
|
&user,
|
||||||
&rules_for_user,
|
&rules_for_user,
|
||||||
&power_levels,
|
&power_levels,
|
||||||
&sync_pdu,
|
&sync_pdu,
|
||||||
@@ -1386,7 +1391,7 @@ impl Rooms {
|
|||||||
highlights.push(userroom_id);
|
highlights.push(userroom_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for senderkey in db.pusher.get_pusher_senderkeys(user) {
|
for senderkey in db.pusher.get_pusher_senderkeys(&user) {
|
||||||
db.sending.send_push_pdu(&*pdu_id, senderkey)?;
|
db.sending.send_push_pdu(&*pdu_id, senderkey)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1399,7 +1404,7 @@ impl Rooms {
|
|||||||
match pdu.kind {
|
match pdu.kind {
|
||||||
EventType::RoomRedaction => {
|
EventType::RoomRedaction => {
|
||||||
if let Some(redact_id) = &pdu.redacts {
|
if let Some(redact_id) = &pdu.redacts {
|
||||||
self.redact_pdu(redact_id, pdu)?;
|
self.redact_pdu(&redact_id, &pdu)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventType::RoomMember => {
|
EventType::RoomMember => {
|
||||||
@@ -1536,7 +1541,7 @@ impl Rooms {
|
|||||||
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();
|
||||||
@@ -1739,9 +1744,9 @@ impl Rooms {
|
|||||||
state_ids_compressed: HashSet<CompressedStateEvent>,
|
state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let shorteventid = self.get_or_create_shorteventid(event_id, globals)?;
|
let shorteventid = self.get_or_create_shorteventid(&event_id, globals)?;
|
||||||
|
|
||||||
let previous_shortstatehash = self.current_shortstatehash(room_id)?;
|
let previous_shortstatehash = self.current_shortstatehash(&room_id)?;
|
||||||
|
|
||||||
let state_hash = self.calculate_hash(
|
let state_hash = self.calculate_hash(
|
||||||
&state_ids_compressed
|
&state_ids_compressed
|
||||||
@@ -1813,7 +1818,7 @@ impl Rooms {
|
|||||||
.map_or_else(|| Ok(Vec::new()), |p| self.load_shortstatehash_info(p))?;
|
.map_or_else(|| Ok(Vec::new()), |p| self.load_shortstatehash_info(p))?;
|
||||||
|
|
||||||
let shortstatekey =
|
let shortstatekey =
|
||||||
self.get_or_create_shortstatekey(&new_pdu.kind, state_key, globals)?;
|
self.get_or_create_shortstatekey(&new_pdu.kind, &state_key, globals)?;
|
||||||
|
|
||||||
let new = self.compress_state_event(shortstatekey, &new_pdu.event_id, globals)?;
|
let new = self.compress_state_event(shortstatekey, &new_pdu.event_id, globals)?;
|
||||||
|
|
||||||
@@ -1838,7 +1843,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let mut statediffremoved = HashSet::new();
|
let mut statediffremoved = HashSet::new();
|
||||||
if let Some(replaces) = replaces {
|
if let Some(replaces) = replaces {
|
||||||
statediffremoved.insert(*replaces);
|
statediffremoved.insert(replaces.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.save_state_from_diff(
|
self.save_state_from_diff(
|
||||||
@@ -1951,12 +1956,12 @@ impl Rooms {
|
|||||||
} = pdu_builder;
|
} = pdu_builder;
|
||||||
|
|
||||||
let prev_events = self
|
let prev_events = self
|
||||||
.get_pdu_leaves(room_id)?
|
.get_pdu_leaves(&room_id)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.take(20)
|
.take(20)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let create_event = self.room_state_get(room_id, &EventType::RoomCreate, "")?;
|
let create_event = self.room_state_get(&room_id, &EventType::RoomCreate, "")?;
|
||||||
|
|
||||||
let create_event_content = create_event
|
let create_event_content = create_event
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1986,8 +1991,13 @@ impl Rooms {
|
|||||||
});
|
});
|
||||||
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 = self.get_auth_events(
|
||||||
self.get_auth_events(room_id, &event_type, sender, state_key.as_deref(), &content)?;
|
&room_id,
|
||||||
|
&event_type,
|
||||||
|
&sender,
|
||||||
|
state_key.as_deref(),
|
||||||
|
&content,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Our depth is the maximum depth of prev_events + 1
|
// Our depth is the maximum depth of prev_events + 1
|
||||||
let depth = prev_events
|
let depth = prev_events
|
||||||
@@ -1999,7 +2009,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let mut unsigned = unsigned.unwrap_or_default();
|
let mut unsigned = unsigned.unwrap_or_default();
|
||||||
if let Some(state_key) = &state_key {
|
if let Some(state_key) = &state_key {
|
||||||
if let Some(prev_pdu) = self.room_state_get(room_id, &event_type, state_key)? {
|
if let Some(prev_pdu) = self.room_state_get(&room_id, &event_type, &state_key)? {
|
||||||
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(),
|
||||||
@@ -2034,10 +2044,10 @@ impl Rooms {
|
|||||||
|
|
||||||
let auth_check = state_res::auth_check(
|
let auth_check = state_res::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&pdu,
|
&Arc::new(pdu.clone()),
|
||||||
create_prev_event,
|
create_prev_event,
|
||||||
None::<PduEvent>, // TODO: third_party_invite
|
None, // TODO: third_party_invite
|
||||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
|k, s| auth_events.get(&(k.clone(), s.to_owned())).map(Arc::clone),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("{:?}", e);
|
error!("{:?}", e);
|
||||||
@@ -2102,7 +2112,7 @@ impl Rooms {
|
|||||||
|
|
||||||
// We set the room state after inserting the pdu, so that we never have a moment in time
|
// We set the room state after inserting the pdu, so that we never have a moment in time
|
||||||
// where events in the current room state do not exist
|
// where events in the current room state do not exist
|
||||||
self.set_room_state(room_id, statehashid)?;
|
self.set_room_state(&room_id, statehashid)?;
|
||||||
|
|
||||||
for server in self
|
for server in self
|
||||||
.room_servers(room_id)
|
.room_servers(room_id)
|
||||||
@@ -2147,10 +2157,10 @@ impl Rooms {
|
|||||||
&& pdu
|
&& pdu
|
||||||
.state_key
|
.state_key
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |state_key| users.is_match(state_key))
|
.map_or(false, |state_key| users.is_match(&state_key))
|
||||||
};
|
};
|
||||||
let matching_aliases = |aliases: &Regex| {
|
let matching_aliases = |aliases: &Regex| {
|
||||||
self.room_aliases(room_id)
|
self.room_aliases(&room_id)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.any(|room_alias| aliases.is_match(room_alias.as_str()))
|
.any(|room_alias| aliases.is_match(room_alias.as_str()))
|
||||||
};
|
};
|
||||||
@@ -2293,7 +2303,7 @@ impl Rooms {
|
|||||||
let mut pdu = self
|
let mut pdu = self
|
||||||
.get_pdu_from_id(&pdu_id)?
|
.get_pdu_from_id(&pdu_id)?
|
||||||
.ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?;
|
.ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?;
|
||||||
pdu.redact(reason)?;
|
pdu.redact(&reason)?;
|
||||||
self.replace_pdu(&pdu_id, &pdu)?;
|
self.replace_pdu(&pdu_id, &pdu)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@@ -2341,13 +2351,13 @@ impl Rooms {
|
|||||||
match &membership {
|
match &membership {
|
||||||
member::MembershipState::Join => {
|
member::MembershipState::Join => {
|
||||||
// Check if the user never joined this room
|
// Check if the user never joined this room
|
||||||
if !self.once_joined(user_id, room_id)? {
|
if !self.once_joined(&user_id, &room_id)? {
|
||||||
// Add the user ID to the join list then
|
// Add the user ID to the join list then
|
||||||
self.roomuseroncejoinedids.insert(&userroom_id, &[])?;
|
self.roomuseroncejoinedids.insert(&userroom_id, &[])?;
|
||||||
|
|
||||||
// Check if the room has a predecessor
|
// Check if the room has a predecessor
|
||||||
if let Some(predecessor) = self
|
if let Some(predecessor) = self
|
||||||
.room_state_get(room_id, &EventType::RoomCreate, "")?
|
.room_state_get(&room_id, &EventType::RoomCreate, "")?
|
||||||
.and_then(|create| {
|
.and_then(|create| {
|
||||||
serde_json::from_value::<
|
serde_json::from_value::<
|
||||||
Raw<ruma::events::room::create::CreateEventContent>,
|
Raw<ruma::events::room::create::CreateEventContent>,
|
||||||
@@ -2448,12 +2458,12 @@ impl Rooms {
|
|||||||
let is_ignored = db
|
let is_ignored = db
|
||||||
.account_data
|
.account_data
|
||||||
.get::<ignored_user_list::IgnoredUserListEvent>(
|
.get::<ignored_user_list::IgnoredUserListEvent>(
|
||||||
None, // Ignored users are in global account data
|
None, // Ignored users are in global account data
|
||||||
user_id, // Receiver
|
&user_id, // Receiver
|
||||||
EventType::IgnoredUserList,
|
EventType::IgnoredUserList,
|
||||||
)?
|
)?
|
||||||
.map_or(false, |ignored| {
|
.map_or(false, |ignored| {
|
||||||
ignored.content.ignored_users.contains(sender)
|
ignored.content.ignored_users.contains(&sender)
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_ignored {
|
if is_ignored {
|
||||||
@@ -2515,7 +2525,7 @@ impl Rooms {
|
|||||||
let mut joined_servers = HashSet::new();
|
let mut joined_servers = HashSet::new();
|
||||||
let mut real_users = HashSet::new();
|
let mut real_users = HashSet::new();
|
||||||
|
|
||||||
for joined in self.room_members(room_id).filter_map(|r| r.ok()) {
|
for joined in self.room_members(&room_id).filter_map(|r| r.ok()) {
|
||||||
joined_servers.insert(joined.server_name().to_owned());
|
joined_servers.insert(joined.server_name().to_owned());
|
||||||
if joined.server_name() == db.globals.server_name()
|
if joined.server_name() == db.globals.server_name()
|
||||||
&& !db.users.is_deactivated(&joined).unwrap_or(true)
|
&& !db.users.is_deactivated(&joined).unwrap_or(true)
|
||||||
@@ -2525,7 +2535,7 @@ impl Rooms {
|
|||||||
joinedcount += 1;
|
joinedcount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for invited in self.room_members_invited(room_id).filter_map(|r| r.ok()) {
|
for invited in self.room_members_invited(&room_id).filter_map(|r| r.ok()) {
|
||||||
joined_servers.insert(invited.server_name().to_owned());
|
joined_servers.insert(invited.server_name().to_owned());
|
||||||
invitedcount += 1;
|
invitedcount += 1;
|
||||||
}
|
}
|
||||||
@@ -2594,7 +2604,7 @@ impl Rooms {
|
|||||||
if let Some(users) = maybe {
|
if let Some(users) = maybe {
|
||||||
Ok(users)
|
Ok(users)
|
||||||
} else {
|
} else {
|
||||||
self.update_joined_count(room_id, db)?;
|
self.update_joined_count(room_id, &db)?;
|
||||||
Ok(Arc::clone(
|
Ok(Arc::clone(
|
||||||
self.our_real_users_cache
|
self.our_real_users_cache
|
||||||
.read()
|
.read()
|
||||||
@@ -2643,7 +2653,7 @@ impl Rooms {
|
|||||||
|
|
||||||
let in_room = bridge_user_id
|
let in_room = bridge_user_id
|
||||||
.map_or(false, |id| self.is_joined(&id, room_id).unwrap_or(false))
|
.map_or(false, |id| self.is_joined(&id, room_id).unwrap_or(false))
|
||||||
|| self.room_members(room_id).any(|userid| {
|
|| self.room_members(&room_id).any(|userid| {
|
||||||
userid.map_or(false, |userid| {
|
userid.map_or(false, |userid| {
|
||||||
users.iter().any(|r| r.is_match(userid.as_str()))
|
users.iter().any(|r| r.is_match(userid.as_str()))
|
||||||
})
|
})
|
||||||
@@ -2883,21 +2893,21 @@ impl Rooms {
|
|||||||
if let Some(room_id) = room_id {
|
if let Some(room_id) = room_id {
|
||||||
// New alias
|
// New alias
|
||||||
self.alias_roomid
|
self.alias_roomid
|
||||||
.insert(alias.alias().as_bytes(), room_id.as_bytes())?;
|
.insert(&alias.alias().as_bytes(), room_id.as_bytes())?;
|
||||||
let mut aliasid = room_id.as_bytes().to_vec();
|
let mut aliasid = room_id.as_bytes().to_vec();
|
||||||
aliasid.push(0xff);
|
aliasid.push(0xff);
|
||||||
aliasid.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
aliasid.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
||||||
self.aliasid_alias.insert(&aliasid, &*alias.as_bytes())?;
|
self.aliasid_alias.insert(&aliasid, &*alias.as_bytes())?;
|
||||||
} else {
|
} else {
|
||||||
// room_id=None means remove alias
|
// room_id=None means remove alias
|
||||||
if let Some(room_id) = self.alias_roomid.get(alias.alias().as_bytes())? {
|
if let Some(room_id) = self.alias_roomid.get(&alias.alias().as_bytes())? {
|
||||||
let mut prefix = room_id.to_vec();
|
let mut prefix = room_id.to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
||||||
for (key, _) in self.aliasid_alias.scan_prefix(prefix) {
|
for (key, _) in self.aliasid_alias.scan_prefix(prefix) {
|
||||||
self.aliasid_alias.remove(&key)?;
|
self.aliasid_alias.remove(&key)?;
|
||||||
}
|
}
|
||||||
self.alias_roomid.remove(alias.alias().as_bytes())?;
|
self.alias_roomid.remove(&alias.alias().as_bytes())?;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
@@ -3070,7 +3080,7 @@ impl Rooms {
|
|||||||
self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
|
self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
|
||||||
Box::<ServerName>::try_from(
|
Box::<ServerName>::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3103,7 +3113,7 @@ impl Rooms {
|
|||||||
self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
|
self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
|
||||||
RoomId::try_from(
|
RoomId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3125,7 +3135,7 @@ impl Rooms {
|
|||||||
self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
|
self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3139,24 +3149,26 @@ impl Rooms {
|
|||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
pub fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||||
self.roomid_joinedcount
|
Ok(self
|
||||||
|
.roomid_joinedcount
|
||||||
.get(room_id.as_bytes())?
|
.get(room_id.as_bytes())?
|
||||||
.map(|b| {
|
.map(|b| {
|
||||||
utils::u64_from_bytes(&b)
|
utils::u64_from_bytes(&b)
|
||||||
.map_err(|_| Error::bad_database("Invalid joinedcount in db."))
|
.map_err(|_| Error::bad_database("Invalid joinedcount in db."))
|
||||||
})
|
})
|
||||||
.transpose()
|
.transpose()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
pub fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||||
self.roomid_invitedcount
|
Ok(self
|
||||||
|
.roomid_invitedcount
|
||||||
.get(room_id.as_bytes())?
|
.get(room_id.as_bytes())?
|
||||||
.map(|b| {
|
.map(|b| {
|
||||||
utils::u64_from_bytes(&b)
|
utils::u64_from_bytes(&b)
|
||||||
.map_err(|_| Error::bad_database("Invalid joinedcount in db."))
|
.map_err(|_| Error::bad_database("Invalid joinedcount in db."))
|
||||||
})
|
})
|
||||||
.transpose()
|
.transpose()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all User IDs who ever joined a room.
|
/// Returns an iterator over all User IDs who ever joined a room.
|
||||||
@@ -3173,7 +3185,7 @@ impl Rooms {
|
|||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3199,7 +3211,7 @@ impl Rooms {
|
|||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
UserId::try_from(
|
UserId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3252,7 +3264,7 @@ impl Rooms {
|
|||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
RoomId::try_from(
|
RoomId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3278,7 +3290,7 @@ impl Rooms {
|
|||||||
.map(|(key, state)| {
|
.map(|(key, state)| {
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
@@ -3303,7 +3315,7 @@ impl Rooms {
|
|||||||
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
||||||
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(room_id.as_bytes());
|
key.extend_from_slice(&room_id.as_bytes());
|
||||||
|
|
||||||
self.userroomid_invitestate
|
self.userroomid_invitestate
|
||||||
.get(&key)?
|
.get(&key)?
|
||||||
@@ -3324,7 +3336,7 @@ impl Rooms {
|
|||||||
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
||||||
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(room_id.as_bytes());
|
key.extend_from_slice(&room_id.as_bytes());
|
||||||
|
|
||||||
self.userroomid_leftstate
|
self.userroomid_leftstate
|
||||||
.get(&key)?
|
.get(&key)?
|
||||||
@@ -3351,7 +3363,7 @@ impl Rooms {
|
|||||||
.map(|(key, state)| {
|
.map(|(key, state)| {
|
||||||
let room_id = RoomId::try_from(
|
let room_id = RoomId::try_from(
|
||||||
utils::string_from_bytes(
|
utils::string_from_bytes(
|
||||||
key.rsplit(|&b| b == 0xff)
|
&key.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.expect("rsplit always returns an element"),
|
.expect("rsplit always returns an element"),
|
||||||
)
|
)
|
||||||
|
|||||||
+13
-13
@@ -60,7 +60,7 @@ impl RoomEdus {
|
|||||||
let mut room_latest_id = prefix;
|
let mut room_latest_id = prefix;
|
||||||
room_latest_id.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
room_latest_id.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
||||||
room_latest_id.push(0xff);
|
room_latest_id.push(0xff);
|
||||||
room_latest_id.extend_from_slice(user_id.as_bytes());
|
room_latest_id.extend_from_slice(&user_id.as_bytes());
|
||||||
|
|
||||||
self.readreceiptid_readreceipt.insert(
|
self.readreceiptid_readreceipt.insert(
|
||||||
&room_latest_id,
|
&room_latest_id,
|
||||||
@@ -126,7 +126,7 @@ impl RoomEdus {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut key = room_id.as_bytes().to_vec();
|
let mut key = room_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(user_id.as_bytes());
|
key.extend_from_slice(&user_id.as_bytes());
|
||||||
|
|
||||||
self.roomuserid_privateread
|
self.roomuserid_privateread
|
||||||
.insert(&key, &count.to_be_bytes())?;
|
.insert(&key, &count.to_be_bytes())?;
|
||||||
@@ -142,7 +142,7 @@ impl RoomEdus {
|
|||||||
pub fn private_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
pub fn private_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||||
let mut key = room_id.as_bytes().to_vec();
|
let mut key = room_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(user_id.as_bytes());
|
key.extend_from_slice(&user_id.as_bytes());
|
||||||
|
|
||||||
self.roomuserid_privateread
|
self.roomuserid_privateread
|
||||||
.get(&key)?
|
.get(&key)?
|
||||||
@@ -157,7 +157,7 @@ impl RoomEdus {
|
|||||||
pub fn last_privateread_update(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
pub fn last_privateread_update(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||||
let mut key = room_id.as_bytes().to_vec();
|
let mut key = room_id.as_bytes().to_vec();
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(user_id.as_bytes());
|
key.extend_from_slice(&user_id.as_bytes());
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.roomuserid_lastprivatereadupdate
|
.roomuserid_lastprivatereadupdate
|
||||||
@@ -193,7 +193,7 @@ impl RoomEdus {
|
|||||||
.insert(&room_typing_id, &*user_id.as_bytes())?;
|
.insert(&room_typing_id, &*user_id.as_bytes())?;
|
||||||
|
|
||||||
self.roomid_lasttypingupdate
|
self.roomid_lasttypingupdate
|
||||||
.insert(room_id.as_bytes(), &count)?;
|
.insert(&room_id.as_bytes(), &count)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ impl RoomEdus {
|
|||||||
|
|
||||||
if found_outdated {
|
if found_outdated {
|
||||||
self.roomid_lasttypingupdate
|
self.roomid_lasttypingupdate
|
||||||
.insert(room_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
.insert(&room_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -268,7 +268,7 @@ impl RoomEdus {
|
|||||||
|
|
||||||
if found_outdated {
|
if found_outdated {
|
||||||
self.roomid_lasttypingupdate
|
self.roomid_lasttypingupdate
|
||||||
.insert(room_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
.insert(&room_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -285,7 +285,7 @@ impl RoomEdus {
|
|||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.roomid_lasttypingupdate
|
.roomid_lasttypingupdate
|
||||||
.get(room_id.as_bytes())?
|
.get(&room_id.as_bytes())?
|
||||||
.map_or(Ok::<_, Error>(None), |bytes| {
|
.map_or(Ok::<_, Error>(None), |bytes| {
|
||||||
Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| {
|
Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")
|
Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")
|
||||||
@@ -342,7 +342,7 @@ impl RoomEdus {
|
|||||||
presence_id.push(0xff);
|
presence_id.push(0xff);
|
||||||
presence_id.extend_from_slice(&count);
|
presence_id.extend_from_slice(&count);
|
||||||
presence_id.push(0xff);
|
presence_id.push(0xff);
|
||||||
presence_id.extend_from_slice(presence.sender.as_bytes());
|
presence_id.extend_from_slice(&presence.sender.as_bytes());
|
||||||
|
|
||||||
self.presenceid_presence.insert(
|
self.presenceid_presence.insert(
|
||||||
&presence_id,
|
&presence_id,
|
||||||
@@ -361,7 +361,7 @@ impl RoomEdus {
|
|||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn ping_presence(&self, user_id: &UserId) -> Result<()> {
|
pub fn ping_presence(&self, user_id: &UserId) -> Result<()> {
|
||||||
self.userid_lastpresenceupdate.insert(
|
self.userid_lastpresenceupdate.insert(
|
||||||
user_id.as_bytes(),
|
&user_id.as_bytes(),
|
||||||
&utils::millis_since_unix_epoch().to_be_bytes(),
|
&utils::millis_since_unix_epoch().to_be_bytes(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ impl RoomEdus {
|
|||||||
/// Returns the timestamp of the last presence update of this user in millis since the unix epoch.
|
/// Returns the timestamp of the last presence update of this user in millis since the unix epoch.
|
||||||
pub fn last_presence_update(&self, user_id: &UserId) -> Result<Option<u64>> {
|
pub fn last_presence_update(&self, user_id: &UserId) -> Result<Option<u64>> {
|
||||||
self.userid_lastpresenceupdate
|
self.userid_lastpresenceupdate
|
||||||
.get(user_id.as_bytes())?
|
.get(&user_id.as_bytes())?
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
utils::u64_from_bytes(&bytes).map_err(|_| {
|
utils::u64_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("Invalid timestamp in userid_lastpresenceupdate.")
|
Error::bad_database("Invalid timestamp in userid_lastpresenceupdate.")
|
||||||
@@ -394,7 +394,7 @@ impl RoomEdus {
|
|||||||
presence_id.push(0xff);
|
presence_id.push(0xff);
|
||||||
presence_id.extend_from_slice(&last_update.to_be_bytes());
|
presence_id.extend_from_slice(&last_update.to_be_bytes());
|
||||||
presence_id.push(0xff);
|
presence_id.push(0xff);
|
||||||
presence_id.extend_from_slice(user_id.as_bytes());
|
presence_id.extend_from_slice(&user_id.as_bytes());
|
||||||
|
|
||||||
self.presenceid_presence
|
self.presenceid_presence
|
||||||
.get(&presence_id)?
|
.get(&presence_id)?
|
||||||
@@ -480,7 +480,7 @@ impl RoomEdus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.userid_lastpresenceupdate.insert(
|
self.userid_lastpresenceupdate.insert(
|
||||||
user_id.as_bytes(),
|
&user_id.as_bytes(),
|
||||||
&utils::millis_since_unix_epoch().to_be_bytes(),
|
&utils::millis_since_unix_epoch().to_be_bytes(),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -58,9 +58,9 @@ impl OutgoingKind {
|
|||||||
}
|
}
|
||||||
OutgoingKind::Push(user, pushkey) => {
|
OutgoingKind::Push(user, pushkey) => {
|
||||||
let mut p = b"$".to_vec();
|
let mut p = b"$".to_vec();
|
||||||
p.extend_from_slice(user);
|
p.extend_from_slice(&user);
|
||||||
p.push(0xff);
|
p.push(0xff);
|
||||||
p.extend_from_slice(pushkey);
|
p.extend_from_slice(&pushkey);
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
OutgoingKind::Normal(server) => {
|
OutgoingKind::Normal(server) => {
|
||||||
@@ -179,8 +179,8 @@ impl Sending {
|
|||||||
// Insert pdus we found
|
// Insert pdus we found
|
||||||
for (e, key) in &new_events {
|
for (e, key) in &new_events {
|
||||||
let value = if let SendingEventType::Edu(value) = &e.1 { &**value } else { &[] };
|
let value = if let SendingEventType::Edu(value) = &e.1 { &**value } else { &[] };
|
||||||
guard.sending.servercurrentevent_data.insert(key, value).unwrap();
|
guard.sending.servercurrentevent_data.insert(&key, value).unwrap();
|
||||||
guard.sending.servernameevent_data.remove(key).unwrap();
|
guard.sending.servernameevent_data.remove(&key).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
@@ -345,7 +345,7 @@ impl Sending {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let event =
|
let event =
|
||||||
serde_json::from_str::<AnySyncEphemeralRoomEvent>(read_receipt.json().get())
|
serde_json::from_str::<AnySyncEphemeralRoomEvent>(&read_receipt.json().get())
|
||||||
.map_err(|_| Error::bad_database("Invalid edu event in read_receipts."))?;
|
.map_err(|_| Error::bad_database("Invalid edu event in read_receipts."))?;
|
||||||
let federation_event = match event {
|
let federation_event = match event {
|
||||||
AnySyncEphemeralRoomEvent::Receipt(r) => {
|
AnySyncEphemeralRoomEvent::Receipt(r) => {
|
||||||
@@ -486,7 +486,7 @@ impl Sending {
|
|||||||
match event {
|
match event {
|
||||||
SendingEventType::Pdu(pdu_id) => {
|
SendingEventType::Pdu(pdu_id) => {
|
||||||
pdu_jsons.push(db.rooms
|
pdu_jsons.push(db.rooms
|
||||||
.get_pdu_from_id(pdu_id)
|
.get_pdu_from_id(&pdu_id)
|
||||||
.map_err(|e| (kind.clone(), e))?
|
.map_err(|e| (kind.clone(), e))?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
(
|
(
|
||||||
@@ -543,7 +543,7 @@ impl Sending {
|
|||||||
SendingEventType::Pdu(pdu_id) => {
|
SendingEventType::Pdu(pdu_id) => {
|
||||||
pdus.push(
|
pdus.push(
|
||||||
db.rooms
|
db.rooms
|
||||||
.get_pdu_from_id(pdu_id)
|
.get_pdu_from_id(&pdu_id)
|
||||||
.map_err(|e| (kind.clone(), e))?
|
.map_err(|e| (kind.clone(), e))?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
(
|
(
|
||||||
@@ -636,7 +636,7 @@ impl Sending {
|
|||||||
// TODO: check room version and remove event_id if needed
|
// TODO: check room version and remove event_id if needed
|
||||||
let raw = PduEvent::convert_to_outgoing_federation_event(
|
let raw = PduEvent::convert_to_outgoing_federation_event(
|
||||||
db.rooms
|
db.rooms
|
||||||
.get_pdu_json_from_id(pdu_id)
|
.get_pdu_json_from_id(&pdu_id)
|
||||||
.map_err(|e| (OutgoingKind::Normal(server.clone()), e))?
|
.map_err(|e| (OutgoingKind::Normal(server.clone()), e))?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
(
|
(
|
||||||
@@ -711,7 +711,7 @@ impl Sending {
|
|||||||
let event = parts
|
let event = parts
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
|
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
|
||||||
let server = utils::string_from_bytes(server).map_err(|_| {
|
let server = utils::string_from_bytes(&server).map_err(|_| {
|
||||||
Error::bad_database("Invalid server bytes in server_currenttransaction")
|
Error::bad_database("Invalid server bytes in server_currenttransaction")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -750,7 +750,7 @@ impl Sending {
|
|||||||
let event = parts
|
let event = parts
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
|
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
|
||||||
let server = utils::string_from_bytes(server).map_err(|_| {
|
let server = utils::string_from_bytes(&server).map_err(|_| {
|
||||||
Error::bad_database("Invalid server bytes in server_currenttransaction")
|
Error::bad_database("Invalid server bytes in server_currenttransaction")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl Uiaa {
|
|||||||
) -> Result<(bool, UiaaInfo)> {
|
) -> Result<(bool, UiaaInfo)> {
|
||||||
let mut uiaainfo = auth
|
let mut uiaainfo = auth
|
||||||
.session()
|
.session()
|
||||||
.map(|session| self.get_uiaa_session(user_id, device_id, session))
|
.map(|session| self.get_uiaa_session(&user_id, &device_id, session))
|
||||||
.unwrap_or_else(|| Ok(uiaainfo.clone()))?;
|
.unwrap_or_else(|| Ok(uiaainfo.clone()))?;
|
||||||
|
|
||||||
if uiaainfo.session.is_none() {
|
if uiaainfo.session.is_none() {
|
||||||
|
|||||||
+11
-11
@@ -81,13 +81,13 @@ impl Users {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Some((
|
Ok(Some((
|
||||||
UserId::try_from(utils::string_from_bytes(user_bytes).map_err(|_| {
|
UserId::try_from(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(|_| {
|
||||||
Error::bad_database("User ID in token_userdeviceid is invalid.")
|
Error::bad_database("User ID in token_userdeviceid is invalid.")
|
||||||
})?,
|
})?,
|
||||||
utils::string_from_bytes(device_bytes).map_err(|_| {
|
utils::string_from_bytes(&device_bytes).map_err(|_| {
|
||||||
Error::bad_database("Device ID in token_userdeviceid is invalid.")
|
Error::bad_database("Device ID in token_userdeviceid is invalid.")
|
||||||
})?,
|
})?,
|
||||||
)))
|
)))
|
||||||
@@ -121,7 +121,7 @@ impl Users {
|
|||||||
#[tracing::instrument(skip(self, user_id, password))]
|
#[tracing::instrument(skip(self, user_id, password))]
|
||||||
pub fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> {
|
pub fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> {
|
||||||
if let Some(password) = password {
|
if let Some(password) = password {
|
||||||
if let Ok(hash) = utils::calculate_hash(password) {
|
if let Ok(hash) = utils::calculate_hash(&password) {
|
||||||
self.userid_password
|
self.userid_password
|
||||||
.insert(user_id.as_bytes(), hash.as_bytes())?;
|
.insert(user_id.as_bytes(), hash.as_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -245,7 +245,7 @@ impl Users {
|
|||||||
.expect("Device::to_string never fails."),
|
.expect("Device::to_string never fails."),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.set_token(user_id, device_id, token)?;
|
self.set_token(user_id, &device_id, token)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ impl Users {
|
|||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
.map(|(bytes, _)| {
|
.map(|(bytes, _)| {
|
||||||
Ok(utils::string_from_bytes(
|
Ok(utils::string_from_bytes(
|
||||||
bytes
|
&bytes
|
||||||
.rsplit(|&b| b == 0xff)
|
.rsplit(|&b| b == 0xff)
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| Error::bad_database("UserDevice ID in db is invalid."))?,
|
.ok_or_else(|| Error::bad_database("UserDevice ID in db is invalid."))?,
|
||||||
@@ -357,7 +357,7 @@ impl Users {
|
|||||||
// TODO: Use DeviceKeyId::to_string when it's available (and update everything,
|
// TODO: Use DeviceKeyId::to_string when it's available (and update everything,
|
||||||
// because there are no wrapping quotation marks anymore)
|
// because there are no wrapping quotation marks anymore)
|
||||||
key.extend_from_slice(
|
key.extend_from_slice(
|
||||||
serde_json::to_string(one_time_key_key)
|
&serde_json::to_string(one_time_key_key)
|
||||||
.expect("DeviceKeyId::to_string always works")
|
.expect("DeviceKeyId::to_string always works")
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
);
|
);
|
||||||
@@ -368,7 +368,7 @@ impl Users {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.userid_lastonetimekeyupdate
|
self.userid_lastonetimekeyupdate
|
||||||
.insert(user_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
.insert(&user_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,7 @@ impl Users {
|
|||||||
#[tracing::instrument(skip(self, user_id))]
|
#[tracing::instrument(skip(self, user_id))]
|
||||||
pub fn last_one_time_keys_update(&self, user_id: &UserId) -> Result<u64> {
|
pub fn last_one_time_keys_update(&self, user_id: &UserId) -> Result<u64> {
|
||||||
self.userid_lastonetimekeyupdate
|
self.userid_lastonetimekeyupdate
|
||||||
.get(user_id.as_bytes())?
|
.get(&user_id.as_bytes())?
|
||||||
.map(|bytes| {
|
.map(|bytes| {
|
||||||
utils::u64_from_bytes(&bytes).map_err(|_| {
|
utils::u64_from_bytes(&bytes).map_err(|_| {
|
||||||
Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")
|
Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")
|
||||||
@@ -402,7 +402,7 @@ impl Users {
|
|||||||
prefix.push(b':');
|
prefix.push(b':');
|
||||||
|
|
||||||
self.userid_lastonetimekeyupdate
|
self.userid_lastonetimekeyupdate
|
||||||
.insert(user_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
.insert(&user_id.as_bytes(), &globals.next_count()?.to_be_bytes())?;
|
||||||
|
|
||||||
self.onetimekeyid_onetimekeys
|
self.onetimekeyid_onetimekeys
|
||||||
.scan_prefix(prefix)
|
.scan_prefix(prefix)
|
||||||
@@ -680,7 +680,7 @@ impl Users {
|
|||||||
globals: &super::globals::Globals,
|
globals: &super::globals::Globals,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let count = globals.next_count()?.to_be_bytes();
|
let count = globals.next_count()?.to_be_bytes();
|
||||||
for room_id in rooms.rooms_joined(user_id).filter_map(|r| r.ok()) {
|
for room_id in rooms.rooms_joined(&user_id).filter_map(|r| r.ok()) {
|
||||||
// Don't send key updates to unencrypted rooms
|
// Don't send key updates to unencrypted rooms
|
||||||
if rooms
|
if rooms
|
||||||
.room_state_get(&room_id, &EventType::RoomEncryption, "")?
|
.room_state_get(&room_id, &EventType::RoomEncryption, "")?
|
||||||
@@ -961,7 +961,7 @@ impl Users {
|
|||||||
pub fn deactivate_account(&self, user_id: &UserId) -> Result<()> {
|
pub fn deactivate_account(&self, user_id: &UserId) -> Result<()> {
|
||||||
// Remove all associated devices
|
// Remove all associated devices
|
||||||
for device_id in self.all_device_ids(user_id) {
|
for device_id in self.all_device_ids(user_id) {
|
||||||
self.remove_device(user_id, &device_id?)?;
|
self.remove_device(&user_id, &device_id?)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the password to "" to indicate a deactivated account. Hashes will never result in an
|
// Set the password to "" to indicate a deactivated account. Hashes will never result in an
|
||||||
|
|||||||
+6
-17
@@ -199,27 +199,16 @@ async fn main() {
|
|||||||
|
|
||||||
std::env::set_var("RUST_LOG", "warn");
|
std::env::set_var("RUST_LOG", "warn");
|
||||||
|
|
||||||
let config = match raw_config.extract::<Config>() {
|
let config = raw_config
|
||||||
Ok(s) => s,
|
.extract::<Config>()
|
||||||
Err(e) => {
|
.expect("It looks like your config is invalid. Please take a look at the error");
|
||||||
eprintln!("It looks like your config is invalid. The following error occured while parsing it: {}", e);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let start = async {
|
let start = async {
|
||||||
config.warn_deprecated();
|
config.warn_deprecated();
|
||||||
|
|
||||||
let db = match Database::load_or_create(&config).await {
|
let db = Database::load_or_create(&config)
|
||||||
Ok(db) => db,
|
.await
|
||||||
Err(e) => {
|
.expect("config is valid");
|
||||||
eprintln!(
|
|
||||||
"The database couldn't be loaded or created. The following error occured: {}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let rocket = setup_rocket(raw_config, Arc::clone(&db))
|
let rocket = setup_rocket(raw_config, Arc::clone(&db))
|
||||||
.ignite()
|
.ignite()
|
||||||
|
|||||||
+10
-20
@@ -260,47 +260,37 @@ impl state_res::Event for PduEvent {
|
|||||||
fn sender(&self) -> &UserId {
|
fn sender(&self) -> &UserId {
|
||||||
&self.sender
|
&self.sender
|
||||||
}
|
}
|
||||||
|
fn kind(&self) -> EventType {
|
||||||
fn event_type(&self) -> &EventType {
|
self.kind.clone()
|
||||||
&self.kind
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content(&self) -> &serde_json::Value {
|
fn content(&self) -> serde_json::Value {
|
||||||
&self.content
|
self.content.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
|
fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
|
||||||
MilliSecondsSinceUnixEpoch(self.origin_server_ts)
|
MilliSecondsSinceUnixEpoch(self.origin_server_ts)
|
||||||
}
|
}
|
||||||
|
fn state_key(&self) -> Option<String> {
|
||||||
fn state_key(&self) -> Option<&str> {
|
self.state_key.clone()
|
||||||
self.state_key.as_deref()
|
|
||||||
}
|
}
|
||||||
|
fn prev_events(&self) -> Vec<EventId> {
|
||||||
fn prev_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
|
self.prev_events.to_vec()
|
||||||
Box::new(self.prev_events.iter())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depth(&self) -> &UInt {
|
fn depth(&self) -> &UInt {
|
||||||
&self.depth
|
&self.depth
|
||||||
}
|
}
|
||||||
|
fn auth_events(&self) -> Vec<EventId> {
|
||||||
fn auth_events(&self) -> Box<dyn DoubleEndedIterator<Item = &EventId> + '_> {
|
self.auth_events.to_vec()
|
||||||
Box::new(self.auth_events.iter())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redacts(&self) -> Option<&EventId> {
|
fn redacts(&self) -> Option<&EventId> {
|
||||||
self.redacts.as_ref()
|
self.redacts.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &EventHash {
|
fn hashes(&self) -> &EventHash {
|
||||||
&self.hashes
|
&self.hashes
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signatures(&self) -> BTreeMap<Box<ServerName>, BTreeMap<ruma::ServerSigningKeyId, String>> {
|
fn signatures(&self) -> BTreeMap<Box<ServerName>, BTreeMap<ruma::ServerSigningKeyId, String>> {
|
||||||
self.signatures.clone()
|
self.signatures.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned(&self) -> &BTreeMap<String, serde_json::Value> {
|
fn unsigned(&self) -> &BTreeMap<String, serde_json::Value> {
|
||||||
&self.unsigned
|
&self.unsigned
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -66,7 +66,7 @@ where
|
|||||||
let limit = db.globals.max_request_size();
|
let limit = db.globals.max_request_size();
|
||||||
let mut handle = data.open(ByteUnit::Byte(limit.into()));
|
let mut handle = data.open(ByteUnit::Byte(limit.into()));
|
||||||
let mut body = Vec::new();
|
let mut body = Vec::new();
|
||||||
if handle.read_to_end(&mut body).await.is_err() {
|
if let Err(_) = handle.read_to_end(&mut body).await {
|
||||||
// Client disconnected
|
// Client disconnected
|
||||||
// Missing Token
|
// Missing Token
|
||||||
return Failure((Status::new(582), ()));
|
return Failure((Status::new(582), ()));
|
||||||
@@ -123,7 +123,7 @@ where
|
|||||||
match metadata.authentication {
|
match metadata.authentication {
|
||||||
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
||||||
if let Some(token) = token {
|
if let Some(token) = token {
|
||||||
match db.users.find_from_token(token).unwrap() {
|
match db.users.find_from_token(&token).unwrap() {
|
||||||
// Unknown Token
|
// Unknown Token
|
||||||
None => return Failure((Status::new(581), ())),
|
None => return Failure((Status::new(581), ())),
|
||||||
Some((user_id, device_id)) => (
|
Some((user_id, device_id)) => (
|
||||||
|
|||||||
+153
-164
@@ -150,7 +150,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
write_destination_to_cache = true;
|
write_destination_to_cache = true;
|
||||||
|
|
||||||
let result = find_actual_destination(globals, destination).await;
|
let result = find_actual_destination(globals, &destination).await;
|
||||||
|
|
||||||
(result.0, result.1.into_uri_string())
|
(result.0, result.1.into_uri_string())
|
||||||
};
|
};
|
||||||
@@ -359,7 +359,7 @@ async fn find_actual_destination(
|
|||||||
let (host, port) = destination_str.split_at(pos);
|
let (host, port) = destination_str.split_at(pos);
|
||||||
FedDest::Named(host.to_string(), port.to_string())
|
FedDest::Named(host.to_string(), port.to_string())
|
||||||
} else {
|
} else {
|
||||||
match request_well_known(globals, destination.as_str()).await {
|
match request_well_known(globals, &destination.as_str()).await {
|
||||||
// 3: A .well-known file is available
|
// 3: A .well-known file is available
|
||||||
Some(delegated_hostname) => {
|
Some(delegated_hostname) => {
|
||||||
hostname = add_port_to_hostname(&delegated_hostname).into_uri_string();
|
hostname = add_port_to_hostname(&delegated_hostname).into_uri_string();
|
||||||
@@ -806,7 +806,7 @@ pub async fn send_transaction_message_route(
|
|||||||
.event_ids
|
.event_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|id| {
|
.filter_map(|id| {
|
||||||
db.rooms.get_pdu_count(id).ok().flatten().map(|r| (id, r))
|
db.rooms.get_pdu_count(&id).ok().flatten().map(|r| (id, r))
|
||||||
})
|
})
|
||||||
.max_by_key(|(_, count)| *count)
|
.max_by_key(|(_, count)| *count)
|
||||||
{
|
{
|
||||||
@@ -875,8 +875,8 @@ pub async fn send_transaction_message_route(
|
|||||||
DeviceIdOrAllDevices::DeviceId(target_device_id) => {
|
DeviceIdOrAllDevices::DeviceId(target_device_id) => {
|
||||||
db.users.add_to_device_event(
|
db.users.add_to_device_event(
|
||||||
&sender,
|
&sender,
|
||||||
target_user_id,
|
&target_user_id,
|
||||||
target_device_id,
|
&target_device_id,
|
||||||
&ev_type.to_string(),
|
&ev_type.to_string(),
|
||||||
event.deserialize_as().map_err(|_| {
|
event.deserialize_as().map_err(|_| {
|
||||||
Error::BadRequest(
|
Error::BadRequest(
|
||||||
@@ -889,10 +889,10 @@ pub async fn send_transaction_message_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceIdOrAllDevices::AllDevices => {
|
DeviceIdOrAllDevices::AllDevices => {
|
||||||
for target_device_id in db.users.all_device_ids(target_user_id) {
|
for target_device_id in db.users.all_device_ids(&target_user_id) {
|
||||||
db.users.add_to_device_event(
|
db.users.add_to_device_event(
|
||||||
&sender,
|
&sender,
|
||||||
target_user_id,
|
&target_user_id,
|
||||||
&target_device_id?,
|
&target_device_id?,
|
||||||
&ev_type.to_string(),
|
&ev_type.to_string(),
|
||||||
event.deserialize_as().map_err(|_| {
|
event.deserialize_as().map_err(|_| {
|
||||||
@@ -959,7 +959,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
db: &'a Database,
|
db: &'a Database,
|
||||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
||||||
) -> StdResult<Option<Vec<u8>>, String> {
|
) -> StdResult<Option<Vec<u8>>, String> {
|
||||||
match db.rooms.exists(room_id) {
|
match db.rooms.exists(&room_id) {
|
||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
_ => {
|
_ => {
|
||||||
return Err("Room is unknown to this server.".to_string());
|
return Err("Room is unknown to this server.".to_string());
|
||||||
@@ -967,22 +967,16 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. Skip the PDU if we already have it as a timeline event
|
// 1. Skip the PDU if we already have it as a timeline event
|
||||||
if let Ok(Some(pdu_id)) = db.rooms.get_pdu_id(event_id) {
|
if let Ok(Some(pdu_id)) = db.rooms.get_pdu_id(&event_id) {
|
||||||
return Ok(Some(pdu_id.to_vec()));
|
return Ok(Some(pdu_id.to_vec()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let create_event = db
|
let create_event = db
|
||||||
.rooms
|
.rooms
|
||||||
.room_state_get(room_id, &EventType::RoomCreate, "")
|
.room_state_get(&room_id, &EventType::RoomCreate, "")
|
||||||
.map_err(|_| "Failed to ask database for event.".to_owned())?
|
.map_err(|_| "Failed to ask database for event.".to_owned())?
|
||||||
.ok_or_else(|| "Failed to find create event in db.".to_owned())?;
|
.ok_or_else(|| "Failed to find create event in db.".to_owned())?;
|
||||||
|
|
||||||
let first_pdu_in_room = db
|
|
||||||
.rooms
|
|
||||||
.first_pdu_in_room(room_id)
|
|
||||||
.map_err(|_| "Error loading first room event.".to_owned())?
|
|
||||||
.expect("Room exists");
|
|
||||||
|
|
||||||
let (incoming_pdu, val) = handle_outlier_pdu(
|
let (incoming_pdu, val) = handle_outlier_pdu(
|
||||||
origin,
|
origin,
|
||||||
&create_event,
|
&create_event,
|
||||||
@@ -999,19 +993,20 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if incoming_pdu.origin_server_ts < first_pdu_in_room.origin_server_ts {
|
if incoming_pdu.origin_server_ts
|
||||||
|
< db.rooms
|
||||||
|
.first_pdu_in_room(&room_id)
|
||||||
|
.map_err(|_| "Error loading first room event.".to_owned())?
|
||||||
|
.expect("Room exists")
|
||||||
|
.origin_server_ts
|
||||||
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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::new();
|
||||||
let mut eventid_info = HashMap::new();
|
let mut eventid_info = HashMap::new();
|
||||||
let mut todo_outlier_stack = incoming_pdu
|
let mut todo_outlier_stack = incoming_pdu.prev_events.clone();
|
||||||
.prev_events
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(Arc::new)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut amount = 0;
|
let mut amount = 0;
|
||||||
|
|
||||||
@@ -1021,7 +1016,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
origin,
|
origin,
|
||||||
&[prev_event_id.clone()],
|
&[prev_event_id.clone()],
|
||||||
&create_event,
|
&create_event,
|
||||||
room_id,
|
&room_id,
|
||||||
pub_key_map,
|
pub_key_map,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -1030,38 +1025,44 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(json) =
|
if let Some(json) =
|
||||||
json_opt.or_else(|| db.rooms.get_outlier_pdu_json(&prev_event_id).ok().flatten())
|
json_opt.or_else(|| db.rooms.get_outlier_pdu_json(&prev_event_id).ok().flatten())
|
||||||
{
|
{
|
||||||
if pdu.origin_server_ts > first_pdu_in_room.origin_server_ts {
|
if pdu.origin_server_ts
|
||||||
|
> db.rooms
|
||||||
|
.first_pdu_in_room(&room_id)
|
||||||
|
.map_err(|_| "Error loading first room event.".to_owned())?
|
||||||
|
.expect("Room exists")
|
||||||
|
.origin_server_ts
|
||||||
|
{
|
||||||
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(),
|
||||||
);
|
);
|
||||||
|
eventid_info.insert(prev_event_id.clone(), (pdu, json));
|
||||||
} 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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1076,7 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
MilliSecondsSinceUnixEpoch(
|
MilliSecondsSinceUnixEpoch(
|
||||||
eventid_info
|
eventid_info
|
||||||
.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.clone()),
|
||||||
),
|
),
|
||||||
ruma::event_id!("$notimportant"),
|
ruma::event_id!("$notimportant"),
|
||||||
))
|
))
|
||||||
@@ -1088,10 +1089,6 @@ pub(crate) async fn handle_incoming_pdu<'a>(
|
|||||||
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 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let event_id = pdu.event_id.clone();
|
let event_id = pdu.event_id.clone();
|
||||||
if let Err(e) = upgrade_outlier_to_timeline_pdu(
|
if let Err(e) = upgrade_outlier_to_timeline_pdu(
|
||||||
@@ -1146,7 +1143,7 @@ fn handle_outlier_pdu<'a>(
|
|||||||
|
|
||||||
// We go through all the signatures we see on the value and fetch the corresponding signing
|
// We go through all the signatures we see on the value and fetch the corresponding signing
|
||||||
// keys
|
// keys
|
||||||
fetch_required_signing_keys(&value, pub_key_map, db)
|
fetch_required_signing_keys(&value, &pub_key_map, db)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
@@ -1204,14 +1201,9 @@ fn handle_outlier_pdu<'a>(
|
|||||||
fetch_and_handle_outliers(
|
fetch_and_handle_outliers(
|
||||||
db,
|
db,
|
||||||
origin,
|
origin,
|
||||||
&incoming_pdu
|
&incoming_pdu.auth_events,
|
||||||
.auth_events
|
&create_event,
|
||||||
.iter()
|
&room_id,
|
||||||
.cloned()
|
|
||||||
.map(Arc::new)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
create_event,
|
|
||||||
room_id,
|
|
||||||
pub_key_map,
|
pub_key_map,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -1256,7 +1248,7 @@ fn handle_outlier_pdu<'a>(
|
|||||||
if auth_events
|
if auth_events
|
||||||
.get(&(EventType::RoomCreate, "".to_owned()))
|
.get(&(EventType::RoomCreate, "".to_owned()))
|
||||||
.map(|a| a.as_ref())
|
.map(|a| a.as_ref())
|
||||||
!= Some(create_event)
|
!= Some(&create_event)
|
||||||
{
|
{
|
||||||
return Err("Incoming event refers to wrong create event.".to_owned());
|
return Err("Incoming event refers to wrong create event.".to_owned());
|
||||||
}
|
}
|
||||||
@@ -1273,12 +1265,14 @@ fn handle_outlier_pdu<'a>(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let incoming_pdu = Arc::new(incoming_pdu.clone());
|
||||||
|
|
||||||
if !state_res::event_auth::auth_check(
|
if !state_res::event_auth::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
previous_create,
|
previous_create.clone(),
|
||||||
None::<PduEvent>, // TODO: third party invite
|
None, // TODO: third party invite
|
||||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
|k, s| auth_events.get(&(k.clone(), s.to_owned())).map(Arc::clone),
|
||||||
)
|
)
|
||||||
.map_err(|_e| "Auth check failed".to_string())?
|
.map_err(|_e| "Auth check failed".to_string())?
|
||||||
{
|
{
|
||||||
@@ -1293,7 +1287,7 @@ fn handle_outlier_pdu<'a>(
|
|||||||
.map_err(|_| "Failed to add pdu as outlier.".to_owned())?;
|
.map_err(|_| "Failed to add pdu as outlier.".to_owned())?;
|
||||||
debug!("Added pdu as outlier.");
|
debug!("Added pdu as outlier.");
|
||||||
|
|
||||||
Ok((Arc::new(incoming_pdu), val))
|
Ok((incoming_pdu, val))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,7 +1357,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, prev_event.clone());
|
||||||
// Now it's the state after the pdu
|
// Now it's the state after the pdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1393,48 +1387,52 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if okay {
|
if okay {
|
||||||
let mut fork_states = Vec::with_capacity(extremity_sstatehashes.len());
|
let fork_states: Vec<_> = extremity_sstatehashes
|
||||||
let mut auth_chain_sets = Vec::with_capacity(extremity_sstatehashes.len());
|
.into_iter()
|
||||||
|
.map(|(sstatehash, prev_event)| {
|
||||||
for (sstatehash, prev_event) in extremity_sstatehashes {
|
let mut leaf_state = db
|
||||||
let mut leaf_state: BTreeMap<_, _> = db
|
|
||||||
.rooms
|
|
||||||
.state_full_ids(sstatehash)
|
|
||||||
.map_err(|_| "Failed to ask db for room state.".to_owned())?;
|
|
||||||
|
|
||||||
if let Some(state_key) = &prev_event.state_key {
|
|
||||||
let shortstatekey = db
|
|
||||||
.rooms
|
.rooms
|
||||||
.get_or_create_shortstatekey(&prev_event.kind, state_key, &db.globals)
|
.state_full_ids(sstatehash)
|
||||||
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
.map_err(|_| "Failed to ask db for room state.".to_owned())?;
|
||||||
leaf_state.insert(shortstatekey, Arc::new(prev_event.event_id.clone()));
|
|
||||||
// Now it's the state after the pdu
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut state = StateMap::with_capacity(leaf_state.len());
|
if let Some(state_key) = &prev_event.state_key {
|
||||||
let mut starting_events = Vec::with_capacity(leaf_state.len());
|
let shortstatekey = db
|
||||||
|
.rooms
|
||||||
|
.get_or_create_shortstatekey(&prev_event.kind, state_key, &db.globals)
|
||||||
|
.map_err(|_| "Failed to create shortstatekey.".to_owned())?;
|
||||||
|
leaf_state.insert(shortstatekey, prev_event.event_id.clone());
|
||||||
|
// Now it's the state after the pdu
|
||||||
|
}
|
||||||
|
|
||||||
for (k, id) in leaf_state {
|
leaf_state
|
||||||
let k = db
|
.into_iter()
|
||||||
.rooms
|
.map(|(k, id)| (db.rooms.get_statekey_from_short(k).map(|k| (k, id))))
|
||||||
.get_statekey_from_short(k)
|
.collect::<Result<StateMap<_>>>()
|
||||||
.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());
|
.collect::<StdResult<_, _>>()?;
|
||||||
starting_events.push(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let mut auth_chain_sets = Vec::new();
|
||||||
|
for state in &fork_states {
|
||||||
auth_chain_sets.push(
|
auth_chain_sets.push(
|
||||||
get_auth_chain(room_id, starting_events, db)
|
get_auth_chain(
|
||||||
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
&room_id,
|
||||||
.map(|event_id| (*event_id).clone())
|
state.iter().map(|(_, id)| id.clone()).collect(),
|
||||||
.collect(),
|
db,
|
||||||
|
)
|
||||||
|
.map_err(|_| "Failed to load auth chain.".to_owned())?
|
||||||
|
.map(|event_id| event_id.clone())
|
||||||
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
fork_states.push(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fork_states = fork_states
|
||||||
|
.into_iter()
|
||||||
|
.map(|map| map.into_iter().map(|(k, id)| (k, id.clone())).collect())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
state_at_incoming_event = match state_res::resolve(
|
state_at_incoming_event = match state_res::resolve(
|
||||||
|
&room_id,
|
||||||
room_version_id,
|
room_version_id,
|
||||||
&fork_states,
|
&fork_states,
|
||||||
auth_chain_sets,
|
auth_chain_sets,
|
||||||
@@ -1454,7 +1452,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::<StdResult<_, String>>()?,
|
.collect::<StdResult<_, String>>()?,
|
||||||
),
|
),
|
||||||
@@ -1476,7 +1474,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
&db.globals,
|
&db.globals,
|
||||||
origin,
|
origin,
|
||||||
get_room_state_ids::v1::Request {
|
get_room_state_ids::v1::Request {
|
||||||
room_id,
|
room_id: &room_id,
|
||||||
event_id: &incoming_pdu.event_id,
|
event_id: &incoming_pdu.event_id,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -1485,15 +1483,11 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
warn!("Fetching state events at event.");
|
warn!("Fetching state events at event.");
|
||||||
let state_vec = fetch_and_handle_outliers(
|
let state_vec = fetch_and_handle_outliers(
|
||||||
db,
|
&db,
|
||||||
origin,
|
origin,
|
||||||
&res.pdu_ids
|
&res.pdu_ids,
|
||||||
.iter()
|
&create_event,
|
||||||
.cloned()
|
&room_id,
|
||||||
.map(Arc::new)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
create_event,
|
|
||||||
room_id,
|
|
||||||
pub_key_map,
|
pub_key_map,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -1512,7 +1506,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(pdu.event_id.clone());
|
||||||
}
|
}
|
||||||
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."
|
||||||
@@ -1528,9 +1522,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.map_err(|_| "Failed to talk to db.")?
|
.map_err(|_| "Failed to talk to db.")?
|
||||||
.expect("Room exists");
|
.expect("Room exists");
|
||||||
|
|
||||||
if state.get(&create_shortstatekey).map(|id| id.as_ref())
|
if state.get(&create_shortstatekey) != Some(&create_event.event_id) {
|
||||||
!= Some(&create_event.event_id)
|
|
||||||
{
|
|
||||||
return Err("Incoming event refers to wrong create event.".to_owned());
|
return Err("Incoming event refers to wrong create event.".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1562,15 +1554,15 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
let check_result = state_res::event_auth::auth_check(
|
let check_result = state_res::event_auth::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
previous_create.as_deref(),
|
previous_create.clone(),
|
||||||
None::<PduEvent>, // TODO: third party invite
|
None, // TODO: third party invite
|
||||||
|k, s| {
|
|k, s| {
|
||||||
db.rooms
|
db.rooms
|
||||||
.get_shortstatekey(k, s)
|
.get_shortstatekey(&k, &s)
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.and_then(|shortstatekey| state_at_incoming_event.get(&shortstatekey))
|
.and_then(|shortstatekey| state_at_incoming_event.get(&shortstatekey))
|
||||||
.and_then(|event_id| db.rooms.get_pdu(event_id).ok().flatten())
|
.and_then(|event_id| db.rooms.get_pdu(&event_id).ok().flatten())
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.map_err(|_e| "Auth check failed.".to_owned())?;
|
.map_err(|_e| "Auth check failed.".to_owned())?;
|
||||||
@@ -1596,7 +1588,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
// applied. We start with the previous extremities (aka leaves)
|
// applied. We start with the previous extremities (aka leaves)
|
||||||
let mut extremities = db
|
let mut extremities = db
|
||||||
.rooms
|
.rooms
|
||||||
.get_pdu_leaves(room_id)
|
.get_pdu_leaves(&room_id)
|
||||||
.map_err(|_| "Failed to load room leaves".to_owned())?;
|
.map_err(|_| "Failed to load room leaves".to_owned())?;
|
||||||
|
|
||||||
// Remove any forward extremities that are referenced by this incoming event's prev_events
|
// Remove any forward extremities that are referenced by this incoming event's prev_events
|
||||||
@@ -1607,11 +1599,11 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only keep those extremities were not referenced yet
|
// Only keep those extremities were not referenced yet
|
||||||
extremities.retain(|id| !matches!(db.rooms.is_event_referenced(room_id, id), Ok(true)));
|
extremities.retain(|id| !matches!(db.rooms.is_event_referenced(&room_id, id), Ok(true)));
|
||||||
|
|
||||||
let current_sstatehash = db
|
let current_sstatehash = db
|
||||||
.rooms
|
.rooms
|
||||||
.current_shortstatehash(room_id)
|
.current_shortstatehash(&room_id)
|
||||||
.map_err(|_| "Failed to load current state hash.".to_owned())?
|
.map_err(|_| "Failed to load current state hash.".to_owned())?
|
||||||
.expect("every room has state");
|
.expect("every room has state");
|
||||||
|
|
||||||
@@ -1623,7 +1615,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
let auth_events = db
|
let auth_events = db
|
||||||
.rooms
|
.rooms
|
||||||
.get_auth_events(
|
.get_auth_events(
|
||||||
room_id,
|
&room_id,
|
||||||
&incoming_pdu.kind,
|
&incoming_pdu.kind,
|
||||||
&incoming_pdu.sender,
|
&incoming_pdu.sender,
|
||||||
incoming_pdu.state_key.as_deref(),
|
incoming_pdu.state_key.as_deref(),
|
||||||
@@ -1635,7 +1627,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(shortstatekey, id)| {
|
.map(|(shortstatekey, id)| {
|
||||||
db.rooms
|
db.rooms
|
||||||
.compress_state_event(*shortstatekey, id, &db.globals)
|
.compress_state_event(*shortstatekey, &id, &db.globals)
|
||||||
.map_err(|_| "Failed to compress_state_event".to_owned())
|
.map_err(|_| "Failed to compress_state_event".to_owned())
|
||||||
})
|
})
|
||||||
.collect::<StdResult<_, String>>()?;
|
.collect::<StdResult<_, String>>()?;
|
||||||
@@ -1646,15 +1638,15 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
let soft_fail = !state_res::event_auth::auth_check(
|
let soft_fail = !state_res::event_auth::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
previous_create.as_deref(),
|
previous_create,
|
||||||
None::<PduEvent>,
|
None,
|
||||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
|k, s| auth_events.get(&(k.clone(), s.to_owned())).map(Arc::clone),
|
||||||
)
|
)
|
||||||
.map_err(|_e| "Auth check failed.".to_owned())?;
|
.map_err(|_e| "Auth check failed.".to_owned())?;
|
||||||
|
|
||||||
if soft_fail {
|
if soft_fail {
|
||||||
append_incoming_pdu(
|
append_incoming_pdu(
|
||||||
db,
|
&db,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
val,
|
val,
|
||||||
extremities,
|
extremities,
|
||||||
@@ -1678,7 +1670,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
for id in dbg!(&extremities) {
|
for id in dbg!(&extremities) {
|
||||||
match db
|
match db
|
||||||
.rooms
|
.rooms
|
||||||
.get_pdu(id)
|
.get_pdu(&id)
|
||||||
.map_err(|_| "Failed to ask db for pdu.".to_owned())?
|
.map_err(|_| "Failed to ask db for pdu.".to_owned())?
|
||||||
{
|
{
|
||||||
Some(leaf_pdu) => {
|
Some(leaf_pdu) => {
|
||||||
@@ -1725,7 +1717,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, leaf_pdu.event_id.clone());
|
||||||
// Now it's the state after the pdu
|
// Now it's the state after the pdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1740,9 +1732,9 @@ 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, incoming_pdu.event_id.clone());
|
||||||
}
|
}
|
||||||
fork_states.push(state_after);
|
fork_states.push(state_after.clone());
|
||||||
|
|
||||||
let mut update_state = false;
|
let mut update_state = false;
|
||||||
// 14. Use state resolution to find new room state
|
// 14. Use state resolution to find new room state
|
||||||
@@ -1755,7 +1747,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(k, id)| {
|
.map(|(k, id)| {
|
||||||
db.rooms
|
db.rooms
|
||||||
.compress_state_event(*k, id, &db.globals)
|
.compress_state_event(*k, &id, &db.globals)
|
||||||
.map_err(|_| "Failed to compress_state_event.".to_owned())
|
.map_err(|_| "Failed to compress_state_event.".to_owned())
|
||||||
})
|
})
|
||||||
.collect::<StdResult<_, String>>()?
|
.collect::<StdResult<_, String>>()?
|
||||||
@@ -1767,12 +1759,12 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
for state in &fork_states {
|
for state in &fork_states {
|
||||||
auth_chain_sets.push(
|
auth_chain_sets.push(
|
||||||
get_auth_chain(
|
get_auth_chain(
|
||||||
room_id,
|
&room_id,
|
||||||
state.iter().map(|(_, id)| id.clone()).collect(),
|
state.iter().map(|(_, id)| id.clone()).collect(),
|
||||||
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())
|
.map(|event_id| event_id.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1781,17 +1773,14 @@ 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.clone())))
|
||||||
db.rooms
|
|
||||||
.get_statekey_from_short(k)
|
|
||||||
.map(|k| (k, (*id).clone()))
|
|
||||||
})
|
|
||||||
.collect::<Result<StateMap<_>>>()
|
.collect::<Result<StateMap<_>>>()
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()
|
.collect::<Result<Vec<_>>>()
|
||||||
.map_err(|_| "Failed to get_statekey_from_short.".to_owned())?;
|
.map_err(|_| "Failed to get_statekey_from_short.".to_owned())?;
|
||||||
|
|
||||||
let state = match state_res::resolve(
|
let state = match state_res::resolve(
|
||||||
|
&room_id,
|
||||||
room_version_id,
|
room_version_id,
|
||||||
fork_states,
|
fork_states,
|
||||||
auth_chain_sets,
|
auth_chain_sets,
|
||||||
@@ -1826,7 +1815,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
// Set the new room state to the resolved state
|
// Set the new room state to the resolved state
|
||||||
if update_state {
|
if update_state {
|
||||||
db.rooms
|
db.rooms
|
||||||
.force_state(room_id, new_room_state, db)
|
.force_state(&room_id, new_room_state, &db)
|
||||||
.map_err(|_| "Failed to set new room state.".to_owned())?;
|
.map_err(|_| "Failed to set new room state.".to_owned())?;
|
||||||
}
|
}
|
||||||
debug!("Updated resolved state");
|
debug!("Updated resolved state");
|
||||||
@@ -1839,7 +1828,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
// represent the state for this event.
|
// represent the state for this event.
|
||||||
|
|
||||||
let pdu_id = append_incoming_pdu(
|
let pdu_id = append_incoming_pdu(
|
||||||
db,
|
&db,
|
||||||
&incoming_pdu,
|
&incoming_pdu,
|
||||||
val,
|
val,
|
||||||
extremities,
|
extremities,
|
||||||
@@ -1869,7 +1858,7 @@ async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
pub(crate) fn fetch_and_handle_outliers<'a>(
|
pub(crate) fn fetch_and_handle_outliers<'a>(
|
||||||
db: &'a Database,
|
db: &'a Database,
|
||||||
origin: &'a ServerName,
|
origin: &'a ServerName,
|
||||||
events: &'a [Arc<EventId>],
|
events: &'a [EventId],
|
||||||
create_event: &'a PduEvent,
|
create_event: &'a PduEvent,
|
||||||
room_id: &'a RoomId,
|
room_id: &'a RoomId,
|
||||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>,
|
||||||
@@ -1884,7 +1873,7 @@ 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) {
|
||||||
@@ -1900,7 +1889,7 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
// a. Look in the main timeline (pduid_pdu tree)
|
// a. Look in the main timeline (pduid_pdu tree)
|
||||||
// b. Look at outlier pdu tree
|
// b. Look at outlier pdu tree
|
||||||
// (get_pdu_json checks both)
|
// (get_pdu_json checks both)
|
||||||
let local_pdu = db.rooms.get_pdu(id);
|
let local_pdu = db.rooms.get_pdu(&id);
|
||||||
let pdu = match local_pdu {
|
let pdu = match local_pdu {
|
||||||
Ok(Some(pdu)) => {
|
Ok(Some(pdu)) => {
|
||||||
trace!("Found {} in db", id);
|
trace!("Found {} in db", id);
|
||||||
@@ -1914,7 +1903,7 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
.send_federation_request(
|
.send_federation_request(
|
||||||
&db.globals,
|
&db.globals,
|
||||||
origin,
|
origin,
|
||||||
get_event::v1::Request { event_id: id },
|
get_event::v1::Request { event_id: &id },
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@@ -1924,12 +1913,12 @@ 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.clone());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if calculated_event_id != **id {
|
if calculated_event_id != *id {
|
||||||
warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}",
|
warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}",
|
||||||
id, calculated_event_id, &res.pdu);
|
id, calculated_event_id, &res.pdu);
|
||||||
}
|
}
|
||||||
@@ -1938,8 +1927,8 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
|
|||||||
match handle_outlier_pdu(
|
match handle_outlier_pdu(
|
||||||
origin,
|
origin,
|
||||||
create_event,
|
create_event,
|
||||||
id,
|
&id,
|
||||||
room_id,
|
&room_id,
|
||||||
value.clone(),
|
value.clone(),
|
||||||
db,
|
db,
|
||||||
pub_key_map,
|
pub_key_map,
|
||||||
@@ -1949,14 +1938,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.clone());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Failed to fetch event: {}", id);
|
warn!("Failed to fetch event: {}", id);
|
||||||
back_off((**id).clone());
|
back_off(id.clone());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2087,7 +2076,7 @@ pub(crate) async fn fetch_signing_keys(
|
|||||||
.sending
|
.sending
|
||||||
.send_federation_request(
|
.send_federation_request(
|
||||||
&db.globals,
|
&db.globals,
|
||||||
server,
|
&server,
|
||||||
get_remote_server_keys::v2::Request::new(
|
get_remote_server_keys::v2::Request::new(
|
||||||
origin,
|
origin,
|
||||||
MilliSecondsSinceUnixEpoch::from_system_time(
|
MilliSecondsSinceUnixEpoch::from_system_time(
|
||||||
@@ -2166,7 +2155,7 @@ fn append_incoming_pdu(
|
|||||||
pdu,
|
pdu,
|
||||||
pdu_json,
|
pdu_json,
|
||||||
&new_room_leaves.into_iter().collect::<Vec<_>>(),
|
&new_room_leaves.into_iter().collect::<Vec<_>>(),
|
||||||
db,
|
&db,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for appservice in db.appservice.all()? {
|
for appservice in db.appservice.all()? {
|
||||||
@@ -2204,7 +2193,7 @@ fn append_incoming_pdu(
|
|||||||
&& pdu
|
&& pdu
|
||||||
.state_key
|
.state_key
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |state_key| users.is_match(state_key))
|
.map_or(false, |state_key| users.is_match(&state_key))
|
||||||
};
|
};
|
||||||
let matching_aliases = |aliases: &Regex| {
|
let matching_aliases = |aliases: &Regex| {
|
||||||
db.rooms
|
db.rooms
|
||||||
@@ -2228,9 +2217,9 @@ fn append_incoming_pdu(
|
|||||||
#[tracing::instrument(skip(starting_events, db))]
|
#[tracing::instrument(skip(starting_events, db))]
|
||||||
pub(crate) fn get_auth_chain<'a>(
|
pub(crate) fn get_auth_chain<'a>(
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
starting_events: Vec<Arc<EventId>>,
|
starting_events: Vec<EventId>,
|
||||||
db: &'a Database,
|
db: &'a Database,
|
||||||
) -> Result<impl Iterator<Item = Arc<EventId>> + 'a> {
|
) -> Result<impl Iterator<Item = EventId> + 'a> {
|
||||||
const NUM_BUCKETS: usize = 50;
|
const NUM_BUCKETS: usize = 50;
|
||||||
|
|
||||||
let mut buckets = vec![BTreeSet::new(); NUM_BUCKETS];
|
let mut buckets = vec![BTreeSet::new(); NUM_BUCKETS];
|
||||||
@@ -2271,7 +2260,7 @@ pub(crate) fn get_auth_chain<'a>(
|
|||||||
chunk_cache.extend(cached.iter().cloned());
|
chunk_cache.extend(cached.iter().cloned());
|
||||||
} else {
|
} else {
|
||||||
misses2 += 1;
|
misses2 += 1;
|
||||||
let auth_chain = Arc::new(get_auth_chain_inner(room_id, &event_id, db)?);
|
let auth_chain = Arc::new(get_auth_chain_inner(&room_id, &event_id, db)?);
|
||||||
db.rooms
|
db.rooms
|
||||||
.cache_auth_chain(vec![sevent_id], Arc::clone(&auth_chain))?;
|
.cache_auth_chain(vec![sevent_id], Arc::clone(&auth_chain))?;
|
||||||
println!(
|
println!(
|
||||||
@@ -2506,12 +2495,12 @@ pub fn get_event_authorization_route(
|
|||||||
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![body.event_id.clone()], &db)?;
|
||||||
|
|
||||||
Ok(get_event_authorization::v1::Response {
|
Ok(get_event_authorization::v1::Response {
|
||||||
auth_chain: auth_chain_ids
|
auth_chain: auth_chain_ids
|
||||||
.filter_map(|id| db.rooms.get_pdu_json(&id).ok()?)
|
.filter_map(|id| Some(db.rooms.get_pdu_json(&id).ok()??))
|
||||||
.map(PduEvent::convert_to_outgoing_federation_event)
|
.map(|event| PduEvent::convert_to_outgoing_federation_event(event))
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
@@ -2564,7 +2553,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![body.event_id.clone()], &db)?;
|
||||||
|
|
||||||
Ok(get_room_state::v1::Response {
|
Ok(get_room_state::v1::Response {
|
||||||
auth_chain: auth_chain_ids
|
auth_chain: auth_chain_ids
|
||||||
@@ -2620,13 +2609,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)
|
||||||
.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![body.event_id.clone()], &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.collect(),
|
||||||
pdu_ids,
|
pdu_ids,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
@@ -2768,10 +2757,10 @@ pub fn create_join_event_template_route(
|
|||||||
|
|
||||||
let auth_check = state_res::auth_check(
|
let auth_check = state_res::auth_check(
|
||||||
&room_version,
|
&room_version,
|
||||||
&pdu,
|
&Arc::new(pdu.clone()),
|
||||||
create_prev_event.as_deref(),
|
create_prev_event,
|
||||||
None::<PduEvent>, // TODO: third_party_invite
|
None, // TODO: third_party_invite
|
||||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
|k, s| auth_events.get(&(k.clone(), s.to_owned())).map(Arc::clone),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("{:?}", e);
|
error!("{:?}", e);
|
||||||
@@ -2819,7 +2808,7 @@ async fn create_join_event(
|
|||||||
// We need to return the state prior to joining, let's keep a reference to that here
|
// We need to return the state prior to joining, let's keep a reference to that here
|
||||||
let shortstatehash = db
|
let shortstatehash = db
|
||||||
.rooms
|
.rooms
|
||||||
.current_shortstatehash(room_id)?
|
.current_shortstatehash(&room_id)?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"Pdu state not found.",
|
"Pdu state not found.",
|
||||||
@@ -2829,7 +2818,7 @@ async fn create_join_event(
|
|||||||
// let mut auth_cache = EventMap::new();
|
// let mut auth_cache = EventMap::new();
|
||||||
|
|
||||||
// We do not add the event_id field to the pdu here because of signature and hashes checks
|
// We do not add the event_id field to the pdu here because of signature and hashes checks
|
||||||
let (event_id, value) = match crate::pdu::gen_event_id_canonical_json(pdu) {
|
let (event_id, value) = match crate::pdu::gen_event_id_canonical_json(&pdu) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Event could not be converted to canonical json
|
// Event could not be converted to canonical json
|
||||||
@@ -2858,7 +2847,7 @@ async fn create_join_event(
|
|||||||
.or_default(),
|
.or_default(),
|
||||||
);
|
);
|
||||||
let mutex_lock = mutex.lock().await;
|
let mutex_lock = mutex.lock().await;
|
||||||
let pdu_id = handle_incoming_pdu(&origin, &event_id, room_id, value, true, db, &pub_key_map)
|
let pdu_id = handle_incoming_pdu(&origin, &event_id, &room_id, value, true, &db, &pub_key_map)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
warn!("Error while handling incoming send join PDU: {}", e);
|
warn!("Error while handling incoming send join PDU: {}", e);
|
||||||
@@ -2875,14 +2864,14 @@ async fn create_join_event(
|
|||||||
|
|
||||||
let state_ids = db.rooms.state_full_ids(shortstatehash)?;
|
let state_ids = db.rooms.state_full_ids(shortstatehash)?;
|
||||||
let auth_chain_ids = get_auth_chain(
|
let auth_chain_ids = get_auth_chain(
|
||||||
room_id,
|
&room_id,
|
||||||
state_ids.iter().map(|(_, id)| id.clone()).collect(),
|
state_ids.iter().map(|(_, id)| id.clone()).collect(),
|
||||||
db,
|
&db,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for server in db
|
for server in db
|
||||||
.rooms
|
.rooms
|
||||||
.room_servers(room_id)
|
.room_servers(&room_id)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.filter(|server| &**server != db.globals.server_name())
|
.filter(|server| &**server != db.globals.server_name())
|
||||||
{
|
{
|
||||||
@@ -2898,7 +2887,7 @@ async fn create_join_event(
|
|||||||
.collect(),
|
.collect(),
|
||||||
state: state_ids
|
state: state_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(_, id)| db.rooms.get_pdu_json(id).ok().flatten())
|
.filter_map(|(_, id)| db.rooms.get_pdu_json(&id).ok().flatten())
|
||||||
.map(PduEvent::convert_to_outgoing_federation_event)
|
.map(PduEvent::convert_to_outgoing_federation_event)
|
||||||
.collect(),
|
.collect(),
|
||||||
})
|
})
|
||||||
@@ -3294,7 +3283,7 @@ fn get_server_keys_from_cache(
|
|||||||
|
|
||||||
let event_id = EventId::try_from(&*format!(
|
let event_id = EventId::try_from(&*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")
|
||||||
))
|
))
|
||||||
.expect("ruma's reference hashes are valid event ids");
|
.expect("ruma's reference hashes are valid event ids");
|
||||||
@@ -3386,10 +3375,10 @@ pub(crate) async fn fetch_join_signing_keys(
|
|||||||
// Try to fetch keys, failure is okay
|
// Try to fetch keys, failure is okay
|
||||||
// Servers we couldn't find in the cache will be added to `servers`
|
// Servers we couldn't find in the cache will be added to `servers`
|
||||||
for pdu in &event.room_state.state {
|
for pdu in &event.room_state.state {
|
||||||
let _ = get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm, db);
|
let _ = get_server_keys_from_cache(pdu, &mut servers, &room_version, &mut pkm, &db);
|
||||||
}
|
}
|
||||||
for pdu in &event.room_state.auth_chain {
|
for pdu in &event.room_state.auth_chain {
|
||||||
let _ = get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm, db);
|
let _ = get_server_keys_from_cache(pdu, &mut servers, &room_version, &mut pkm, &db);
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(pkm);
|
drop(pkm);
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
const puppeteer = require('puppeteer');
|
||||||
|
|
||||||
|
run().then(() => console.log('Done')).catch(error => {
|
||||||
|
console.error("Registration test failed.");
|
||||||
|
console.error("There might be a screenshot of the failure in the artifacts.\n");
|
||||||
|
console.error(error);
|
||||||
|
process.exit(111);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
|
||||||
|
const elementUrl = process.argv[process.argv.length - 2];
|
||||||
|
console.debug("Testing registration with ElementWeb hosted at "+ elementUrl);
|
||||||
|
|
||||||
|
const homeserverUrl = process.argv[process.argv.length - 1];
|
||||||
|
console.debug("Homeserver url: "+ homeserverUrl);
|
||||||
|
|
||||||
|
const username = "testuser" + String(Math.floor(Math.random() * 100000));
|
||||||
|
const password = "testpassword" + String(Math.floor(Math.random() * 100000));
|
||||||
|
console.debug("Testuser for this run:\n User: " + username + "\n Password: " + password);
|
||||||
|
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
headless: true, args: [
|
||||||
|
"--no-sandbox"
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.goto(elementUrl);
|
||||||
|
|
||||||
|
await page.screenshot({ path: '01-element-web-opened.png' });
|
||||||
|
|
||||||
|
console.debug("Click [Create Account] button");
|
||||||
|
await page.waitForSelector('a.mx_ButtonCreateAccount');
|
||||||
|
await page.click('a.mx_ButtonCreateAccount');
|
||||||
|
|
||||||
|
await page.screenshot({ path: '02-clicked-create-account-button.png' });
|
||||||
|
|
||||||
|
// The webapp should have loaded right now, if anything takes more than 5 seconds, something probably broke
|
||||||
|
page.setDefaultTimeout(5000);
|
||||||
|
|
||||||
|
console.debug("Click [Edit] to switch homeserver");
|
||||||
|
await page.waitForSelector('div.mx_ServerPicker_change');
|
||||||
|
await page.click('div.mx_ServerPicker_change');
|
||||||
|
|
||||||
|
await page.screenshot({ path: '03-clicked-edit-homeserver-button.png' });
|
||||||
|
|
||||||
|
console.debug("Type in local homeserver url");
|
||||||
|
await page.waitForSelector('input#mx_homeserverInput');
|
||||||
|
await page.click('input#mx_homeserverInput');
|
||||||
|
await page.click('input#mx_homeserverInput');
|
||||||
|
await page.keyboard.type(homeserverUrl);
|
||||||
|
|
||||||
|
await page.screenshot({ path: '04-typed-in-homeserver.png' });
|
||||||
|
|
||||||
|
console.debug("[Continue] with changed homeserver");
|
||||||
|
await page.waitForSelector("div.mx_ServerPickerDialog_continue");
|
||||||
|
await page.click('div.mx_ServerPickerDialog_continue');
|
||||||
|
|
||||||
|
await page.screenshot({ path: '05-back-to-enter-user-credentials.png' });
|
||||||
|
|
||||||
|
console.debug("Type in username");
|
||||||
|
await page.waitForSelector("input#mx_RegistrationForm_username");
|
||||||
|
await page.click('input#mx_RegistrationForm_username');
|
||||||
|
await page.keyboard.type(username);
|
||||||
|
|
||||||
|
await page.screenshot({ path: '06-typed-in-username.png' });
|
||||||
|
|
||||||
|
console.debug("Type in password");
|
||||||
|
await page.waitForSelector("input#mx_RegistrationForm_password");
|
||||||
|
await page.click('input#mx_RegistrationForm_password');
|
||||||
|
await page.keyboard.type(password);
|
||||||
|
|
||||||
|
await page.screenshot({ path: '07-typed-in-password-once.png' });
|
||||||
|
|
||||||
|
console.debug("Type in password again");
|
||||||
|
await page.waitForSelector("input#mx_RegistrationForm_passwordConfirm");
|
||||||
|
await page.click('input#mx_RegistrationForm_passwordConfirm');
|
||||||
|
await page.keyboard.type(password);
|
||||||
|
|
||||||
|
await page.screenshot({ path: '08-typed-in-password-twice.png' });
|
||||||
|
|
||||||
|
console.debug("Click on [Register] to finish the account creation");
|
||||||
|
await page.waitForSelector("input.mx_Login_submit");
|
||||||
|
await page.click('input.mx_Login_submit');
|
||||||
|
|
||||||
|
await page.screenshot({ path: '09-clicked-on-register-button.png' });
|
||||||
|
|
||||||
|
// Waiting for the app to login can take some time, so be patient.
|
||||||
|
page.setDefaultTimeout(10000);
|
||||||
|
|
||||||
|
console.debug("Wait for chat window to show up");
|
||||||
|
await page.waitForSelector("div.mx_HomePage_default_buttons");
|
||||||
|
console.debug("Apparently the registration worked.");
|
||||||
|
|
||||||
|
await page.screenshot({ path: '10-logged-in-homescreen.png' });
|
||||||
|
|
||||||
|
|
||||||
|
// Close the browser and exit the script
|
||||||
|
await browser.close();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user