mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-15 10:03:09 -06:00
Merge branch 'main' of github.com:matrix-org/dendrite into s7evink/docs
This commit is contained in:
commit
a9ff322343
1
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
1
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
|
|
@ -17,7 +17,6 @@ see: https://www.matrix.org/security-disclosure-policy/
|
||||||
### Background information
|
### Background information
|
||||||
<!-- Please include versions of all software when known e.g database versions, docker versions, client versions -->
|
<!-- Please include versions of all software when known e.g database versions, docker versions, client versions -->
|
||||||
- **Dendrite version or git SHA**:
|
- **Dendrite version or git SHA**:
|
||||||
- **Monolith or Polylith?**:
|
|
||||||
- **SQLite3 or Postgres?**:
|
- **SQLite3 or Postgres?**:
|
||||||
- **Running in Docker?**:
|
- **Running in Docker?**:
|
||||||
- **`go version`**:
|
- **`go version`**:
|
||||||
|
|
|
||||||
78
.github/workflows/dendrite.yml
vendored
78
.github/workflows/dendrite.yml
vendored
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: "stable"
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
|
|
@ -62,14 +62,14 @@ jobs:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: "stable"
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
|
||||||
# run go test with different go versions
|
# run go test with different go versions
|
||||||
test:
|
test:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
name: Unit tests (Go ${{ matrix.go }})
|
name: Unit tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Service containers to run with `container-job`
|
# Service containers to run with `container-job`
|
||||||
services:
|
services:
|
||||||
|
|
@ -91,25 +91,21 @@ jobs:
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 5
|
--health-retries 5
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
go: ["1.19"]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: "stable"
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
# manually set up caches, as they otherwise clash with different steps using setup-go with cache=true
|
# manually set up caches, as they otherwise clash with different steps using setup-go with cache=true
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}-unit-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-stable-unit-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go${{ matrix.go }}-unit-
|
${{ runner.os }}-go-stable-unit-
|
||||||
- name: Set up gotestfmt
|
- name: Set up gotestfmt
|
||||||
uses: gotesttools/gotestfmt-action@v2
|
uses: gotesttools/gotestfmt-action@v2
|
||||||
with:
|
with:
|
||||||
|
|
@ -130,7 +126,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
go: ["1.18", "1.19"]
|
|
||||||
goos: ["linux"]
|
goos: ["linux"]
|
||||||
goarch: ["amd64", "386"]
|
goarch: ["amd64", "386"]
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -138,15 +133,15 @@ jobs:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: "stable"
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-
|
key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-
|
||||||
- name: Install dependencies x86
|
- name: Install dependencies x86
|
||||||
if: ${{ matrix.goarch == '386' }}
|
if: ${{ matrix.goarch == '386' }}
|
||||||
run: sudo apt update && sudo apt-get install -y gcc-multilib
|
run: sudo apt update && sudo apt-get install -y gcc-multilib
|
||||||
|
|
@ -164,23 +159,22 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go: ["1.18", "1.19"]
|
|
||||||
goos: ["windows"]
|
goos: ["windows"]
|
||||||
goarch: ["amd64"]
|
goarch: ["amd64"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup Go ${{ matrix.go }}
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: "stable"
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}${{ matrix.goos }}-${{ matrix.goarch }}-
|
key: ${{ runner.os }}-go-stable-${{ matrix.goos }}-${{ matrix.goarch }}-
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt update && sudo apt install -y gcc-mingw-w64-x86-64 # install required gcc
|
run: sudo apt update && sudo apt install -y gcc-mingw-w64-x86-64 # install required gcc
|
||||||
- env:
|
- env:
|
||||||
|
|
@ -206,7 +200,7 @@ jobs:
|
||||||
integration:
|
integration:
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
needs: initial-tests-done
|
needs: initial-tests-done
|
||||||
name: Integration tests (Go ${{ matrix.go }})
|
name: Integration tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Service containers to run with `container-job`
|
# Service containers to run with `container-job`
|
||||||
services:
|
services:
|
||||||
|
|
@ -228,16 +222,12 @@ jobs:
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 5
|
--health-retries 5
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
go: ["1.19"]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: "stable"
|
||||||
- name: Set up gotestfmt
|
- name: Set up gotestfmt
|
||||||
uses: gotesttools/gotestfmt-action@v2
|
uses: gotesttools/gotestfmt-action@v2
|
||||||
with:
|
with:
|
||||||
|
|
@ -248,9 +238,9 @@ jobs:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go${{ matrix.go }}-test-race-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-stable-test-race-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go${{ matrix.go }}-test-race-
|
${{ runner.os }}-go-stable-test-race-
|
||||||
- run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt
|
- run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt
|
||||||
env:
|
env:
|
||||||
POSTGRES_HOST: localhost
|
POSTGRES_HOST: localhost
|
||||||
|
|
@ -261,6 +251,7 @@ jobs:
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
flags: unittests
|
flags: unittests
|
||||||
|
fail_ci_if_error: true
|
||||||
|
|
||||||
# run database upgrade tests
|
# run database upgrade tests
|
||||||
upgrade_test:
|
upgrade_test:
|
||||||
|
|
@ -273,7 +264,7 @@ jobs:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.18"
|
go-version: "stable"
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build upgrade-tests
|
- name: Build upgrade-tests
|
||||||
run: go build ./cmd/dendrite-upgrade-tests
|
run: go build ./cmd/dendrite-upgrade-tests
|
||||||
|
|
@ -293,7 +284,7 @@ jobs:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.18"
|
go-version: "stable"
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build upgrade-tests
|
- name: Build upgrade-tests
|
||||||
run: go build ./cmd/dendrite-upgrade-tests
|
run: go build ./cmd/dendrite-upgrade-tests
|
||||||
|
|
@ -317,19 +308,9 @@ jobs:
|
||||||
- label: SQLite Cgo
|
- label: SQLite Cgo
|
||||||
cgo: 1
|
cgo: 1
|
||||||
|
|
||||||
- label: SQLite native, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
|
|
||||||
- label: SQLite Cgo, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 1
|
|
||||||
|
|
||||||
- label: PostgreSQL
|
- label: PostgreSQL
|
||||||
postgres: postgres
|
postgres: postgres
|
||||||
|
|
||||||
- label: PostgreSQL, full HTTP APIs
|
|
||||||
postgres: postgres
|
|
||||||
api: full-http
|
|
||||||
container:
|
container:
|
||||||
image: matrixdotorg/sytest-dendrite
|
image: matrixdotorg/sytest-dendrite
|
||||||
volumes:
|
volumes:
|
||||||
|
|
@ -338,7 +319,6 @@ jobs:
|
||||||
- /root/.cache/go-mod:/gopath/pkg/mod
|
- /root/.cache/go-mod:/gopath/pkg/mod
|
||||||
env:
|
env:
|
||||||
POSTGRES: ${{ matrix.postgres && 1}}
|
POSTGRES: ${{ matrix.postgres && 1}}
|
||||||
API: ${{ matrix.api && 1 }}
|
|
||||||
SYTEST_BRANCH: ${{ github.head_ref }}
|
SYTEST_BRANCH: ${{ github.head_ref }}
|
||||||
CGO_ENABLED: ${{ matrix.cgo && 1 }}
|
CGO_ENABLED: ${{ matrix.cgo && 1 }}
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -390,22 +370,9 @@ jobs:
|
||||||
- label: SQLite Cgo
|
- label: SQLite Cgo
|
||||||
cgo: 1
|
cgo: 1
|
||||||
|
|
||||||
- label: SQLite native, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 0
|
|
||||||
|
|
||||||
- label: SQLite Cgo, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 1
|
|
||||||
|
|
||||||
- label: PostgreSQL
|
- label: PostgreSQL
|
||||||
postgres: Postgres
|
postgres: Postgres
|
||||||
cgo: 0
|
cgo: 0
|
||||||
|
|
||||||
- label: PostgreSQL, full HTTP APIs
|
|
||||||
postgres: Postgres
|
|
||||||
api: full-http
|
|
||||||
cgo: 0
|
|
||||||
steps:
|
steps:
|
||||||
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
|
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
|
||||||
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
|
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
|
||||||
|
|
@ -447,7 +414,7 @@ jobs:
|
||||||
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
|
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
|
||||||
done
|
done
|
||||||
# Build initial Dendrite image
|
# Build initial Dendrite image
|
||||||
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
|
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
|
||||||
working-directory: dendrite
|
working-directory: dendrite
|
||||||
env:
|
env:
|
||||||
DOCKER_BUILDKIT: 1
|
DOCKER_BUILDKIT: 1
|
||||||
|
|
@ -459,8 +426,7 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
name: Run Complement Tests
|
name: Run Complement Tests
|
||||||
env:
|
env:
|
||||||
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }}
|
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }}
|
||||||
COMPLEMENT_DENDRITE_API: ${{ matrix.api && 1 }}
|
|
||||||
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
|
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
|
||||||
working-directory: complement
|
working-directory: complement
|
||||||
|
|
||||||
|
|
|
||||||
82
.github/workflows/docker.yml
vendored
82
.github/workflows/docker.yml
vendored
|
|
@ -61,7 +61,6 @@ jobs:
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
context: .
|
context: .
|
||||||
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
||||||
target: monolith
|
|
||||||
platforms: ${{ env.PLATFORMS }}
|
platforms: ${{ env.PLATFORMS }}
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|
@ -77,7 +76,6 @@ jobs:
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
context: .
|
context: .
|
||||||
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
||||||
target: monolith
|
|
||||||
platforms: ${{ env.PLATFORMS }}
|
platforms: ${{ env.PLATFORMS }}
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|
@ -98,86 +96,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
sarif_file: "trivy-results.sarif"
|
sarif_file: "trivy-results.sarif"
|
||||||
|
|
||||||
polylith:
|
|
||||||
name: Polylith image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
security-events: write # To upload Trivy sarif files
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Get release tag & build flags
|
|
||||||
if: github.event_name == 'release' # Only for GitHub releases
|
|
||||||
run: |
|
|
||||||
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
|
||||||
echo "BUILD=$(git rev-parse --short HEAD || \"\")" >> $GITHUB_ENV
|
|
||||||
BRANCH=$(git symbolic-ref --short HEAD | tr -d \/)
|
|
||||||
[ ${BRANCH} == "main" ] && BRANCH=""
|
|
||||||
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
username: ${{ env.DOCKER_HUB_USER }}
|
|
||||||
password: ${{ secrets.DOCKER_TOKEN }}
|
|
||||||
- name: Login to GitHub Containers
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build main polylith image
|
|
||||||
if: github.ref_name == 'main'
|
|
||||||
id: docker_build_polylith
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
context: .
|
|
||||||
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
|
||||||
target: polylith
|
|
||||||
platforms: ${{ env.PLATFORMS }}
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
|
|
||||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
|
|
||||||
|
|
||||||
- name: Build release polylith image
|
|
||||||
if: github.event_name == 'release' # Only for GitHub releases
|
|
||||||
id: docker_build_polylith_release
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
context: .
|
|
||||||
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
|
|
||||||
target: polylith
|
|
||||||
platforms: ${{ env.PLATFORMS }}
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:latest
|
|
||||||
${{ env.DOCKER_NAMESPACE }}/dendrite-polylith:${{ env.RELEASE_VERSION }}
|
|
||||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:latest
|
|
||||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ env.RELEASE_VERSION }}
|
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner
|
|
||||||
uses: aquasecurity/trivy-action@master
|
|
||||||
with:
|
|
||||||
image-ref: ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-polylith:${{ github.ref_name }}
|
|
||||||
format: "sarif"
|
|
||||||
output: "trivy-results.sarif"
|
|
||||||
|
|
||||||
- name: Upload Trivy scan results to GitHub Security tab
|
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
|
||||||
with:
|
|
||||||
sarif_file: "trivy-results.sarif"
|
|
||||||
|
|
||||||
demo-pinecone:
|
demo-pinecone:
|
||||||
name: Pinecone demo image
|
name: Pinecone demo image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
35
.github/workflows/schedules.yaml
vendored
35
.github/workflows/schedules.yaml
vendored
|
|
@ -24,19 +24,8 @@ jobs:
|
||||||
- label: SQLite Cgo
|
- label: SQLite Cgo
|
||||||
cgo: 1
|
cgo: 1
|
||||||
|
|
||||||
- label: SQLite native, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
|
|
||||||
- label: SQLite Cgo, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 1
|
|
||||||
|
|
||||||
- label: PostgreSQL
|
- label: PostgreSQL
|
||||||
postgres: postgres
|
postgres: postgres
|
||||||
|
|
||||||
- label: PostgreSQL, full HTTP APIs
|
|
||||||
postgres: postgres
|
|
||||||
api: full-http
|
|
||||||
container:
|
container:
|
||||||
image: matrixdotorg/sytest-dendrite:latest
|
image: matrixdotorg/sytest-dendrite:latest
|
||||||
volumes:
|
volumes:
|
||||||
|
|
@ -45,7 +34,6 @@ jobs:
|
||||||
- /root/.cache/go-mod:/gopath/pkg/mod
|
- /root/.cache/go-mod:/gopath/pkg/mod
|
||||||
env:
|
env:
|
||||||
POSTGRES: ${{ matrix.postgres && 1}}
|
POSTGRES: ${{ matrix.postgres && 1}}
|
||||||
API: ${{ matrix.api && 1 }}
|
|
||||||
SYTEST_BRANCH: ${{ github.head_ref }}
|
SYTEST_BRANCH: ${{ github.head_ref }}
|
||||||
RACE_DETECTION: 1
|
RACE_DETECTION: 1
|
||||||
COVER: 1
|
COVER: 1
|
||||||
|
|
@ -93,7 +81,7 @@ jobs:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '>=1.19.0'
|
go-version: 'stable'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
|
|
@ -125,22 +113,9 @@ jobs:
|
||||||
- label: SQLite Cgo
|
- label: SQLite Cgo
|
||||||
cgo: 1
|
cgo: 1
|
||||||
|
|
||||||
- label: SQLite native, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 0
|
|
||||||
|
|
||||||
- label: SQLite Cgo, full HTTP APIs
|
|
||||||
api: full-http
|
|
||||||
cgo: 1
|
|
||||||
|
|
||||||
- label: PostgreSQL
|
- label: PostgreSQL
|
||||||
postgres: Postgres
|
postgres: Postgres
|
||||||
cgo: 0
|
cgo: 0
|
||||||
|
|
||||||
- label: PostgreSQL, full HTTP APIs
|
|
||||||
postgres: Postgres
|
|
||||||
api: full-http
|
|
||||||
cgo: 0
|
|
||||||
steps:
|
steps:
|
||||||
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
|
# Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
|
||||||
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
|
# See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
|
||||||
|
|
@ -182,7 +157,7 @@ jobs:
|
||||||
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
|
(wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
|
||||||
done
|
done
|
||||||
# Build initial Dendrite image
|
# Build initial Dendrite image
|
||||||
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
|
- run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
|
||||||
working-directory: dendrite
|
working-directory: dendrite
|
||||||
env:
|
env:
|
||||||
DOCKER_BUILDKIT: 1
|
DOCKER_BUILDKIT: 1
|
||||||
|
|
@ -203,8 +178,7 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
name: Run Complement Tests
|
name: Run Complement Tests
|
||||||
env:
|
env:
|
||||||
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.api }}${{ matrix.cgo }}
|
COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }}
|
||||||
COMPLEMENT_DENDRITE_API: ${{ matrix.api && 1 }}
|
|
||||||
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
|
COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
|
||||||
COMPLEMENT_DENDRITE_COVER: 1
|
COMPLEMENT_DENDRITE_COVER: 1
|
||||||
COMPLEMENT_POST_TEST_SCRIPT: /tmp/posttest.sh
|
COMPLEMENT_POST_TEST_SCRIPT: /tmp/posttest.sh
|
||||||
|
|
@ -229,7 +203,7 @@ jobs:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '>=1.19.0'
|
go-version: 'stable'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
|
|
@ -269,6 +243,7 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
CI_PACKAGE: true
|
CI_PACKAGE: true
|
||||||
|
NODE_OPTIONS: "--openssl-legacy-provider"
|
||||||
run: yarn build
|
run: yarn build
|
||||||
working-directory: ./element-web
|
working-directory: ./element-web
|
||||||
- name: Edit Test Config
|
- name: Edit Test Config
|
||||||
|
|
|
||||||
16
CHANGES.md
16
CHANGES.md
|
|
@ -1,5 +1,21 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Dendrite 0.11.1 (2023-02-10)
|
||||||
|
|
||||||
|
**⚠️ DEPRECATION WARNING: This is the last release to have polylith and HTTP API mode. Future releases are monolith only.**
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Dendrite can now be compiled against Go 1.20
|
||||||
|
* Initial store and forward support has been added
|
||||||
|
* A landing page showing that Dendrite is running has been added (contributed by [LukasLJL](https://github.com/LukasLJL))
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- `/sync` is now using significantly less database round trips when using Postgres, resulting in faster initial syncs, allowing larger accounts to login again
|
||||||
|
- Many under the hood pinecone improvements
|
||||||
|
- Publishing rooms is now possible again
|
||||||
|
|
||||||
## Dendrite 0.11.0 (2023-01-20)
|
## Dendrite 0.11.0 (2023-01-20)
|
||||||
|
|
||||||
The last three missing federation API Sytests have been fixed - bringing us to 100% server-server Synapse parity, with client-server parity at 93% 🎉
|
The last three missing federation API Sytests have been fixed - bringing us to 100% server-server Synapse parity, with client-server parity at 93% 🎉
|
||||||
|
|
|
||||||
38
Dockerfile
38
Dockerfile
|
|
@ -1,10 +1,15 @@
|
||||||
#syntax=docker/dockerfile:1.2
|
#syntax=docker/dockerfile:1.2
|
||||||
|
|
||||||
|
#
|
||||||
|
# base installs required dependencies and runs go mod download to cache dependencies
|
||||||
|
#
|
||||||
|
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.20-alpine AS base
|
||||||
|
RUN apk --update --no-cache add bash build-base curl
|
||||||
|
|
||||||
#
|
#
|
||||||
# build creates all needed binaries
|
# build creates all needed binaries
|
||||||
#
|
#
|
||||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.19-alpine AS build
|
FROM --platform=${BUILDPLATFORM} base AS build
|
||||||
RUN apk --update --no-cache add bash build-base curl
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
@ -18,44 +23,27 @@ RUN --mount=target=. \
|
||||||
CGO_ENABLED=$([ "$TARGETARCH" = "$USERARCH" ] && echo "1" || echo "0") \
|
CGO_ENABLED=$([ "$TARGETARCH" = "$USERARCH" ] && echo "1" || echo "0") \
|
||||||
go build -v -ldflags="${FLAGS}" -trimpath -o /out/ ./cmd/...
|
go build -v -ldflags="${FLAGS}" -trimpath -o /out/ ./cmd/...
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# The dendrite base image
|
# Builds the Dendrite image containing all required binaries
|
||||||
#
|
#
|
||||||
FROM alpine:latest AS dendrite-base
|
FROM alpine:latest
|
||||||
RUN apk --update --no-cache add curl
|
RUN apk --update --no-cache add curl
|
||||||
|
LABEL org.opencontainers.image.title="Dendrite"
|
||||||
LABEL org.opencontainers.image.description="Next-generation Matrix homeserver written in Go"
|
LABEL org.opencontainers.image.description="Next-generation Matrix homeserver written in Go"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/matrix-org/dendrite"
|
LABEL org.opencontainers.image.source="https://github.com/matrix-org/dendrite"
|
||||||
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
||||||
LABEL org.opencontainers.image.documentation="https://matrix-org.github.io/dendrite/"
|
LABEL org.opencontainers.image.documentation="https://matrix-org.github.io/dendrite/"
|
||||||
LABEL org.opencontainers.image.vendor="The Matrix.org Foundation C.I.C."
|
LABEL org.opencontainers.image.vendor="The Matrix.org Foundation C.I.C."
|
||||||
|
|
||||||
#
|
|
||||||
# Builds the polylith image and only contains the polylith binary
|
|
||||||
#
|
|
||||||
FROM dendrite-base AS polylith
|
|
||||||
LABEL org.opencontainers.image.title="Dendrite (Polylith)"
|
|
||||||
|
|
||||||
COPY --from=build /out/dendrite-polylith-multi /usr/bin/
|
|
||||||
|
|
||||||
VOLUME /etc/dendrite
|
|
||||||
WORKDIR /etc/dendrite
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dendrite-polylith-multi"]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Builds the monolith image and contains all required binaries
|
|
||||||
#
|
|
||||||
FROM dendrite-base AS monolith
|
|
||||||
LABEL org.opencontainers.image.title="Dendrite (Monolith)"
|
|
||||||
|
|
||||||
COPY --from=build /out/create-account /usr/bin/create-account
|
COPY --from=build /out/create-account /usr/bin/create-account
|
||||||
COPY --from=build /out/generate-config /usr/bin/generate-config
|
COPY --from=build /out/generate-config /usr/bin/generate-config
|
||||||
COPY --from=build /out/generate-keys /usr/bin/generate-keys
|
COPY --from=build /out/generate-keys /usr/bin/generate-keys
|
||||||
COPY --from=build /out/dendrite-monolith-server /usr/bin/dendrite-monolith-server
|
COPY --from=build /out/dendrite /usr/bin/dendrite
|
||||||
|
|
||||||
VOLUME /etc/dendrite
|
VOLUME /etc/dendrite
|
||||||
WORKDIR /etc/dendrite
|
WORKDIR /etc/dendrite
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dendrite-monolith-server"]
|
ENTRYPOINT ["/usr/bin/dendrite"]
|
||||||
EXPOSE 8008 8448
|
EXPOSE 8008 8448
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ This does not mean:
|
||||||
- Dendrite is ready for massive homeserver deployments. There is no sharding of microservices (although it is possible to run them on separate machines) and there is no high-availability/clustering support.
|
- Dendrite is ready for massive homeserver deployments. There is no sharding of microservices (although it is possible to run them on separate machines) and there is no high-availability/clustering support.
|
||||||
|
|
||||||
Currently, we expect Dendrite to function well for small (10s/100s of users) homeserver deployments as well as P2P Matrix nodes in-browser or on mobile devices.
|
Currently, we expect Dendrite to function well for small (10s/100s of users) homeserver deployments as well as P2P Matrix nodes in-browser or on mobile devices.
|
||||||
In the future, we will be able to scale up to gigantic servers (equivalent to `matrix.org`) via polylith mode.
|
|
||||||
|
|
||||||
If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or join us in:
|
If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or join us in:
|
||||||
|
|
||||||
|
|
@ -88,7 +87,7 @@ Then point your favourite Matrix client at `http://localhost:8008` or `https://l
|
||||||
|
|
||||||
We use a script called Are We Synapse Yet which checks Sytest compliance rates. Sytest is a black-box homeserver
|
We use a script called Are We Synapse Yet which checks Sytest compliance rates. Sytest is a black-box homeserver
|
||||||
test rig with around 900 tests. The script works out how many of these tests are passing on Dendrite and it
|
test rig with around 900 tests. The script works out how many of these tests are passing on Dendrite and it
|
||||||
updates with CI. As of August 2022 we're at around 90% CS API coverage and 95% Federation coverage, though check
|
updates with CI. As of January 2023, we have 100% server-server parity with Synapse, and the client-server parity is at 93% , though check
|
||||||
CI for the latest numbers. In practice, this means you can communicate locally and via federation with Synapse
|
CI for the latest numbers. In practice, this means you can communicate locally and via federation with Synapse
|
||||||
servers such as matrix.org reasonably well, although there are still some missing features (like SSO and Third-party ID APIs).
|
servers such as matrix.org reasonably well, although there are still some missing features (like SSO and Third-party ID APIs).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,12 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||||
"github.com/matrix-org/dendrite/appservice/consumers"
|
"github.com/matrix-org/dendrite/appservice/consumers"
|
||||||
"github.com/matrix-org/dendrite/appservice/inthttp"
|
|
||||||
"github.com/matrix-org/dendrite/appservice/query"
|
"github.com/matrix-org/dendrite/appservice/query"
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
|
@ -36,16 +34,11 @@ import (
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddInternalRoutes registers HTTP handlers for internal API calls
|
|
||||||
func AddInternalRoutes(router *mux.Router, queryAPI appserviceAPI.AppServiceInternalAPI, enableMetrics bool) {
|
|
||||||
inthttp.AddRoutes(queryAPI, router, enableMetrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
||||||
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
||||||
func NewInternalAPI(
|
func NewInternalAPI(
|
||||||
base *base.BaseDendrite,
|
base *base.BaseDendrite,
|
||||||
userAPI userapi.UserInternalAPI,
|
userAPI userapi.AppserviceUserAPI,
|
||||||
rsAPI roomserverAPI.RoomserverInternalAPI,
|
rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
) appserviceAPI.AppServiceInternalAPI {
|
) appserviceAPI.AppServiceInternalAPI {
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice"
|
"github.com/matrix-org/dendrite/appservice"
|
||||||
"github.com/matrix-org/dendrite/appservice/api"
|
"github.com/matrix-org/dendrite/appservice/api"
|
||||||
"github.com/matrix-org/dendrite/appservice/inthttp"
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
|
|
@ -129,26 +125,10 @@ func TestAppserviceInternalAPI(t *testing.T) {
|
||||||
|
|
||||||
// Create required internal APIs
|
// Create required internal APIs
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
usrAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, nil, rsAPI, nil)
|
usrAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
asAPI := appservice.NewInternalAPI(base, usrAPI, rsAPI)
|
asAPI := appservice.NewInternalAPI(base, usrAPI, rsAPI)
|
||||||
|
|
||||||
// Finally execute the tests
|
runCases(t, asAPI)
|
||||||
t.Run("HTTP API", func(t *testing.T) {
|
|
||||||
router := mux.NewRouter().PathPrefix(httputil.InternalPathPrefix).Subrouter()
|
|
||||||
appservice.AddInternalRoutes(router, asAPI, base.EnableMetrics)
|
|
||||||
apiURL, cancel := test.ListenAndServe(t, router, false)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
asHTTPApi, err := inthttp.NewAppserviceClient(apiURL, &http.Client{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create HTTP client: %s", err)
|
|
||||||
}
|
|
||||||
runCases(t, asHTTPApi)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Monolith", func(t *testing.T) {
|
|
||||||
runCases(t, asAPI)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice/api"
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP paths for the internal HTTP APIs
|
|
||||||
const (
|
|
||||||
AppServiceRoomAliasExistsPath = "/appservice/RoomAliasExists"
|
|
||||||
AppServiceUserIDExistsPath = "/appservice/UserIDExists"
|
|
||||||
AppServiceLocationsPath = "/appservice/locations"
|
|
||||||
AppServiceUserPath = "/appservice/users"
|
|
||||||
AppServiceProtocolsPath = "/appservice/protocols"
|
|
||||||
)
|
|
||||||
|
|
||||||
// httpAppServiceQueryAPI contains the URL to an appservice query API and a
|
|
||||||
// reference to a httpClient used to reach it
|
|
||||||
type httpAppServiceQueryAPI struct {
|
|
||||||
appserviceURL string
|
|
||||||
httpClient *http.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAppserviceClient creates a AppServiceQueryAPI implemented by talking
|
|
||||||
// to a HTTP POST API.
|
|
||||||
// If httpClient is nil an error is returned
|
|
||||||
func NewAppserviceClient(
|
|
||||||
appserviceURL string,
|
|
||||||
httpClient *http.Client,
|
|
||||||
) (api.AppServiceInternalAPI, error) {
|
|
||||||
if httpClient == nil {
|
|
||||||
return nil, errors.New("NewRoomserverAliasAPIHTTP: httpClient is <nil>")
|
|
||||||
}
|
|
||||||
return &httpAppServiceQueryAPI{appserviceURL, httpClient}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoomAliasExists implements AppServiceQueryAPI
|
|
||||||
func (h *httpAppServiceQueryAPI) RoomAliasExists(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.RoomAliasExistsRequest,
|
|
||||||
response *api.RoomAliasExistsResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"RoomAliasExists", h.appserviceURL+AppServiceRoomAliasExistsPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserIDExists implements AppServiceQueryAPI
|
|
||||||
func (h *httpAppServiceQueryAPI) UserIDExists(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.UserIDExistsRequest,
|
|
||||||
response *api.UserIDExistsResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"UserIDExists", h.appserviceURL+AppServiceUserIDExistsPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpAppServiceQueryAPI) Locations(ctx context.Context, request *api.LocationRequest, response *api.LocationResponse) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"ASLocation", h.appserviceURL+AppServiceLocationsPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpAppServiceQueryAPI) User(ctx context.Context, request *api.UserRequest, response *api.UserResponse) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"ASUser", h.appserviceURL+AppServiceUserPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpAppServiceQueryAPI) Protocols(ctx context.Context, request *api.ProtocolRequest, response *api.ProtocolResponse) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"ASProtocols", h.appserviceURL+AppServiceProtocolsPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice/api"
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddRoutes adds the AppServiceQueryAPI handlers to the http.ServeMux.
|
|
||||||
func AddRoutes(a api.AppServiceInternalAPI, internalAPIMux *mux.Router, enableMetrics bool) {
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
AppServiceRoomAliasExistsPath,
|
|
||||||
httputil.MakeInternalRPCAPI("AppserviceRoomAliasExists", enableMetrics, a.RoomAliasExists),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
AppServiceUserIDExistsPath,
|
|
||||||
httputil.MakeInternalRPCAPI("AppserviceUserIDExists", enableMetrics, a.UserIDExists),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
AppServiceProtocolsPath,
|
|
||||||
httputil.MakeInternalRPCAPI("AppserviceProtocols", enableMetrics, a.Protocols),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
AppServiceLocationsPath,
|
|
||||||
httputil.MakeInternalRPCAPI("AppserviceLocations", enableMetrics, a.Locations),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
AppServiceUserPath,
|
|
||||||
httputil.MakeInternalRPCAPI("AppserviceUser", enableMetrics, a.User),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
"github.com/matrix-org/dendrite/federationapi"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup"
|
"github.com/matrix-org/dendrite/setup"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
|
@ -177,19 +176,17 @@ func startup() {
|
||||||
if err := cfg.Derive(); err != nil {
|
if err := cfg.Derive(); err != nil {
|
||||||
logrus.Fatalf("Failed to derive values from config: %s", err)
|
logrus.Fatalf("Failed to derive values from config: %s", err)
|
||||||
}
|
}
|
||||||
base := base.NewBaseDendrite(cfg, "Monolith")
|
base := base.NewBaseDendrite(cfg)
|
||||||
defer base.Close() // nolint: errcheck
|
defer base.Close() // nolint: errcheck
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
|
|
||||||
federation := conn.CreateFederationClient(base, pSessions)
|
federation := conn.CreateFederationClient(base, pSessions)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation, rsAPI)
|
|
||||||
|
|
||||||
serverKeyAPI := &signing.YggdrasilKeys{}
|
serverKeyAPI := &signing.YggdrasilKeys{}
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
|
|
||||||
userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, nil, keyAPI, rsAPI, base.PushGatewayHTTPClient())
|
userAPI := userapi.NewInternalAPI(base, rsAPI, federation)
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
asQuery := appservice.NewInternalAPI(
|
asQuery := appservice.NewInternalAPI(
|
||||||
base, userAPI, rsAPI,
|
base, userAPI, rsAPI,
|
||||||
|
|
@ -208,14 +205,12 @@ func startup() {
|
||||||
FederationAPI: fedSenderAPI,
|
FederationAPI: fedSenderAPI,
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyAPI,
|
|
||||||
//ServerKeyAPI: serverKeyAPI,
|
//ServerKeyAPI: serverKeyAPI,
|
||||||
ExtPublicRoomsProvider: rooms.NewPineconeRoomProvider(pRouter, pSessions, fedSenderAPI, federation),
|
ExtPublicRoomsProvider: rooms.NewPineconeRoomProvider(pRouter, pSessions, fedSenderAPI, federation),
|
||||||
}
|
}
|
||||||
monolith.AddAllPublicRoutes(base)
|
monolith.AddAllPublicRoutes(base)
|
||||||
|
|
||||||
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||||
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
|
|
||||||
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
||||||
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,25 +5,21 @@ These are Docker images for Dendrite!
|
||||||
They can be found on Docker Hub:
|
They can be found on Docker Hub:
|
||||||
|
|
||||||
- [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith) for monolith deployments
|
- [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith) for monolith deployments
|
||||||
- [matrixdotorg/dendrite-polylith](https://hub.docker.com/r/matrixdotorg/dendrite-polylith) for polylith deployments
|
|
||||||
|
|
||||||
## Dockerfiles
|
## Dockerfiles
|
||||||
|
|
||||||
The `Dockerfile` is a multistage file which can build all four Dendrite
|
The `Dockerfile` is a multistage file which can build Dendrite. From the root of the Dendrite
|
||||||
images depending on the supplied `--target`. From the root of the Dendrite
|
|
||||||
repository, run:
|
repository, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build . --target monolith -t matrixdotorg/dendrite-monolith
|
docker build . --target monolith -t matrixdotorg/dendrite-monolith
|
||||||
docker build . --target polylith -t matrixdotorg/dendrite-monolith
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compose files
|
## Compose files
|
||||||
|
|
||||||
There are two sample `docker-compose` files:
|
There is one sample `docker-compose` files:
|
||||||
|
|
||||||
- `docker-compose.monolith.yml` which runs a monolith Dendrite deployment
|
- `docker-compose.monolith.yml` which runs a monolith Dendrite deployment
|
||||||
- `docker-compose.polylith.yml` which runs a polylith Dendrite deployment
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|
@ -49,7 +45,7 @@ docker run --rm --entrypoint="" \
|
||||||
|
|
||||||
The key files will now exist in your current working directory, and can be mounted into place.
|
The key files will now exist in your current working directory, and can be mounted into place.
|
||||||
|
|
||||||
## Starting Dendrite as a monolith deployment
|
## Starting Dendrite
|
||||||
|
|
||||||
Create your config based on the [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml) sample configuration file.
|
Create your config based on the [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml) sample configuration file.
|
||||||
|
|
||||||
|
|
@ -59,16 +55,6 @@ Then start the deployment:
|
||||||
docker-compose -f docker-compose.monolith.yml up
|
docker-compose -f docker-compose.monolith.yml up
|
||||||
```
|
```
|
||||||
|
|
||||||
## Starting Dendrite as a polylith deployment
|
|
||||||
|
|
||||||
Create your config based on the [`dendrite-sample.polylith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.polylith.yaml) sample configuration file.
|
|
||||||
|
|
||||||
Then start the deployment:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker-compose -f docker-compose.polylith.yml up
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building the images
|
## Building the images
|
||||||
|
|
||||||
The `build/docker/images-build.sh` script will build the base image, followed by
|
The `build/docker/images-build.sh` script will build the base image, followed by
|
||||||
|
|
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
version: "3.4"
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
hostname: postgres
|
|
||||||
image: postgres:15-alpine
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
# This will create a docker volume to persist the database files in.
|
|
||||||
# If you prefer those files to be outside of docker, you'll need to change this.
|
|
||||||
- dendrite_postgres_data:/var/lib/postgresql/data
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: itsasecret
|
|
||||||
POSTGRES_USER: dendrite
|
|
||||||
POSTGRES_DATABASE: dendrite
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U dendrite"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
jetstream:
|
|
||||||
hostname: jetstream
|
|
||||||
image: nats:latest
|
|
||||||
command: |
|
|
||||||
--jetstream
|
|
||||||
--store_dir /var/lib/nats
|
|
||||||
--cluster_name Dendrite
|
|
||||||
volumes:
|
|
||||||
- dendrite_jetstream:/var/lib/nats
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
# This "component" will exit immediately, it's only purpose is
|
|
||||||
# to provide the common settings
|
|
||||||
component:
|
|
||||||
image: matrixdotorg/dendrite-polylith:latest
|
|
||||||
restart: "no"
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
volumes:
|
|
||||||
- ./config:/etc/dendrite
|
|
||||||
depends_on:
|
|
||||||
jetstream:
|
|
||||||
condition: service_started
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
client_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: client_api
|
|
||||||
command: clientapi
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
user_api:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
media_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: media_api
|
|
||||||
command: mediaapi
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- dendrite_media:/var/dendrite/media
|
|
||||||
|
|
||||||
sync_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: sync_api
|
|
||||||
command: syncapi
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- dendrite_search_index:/var/dendrite/searchindex
|
|
||||||
depends_on:
|
|
||||||
room_server:
|
|
||||||
condition: service_started
|
|
||||||
user_api:
|
|
||||||
condition: service_started
|
|
||||||
key_server:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
room_server:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: room_server
|
|
||||||
command: roomserver
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
federation_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: federation_api
|
|
||||||
command: federationapi
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
room_server:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
key_server:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: key_server
|
|
||||||
command: keyserver
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
room_server:
|
|
||||||
condition: service_started
|
|
||||||
federation_api:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
user_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: user_api
|
|
||||||
command: userapi
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
room_server:
|
|
||||||
condition: service_started
|
|
||||||
key_server:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
appservice_api:
|
|
||||||
extends:
|
|
||||||
service: component
|
|
||||||
hostname: appservice_api
|
|
||||||
command: appservice
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
room_server:
|
|
||||||
condition: service_started
|
|
||||||
user_api:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
networks:
|
|
||||||
internal:
|
|
||||||
attachable: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
dendrite_jetstream:
|
|
||||||
dendrite_postgres_data:
|
|
||||||
dendrite_media:
|
|
||||||
dendrite_search_index:
|
|
||||||
|
|
@ -7,6 +7,5 @@ TAG=${1:-latest}
|
||||||
echo "Building tag '${TAG}'"
|
echo "Building tag '${TAG}'"
|
||||||
|
|
||||||
docker build . --target monolith -t matrixdotorg/dendrite-monolith:${TAG}
|
docker build . --target monolith -t matrixdotorg/dendrite-monolith:${TAG}
|
||||||
docker build . --target polylith -t matrixdotorg/dendrite-monolith:${TAG}
|
|
||||||
docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone:${TAG}
|
docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone:${TAG}
|
||||||
docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil:${TAG}
|
docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil:${TAG}
|
||||||
|
|
@ -5,4 +5,3 @@ TAG=${1:-latest}
|
||||||
echo "Pulling tag '${TAG}'"
|
echo "Pulling tag '${TAG}'"
|
||||||
|
|
||||||
docker pull matrixdotorg/dendrite-monolith:${TAG}
|
docker pull matrixdotorg/dendrite-monolith:${TAG}
|
||||||
docker pull matrixdotorg/dendrite-polylith:${TAG}
|
|
||||||
|
|
@ -5,4 +5,3 @@ TAG=${1:-latest}
|
||||||
echo "Pushing tag '${TAG}'"
|
echo "Pushing tag '${TAG}'"
|
||||||
|
|
||||||
docker push matrixdotorg/dendrite-monolith:${TAG}
|
docker push matrixdotorg/dendrite-monolith:${TAG}
|
||||||
docker push matrixdotorg/dendrite-polylith:${TAG}
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
"github.com/matrix-org/dendrite/federationapi"
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
"github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup"
|
"github.com/matrix-org/dendrite/setup"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
|
@ -127,8 +126,8 @@ func (m *DendriteMonolith) Start() {
|
||||||
|
|
||||||
cfg := &config.Dendrite{}
|
cfg := &config.Dendrite{}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||||
cfg.Global.PrivateKey = sk
|
cfg.Global.PrivateKey = sk
|
||||||
|
|
@ -149,7 +148,7 @@ func (m *DendriteMonolith) Start() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
base := base.NewBaseDendrite(cfg, "Monolith")
|
base := base.NewBaseDendrite(cfg)
|
||||||
base.ConfigureAdminEndpoints()
|
base.ConfigureAdminEndpoints()
|
||||||
m.processContext = base.ProcessContext
|
m.processContext = base.ProcessContext
|
||||||
defer base.Close() // nolint: errcheck
|
defer base.Close() // nolint: errcheck
|
||||||
|
|
@ -165,9 +164,7 @@ func (m *DendriteMonolith) Start() {
|
||||||
base, federation, rsAPI, base.Caches, keyRing, true,
|
base, federation, rsAPI, base.Caches, keyRing, true,
|
||||||
)
|
)
|
||||||
|
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, federation)
|
||||||
userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI, rsAPI, base.PushGatewayHTTPClient())
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
||||||
rsAPI.SetAppserviceAPI(asAPI)
|
rsAPI.SetAppserviceAPI(asAPI)
|
||||||
|
|
@ -186,7 +183,6 @@ func (m *DendriteMonolith) Start() {
|
||||||
FederationAPI: fsAPI,
|
FederationAPI: fsAPI,
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyAPI,
|
|
||||||
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
||||||
ygg, fsAPI, federation,
|
ygg, fsAPI, federation,
|
||||||
),
|
),
|
||||||
|
|
@ -194,7 +190,6 @@ func (m *DendriteMonolith) Start() {
|
||||||
monolith.AddAllPublicRoutes(base)
|
monolith.AddAllPublicRoutes(base)
|
||||||
|
|
||||||
httpRouter := mux.NewRouter()
|
httpRouter := mux.NewRouter()
|
||||||
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
|
|
||||||
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
||||||
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
||||||
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)
|
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ RUN --mount=target=. \
|
||||||
--mount=type=cache,target=/root/.cache/go-build \
|
--mount=type=cache,target=/root/.cache/go-build \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
|
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
|
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/dendrite-monolith-server && \
|
CGO_ENABLED=${CGO} go build -o /dendrite/dendrite ./cmd/dendrite && \
|
||||||
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite-monolith-server && \
|
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite && \
|
||||||
cp build/scripts/complement-cmd.sh /complement-cmd.sh
|
cp build/scripts/complement-cmd.sh /complement-cmd.sh
|
||||||
|
|
||||||
WORKDIR /dendrite
|
WORKDIR /dendrite
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ WORKDIR /runtime
|
||||||
# This script compiles Dendrite for us.
|
# This script compiles Dendrite for us.
|
||||||
RUN echo '\
|
RUN echo '\
|
||||||
#!/bin/bash -eux \n\
|
#!/bin/bash -eux \n\
|
||||||
if test -f "/runtime/dendrite-monolith-server" && test -f "/runtime/dendrite-monolith-server-cover"; then \n\
|
if test -f "/runtime/dendrite" && test -f "/runtime/dendrite-cover"; then \n\
|
||||||
echo "Skipping compilation; binaries exist" \n\
|
echo "Skipping compilation; binaries exist" \n\
|
||||||
exit 0 \n\
|
exit 0 \n\
|
||||||
fi \n\
|
fi \n\
|
||||||
cd /dendrite \n\
|
cd /dendrite \n\
|
||||||
go build -v -o /runtime /dendrite/cmd/dendrite-monolith-server \n\
|
go build -v -o /runtime /dendrite/cmd/dendrite \n\
|
||||||
go test -c -cover -covermode=atomic -o /runtime/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." /dendrite/cmd/dendrite-monolith-server \n\
|
go test -c -cover -covermode=atomic -o /runtime/dendrite-cover -coverpkg "github.com/matrix-org/..." /dendrite/cmd/dendrite \n\
|
||||||
' > compile.sh && chmod +x compile.sh
|
' > compile.sh && chmod +x compile.sh
|
||||||
|
|
||||||
# This script runs Dendrite for us. Must be run in the /runtime directory.
|
# This script runs Dendrite for us. Must be run in the /runtime directory.
|
||||||
|
|
@ -35,8 +35,8 @@ RUN echo '\
|
||||||
./generate-keys -keysize 1024 --server $SERVER_NAME --tls-cert server.crt --tls-key server.key --tls-authority-cert /complement/ca/ca.crt --tls-authority-key /complement/ca/ca.key \n\
|
./generate-keys -keysize 1024 --server $SERVER_NAME --tls-cert server.crt --tls-key server.key --tls-authority-cert /complement/ca/ca.crt --tls-authority-key /complement/ca/ca.key \n\
|
||||||
./generate-config -server $SERVER_NAME --ci > dendrite.yaml \n\
|
./generate-config -server $SERVER_NAME --ci > dendrite.yaml \n\
|
||||||
cp /complement/ca/ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates \n\
|
cp /complement/ca/ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates \n\
|
||||||
[ ${COVER} -eq 1 ] && exec ./dendrite-monolith-server-cover --test.coverprofile=integrationcover.log --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
|
[ ${COVER} -eq 1 ] && exec ./dendrite-cover --test.coverprofile=integrationcover.log --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
|
||||||
exec ./dendrite-monolith-server --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
|
exec ./dendrite --really-enable-open-registration --tls-cert server.crt --tls-key server.key --config dendrite.yaml \n\
|
||||||
' > run.sh && chmod +x run.sh
|
' > run.sh && chmod +x run.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ RUN --mount=target=. \
|
||||||
--mount=type=cache,target=/root/.cache/go-build \
|
--mount=type=cache,target=/root/.cache/go-build \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
|
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-config && \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
|
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/generate-keys && \
|
||||||
CGO_ENABLED=${CGO} go build -o /dendrite ./cmd/dendrite-monolith-server && \
|
CGO_ENABLED=${CGO} go build -o /dendrite/dendrite ./cmd/dendrite && \
|
||||||
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-monolith-server-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite-monolith-server && \
|
CGO_ENABLED=${CGO} go test -c -cover -covermode=atomic -o /dendrite/dendrite-cover -coverpkg "github.com/matrix-org/..." ./cmd/dendrite && \
|
||||||
cp build/scripts/complement-cmd.sh /complement-cmd.sh
|
cp build/scripts/complement-cmd.sh /complement-cmd.sh
|
||||||
|
|
||||||
WORKDIR /dendrite
|
WORKDIR /dendrite
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,17 @@
|
||||||
|
|
||||||
if [[ "${COVER}" -eq 1 ]]; then
|
if [[ "${COVER}" -eq 1 ]]; then
|
||||||
echo "Running with coverage"
|
echo "Running with coverage"
|
||||||
exec /dendrite/dendrite-monolith-server-cover \
|
exec /dendrite/dendrite-cover \
|
||||||
--really-enable-open-registration \
|
--really-enable-open-registration \
|
||||||
--tls-cert server.crt \
|
--tls-cert server.crt \
|
||||||
--tls-key server.key \
|
--tls-key server.key \
|
||||||
--config dendrite.yaml \
|
--config dendrite.yaml \
|
||||||
-api=${API:-0} \
|
|
||||||
--test.coverprofile=complementcover.log
|
--test.coverprofile=complementcover.log
|
||||||
else
|
else
|
||||||
echo "Not running with coverage"
|
echo "Not running with coverage"
|
||||||
exec /dendrite/dendrite-monolith-server \
|
exec /dendrite/dendrite \
|
||||||
--really-enable-open-registration \
|
--really-enable-open-registration \
|
||||||
--tls-cert server.crt \
|
--tls-cert server.crt \
|
||||||
--tls-key server.key \
|
--tls-key server.key \
|
||||||
--config dendrite.yaml \
|
--config dendrite.yaml
|
||||||
-api=${API:-0}
|
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
"github.com/matrix-org/dendrite/federationapi"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
|
@ -41,11 +40,9 @@ func TestAdminResetPassword(t *testing.T) {
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
// Needed for changing the password/login
|
// Needed for changing the password/login
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
|
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
|
||||||
AddPublicRoutes(base, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, nil)
|
AddPublicRoutes(base, nil, rsAPI, nil, nil, nil, userAPI, nil, nil)
|
||||||
|
|
||||||
// Create the users in the userapi and login
|
// Create the users in the userapi and login
|
||||||
accessTokens := map[*test.User]string{
|
accessTokens := map[*test.User]string{
|
||||||
|
|
@ -159,14 +156,12 @@ func TestPurgeRoom(t *testing.T) {
|
||||||
|
|
||||||
fedClient := base.CreateFederationClient()
|
fedClient := base.CreateFederationClient()
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fedClient, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
|
|
||||||
// this starts the JetStream consumers
|
// this starts the JetStream consumers
|
||||||
syncapi.AddPublicRoutes(base, userAPI, rsAPI, keyAPI)
|
syncapi.AddPublicRoutes(base, userAPI, rsAPI)
|
||||||
federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true)
|
federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true)
|
||||||
rsAPI.SetFederationAPI(nil, nil)
|
rsAPI.SetFederationAPI(nil, nil)
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
// Create the room
|
// Create the room
|
||||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
||||||
|
|
@ -174,7 +169,7 @@ func TestPurgeRoom(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
|
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
|
||||||
AddPublicRoutes(base, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, nil)
|
AddPublicRoutes(base, nil, rsAPI, nil, nil, nil, userAPI, nil, nil)
|
||||||
|
|
||||||
// Create the users in the userapi and login
|
// Create the users in the userapi and login
|
||||||
accessTokens := map[*test.User]string{
|
accessTokens := map[*test.User]string{
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
package clientapi
|
package clientapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||||
|
|
@ -23,11 +24,9 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/routing"
|
"github.com/matrix-org/dendrite/clientapi/routing"
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/internal/transactions"
|
"github.com/matrix-org/dendrite/internal/transactions"
|
||||||
keyserverAPI "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddPublicRoutes sets up and registers HTTP handlers for the ClientAPI component.
|
// AddPublicRoutes sets up and registers HTTP handlers for the ClientAPI component.
|
||||||
|
|
@ -40,7 +39,6 @@ func AddPublicRoutes(
|
||||||
fsAPI federationAPI.ClientFederationAPI,
|
fsAPI federationAPI.ClientFederationAPI,
|
||||||
userAPI userapi.ClientUserAPI,
|
userAPI userapi.ClientUserAPI,
|
||||||
userDirectoryProvider userapi.QuerySearchProfilesAPI,
|
userDirectoryProvider userapi.QuerySearchProfilesAPI,
|
||||||
keyAPI keyserverAPI.ClientKeyAPI,
|
|
||||||
extRoomsProvider api.ExtraPublicRoomsProvider,
|
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
) {
|
) {
|
||||||
cfg := &base.Cfg.ClientAPI
|
cfg := &base.Cfg.ClientAPI
|
||||||
|
|
@ -61,7 +59,7 @@ func AddPublicRoutes(
|
||||||
base,
|
base,
|
||||||
cfg, rsAPI, asAPI,
|
cfg, rsAPI, asAPI,
|
||||||
userAPI, userDirectoryProvider, federation,
|
userAPI, userDirectoryProvider, federation,
|
||||||
syncProducer, transactionsCache, fsAPI, keyAPI,
|
syncProducer, transactionsCache, fsAPI,
|
||||||
extRoomsProvider, mscCfg, natsClient,
|
extRoomsProvider, mscCfg, natsClient,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,13 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AdminEvacuateRoom(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
func AdminEvacuateRoom(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
|
|
@ -56,7 +55,7 @@ func AdminEvacuateRoom(req *http.Request, cfg *config.ClientAPI, device *userapi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdminEvacuateUser(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
func AdminEvacuateUser(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
|
|
@ -99,7 +98,7 @@ func AdminEvacuateUser(req *http.Request, cfg *config.ClientAPI, device *userapi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdminPurgeRoom(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
func AdminPurgeRoom(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
|
|
@ -130,7 +129,7 @@ func AdminPurgeRoom(req *http.Request, cfg *config.ClientAPI, device *userapi.De
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.Device, userAPI api.ClientUserAPI) util.JSONResponse {
|
||||||
if req.Body == nil {
|
if req.Body == nil {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
|
|
@ -150,8 +149,8 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *userap
|
||||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accAvailableResp := &userapi.QueryAccountAvailabilityResponse{}
|
accAvailableResp := &api.QueryAccountAvailabilityResponse{}
|
||||||
if err = userAPI.QueryAccountAvailability(req.Context(), &userapi.QueryAccountAvailabilityRequest{
|
if err = userAPI.QueryAccountAvailability(req.Context(), &api.QueryAccountAvailabilityRequest{
|
||||||
Localpart: localpart,
|
Localpart: localpart,
|
||||||
ServerName: serverName,
|
ServerName: serverName,
|
||||||
}, accAvailableResp); err != nil {
|
}, accAvailableResp); err != nil {
|
||||||
|
|
@ -186,13 +185,13 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *userap
|
||||||
return *internal.PasswordResponse(err)
|
return *internal.PasswordResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateReq := &userapi.PerformPasswordUpdateRequest{
|
updateReq := &api.PerformPasswordUpdateRequest{
|
||||||
Localpart: localpart,
|
Localpart: localpart,
|
||||||
ServerName: serverName,
|
ServerName: serverName,
|
||||||
Password: request.Password,
|
Password: request.Password,
|
||||||
LogoutDevices: true,
|
LogoutDevices: true,
|
||||||
}
|
}
|
||||||
updateRes := &userapi.PerformPasswordUpdateResponse{}
|
updateRes := &api.PerformPasswordUpdateResponse{}
|
||||||
if err := userAPI.PerformPasswordUpdate(req.Context(), updateReq, updateRes); err != nil {
|
if err := userAPI.PerformPasswordUpdate(req.Context(), updateReq, updateRes); err != nil {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
|
|
@ -209,7 +208,7 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *userap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdminReindex(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, natsClient *nats.Conn) util.JSONResponse {
|
func AdminReindex(req *http.Request, cfg *config.ClientAPI, device *api.Device, natsClient *nats.Conn) util.JSONResponse {
|
||||||
_, err := natsClient.RequestMsg(nats.NewMsg(cfg.Matrix.JetStream.Prefixed(jetstream.InputFulltextReindex)), time.Second*10)
|
_, err := natsClient.RequestMsg(nats.NewMsg(cfg.Matrix.JetStream.Prefixed(jetstream.InputFulltextReindex)), time.Second*10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("failed to publish nats message")
|
logrus.WithError(err).Error("failed to publish nats message")
|
||||||
|
|
@ -255,7 +254,7 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdminDownloadState(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
func AdminDownloadState(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ func Test_AuthFallback(t *testing.T) {
|
||||||
for _, wantErr := range []bool{false, true} {
|
for _, wantErr := range []bool{false, true} {
|
||||||
t.Run(fmt.Sprintf("useHCaptcha(%v) - recaptchaEnabled(%v) - wantErr(%v)", useHCaptcha, recaptchaEnabled, wantErr), func(t *testing.T) {
|
t.Run(fmt.Sprintf("useHCaptcha(%v) - recaptchaEnabled(%v) - wantErr(%v)", useHCaptcha, recaptchaEnabled, wantErr), func(t *testing.T) {
|
||||||
// Set the defaults for each test
|
// Set the defaults for each test
|
||||||
base.Cfg.ClientAPI.Defaults(config.DefaultOpts{Generate: true, Monolithic: true})
|
base.Cfg.ClientAPI.Defaults(config.DefaultOpts{Generate: true, SingleDatabase: true})
|
||||||
base.Cfg.ClientAPI.RecaptchaEnabled = recaptchaEnabled
|
base.Cfg.ClientAPI.RecaptchaEnabled = recaptchaEnabled
|
||||||
base.Cfg.ClientAPI.RecaptchaPublicKey = "pub"
|
base.Cfg.ClientAPI.RecaptchaPublicKey = "pub"
|
||||||
base.Cfg.ClientAPI.RecaptchaPrivateKey = "priv"
|
base.Cfg.ClientAPI.RecaptchaPrivateKey = "priv"
|
||||||
|
|
@ -33,7 +33,7 @@ func Test_AuthFallback(t *testing.T) {
|
||||||
base.Cfg.ClientAPI.RecaptchaSitekeyClass = "h-captcha"
|
base.Cfg.ClientAPI.RecaptchaSitekeyClass = "h-captcha"
|
||||||
}
|
}
|
||||||
cfgErrs := &config.ConfigErrors{}
|
cfgErrs := &config.ConfigErrors{}
|
||||||
base.Cfg.ClientAPI.Verify(cfgErrs, true)
|
base.Cfg.ClientAPI.Verify(cfgErrs)
|
||||||
if len(*cfgErrs) > 0 {
|
if len(*cfgErrs) > 0 {
|
||||||
t.Fatalf("(hCaptcha=%v) unexpected config errors: %s", useHCaptcha, cfgErrs.Error())
|
t.Fatalf("(hCaptcha=%v) unexpected config errors: %s", useHCaptcha, cfgErrs.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice"
|
"github.com/matrix-org/dendrite/appservice"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
"github.com/matrix-org/dendrite/test/testrig"
|
"github.com/matrix-org/dendrite/test/testrig"
|
||||||
|
|
@ -29,8 +28,7 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
|
||||||
defer baseClose()
|
defer baseClose()
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
||||||
rsAPI.SetFederationAPI(nil, nil) // creates the rs.Inputer etc
|
rsAPI.SetFederationAPI(nil, nil) // creates the rs.Inputer etc
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -34,8 +33,8 @@ type crossSigningRequest struct {
|
||||||
|
|
||||||
func UploadCrossSigningDeviceKeys(
|
func UploadCrossSigningDeviceKeys(
|
||||||
req *http.Request, userInteractiveAuth *auth.UserInteractive,
|
req *http.Request, userInteractiveAuth *auth.UserInteractive,
|
||||||
keyserverAPI api.ClientKeyAPI, device *userapi.Device,
|
keyserverAPI api.ClientKeyAPI, device *api.Device,
|
||||||
accountAPI userapi.ClientUserAPI, cfg *config.ClientAPI,
|
accountAPI api.ClientUserAPI, cfg *config.ClientAPI,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
uploadReq := &crossSigningRequest{}
|
uploadReq := &crossSigningRequest{}
|
||||||
uploadRes := &api.PerformUploadDeviceKeysResponse{}
|
uploadRes := &api.PerformUploadDeviceKeysResponse{}
|
||||||
|
|
@ -107,7 +106,7 @@ func UploadCrossSigningDeviceKeys(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UploadCrossSigningDeviceSignatures(req *http.Request, keyserverAPI api.ClientKeyAPI, device *userapi.Device) util.JSONResponse {
|
func UploadCrossSigningDeviceSignatures(req *http.Request, keyserverAPI api.ClientKeyAPI, device *api.Device) util.JSONResponse {
|
||||||
uploadReq := &api.PerformUploadDeviceSignaturesRequest{}
|
uploadReq := &api.PerformUploadDeviceSignaturesRequest{}
|
||||||
uploadRes := &api.PerformUploadDeviceSignaturesResponse{}
|
uploadRes := &api.PerformUploadDeviceSignaturesResponse{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type uploadKeysRequest struct {
|
type uploadKeysRequest struct {
|
||||||
|
|
@ -32,7 +31,7 @@ type uploadKeysRequest struct {
|
||||||
OneTimeKeys map[string]json.RawMessage `json:"one_time_keys"`
|
OneTimeKeys map[string]json.RawMessage `json:"one_time_keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func UploadKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *userapi.Device) util.JSONResponse {
|
func UploadKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device) util.JSONResponse {
|
||||||
var r uploadKeysRequest
|
var r uploadKeysRequest
|
||||||
resErr := httputil.UnmarshalJSONRequest(req, &r)
|
resErr := httputil.UnmarshalJSONRequest(req, &r)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
|
|
@ -106,7 +105,7 @@ func (r *queryKeysRequest) GetTimeout() time.Duration {
|
||||||
return timeout
|
return timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func QueryKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *userapi.Device) util.JSONResponse {
|
func QueryKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device) util.JSONResponse {
|
||||||
var r queryKeysRequest
|
var r queryKeysRequest
|
||||||
resErr := httputil.UnmarshalJSONRequest(req, &r)
|
resErr := httputil.UnmarshalJSONRequest(req, &r)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
|
@ -45,15 +44,6 @@ func LeaveRoomByID(
|
||||||
JSON: jsonerror.LeaveServerNoticeError(),
|
JSON: jsonerror.LeaveServerNoticeError(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch e := err.(type) {
|
|
||||||
case httputil.InternalAPIError:
|
|
||||||
if e.Message == jsonerror.LeaveServerNoticeError().Error() {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: jsonerror.LeaveServerNoticeError(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
JSON: jsonerror.Unknown(err.Error()),
|
JSON: jsonerror.Unknown(err.Error()),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
@ -39,12 +38,10 @@ func TestLogin(t *testing.T) {
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
// Needed for /login
|
// Needed for /login
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
|
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
|
||||||
Setup(base, &base.Cfg.ClientAPI, nil, nil, userAPI, nil, nil, nil, nil, nil, keyAPI, nil, &base.Cfg.MSCs, nil)
|
Setup(base, &base.Cfg.ClientAPI, nil, nil, userAPI, nil, nil, nil, nil, nil, nil, &base.Cfg.MSCs, nil)
|
||||||
|
|
||||||
// Create password
|
// Create password
|
||||||
password := util.RandomString(8)
|
password := util.RandomString(8)
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
internalHTTPUtil "github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||||
|
|
@ -861,16 +859,6 @@ func completeRegistration(
|
||||||
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
|
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch e := err.(type) {
|
|
||||||
case internalHTTPUtil.InternalAPIError:
|
|
||||||
conflictErr := &userapi.ErrorConflict{Message: sqlutil.ErrUserExists.Error()}
|
|
||||||
if e.Message == conflictErr.Error() {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
JSON: jsonerror.Unknown("failed to create account: " + err.Error()),
|
JSON: jsonerror.Unknown("failed to create account: " + err.Error()),
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
|
|
@ -201,8 +200,8 @@ func TestValidationOfApplicationServices(t *testing.T) {
|
||||||
// Set up a config
|
// Set up a config
|
||||||
fakeConfig := &config.Dendrite{}
|
fakeConfig := &config.Dendrite{}
|
||||||
fakeConfig.Defaults(config.DefaultOpts{
|
fakeConfig.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
fakeConfig.Global.ServerName = "localhost"
|
fakeConfig.Global.ServerName = "localhost"
|
||||||
fakeConfig.ClientAPI.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService}
|
fakeConfig.ClientAPI.Derived.ApplicationServices = []config.ApplicationService{fakeApplicationService}
|
||||||
|
|
@ -409,9 +408,7 @@ func Test_register(t *testing.T) {
|
||||||
defer baseClose()
|
defer baseClose()
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|
@ -582,9 +579,7 @@ func TestRegisterUserWithDisplayName(t *testing.T) {
|
||||||
base.Cfg.Global.ServerName = "server"
|
base.Cfg.Global.ServerName = "server"
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
deviceName, deviceID := "deviceName", "deviceID"
|
deviceName, deviceID := "deviceName", "deviceID"
|
||||||
expectedDisplayName := "DisplayName"
|
expectedDisplayName := "DisplayName"
|
||||||
response := completeRegistration(
|
response := completeRegistration(
|
||||||
|
|
@ -623,9 +618,7 @@ func TestRegisterAdminUsingSharedSecret(t *testing.T) {
|
||||||
base.Cfg.ClientAPI.RegistrationSharedSecret = sharedSecret
|
base.Cfg.ClientAPI.RegistrationSharedSecret = sharedSecret
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, nil)
|
||||||
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
expectedDisplayName := "rabbit"
|
expectedDisplayName := "rabbit"
|
||||||
jsonStr := []byte(`{"admin":true,"mac":"24dca3bba410e43fe64b9b5c28306693bf3baa9f","nonce":"759f047f312b99ff428b21d581256f8592b8976e58bc1b543972dc6147e529a79657605b52d7becd160ff5137f3de11975684319187e06901955f79e5a6c5a79","password":"wonderland","username":"alice","displayname":"rabbit"}`)
|
jsonStr := []byte(`{"admin":true,"mac":"24dca3bba410e43fe64b9b5c28306693bf3baa9f","nonce":"759f047f312b99ff428b21d581256f8592b8976e58bc1b543972dc6147e529a79657605b52d7becd160ff5137f3de11975684319187e06901955f79e5a6c5a79","password":"wonderland","username":"alice","displayname":"rabbit"}`)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
|
@ -37,11 +38,9 @@ import (
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/internal/transactions"
|
"github.com/matrix-org/dendrite/internal/transactions"
|
||||||
keyserverAPI "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
||||||
|
|
@ -61,7 +60,6 @@ func Setup(
|
||||||
syncProducer *producers.SyncAPIProducer,
|
syncProducer *producers.SyncAPIProducer,
|
||||||
transactionsCache *transactions.Cache,
|
transactionsCache *transactions.Cache,
|
||||||
federationSender federationAPI.ClientFederationAPI,
|
federationSender federationAPI.ClientFederationAPI,
|
||||||
keyAPI keyserverAPI.ClientKeyAPI,
|
|
||||||
extRoomsProvider api.ExtraPublicRoomsProvider,
|
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
mscCfg *config.MSCs, natsClient *nats.Conn,
|
mscCfg *config.MSCs, natsClient *nats.Conn,
|
||||||
) {
|
) {
|
||||||
|
|
@ -192,7 +190,7 @@ func Setup(
|
||||||
|
|
||||||
dendriteAdminRouter.Handle("/admin/refreshDevices/{userID}",
|
dendriteAdminRouter.Handle("/admin/refreshDevices/{userID}",
|
||||||
httputil.MakeAdminAPI("admin_refresh_devices", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAdminAPI("admin_refresh_devices", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return AdminMarkAsStale(req, cfg, keyAPI)
|
return AdminMarkAsStale(req, cfg, userAPI)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
||||||
|
|
@ -1372,11 +1370,11 @@ func Setup(
|
||||||
// Cross-signing device keys
|
// Cross-signing device keys
|
||||||
|
|
||||||
postDeviceSigningKeys := httputil.MakeAuthAPI("post_device_signing_keys", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
postDeviceSigningKeys := httputil.MakeAuthAPI("post_device_signing_keys", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return UploadCrossSigningDeviceKeys(req, userInteractiveAuth, keyAPI, device, userAPI, cfg)
|
return UploadCrossSigningDeviceKeys(req, userInteractiveAuth, userAPI, device, userAPI, cfg)
|
||||||
})
|
})
|
||||||
|
|
||||||
postDeviceSigningSignatures := httputil.MakeAuthAPI("post_device_signing_signatures", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
postDeviceSigningSignatures := httputil.MakeAuthAPI("post_device_signing_signatures", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return UploadCrossSigningDeviceSignatures(req, keyAPI, device)
|
return UploadCrossSigningDeviceSignatures(req, userAPI, device)
|
||||||
}, httputil.WithAllowGuests())
|
}, httputil.WithAllowGuests())
|
||||||
|
|
||||||
v3mux.Handle("/keys/device_signing/upload", postDeviceSigningKeys).Methods(http.MethodPost, http.MethodOptions)
|
v3mux.Handle("/keys/device_signing/upload", postDeviceSigningKeys).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
@ -1388,22 +1386,22 @@ func Setup(
|
||||||
// Supplying a device ID is deprecated.
|
// Supplying a device ID is deprecated.
|
||||||
v3mux.Handle("/keys/upload/{deviceID}",
|
v3mux.Handle("/keys/upload/{deviceID}",
|
||||||
httputil.MakeAuthAPI("keys_upload", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("keys_upload", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return UploadKeys(req, keyAPI, device)
|
return UploadKeys(req, userAPI, device)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
v3mux.Handle("/keys/upload",
|
v3mux.Handle("/keys/upload",
|
||||||
httputil.MakeAuthAPI("keys_upload", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("keys_upload", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return UploadKeys(req, keyAPI, device)
|
return UploadKeys(req, userAPI, device)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
v3mux.Handle("/keys/query",
|
v3mux.Handle("/keys/query",
|
||||||
httputil.MakeAuthAPI("keys_query", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("keys_query", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return QueryKeys(req, keyAPI, device)
|
return QueryKeys(req, userAPI, device)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
v3mux.Handle("/keys/claim",
|
v3mux.Handle("/keys/claim",
|
||||||
httputil.MakeAuthAPI("keys_claim", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("keys_claim", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return ClaimKeys(req, keyAPI)
|
return ClaimKeys(req, userAPI)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
v3mux.Handle("/rooms/{roomId}/receipt/{receiptType}/{eventId}",
|
v3mux.Handle("/rooms/{roomId}/receipt/{receiptType}/{eventId}",
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import (
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/relayapi"
|
"github.com/matrix-org/dendrite/relayapi"
|
||||||
relayAPI "github.com/matrix-org/dendrite/relayapi/api"
|
relayAPI "github.com/matrix-org/dendrite/relayapi/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
|
|
@ -80,8 +79,8 @@ type P2PMonolith struct {
|
||||||
func GenerateDefaultConfig(sk ed25519.PrivateKey, storageDir string, cacheDir string, dbPrefix string) *config.Dendrite {
|
func GenerateDefaultConfig(sk ed25519.PrivateKey, storageDir string, cacheDir string, dbPrefix string) *config.Dendrite {
|
||||||
cfg := config.Dendrite{}
|
cfg := config.Dendrite{}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
cfg.Global.PrivateKey = sk
|
cfg.Global.PrivateKey = sk
|
||||||
cfg.Global.JetStream.StoragePath = config.Path(fmt.Sprintf("%s/", filepath.Join(cacheDir, dbPrefix)))
|
cfg.Global.JetStream.StoragePath = config.Path(fmt.Sprintf("%s/", filepath.Join(cacheDir, dbPrefix)))
|
||||||
|
|
@ -121,9 +120,9 @@ func (p *P2PMonolith) SetupPinecone(sk ed25519.PrivateKey) {
|
||||||
|
|
||||||
func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelaying bool, enableMetrics bool, enableWebsockets bool) {
|
func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelaying bool, enableMetrics bool, enableWebsockets bool) {
|
||||||
if enableMetrics {
|
if enableMetrics {
|
||||||
p.BaseDendrite = base.NewBaseDendrite(cfg, "Monolith")
|
p.BaseDendrite = base.NewBaseDendrite(cfg)
|
||||||
} else {
|
} else {
|
||||||
p.BaseDendrite = base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics)
|
p.BaseDendrite = base.NewBaseDendrite(cfg, base.DisableMetrics)
|
||||||
}
|
}
|
||||||
p.port = port
|
p.port = port
|
||||||
p.BaseDendrite.ConfigureAdminEndpoints()
|
p.BaseDendrite.ConfigureAdminEndpoints()
|
||||||
|
|
@ -139,9 +138,7 @@ func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelayi
|
||||||
p.BaseDendrite, federation, rsAPI, p.BaseDendrite.Caches, keyRing, true,
|
p.BaseDendrite, federation, rsAPI, p.BaseDendrite.Caches, keyRing, true,
|
||||||
)
|
)
|
||||||
|
|
||||||
keyAPI := keyserver.NewInternalAPI(p.BaseDendrite, &p.BaseDendrite.Cfg.KeyServer, fsAPI, rsComponent)
|
userAPI := userapi.NewInternalAPI(p.BaseDendrite, rsAPI, federation)
|
||||||
userAPI := userapi.NewInternalAPI(p.BaseDendrite, &cfg.UserAPI, nil, keyAPI, rsAPI, p.BaseDendrite.PushGatewayHTTPClient())
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
asAPI := appservice.NewInternalAPI(p.BaseDendrite, userAPI, rsAPI)
|
asAPI := appservice.NewInternalAPI(p.BaseDendrite, userAPI, rsAPI)
|
||||||
|
|
||||||
|
|
@ -175,7 +172,6 @@ func (p *P2PMonolith) SetupDendrite(cfg *config.Dendrite, port int, enableRelayi
|
||||||
FederationAPI: fsAPI,
|
FederationAPI: fsAPI,
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyAPI,
|
|
||||||
RelayAPI: relayAPI,
|
RelayAPI: relayAPI,
|
||||||
ExtPublicRoomsProvider: roomProvider,
|
ExtPublicRoomsProvider: roomProvider,
|
||||||
ExtUserDirectoryProvider: userProvider,
|
ExtUserDirectoryProvider: userProvider,
|
||||||
|
|
@ -236,7 +232,6 @@ func (p *P2PMonolith) Addr() string {
|
||||||
|
|
||||||
func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) {
|
func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) {
|
||||||
p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath()
|
p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||||
p.httpMux.PathPrefix(httputil.InternalPathPrefix).Handler(p.BaseDendrite.InternalAPIMux)
|
|
||||||
p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.PublicClientAPIMux)
|
p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.PublicClientAPIMux)
|
||||||
p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux)
|
p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux)
|
||||||
p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.DendriteAdminMux)
|
p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.DendriteAdminMux)
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
"github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/setup"
|
"github.com/matrix-org/dendrite/setup"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
|
@ -117,8 +116,8 @@ func main() {
|
||||||
cfg = setup.ParseFlags(true)
|
cfg = setup.ParseFlags(true)
|
||||||
} else {
|
} else {
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
cfg.Global.PrivateKey = sk
|
cfg.Global.PrivateKey = sk
|
||||||
cfg.Global.JetStream.StoragePath = config.Path(filepath.Join(*instanceDir, *instanceName))
|
cfg.Global.JetStream.StoragePath = config.Path(filepath.Join(*instanceDir, *instanceName))
|
||||||
|
|
@ -143,7 +142,7 @@ func main() {
|
||||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||||
|
|
||||||
base := base.NewBaseDendrite(cfg, "Monolith")
|
base := base.NewBaseDendrite(cfg)
|
||||||
base.ConfigureAdminEndpoints()
|
base.ConfigureAdminEndpoints()
|
||||||
defer base.Close() // nolint: errcheck
|
defer base.Close() // nolint: errcheck
|
||||||
|
|
||||||
|
|
@ -157,16 +156,11 @@ func main() {
|
||||||
serverKeyAPI := &signing.YggdrasilKeys{}
|
serverKeyAPI := &signing.YggdrasilKeys{}
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
|
|
||||||
rsComponent := roomserver.NewInternalAPI(
|
rsAPI := roomserver.NewInternalAPI(
|
||||||
base,
|
base,
|
||||||
)
|
)
|
||||||
|
|
||||||
keyAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, federation, rsComponent)
|
userAPI := userapi.NewInternalAPI(base, rsAPI, federation)
|
||||||
|
|
||||||
rsAPI := rsComponent
|
|
||||||
|
|
||||||
userAPI := userapi.NewInternalAPI(base, &cfg.UserAPI, nil, keyAPI, rsAPI, base.PushGatewayHTTPClient())
|
|
||||||
keyAPI.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
||||||
rsAPI.SetAppserviceAPI(asAPI)
|
rsAPI.SetAppserviceAPI(asAPI)
|
||||||
|
|
@ -174,7 +168,7 @@ func main() {
|
||||||
base, federation, rsAPI, base.Caches, keyRing, true,
|
base, federation, rsAPI, base.Caches, keyRing, true,
|
||||||
)
|
)
|
||||||
|
|
||||||
rsComponent.SetFederationAPI(fsAPI, keyRing)
|
rsAPI.SetFederationAPI(fsAPI, keyRing)
|
||||||
|
|
||||||
monolith := setup.Monolith{
|
monolith := setup.Monolith{
|
||||||
Config: base.Cfg,
|
Config: base.Cfg,
|
||||||
|
|
@ -186,7 +180,6 @@ func main() {
|
||||||
FederationAPI: fsAPI,
|
FederationAPI: fsAPI,
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyAPI,
|
|
||||||
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
||||||
ygg, fsAPI, federation,
|
ygg, fsAPI, federation,
|
||||||
),
|
),
|
||||||
|
|
@ -197,7 +190,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||||
httpRouter.PathPrefix(httputil.InternalPathPrefix).Handler(base.InternalAPIMux)
|
|
||||||
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux)
|
||||||
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux)
|
||||||
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)
|
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux)
|
||||||
|
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
// Copyright 2017 Vector Creations Ltd
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice"
|
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/setup"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
"github.com/matrix-org/dendrite/setup/mscs"
|
|
||||||
"github.com/matrix-org/dendrite/userapi"
|
|
||||||
uapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
httpBindAddr = flag.String("http-bind-address", ":8008", "The HTTP listening port for the server")
|
|
||||||
httpsBindAddr = flag.String("https-bind-address", ":8448", "The HTTPS listening port for the server")
|
|
||||||
apiBindAddr = flag.String("api-bind-address", "localhost:18008", "The HTTP listening port for the internal HTTP APIs (if -api is enabled)")
|
|
||||||
certFile = flag.String("tls-cert", "", "The PEM formatted X509 certificate to use for TLS")
|
|
||||||
keyFile = flag.String("tls-key", "", "The PEM private key to use for TLS")
|
|
||||||
enableHTTPAPIs = flag.Bool("api", false, "Use HTTP APIs instead of short-circuiting (warning: exposes API endpoints!)")
|
|
||||||
traceInternal = os.Getenv("DENDRITE_TRACE_INTERNAL") == "1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cfg := setup.ParseFlags(true)
|
|
||||||
httpAddr := config.HTTPAddress("http://" + *httpBindAddr)
|
|
||||||
httpsAddr := config.HTTPAddress("https://" + *httpsBindAddr)
|
|
||||||
httpAPIAddr := httpAddr
|
|
||||||
options := []basepkg.BaseDendriteOptions{}
|
|
||||||
if *enableHTTPAPIs {
|
|
||||||
logrus.Warnf("DANGER! The -api option is enabled, exposing internal APIs on %q!", *apiBindAddr)
|
|
||||||
httpAPIAddr = config.HTTPAddress("http://" + *apiBindAddr)
|
|
||||||
// If the HTTP APIs are enabled then we need to update the Listen
|
|
||||||
// statements in the configuration so that we know where to find
|
|
||||||
// the API endpoints. They'll listen on the same port as the monolith
|
|
||||||
// itself.
|
|
||||||
cfg.AppServiceAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.ClientAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.FederationAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.KeyServer.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.MediaAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.RoomServer.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.SyncAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
cfg.UserAPI.InternalAPI.Connect = httpAPIAddr
|
|
||||||
options = append(options, basepkg.UseHTTPAPIs)
|
|
||||||
}
|
|
||||||
|
|
||||||
base := basepkg.NewBaseDendrite(cfg, "Monolith", options...)
|
|
||||||
defer base.Close() // nolint: errcheck
|
|
||||||
|
|
||||||
federation := base.CreateFederationClient()
|
|
||||||
|
|
||||||
rsImpl := roomserver.NewInternalAPI(base)
|
|
||||||
// call functions directly on the impl unless running in HTTP mode
|
|
||||||
rsAPI := rsImpl
|
|
||||||
if base.UseHTTPAPIs {
|
|
||||||
roomserver.AddInternalRoutes(base.InternalAPIMux, rsImpl, base.EnableMetrics)
|
|
||||||
rsAPI = base.RoomserverHTTPClient()
|
|
||||||
}
|
|
||||||
if traceInternal {
|
|
||||||
rsAPI = &api.RoomserverInternalAPITrace{
|
|
||||||
Impl: rsAPI,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fsAPI := federationapi.NewInternalAPI(
|
|
||||||
base, federation, rsAPI, base.Caches, nil, false,
|
|
||||||
)
|
|
||||||
fsImplAPI := fsAPI
|
|
||||||
if base.UseHTTPAPIs {
|
|
||||||
federationapi.AddInternalRoutes(base.InternalAPIMux, fsAPI, base.EnableMetrics)
|
|
||||||
fsAPI = base.FederationAPIHTTPClient()
|
|
||||||
}
|
|
||||||
keyRing := fsAPI.KeyRing()
|
|
||||||
|
|
||||||
keyImpl := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI, rsAPI)
|
|
||||||
keyAPI := keyImpl
|
|
||||||
if base.UseHTTPAPIs {
|
|
||||||
keyserver.AddInternalRoutes(base.InternalAPIMux, keyAPI, base.EnableMetrics)
|
|
||||||
keyAPI = base.KeyServerHTTPClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
pgClient := base.PushGatewayHTTPClient()
|
|
||||||
userImpl := userapi.NewInternalAPI(base, &cfg.UserAPI, cfg.Derived.ApplicationServices, keyAPI, rsAPI, pgClient)
|
|
||||||
userAPI := userImpl
|
|
||||||
if base.UseHTTPAPIs {
|
|
||||||
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI, base.EnableMetrics)
|
|
||||||
userAPI = base.UserAPIClient()
|
|
||||||
}
|
|
||||||
if traceInternal {
|
|
||||||
userAPI = &uapi.UserInternalAPITrace{
|
|
||||||
Impl: userAPI,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This should use userAPI, not userImpl, but the appservice setup races with
|
|
||||||
// the listeners and panics at startup if it tries to create appservice accounts
|
|
||||||
// before the listeners are up.
|
|
||||||
asAPI := appservice.NewInternalAPI(base, userImpl, rsAPI)
|
|
||||||
if base.UseHTTPAPIs {
|
|
||||||
appservice.AddInternalRoutes(base.InternalAPIMux, asAPI, base.EnableMetrics)
|
|
||||||
asAPI = base.AppserviceHTTPClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
// The underlying roomserver implementation needs to be able to call the fedsender.
|
|
||||||
// This is different to rsAPI which can be the http client which doesn't need this
|
|
||||||
// dependency. Other components also need updating after their dependencies are up.
|
|
||||||
rsImpl.SetFederationAPI(fsAPI, keyRing)
|
|
||||||
rsImpl.SetAppserviceAPI(asAPI)
|
|
||||||
rsImpl.SetUserAPI(userAPI)
|
|
||||||
keyImpl.SetUserAPI(userAPI)
|
|
||||||
|
|
||||||
monolith := setup.Monolith{
|
|
||||||
Config: base.Cfg,
|
|
||||||
Client: base.CreateClient(),
|
|
||||||
FedClient: federation,
|
|
||||||
KeyRing: keyRing,
|
|
||||||
|
|
||||||
AppserviceAPI: asAPI,
|
|
||||||
// always use the concrete impl here even in -http mode because adding public routes
|
|
||||||
// must be done on the concrete impl not an HTTP client else fedapi will call itself
|
|
||||||
FederationAPI: fsImplAPI,
|
|
||||||
RoomserverAPI: rsAPI,
|
|
||||||
UserAPI: userAPI,
|
|
||||||
KeyAPI: keyAPI,
|
|
||||||
}
|
|
||||||
monolith.AddAllPublicRoutes(base)
|
|
||||||
|
|
||||||
if len(base.Cfg.MSCs.MSCs) > 0 {
|
|
||||||
if err := mscs.Enable(base, &monolith); err != nil {
|
|
||||||
logrus.WithError(err).Fatalf("Failed to enable MSCs")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose the matrix APIs directly rather than putting them under a /api path.
|
|
||||||
go func() {
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
httpAPIAddr, // internal API
|
|
||||||
httpAddr, // external API
|
|
||||||
nil, nil, // TLS settings
|
|
||||||
)
|
|
||||||
}()
|
|
||||||
// Handle HTTPS if certificate and key are provided
|
|
||||||
if *certFile != "" && *keyFile != "" {
|
|
||||||
go func() {
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
basepkg.NoListener, // internal API
|
|
||||||
httpsAddr, // external API
|
|
||||||
certFile, keyFile, // TLS settings
|
|
||||||
)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
|
|
||||||
base.WaitForShutdown()
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/cmd/dendrite-polylith-multi/personalities"
|
|
||||||
"github.com/matrix-org/dendrite/setup"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type entrypoint func(base *base.BaseDendrite, cfg *config.Dendrite)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cfg := setup.ParseFlags(false)
|
|
||||||
|
|
||||||
component := ""
|
|
||||||
if flag.NFlag() > 0 {
|
|
||||||
component = flag.Arg(0) // ./dendrite-polylith-multi --config=... clientapi
|
|
||||||
} else if len(os.Args) > 1 {
|
|
||||||
component = os.Args[1] // ./dendrite-polylith-multi clientapi
|
|
||||||
}
|
|
||||||
|
|
||||||
components := map[string]entrypoint{
|
|
||||||
"appservice": personalities.Appservice,
|
|
||||||
"clientapi": personalities.ClientAPI,
|
|
||||||
"federationapi": personalities.FederationAPI,
|
|
||||||
"keyserver": personalities.KeyServer,
|
|
||||||
"mediaapi": personalities.MediaAPI,
|
|
||||||
"roomserver": personalities.RoomServer,
|
|
||||||
"syncapi": personalities.SyncAPI,
|
|
||||||
"userapi": personalities.UserAPI,
|
|
||||||
}
|
|
||||||
|
|
||||||
start, ok := components[component]
|
|
||||||
if !ok {
|
|
||||||
if component == "" {
|
|
||||||
logrus.Errorf("No component specified")
|
|
||||||
logrus.Info("The first argument on the command line must be the name of the component to run")
|
|
||||||
} else {
|
|
||||||
logrus.Errorf("Unknown component %q specified", component)
|
|
||||||
}
|
|
||||||
|
|
||||||
var list []string
|
|
||||||
for c := range components {
|
|
||||||
list = append(list, c)
|
|
||||||
}
|
|
||||||
logrus.Infof("Valid components: %s", strings.Join(list, ", "))
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Infof("Starting %q component", component)
|
|
||||||
|
|
||||||
base := base.NewBaseDendrite(cfg, component, base.PolylithMode) // TODO
|
|
||||||
defer base.Close() // nolint: errcheck
|
|
||||||
|
|
||||||
go start(base, cfg)
|
|
||||||
base.WaitForShutdown()
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/appservice"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Appservice(base *base.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
userAPI := base.UserAPIClient()
|
|
||||||
rsAPI := base.RoomserverHTTPClient()
|
|
||||||
|
|
||||||
intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
|
||||||
appservice.AddInternalRoutes(base.InternalAPIMux, intAPI, base.EnableMetrics)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.AppServiceAPI.InternalAPI.Listen, // internal listener
|
|
||||||
basepkg.NoListener, // external listener
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/clientapi"
|
|
||||||
"github.com/matrix-org/dendrite/internal/transactions"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ClientAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
federation := base.CreateFederationClient()
|
|
||||||
|
|
||||||
asQuery := base.AppserviceHTTPClient()
|
|
||||||
rsAPI := base.RoomserverHTTPClient()
|
|
||||||
fsAPI := base.FederationAPIHTTPClient()
|
|
||||||
userAPI := base.UserAPIClient()
|
|
||||||
keyAPI := base.KeyServerHTTPClient()
|
|
||||||
|
|
||||||
clientapi.AddPublicRoutes(
|
|
||||||
base, federation, rsAPI, asQuery,
|
|
||||||
transactions.New(), fsAPI, userAPI, userAPI,
|
|
||||||
keyAPI, nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.ClientAPI.InternalAPI.Listen,
|
|
||||||
base.Cfg.ClientAPI.ExternalAPI.Listen,
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func FederationAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
userAPI := base.UserAPIClient()
|
|
||||||
federation := base.CreateFederationClient()
|
|
||||||
rsAPI := base.RoomserverHTTPClient()
|
|
||||||
keyAPI := base.KeyServerHTTPClient()
|
|
||||||
fsAPI := federationapi.NewInternalAPI(base, federation, rsAPI, base.Caches, nil, true)
|
|
||||||
keyRing := fsAPI.KeyRing()
|
|
||||||
|
|
||||||
federationapi.AddPublicRoutes(
|
|
||||||
base,
|
|
||||||
userAPI, federation, keyRing,
|
|
||||||
rsAPI, fsAPI, keyAPI, nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
federationapi.AddInternalRoutes(base.InternalAPIMux, fsAPI, base.EnableMetrics)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.FederationAPI.InternalAPI.Listen,
|
|
||||||
base.Cfg.FederationAPI.ExternalAPI.Listen,
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/keyserver"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func KeyServer(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
fsAPI := base.FederationAPIHTTPClient()
|
|
||||||
rsAPI := base.RoomserverHTTPClient()
|
|
||||||
intAPI := keyserver.NewInternalAPI(base, &base.Cfg.KeyServer, fsAPI, rsAPI)
|
|
||||||
intAPI.SetUserAPI(base.UserAPIClient())
|
|
||||||
|
|
||||||
keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI, base.EnableMetrics)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.KeyServer.InternalAPI.Listen, // internal listener
|
|
||||||
basepkg.NoListener, // external listener
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RoomServer(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
asAPI := base.AppserviceHTTPClient()
|
|
||||||
fsAPI := base.FederationAPIHTTPClient()
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
|
||||||
rsAPI.SetFederationAPI(fsAPI, fsAPI.KeyRing())
|
|
||||||
rsAPI.SetAppserviceAPI(asAPI)
|
|
||||||
roomserver.AddInternalRoutes(base.InternalAPIMux, rsAPI, base.EnableMetrics)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.RoomServer.InternalAPI.Listen, // internal listener
|
|
||||||
basepkg.NoListener, // external listener
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
"github.com/matrix-org/dendrite/syncapi"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SyncAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
userAPI := base.UserAPIClient()
|
|
||||||
|
|
||||||
rsAPI := base.RoomserverHTTPClient()
|
|
||||||
|
|
||||||
syncapi.AddPublicRoutes(
|
|
||||||
base,
|
|
||||||
userAPI, rsAPI,
|
|
||||||
base.KeyServerHTTPClient(),
|
|
||||||
)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.SyncAPI.InternalAPI.Listen,
|
|
||||||
base.Cfg.SyncAPI.ExternalAPI.Listen,
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package personalities
|
|
||||||
|
|
||||||
import (
|
|
||||||
basepkg "github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
"github.com/matrix-org/dendrite/userapi"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UserAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
|
|
||||||
userAPI := userapi.NewInternalAPI(
|
|
||||||
base, &cfg.UserAPI, cfg.Derived.ApplicationServices,
|
|
||||||
base.KeyServerHTTPClient(), base.RoomserverHTTPClient(),
|
|
||||||
base.PushGatewayHTTPClient(),
|
|
||||||
)
|
|
||||||
|
|
||||||
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI, base.EnableMetrics)
|
|
||||||
|
|
||||||
base.SetupAndServeHTTP(
|
|
||||||
base.Cfg.UserAPI.InternalAPI.Listen, // internal listener
|
|
||||||
basepkg.NoListener, // external listener
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -45,6 +45,10 @@ var (
|
||||||
|
|
||||||
const HEAD = "HEAD"
|
const HEAD = "HEAD"
|
||||||
|
|
||||||
|
// The binary was renamed after v0.11.1, so everything after that should use the new name
|
||||||
|
var binaryChangeVersion, _ = semver.NewVersion("v0.11.1")
|
||||||
|
var latest, _ = semver.NewVersion("v6.6.6") // Dummy version, used as "HEAD"
|
||||||
|
|
||||||
// Embed the Dockerfile to use when building dendrite versions.
|
// Embed the Dockerfile to use when building dendrite versions.
|
||||||
// We cannot use the dockerfile associated with the repo with each version sadly due to changes in
|
// We cannot use the dockerfile associated with the repo with each version sadly due to changes in
|
||||||
// Docker versions. Specifically, earlier Dendrite versions are incompatible with newer Docker clients
|
// Docker versions. Specifically, earlier Dendrite versions are incompatible with newer Docker clients
|
||||||
|
|
@ -54,12 +58,13 @@ const HEAD = "HEAD"
|
||||||
const DockerfilePostgreSQL = `FROM golang:1.18-stretch as build
|
const DockerfilePostgreSQL = `FROM golang:1.18-stretch as build
|
||||||
RUN apt-get update && apt-get install -y postgresql
|
RUN apt-get update && apt-get install -y postgresql
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
ARG BINARY
|
||||||
|
|
||||||
# Copy the build context to the repo as this is the right dendrite code. This is different to the
|
# Copy the build context to the repo as this is the right dendrite code. This is different to the
|
||||||
# Complement Dockerfile which wgets a branch.
|
# Complement Dockerfile which wgets a branch.
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN go build ./cmd/dendrite-monolith-server
|
RUN go build ./cmd/${BINARY}
|
||||||
RUN go build ./cmd/generate-keys
|
RUN go build ./cmd/generate-keys
|
||||||
RUN go build ./cmd/generate-config
|
RUN go build ./cmd/generate-config
|
||||||
RUN go build ./cmd/create-account
|
RUN go build ./cmd/create-account
|
||||||
|
|
@ -88,22 +93,24 @@ done \n\
|
||||||
\n\
|
\n\
|
||||||
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
|
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
|
||||||
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
|
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
|
||||||
./dendrite-monolith-server --really-enable-open-registration ${PARAMS} || ./dendrite-monolith-server ${PARAMS} \n\
|
./${BINARY} --really-enable-open-registration ${PARAMS} || ./${BINARY} ${PARAMS} \n\
|
||||||
' > run_dendrite.sh && chmod +x run_dendrite.sh
|
' > run_dendrite.sh && chmod +x run_dendrite.sh
|
||||||
|
|
||||||
ENV SERVER_NAME=localhost
|
ENV SERVER_NAME=localhost
|
||||||
|
ENV BINARY=dendrite
|
||||||
EXPOSE 8008 8448
|
EXPOSE 8008 8448
|
||||||
CMD /build/run_dendrite.sh `
|
CMD /build/run_dendrite.sh`
|
||||||
|
|
||||||
const DockerfileSQLite = `FROM golang:1.18-stretch as build
|
const DockerfileSQLite = `FROM golang:1.18-stretch as build
|
||||||
RUN apt-get update && apt-get install -y postgresql
|
RUN apt-get update && apt-get install -y postgresql
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
ARG BINARY
|
||||||
|
|
||||||
# Copy the build context to the repo as this is the right dendrite code. This is different to the
|
# Copy the build context to the repo as this is the right dendrite code. This is different to the
|
||||||
# Complement Dockerfile which wgets a branch.
|
# Complement Dockerfile which wgets a branch.
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN go build ./cmd/dendrite-monolith-server
|
RUN go build ./cmd/${BINARY}
|
||||||
RUN go build ./cmd/generate-keys
|
RUN go build ./cmd/generate-keys
|
||||||
RUN go build ./cmd/generate-config
|
RUN go build ./cmd/generate-config
|
||||||
RUN go build ./cmd/create-account
|
RUN go build ./cmd/create-account
|
||||||
|
|
@ -118,10 +125,11 @@ RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postg
|
||||||
RUN echo '\
|
RUN echo '\
|
||||||
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
|
sed -i "s/server_name: localhost/server_name: ${SERVER_NAME}/g" dendrite.yaml \n\
|
||||||
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
|
PARAMS="--tls-cert server.crt --tls-key server.key --config dendrite.yaml" \n\
|
||||||
./dendrite-monolith-server --really-enable-open-registration ${PARAMS} || ./dendrite-monolith-server ${PARAMS} \n\
|
./${BINARY} --really-enable-open-registration ${PARAMS} || ./${BINARY} ${PARAMS} \n\
|
||||||
' > run_dendrite.sh && chmod +x run_dendrite.sh
|
' > run_dendrite.sh && chmod +x run_dendrite.sh
|
||||||
|
|
||||||
ENV SERVER_NAME=localhost
|
ENV SERVER_NAME=localhost
|
||||||
|
ENV BINARY=dendrite
|
||||||
EXPOSE 8008 8448
|
EXPOSE 8008 8448
|
||||||
CMD /build/run_dendrite.sh `
|
CMD /build/run_dendrite.sh `
|
||||||
|
|
||||||
|
|
@ -182,7 +190,7 @@ func downloadArchive(cli *http.Client, tmpDir, archiveURL string, dockerfile []b
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildDendrite builds Dendrite on the branchOrTagName given. Returns the image ID or an error
|
// buildDendrite builds Dendrite on the branchOrTagName given. Returns the image ID or an error
|
||||||
func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir, branchOrTagName string) (string, error) {
|
func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir string, branchOrTagName, binary string) (string, error) {
|
||||||
var tarball *bytes.Buffer
|
var tarball *bytes.Buffer
|
||||||
var err error
|
var err error
|
||||||
// If a custom HEAD location is given, use that, else pull from github. Mostly useful for CI
|
// If a custom HEAD location is given, use that, else pull from github. Mostly useful for CI
|
||||||
|
|
@ -216,6 +224,9 @@ func buildDendrite(httpClient *http.Client, dockerClient *client.Client, tmpDir,
|
||||||
log.Printf("%s: Building version %s\n", branchOrTagName, branchOrTagName)
|
log.Printf("%s: Building version %s\n", branchOrTagName, branchOrTagName)
|
||||||
res, err := dockerClient.ImageBuild(context.Background(), tarball, types.ImageBuildOptions{
|
res, err := dockerClient.ImageBuild(context.Background(), tarball, types.ImageBuildOptions{
|
||||||
Tags: []string{"dendrite-upgrade"},
|
Tags: []string{"dendrite-upgrade"},
|
||||||
|
BuildArgs: map[string]*string{
|
||||||
|
"BINARY": &binary,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to start building image: %s", err)
|
return "", fmt.Errorf("failed to start building image: %s", err)
|
||||||
|
|
@ -272,7 +283,7 @@ func getAndSortVersionsFromGithub(httpClient *http.Client) (semVers []*semver.Ve
|
||||||
return semVers, nil
|
return semVers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateVersions(cli *http.Client, from, to string, direct bool) []string {
|
func calculateVersions(cli *http.Client, from, to string, direct bool) []*semver.Version {
|
||||||
semvers, err := getAndSortVersionsFromGithub(cli)
|
semvers, err := getAndSortVersionsFromGithub(cli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to collect semvers from github: %s", err)
|
log.Fatalf("failed to collect semvers from github: %s", err)
|
||||||
|
|
@ -320,28 +331,25 @@ func calculateVersions(cli *http.Client, from, to string, direct bool) []string
|
||||||
}
|
}
|
||||||
semvers = semvers[:i+1]
|
semvers = semvers[:i+1]
|
||||||
}
|
}
|
||||||
var versions []string
|
|
||||||
for _, sv := range semvers {
|
|
||||||
versions = append(versions, sv.Original())
|
|
||||||
}
|
|
||||||
if to == HEAD {
|
if to == HEAD {
|
||||||
versions = append(versions, HEAD)
|
semvers = append(semvers, latest)
|
||||||
}
|
}
|
||||||
if direct {
|
if direct {
|
||||||
versions = []string{versions[0], versions[len(versions)-1]}
|
semvers = []*semver.Version{semvers[0], semvers[len(semvers)-1]}
|
||||||
}
|
}
|
||||||
return versions
|
return semvers
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, baseTempDir string, concurrency int, branchOrTagNames []string) map[string]string {
|
func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, baseTempDir string, concurrency int, versions []*semver.Version) map[string]string {
|
||||||
// concurrently build all versions, this can be done in any order. The mutex protects the map
|
// concurrently build all versions, this can be done in any order. The mutex protects the map
|
||||||
branchToImageID := make(map[string]string)
|
branchToImageID := make(map[string]string)
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(concurrency)
|
wg.Add(concurrency)
|
||||||
ch := make(chan string, len(branchOrTagNames))
|
ch := make(chan *semver.Version, len(versions))
|
||||||
for _, branchName := range branchOrTagNames {
|
for _, branchName := range versions {
|
||||||
ch <- branchName
|
ch <- branchName
|
||||||
}
|
}
|
||||||
close(ch)
|
close(ch)
|
||||||
|
|
@ -349,11 +357,13 @@ func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, b
|
||||||
for i := 0; i < concurrency; i++ {
|
for i := 0; i < concurrency; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for branchName := range ch {
|
for version := range ch {
|
||||||
|
branchName, binary := versionToBranchAndBinary(version)
|
||||||
|
log.Printf("Building version %s with binary %s", branchName, binary)
|
||||||
tmpDir := baseTempDir + alphaNumerics.ReplaceAllString(branchName, "")
|
tmpDir := baseTempDir + alphaNumerics.ReplaceAllString(branchName, "")
|
||||||
imgID, err := buildDendrite(httpClient, dockerClient, tmpDir, branchName)
|
imgID, err := buildDendrite(httpClient, dockerClient, tmpDir, branchName, binary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%s: failed to build dendrite image: %s", branchName, err)
|
log.Fatalf("%s: failed to build dendrite image: %s", version, err)
|
||||||
}
|
}
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
branchToImageID[branchName] = imgID
|
branchToImageID[branchName] = imgID
|
||||||
|
|
@ -365,13 +375,14 @@ func buildDendriteImages(httpClient *http.Client, dockerClient *client.Client, b
|
||||||
return branchToImageID
|
return branchToImageID
|
||||||
}
|
}
|
||||||
|
|
||||||
func runImage(dockerClient *client.Client, volumeName, version, imageID string) (csAPIURL, containerID string, err error) {
|
func runImage(dockerClient *client.Client, volumeName string, branchNameToImageID map[string]string, version *semver.Version) (csAPIURL, containerID string, err error) {
|
||||||
log.Printf("%s: running image %s\n", version, imageID)
|
branchName, binary := versionToBranchAndBinary(version)
|
||||||
|
imageID := branchNameToImageID[branchName]
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
body, err := dockerClient.ContainerCreate(ctx, &container.Config{
|
body, err := dockerClient.ContainerCreate(ctx, &container.Config{
|
||||||
Image: imageID,
|
Image: imageID,
|
||||||
Env: []string{"SERVER_NAME=hs1"},
|
Env: []string{"SERVER_NAME=hs1", fmt.Sprintf("BINARY=%s", binary)},
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
dendriteUpgradeTestLabel: "yes",
|
dendriteUpgradeTestLabel: "yes",
|
||||||
},
|
},
|
||||||
|
|
@ -384,7 +395,7 @@ func runImage(dockerClient *client.Client, volumeName, version, imageID string)
|
||||||
Target: "/var/lib/postgresql/9.6/main",
|
Target: "/var/lib/postgresql/9.6/main",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil, nil, "dendrite_upgrade_test_"+version)
|
}, nil, nil, "dendrite_upgrade_test_"+branchName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("failed to ContainerCreate: %s", err)
|
return "", "", fmt.Errorf("failed to ContainerCreate: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -451,8 +462,8 @@ func destroyContainer(dockerClient *client.Client, containerID string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAndRunTests(dockerClient *client.Client, volumeName, v string, branchToImageID map[string]string) error {
|
func loadAndRunTests(dockerClient *client.Client, volumeName string, v *semver.Version, branchToImageID map[string]string) error {
|
||||||
csAPIURL, containerID, err := runImage(dockerClient, volumeName, v, branchToImageID[v])
|
csAPIURL, containerID, err := runImage(dockerClient, volumeName, branchToImageID, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run container for branch %v: %v", v, err)
|
return fmt.Errorf("failed to run container for branch %v: %v", v, err)
|
||||||
}
|
}
|
||||||
|
|
@ -470,9 +481,10 @@ func loadAndRunTests(dockerClient *client.Client, volumeName, v string, branchTo
|
||||||
}
|
}
|
||||||
|
|
||||||
// test that create-account is working
|
// test that create-account is working
|
||||||
func testCreateAccount(dockerClient *client.Client, v string, containerID string) error {
|
func testCreateAccount(dockerClient *client.Client, version *semver.Version, containerID string) error {
|
||||||
createUser := strings.ToLower("createaccountuser-" + v)
|
branchName, _ := versionToBranchAndBinary(version)
|
||||||
log.Printf("%s: Creating account %s with create-account\n", v, createUser)
|
createUser := strings.ToLower("createaccountuser-" + branchName)
|
||||||
|
log.Printf("%s: Creating account %s with create-account\n", branchName, createUser)
|
||||||
|
|
||||||
respID, err := dockerClient.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{
|
respID, err := dockerClient.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
|
|
@ -504,9 +516,21 @@ func testCreateAccount(dockerClient *client.Client, v string, containerID string
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyTests(dockerClient *client.Client, volumeName string, versions []string, branchToImageID map[string]string) error {
|
func versionToBranchAndBinary(version *semver.Version) (branchName, binary string) {
|
||||||
|
binary = "dendrite-monolith-server"
|
||||||
|
branchName = version.Original()
|
||||||
|
if version.GreaterThan(binaryChangeVersion) {
|
||||||
|
binary = "dendrite"
|
||||||
|
if version.Equal(latest) {
|
||||||
|
branchName = HEAD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyTests(dockerClient *client.Client, volumeName string, versions []*semver.Version, branchToImageID map[string]string) error {
|
||||||
lastVer := versions[len(versions)-1]
|
lastVer := versions[len(versions)-1]
|
||||||
csAPIURL, containerID, err := runImage(dockerClient, volumeName, lastVer, branchToImageID[lastVer])
|
csAPIURL, containerID, err := runImage(dockerClient, volumeName, branchToImageID, lastVer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run container for branch %v: %v", lastVer, err)
|
return fmt.Errorf("failed to run container for branch %v: %v", lastVer, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver/v3"
|
||||||
"github.com/matrix-org/gomatrix"
|
"github.com/matrix-org/gomatrix"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
@ -22,7 +23,8 @@ type user struct {
|
||||||
// - register alice and bob with branch name muxed into the localpart
|
// - register alice and bob with branch name muxed into the localpart
|
||||||
// - create a DM room for the 2 users and exchange messages
|
// - create a DM room for the 2 users and exchange messages
|
||||||
// - create/join a public #global room and exchange messages
|
// - create/join a public #global room and exchange messages
|
||||||
func runTests(baseURL, branchName string) error {
|
func runTests(baseURL string, v *semver.Version) error {
|
||||||
|
branchName, _ := versionToBranchAndBinary(v)
|
||||||
// register 2 users
|
// register 2 users
|
||||||
users := []user{
|
users := []user{
|
||||||
{
|
{
|
||||||
|
|
@ -164,15 +166,16 @@ func runTests(baseURL, branchName string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyTestsRan checks that the HS has the right rooms/messages
|
// verifyTestsRan checks that the HS has the right rooms/messages
|
||||||
func verifyTestsRan(baseURL string, branchNames []string) error {
|
func verifyTestsRan(baseURL string, versions []*semver.Version) error {
|
||||||
log.Println("Verifying tests....")
|
log.Println("Verifying tests....")
|
||||||
// check we can login as all users
|
// check we can login as all users
|
||||||
var resp *gomatrix.RespLogin
|
var resp *gomatrix.RespLogin
|
||||||
for _, branchName := range branchNames {
|
for _, version := range versions {
|
||||||
client, err := gomatrix.NewClient(baseURL, "", "")
|
client, err := gomatrix.NewClient(baseURL, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
branchName, _ := versionToBranchAndBinary(version)
|
||||||
userLocalparts := []string{
|
userLocalparts := []string{
|
||||||
"alice" + branchName,
|
"alice" + branchName,
|
||||||
"bob" + branchName,
|
"bob" + branchName,
|
||||||
|
|
@ -224,7 +227,7 @@ func verifyTestsRan(baseURL string, branchNames []string) error {
|
||||||
msgCount += 1
|
msgCount += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wantMsgCount := len(branchNames) * 4
|
wantMsgCount := len(versions) * 4
|
||||||
if msgCount != wantMsgCount {
|
if msgCount != wantMsgCount {
|
||||||
return fmt.Errorf("got %d messages in global room, want %d", msgCount, wantMsgCount)
|
return fmt.Errorf("got %d messages in global room, want %d", msgCount, wantMsgCount)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
cmd/dendrite/main.go
Normal file
103
cmd/dendrite/main.go
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// Copyright 2017 Vector Creations Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/appservice"
|
||||||
|
"github.com/matrix-org/dendrite/federationapi"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
|
"github.com/matrix-org/dendrite/setup"
|
||||||
|
basepkg "github.com/matrix-org/dendrite/setup/base"
|
||||||
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
"github.com/matrix-org/dendrite/setup/mscs"
|
||||||
|
"github.com/matrix-org/dendrite/userapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
httpBindAddr = flag.String("http-bind-address", ":8008", "The HTTP listening port for the server")
|
||||||
|
httpsBindAddr = flag.String("https-bind-address", ":8448", "The HTTPS listening port for the server")
|
||||||
|
certFile = flag.String("tls-cert", "", "The PEM formatted X509 certificate to use for TLS")
|
||||||
|
keyFile = flag.String("tls-key", "", "The PEM private key to use for TLS")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg := setup.ParseFlags(true)
|
||||||
|
httpAddr := config.HTTPAddress("http://" + *httpBindAddr)
|
||||||
|
httpsAddr := config.HTTPAddress("https://" + *httpsBindAddr)
|
||||||
|
options := []basepkg.BaseDendriteOptions{}
|
||||||
|
|
||||||
|
base := basepkg.NewBaseDendrite(cfg, options...)
|
||||||
|
defer base.Close() // nolint: errcheck
|
||||||
|
|
||||||
|
federation := base.CreateFederationClient()
|
||||||
|
|
||||||
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
|
|
||||||
|
fsAPI := federationapi.NewInternalAPI(
|
||||||
|
base, federation, rsAPI, base.Caches, nil, false,
|
||||||
|
)
|
||||||
|
|
||||||
|
keyRing := fsAPI.KeyRing()
|
||||||
|
|
||||||
|
userAPI := userapi.NewInternalAPI(base, rsAPI, federation)
|
||||||
|
|
||||||
|
asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI)
|
||||||
|
|
||||||
|
// The underlying roomserver implementation needs to be able to call the fedsender.
|
||||||
|
// This is different to rsAPI which can be the http client which doesn't need this
|
||||||
|
// dependency. Other components also need updating after their dependencies are up.
|
||||||
|
rsAPI.SetFederationAPI(fsAPI, keyRing)
|
||||||
|
rsAPI.SetAppserviceAPI(asAPI)
|
||||||
|
rsAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
|
monolith := setup.Monolith{
|
||||||
|
Config: base.Cfg,
|
||||||
|
Client: base.CreateClient(),
|
||||||
|
FedClient: federation,
|
||||||
|
KeyRing: keyRing,
|
||||||
|
|
||||||
|
AppserviceAPI: asAPI,
|
||||||
|
// always use the concrete impl here even in -http mode because adding public routes
|
||||||
|
// must be done on the concrete impl not an HTTP client else fedapi will call itself
|
||||||
|
FederationAPI: fsAPI,
|
||||||
|
RoomserverAPI: rsAPI,
|
||||||
|
UserAPI: userAPI,
|
||||||
|
}
|
||||||
|
monolith.AddAllPublicRoutes(base)
|
||||||
|
|
||||||
|
if len(base.Cfg.MSCs.MSCs) > 0 {
|
||||||
|
if err := mscs.Enable(base, &monolith); err != nil {
|
||||||
|
logrus.WithError(err).Fatalf("Failed to enable MSCs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose the matrix APIs directly rather than putting them under a /api path.
|
||||||
|
go func() {
|
||||||
|
base.SetupAndServeHTTP(httpAddr, nil, nil)
|
||||||
|
}()
|
||||||
|
// Handle HTTPS if certificate and key are provided
|
||||||
|
if *certFile != "" && *keyFile != "" {
|
||||||
|
go func() {
|
||||||
|
base.SetupAndServeHTTP(httpsAddr, certFile, keyFile)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
|
||||||
|
base.WaitForShutdown()
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,6 @@ func main() {
|
||||||
dbURI := flag.String("db", "", "The DB URI to use for all components (PostgreSQL only)")
|
dbURI := flag.String("db", "", "The DB URI to use for all components (PostgreSQL only)")
|
||||||
dirPath := flag.String("dir", "./", "The folder to use for paths (like SQLite databases, media storage)")
|
dirPath := flag.String("dir", "./", "The folder to use for paths (like SQLite databases, media storage)")
|
||||||
normalise := flag.String("normalise", "", "Normalise an existing configuration file by adding new/missing options and defaults")
|
normalise := flag.String("normalise", "", "Normalise an existing configuration file by adding new/missing options and defaults")
|
||||||
polylith := flag.Bool("polylith", false, "Generate a config that makes sense for polylith deployments")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
var cfg *config.Dendrite
|
var cfg *config.Dendrite
|
||||||
|
|
@ -27,14 +26,14 @@ func main() {
|
||||||
Version: config.Version,
|
Version: config.Version,
|
||||||
}
|
}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: !*polylith,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
if *serverName != "" {
|
if *serverName != "" {
|
||||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(*serverName)
|
cfg.Global.ServerName = gomatrixserverlib.ServerName(*serverName)
|
||||||
}
|
}
|
||||||
uri := config.DataSource(*dbURI)
|
uri := config.DataSource(*dbURI)
|
||||||
if *polylith || uri.IsSQLite() || uri == "" {
|
if uri.IsSQLite() || uri == "" {
|
||||||
for name, db := range map[string]*config.DatabaseOptions{
|
for name, db := range map[string]*config.DatabaseOptions{
|
||||||
"federationapi": &cfg.FederationAPI.Database,
|
"federationapi": &cfg.FederationAPI.Database,
|
||||||
"keyserver": &cfg.KeyServer.Database,
|
"keyserver": &cfg.KeyServer.Database,
|
||||||
|
|
@ -43,6 +42,7 @@ func main() {
|
||||||
"roomserver": &cfg.RoomServer.Database,
|
"roomserver": &cfg.RoomServer.Database,
|
||||||
"syncapi": &cfg.SyncAPI.Database,
|
"syncapi": &cfg.SyncAPI.Database,
|
||||||
"userapi": &cfg.UserAPI.AccountDatabase,
|
"userapi": &cfg.UserAPI.AccountDatabase,
|
||||||
|
"relayapi": &cfg.RelayAPI.Database,
|
||||||
} {
|
} {
|
||||||
if uri == "" {
|
if uri == "" {
|
||||||
path := filepath.Join(*dirPath, fmt.Sprintf("dendrite_%s.db", name))
|
path := filepath.Join(*dirPath, fmt.Sprintf("dendrite_%s.db", name))
|
||||||
|
|
@ -96,7 +96,7 @@ func main() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
if cfg, err = config.Load(*normalise, !*polylith); err != nil {
|
if cfg, err = config.Load(*normalise); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ func main() {
|
||||||
Level: "error",
|
Level: "error",
|
||||||
})
|
})
|
||||||
cfg.ClientAPI.RegistrationDisabled = true
|
cfg.ClientAPI.RegistrationDisabled = true
|
||||||
base := base.NewBaseDendrite(cfg, "ResolveState", base.DisableMetrics)
|
base := base.NewBaseDendrite(cfg, base.DisableMetrics)
|
||||||
args := flag.Args()
|
args := flag.Args()
|
||||||
|
|
||||||
fmt.Println("Room version", *roomVersion)
|
fmt.Println("Room version", *roomVersion)
|
||||||
|
|
|
||||||
|
|
@ -1,416 +0,0 @@
|
||||||
# This is the Dendrite configuration file.
|
|
||||||
#
|
|
||||||
# The configuration is split up into sections - each Dendrite component has a
|
|
||||||
# configuration section, in addition to the "global" section which applies to
|
|
||||||
# all components.
|
|
||||||
|
|
||||||
# The version of the configuration file.
|
|
||||||
version: 2
|
|
||||||
|
|
||||||
# Global Matrix configuration. This configuration applies to all components.
|
|
||||||
global:
|
|
||||||
# The domain name of this homeserver.
|
|
||||||
server_name: localhost
|
|
||||||
|
|
||||||
# The path to the signing private key file, used to sign requests and events.
|
|
||||||
# Note that this is NOT the same private key as used for TLS! To generate a
|
|
||||||
# signing key, use "./bin/generate-keys --private-key matrix_key.pem".
|
|
||||||
private_key: matrix_key.pem
|
|
||||||
|
|
||||||
# The paths and expiry timestamps (as a UNIX timestamp in millisecond precision)
|
|
||||||
# to old signing keys that were formerly in use on this domain name. These
|
|
||||||
# keys will not be used for federation request or event signing, but will be
|
|
||||||
# provided to any other homeserver that asks when trying to verify old events.
|
|
||||||
old_private_keys:
|
|
||||||
# If the old private key file is available:
|
|
||||||
# - private_key: old_matrix_key.pem
|
|
||||||
# expired_at: 1601024554498
|
|
||||||
# If only the public key (in base64 format) and key ID are known:
|
|
||||||
# - public_key: mn59Kxfdq9VziYHSBzI7+EDPDcBS2Xl7jeUdiiQcOnM=
|
|
||||||
# key_id: ed25519:mykeyid
|
|
||||||
# expired_at: 1601024554498
|
|
||||||
|
|
||||||
# How long a remote server can cache our server signing key before requesting it
|
|
||||||
# again. Increasing this number will reduce the number of requests made by other
|
|
||||||
# servers for our key but increases the period that a compromised key will be
|
|
||||||
# considered valid by other homeservers.
|
|
||||||
key_validity_period: 168h0m0s
|
|
||||||
|
|
||||||
# Configuration for in-memory caches. Caches can often improve performance by
|
|
||||||
# keeping frequently accessed items (like events, identifiers etc.) in memory
|
|
||||||
# rather than having to read them from the database.
|
|
||||||
cache:
|
|
||||||
# The estimated maximum size for the global cache in bytes, or in terabytes,
|
|
||||||
# gigabytes, megabytes or kilobytes when the appropriate 'tb', 'gb', 'mb' or
|
|
||||||
# 'kb' suffix is specified. Note that this is not a hard limit, nor is it a
|
|
||||||
# memory limit for the entire process. A cache that is too small may ultimately
|
|
||||||
# provide little or no benefit.
|
|
||||||
max_size_estimated: 1gb
|
|
||||||
|
|
||||||
# The maximum amount of time that a cache entry can live for in memory before
|
|
||||||
# it will be evicted and/or refreshed from the database. Lower values result in
|
|
||||||
# easier admission of new cache entries but may also increase database load in
|
|
||||||
# comparison to higher values, so adjust conservatively. Higher values may make
|
|
||||||
# it harder for new items to make it into the cache, e.g. if new rooms suddenly
|
|
||||||
# become popular.
|
|
||||||
max_age: 1h
|
|
||||||
|
|
||||||
# The server name to delegate server-server communications to, with optional port
|
|
||||||
# e.g. localhost:443
|
|
||||||
well_known_server_name: ""
|
|
||||||
|
|
||||||
# The base URL to delegate client-server communications to e.g. https://localhost
|
|
||||||
well_known_client_name: ""
|
|
||||||
|
|
||||||
# Lists of domains that the server will trust as identity servers to verify third
|
|
||||||
# party identifiers such as phone numbers and email addresses.
|
|
||||||
trusted_third_party_id_servers:
|
|
||||||
- matrix.org
|
|
||||||
- vector.im
|
|
||||||
|
|
||||||
# Disables federation. Dendrite will not be able to communicate with other servers
|
|
||||||
# in the Matrix federation and the federation API will not be exposed.
|
|
||||||
disable_federation: false
|
|
||||||
|
|
||||||
# Configures the handling of presence events. Inbound controls whether we receive
|
|
||||||
# presence events from other servers, outbound controls whether we send presence
|
|
||||||
# events for our local users to other servers.
|
|
||||||
presence:
|
|
||||||
enable_inbound: false
|
|
||||||
enable_outbound: false
|
|
||||||
|
|
||||||
# Configures phone-home statistics reporting. These statistics contain the server
|
|
||||||
# name, number of active users and some information on your deployment config.
|
|
||||||
# We use this information to understand how Dendrite is being used in the wild.
|
|
||||||
report_stats:
|
|
||||||
enabled: false
|
|
||||||
endpoint: https://matrix.org/report-usage-stats/push
|
|
||||||
|
|
||||||
# Server notices allows server admins to send messages to all users on the server.
|
|
||||||
server_notices:
|
|
||||||
enabled: false
|
|
||||||
# The local part, display name and avatar URL (as a mxc:// URL) for the user that
|
|
||||||
# will send the server notices. These are visible to all users on the deployment.
|
|
||||||
local_part: "_server"
|
|
||||||
display_name: "Server Alerts"
|
|
||||||
avatar_url: ""
|
|
||||||
# The room name to be used when sending server notices. This room name will
|
|
||||||
# appear in user clients.
|
|
||||||
room_name: "Server Alerts"
|
|
||||||
|
|
||||||
# Configuration for NATS JetStream
|
|
||||||
jetstream:
|
|
||||||
# A list of NATS Server addresses to connect to. If none are specified, an
|
|
||||||
# internal NATS server will be started automatically when running Dendrite in
|
|
||||||
# monolith mode. For polylith deployments, it is required to specify the address
|
|
||||||
# of at least one NATS Server node.
|
|
||||||
addresses:
|
|
||||||
- hostname:4222
|
|
||||||
|
|
||||||
# Disable the validation of TLS certificates of NATS. This is
|
|
||||||
# not recommended in production since it may allow NATS traffic
|
|
||||||
# to be sent to an insecure endpoint.
|
|
||||||
disable_tls_validation: false
|
|
||||||
|
|
||||||
# The prefix to use for stream names for this homeserver - really only useful
|
|
||||||
# if you are running more than one Dendrite server on the same NATS deployment.
|
|
||||||
topic_prefix: Dendrite
|
|
||||||
|
|
||||||
# Configuration for Prometheus metric collection.
|
|
||||||
metrics:
|
|
||||||
enabled: false
|
|
||||||
basic_auth:
|
|
||||||
username: metrics
|
|
||||||
password: metrics
|
|
||||||
|
|
||||||
# Optional DNS cache. The DNS cache may reduce the load on DNS servers if there
|
|
||||||
# is no local caching resolver available for use.
|
|
||||||
dns_cache:
|
|
||||||
enabled: false
|
|
||||||
cache_size: 256
|
|
||||||
cache_lifetime: "5m" # 5 minutes; https://pkg.go.dev/time@master#ParseDuration
|
|
||||||
|
|
||||||
# Configuration for the Appservice API.
|
|
||||||
app_service_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7777 # The listen address for incoming API requests
|
|
||||||
connect: http://app_service_api:7777 # The connect address for other components to use
|
|
||||||
|
|
||||||
# Disable the validation of TLS certificates of appservices. This is
|
|
||||||
# not recommended in production since it may allow appservice traffic
|
|
||||||
# to be sent to an insecure endpoint.
|
|
||||||
disable_tls_validation: false
|
|
||||||
|
|
||||||
# Appservice configuration files to load into this homeserver.
|
|
||||||
config_files:
|
|
||||||
# - /path/to/appservice_registration.yaml
|
|
||||||
|
|
||||||
# Configuration for the Client API.
|
|
||||||
client_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7771 # The listen address for incoming API requests
|
|
||||||
connect: http://client_api:7771 # The connect address for other components to use
|
|
||||||
external_api:
|
|
||||||
listen: http://[::]:8071
|
|
||||||
|
|
||||||
# Prevents new users from being able to register on this homeserver, except when
|
|
||||||
# using the registration shared secret below.
|
|
||||||
registration_disabled: true
|
|
||||||
|
|
||||||
# Prevents new guest accounts from being created. Guest registration is also
|
|
||||||
# disabled implicitly by setting 'registration_disabled' above.
|
|
||||||
guests_disabled: true
|
|
||||||
|
|
||||||
# If set, allows registration by anyone who knows the shared secret, regardless
|
|
||||||
# of whether registration is otherwise disabled.
|
|
||||||
registration_shared_secret: ""
|
|
||||||
|
|
||||||
# Whether to require reCAPTCHA for registration. If you have enabled registration
|
|
||||||
# then this is HIGHLY RECOMMENDED to reduce the risk of your homeserver being used
|
|
||||||
# for coordinated spam attacks.
|
|
||||||
enable_registration_captcha: false
|
|
||||||
|
|
||||||
# Settings for ReCAPTCHA.
|
|
||||||
recaptcha_public_key: ""
|
|
||||||
recaptcha_private_key: ""
|
|
||||||
recaptcha_bypass_secret: ""
|
|
||||||
|
|
||||||
# To use hcaptcha.com instead of ReCAPTCHA, set the following parameters, otherwise just keep them empty.
|
|
||||||
# recaptcha_siteverify_api: "https://hcaptcha.com/siteverify"
|
|
||||||
# recaptcha_api_js_url: "https://js.hcaptcha.com/1/api.js"
|
|
||||||
# recaptcha_form_field: "h-captcha-response"
|
|
||||||
# recaptcha_sitekey_class: "h-captcha"
|
|
||||||
|
|
||||||
|
|
||||||
# TURN server information that this homeserver should send to clients.
|
|
||||||
turn:
|
|
||||||
turn_user_lifetime: "5m"
|
|
||||||
turn_uris:
|
|
||||||
# - turn:turn.server.org?transport=udp
|
|
||||||
# - turn:turn.server.org?transport=tcp
|
|
||||||
turn_shared_secret: ""
|
|
||||||
# If your TURN server requires static credentials, then you will need to enter
|
|
||||||
# them here instead of supplying a shared secret. Note that these credentials
|
|
||||||
# will be visible to clients!
|
|
||||||
# turn_username: ""
|
|
||||||
# turn_password: ""
|
|
||||||
|
|
||||||
# Settings for rate-limited endpoints. Rate limiting kicks in after the threshold
|
|
||||||
# number of "slots" have been taken by requests from a specific host. Each "slot"
|
|
||||||
# will be released after the cooloff time in milliseconds. Server administrators
|
|
||||||
# and appservice users are exempt from rate limiting by default.
|
|
||||||
rate_limiting:
|
|
||||||
enabled: true
|
|
||||||
threshold: 20
|
|
||||||
cooloff_ms: 500
|
|
||||||
exempt_user_ids:
|
|
||||||
# - "@user:domain.com"
|
|
||||||
|
|
||||||
# Configuration for the Federation API.
|
|
||||||
federation_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7772 # The listen address for incoming API requests
|
|
||||||
connect: http://federation_api:7772 # The connect address for other components to use
|
|
||||||
external_api:
|
|
||||||
listen: http://[::]:8072
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_federationapi?sslmode=disable
|
|
||||||
max_open_conns: 10
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# How many times we will try to resend a failed transaction to a specific server. The
|
|
||||||
# backoff is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds etc. Once
|
|
||||||
# the max retries are exceeded, Dendrite will no longer try to send transactions to
|
|
||||||
# that server until it comes back to life and connects to us again.
|
|
||||||
send_max_retries: 16
|
|
||||||
|
|
||||||
# Disable the validation of TLS certificates of remote federated homeservers. Do not
|
|
||||||
# enable this option in production as it presents a security risk!
|
|
||||||
disable_tls_validation: false
|
|
||||||
|
|
||||||
# Disable HTTP keepalives, which also prevents connection reuse. Dendrite will typically
|
|
||||||
# keep HTTP connections open to remote hosts for 5 minutes as they can be reused much
|
|
||||||
# more quickly than opening new connections each time. Disabling keepalives will close
|
|
||||||
# HTTP connections immediately after a successful request but may result in more CPU and
|
|
||||||
# memory being used on TLS handshakes for each new connection instead.
|
|
||||||
disable_http_keepalives: false
|
|
||||||
|
|
||||||
# Perspective keyservers to use as a backup when direct key fetches fail. This may
|
|
||||||
# be required to satisfy key requests for servers that are no longer online when
|
|
||||||
# joining some rooms.
|
|
||||||
key_perspectives:
|
|
||||||
- server_name: matrix.org
|
|
||||||
keys:
|
|
||||||
- key_id: ed25519:auto
|
|
||||||
public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw
|
|
||||||
- key_id: ed25519:a_RXGa
|
|
||||||
public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ
|
|
||||||
|
|
||||||
# This option will control whether Dendrite will prefer to look up keys directly
|
|
||||||
# or whether it should try perspective servers first, using direct fetches as a
|
|
||||||
# last resort.
|
|
||||||
prefer_direct_fetch: false
|
|
||||||
|
|
||||||
# Configuration for the Key Server (for end-to-end encryption).
|
|
||||||
key_server:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7779 # The listen address for incoming API requests
|
|
||||||
connect: http://key_server:7779 # The connect address for other components to use
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_keyserver?sslmode=disable
|
|
||||||
max_open_conns: 10
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# Configuration for the Media API.
|
|
||||||
media_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7774 # The listen address for incoming API requests
|
|
||||||
connect: http://media_api:7774 # The connect address for other components to use
|
|
||||||
external_api:
|
|
||||||
listen: http://[::]:8074
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_mediaapi?sslmode=disable
|
|
||||||
max_open_conns: 5
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# Storage path for uploaded media. May be relative or absolute.
|
|
||||||
base_path: ./media_store
|
|
||||||
|
|
||||||
# The maximum allowed file size (in bytes) for media uploads to this homeserver
|
|
||||||
# (0 = unlimited). If using a reverse proxy, ensure it allows requests at least
|
|
||||||
#this large (e.g. the client_max_body_size setting in nginx).
|
|
||||||
max_file_size_bytes: 10485760
|
|
||||||
|
|
||||||
# Whether to dynamically generate thumbnails if needed.
|
|
||||||
dynamic_thumbnails: false
|
|
||||||
|
|
||||||
# The maximum number of simultaneous thumbnail generators to run.
|
|
||||||
max_thumbnail_generators: 10
|
|
||||||
|
|
||||||
# A list of thumbnail sizes to be generated for media content.
|
|
||||||
thumbnail_sizes:
|
|
||||||
- width: 32
|
|
||||||
height: 32
|
|
||||||
method: crop
|
|
||||||
- width: 96
|
|
||||||
height: 96
|
|
||||||
method: crop
|
|
||||||
- width: 640
|
|
||||||
height: 480
|
|
||||||
method: scale
|
|
||||||
|
|
||||||
# Configuration for enabling experimental MSCs on this homeserver.
|
|
||||||
mscs:
|
|
||||||
mscs:
|
|
||||||
# - msc2836 # (Threading, see https://github.com/matrix-org/matrix-doc/pull/2836)
|
|
||||||
# - msc2946 # (Spaces Summary, see https://github.com/matrix-org/matrix-doc/pull/2946)
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_mscs?sslmode=disable
|
|
||||||
max_open_conns: 5
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# Configuration for the Room Server.
|
|
||||||
room_server:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7770 # The listen address for incoming API requests
|
|
||||||
connect: http://room_server:7770 # The connect address for other components to use
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_roomserver?sslmode=disable
|
|
||||||
max_open_conns: 10
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# Configuration for the Sync API.
|
|
||||||
sync_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7773 # The listen address for incoming API requests
|
|
||||||
connect: http://sync_api:7773 # The connect address for other components to use
|
|
||||||
external_api:
|
|
||||||
listen: http://[::]:8073
|
|
||||||
database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_syncapi?sslmode=disable
|
|
||||||
max_open_conns: 10
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# Configuration for the full-text search engine.
|
|
||||||
search:
|
|
||||||
# Whether or not search is enabled.
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# The path where the search index will be created in.
|
|
||||||
index_path: "./searchindex"
|
|
||||||
|
|
||||||
# The language most likely to be used on the server - used when indexing, to
|
|
||||||
# ensure the returned results match expectations. A full list of possible languages
|
|
||||||
# can be found at https://github.com/blevesearch/bleve/tree/master/analysis/lang
|
|
||||||
language: "en"
|
|
||||||
|
|
||||||
# This option controls which HTTP header to inspect to find the real remote IP
|
|
||||||
# address of the client. This is likely required if Dendrite is running behind
|
|
||||||
# a reverse proxy server.
|
|
||||||
# real_ip_header: X-Real-IP
|
|
||||||
|
|
||||||
# Configuration for the User API.
|
|
||||||
user_api:
|
|
||||||
internal_api:
|
|
||||||
listen: http://[::]:7781 # The listen address for incoming API requests
|
|
||||||
connect: http://user_api:7781 # The connect address for other components to use
|
|
||||||
account_database:
|
|
||||||
connection_string: postgresql://username:password@hostname/dendrite_userapi?sslmode=disable
|
|
||||||
max_open_conns: 10
|
|
||||||
max_idle_conns: 2
|
|
||||||
conn_max_lifetime: -1
|
|
||||||
|
|
||||||
# The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31
|
|
||||||
# See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information.
|
|
||||||
# Setting this lower makes registration/login consume less CPU resources at the cost
|
|
||||||
# of security should the database be compromised. Setting this higher makes registration/login
|
|
||||||
# consume more CPU resources but makes it harder to brute force password hashes. This value
|
|
||||||
# can be lowered if performing tests or on embedded Dendrite instances (e.g WASM builds).
|
|
||||||
bcrypt_cost: 10
|
|
||||||
|
|
||||||
# The length of time that a token issued for a relying party from
|
|
||||||
# /_matrix/client/r0/user/{userId}/openid/request_token endpoint
|
|
||||||
# is considered to be valid in milliseconds.
|
|
||||||
# The default lifetime is 3600000ms (60 minutes).
|
|
||||||
# openid_token_lifetime_ms: 3600000
|
|
||||||
|
|
||||||
# Users who register on this homeserver will automatically be joined to the rooms listed under "auto_join_rooms" option.
|
|
||||||
# By default, any room aliases included in this list will be created as a publicly joinable room
|
|
||||||
# when the first user registers for the homeserver. If the room already exists,
|
|
||||||
# make certain it is a publicly joinable room, i.e. the join rule of the room must be set to 'public'.
|
|
||||||
# As Spaces are just rooms under the hood, Space aliases may also be used.
|
|
||||||
auto_join_rooms:
|
|
||||||
# - "#main:matrix.org"
|
|
||||||
|
|
||||||
# Configuration for Opentracing.
|
|
||||||
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on
|
|
||||||
# how this works and how to set it up.
|
|
||||||
tracing:
|
|
||||||
enabled: false
|
|
||||||
jaeger:
|
|
||||||
serviceName: ""
|
|
||||||
disabled: false
|
|
||||||
rpc_metrics: false
|
|
||||||
tags: []
|
|
||||||
sampler: null
|
|
||||||
reporter: null
|
|
||||||
headers: null
|
|
||||||
baggage_restrictions: null
|
|
||||||
throttler: null
|
|
||||||
|
|
||||||
# Logging configuration. The "std" logging type controls the logs being sent to
|
|
||||||
# stdout. The "file" logging type controls logs being written to a log folder on
|
|
||||||
# the disk. Supported log levels are "debug", "info", "warn", "error".
|
|
||||||
logging:
|
|
||||||
- type: std
|
|
||||||
level: info
|
|
||||||
- type: file
|
|
||||||
level: info
|
|
||||||
params:
|
|
||||||
path: ./logs
|
|
||||||
|
|
@ -38,7 +38,7 @@ global:
|
||||||
|
|
||||||
# Global database connection pool, for PostgreSQL monolith deployments only. If
|
# Global database connection pool, for PostgreSQL monolith deployments only. If
|
||||||
# this section is populated then you can omit the "database" blocks in all other
|
# this section is populated then you can omit the "database" blocks in all other
|
||||||
# sections. For polylith deployments, or monolith deployments using SQLite databases,
|
# sections. For monolith deployments using SQLite databases,
|
||||||
# you must configure the "database" block for each component instead.
|
# you must configure the "database" block for each component instead.
|
||||||
database:
|
database:
|
||||||
connection_string: postgresql://username:password@hostname/dendrite?sslmode=disable
|
connection_string: postgresql://username:password@hostname/dendrite?sslmode=disable
|
||||||
|
|
@ -110,6 +110,17 @@ global:
|
||||||
|
|
||||||
# Configuration for NATS JetStream
|
# Configuration for NATS JetStream
|
||||||
jetstream:
|
jetstream:
|
||||||
|
# A list of NATS Server addresses to connect to. If none are specified, an
|
||||||
|
# internal NATS server will be started automatically when running Dendrite in
|
||||||
|
# monolith mode.
|
||||||
|
addresses:
|
||||||
|
# - localhost:4222
|
||||||
|
|
||||||
|
# Disable the validation of TLS certificates of NATS. This is
|
||||||
|
# not recommended in production since it may allow NATS traffic
|
||||||
|
# to be sent to an insecure endpoint.
|
||||||
|
disable_tls_validation: false
|
||||||
|
|
||||||
# Persistent directory to store JetStream streams in. This directory should be
|
# Persistent directory to store JetStream streams in. This directory should be
|
||||||
# preserved across Dendrite restarts.
|
# preserved across Dendrite restarts.
|
||||||
storage_path: ./
|
storage_path: ./
|
||||||
|
|
@ -35,11 +35,6 @@ possible to migrate an existing Synapse deployment to Dendrite.
|
||||||
|
|
||||||
No, Dendrite has a very different database schema to Synapse and the two are not interchangeable.
|
No, Dendrite has a very different database schema to Synapse and the two are not interchangeable.
|
||||||
|
|
||||||
## Should I run a monolith or a polylith deployment?
|
|
||||||
|
|
||||||
Monolith deployments are always preferred where possible, and at this time, are far better tested than polylith deployments are. The only reason to consider a polylith deployment is if you wish to run different Dendrite components on separate physical machines, but this is an advanced configuration which we don't
|
|
||||||
recommend.
|
|
||||||
|
|
||||||
## Can I configure which port Dendrite listens on?
|
## Can I configure which port Dendrite listens on?
|
||||||
|
|
||||||
Yes, use the cli flag `-http-bind-address`.
|
Yes, use the cli flag `-http-bind-address`.
|
||||||
|
|
|
||||||
13
docs/INSTALL.md
Normal file
13
docs/INSTALL.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Please note that new installation instructions can be found
|
||||||
|
on the [new documentation site](https://matrix-org.github.io/dendrite/),
|
||||||
|
or alternatively, in the [installation](installation/) folder:
|
||||||
|
|
||||||
|
1. [Planning your deployment](installation/1_planning.md)
|
||||||
|
2. [Setting up the domain](installation/2_domainname.md)
|
||||||
|
3. [Preparing database storage](installation/3_database.md)
|
||||||
|
4. [Generating signing keys](installation/4_signingkey.md)
|
||||||
|
5. [Installing Dendrite](installation/5_install_monolith.md)
|
||||||
|
6. [Populate the configuration](installation/7_configuration.md)
|
||||||
|
7. [Starting Dendrite](installation/8_starting_monolith.md)
|
||||||
|
|
@ -42,7 +42,7 @@ total: (statements) 53.7%
|
||||||
```
|
```
|
||||||
|
|
||||||
The total coverage for this run is the last line at the bottom. However, this value is misleading because Dendrite can run in many different configurations,
|
The total coverage for this run is the last line at the bottom. However, this value is misleading because Dendrite can run in many different configurations,
|
||||||
which will never be tested in a single test run (e.g sqlite or postgres, monolith or polylith). To get a more accurate value, additional processing is required
|
which will never be tested in a single test run (e.g sqlite or postgres). To get a more accurate value, additional processing is required
|
||||||
to remove packages which will never be tested and extension MSCs:
|
to remove packages which will never be tested and extension MSCs:
|
||||||
|
|
||||||
(The following commands use [gocovmerge](https://github.com/wadey/gocovmerge), to merge two or more coverage logs, so make sure you have that installed)
|
(The following commands use [gocovmerge](https://github.com/wadey/gocovmerge), to merge two or more coverage logs, so make sure you have that installed)
|
||||||
|
|
@ -50,17 +50,11 @@ to remove packages which will never be tested and extension MSCs:
|
||||||
```bash
|
```bash
|
||||||
# These commands are all similar but change which package paths are _removed_ from the output.
|
# These commands are all similar but change which package paths are _removed_ from the output.
|
||||||
|
|
||||||
# For Postgres (monolith)
|
# For Postgres
|
||||||
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|inthttp|sqlite|setup/mscs|api_trace' > final.cov && go tool cover -func=final.cov
|
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|sqlite|setup/mscs' > final.cov && go tool cover -func=final.cov
|
||||||
|
|
||||||
# For Postgres (polylith)
|
# For SQLite
|
||||||
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|sqlite|setup/mscs|api_trace' > final.cov && go tool cover -func=final.cov
|
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|postgres|setup/mscs' > final.cov && go tool cover -func=final.cov
|
||||||
|
|
||||||
# For SQLite (monolith)
|
|
||||||
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|inthttp|postgres|setup/mscs|api_trace' > final.cov && go tool cover -func=final.cov
|
|
||||||
|
|
||||||
# For SQLite (polylith)
|
|
||||||
find -name 'integrationcover.log' | xargs gocovmerge | grep -Ev 'relayapi|postgres|setup/mscs|api_trace' > final.cov && go tool cover -func=final.cov
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running unit tests with coverage enabled
|
## Running unit tests with coverage enabled
|
||||||
|
|
|
||||||
0
docs/development/tracing/setup.md
Normal file
0
docs/development/tracing/setup.md
Normal file
|
|
@ -7,6 +7,22 @@ permalink: /installation/planning
|
||||||
|
|
||||||
# Planning your installation
|
# Planning your installation
|
||||||
|
|
||||||
|
## Modes
|
||||||
|
|
||||||
|
Dendrite consists of several components, each responsible for a different aspect of the Matrix protocol.
|
||||||
|
Users can run Dendrite in one of two modes which dictate how these components are executed and communicate.
|
||||||
|
|
||||||
|
* **Monolith mode** runs all components in a single process. Components communicate through an internal NATS
|
||||||
|
server with generally low overhead. This mode dramatically simplifies deployment complexity and offers the
|
||||||
|
best balance between performance and resource usage for low-to-mid volume deployments.
|
||||||
|
|
||||||
|
* **Polylith mode** runs all components in isolated processes. Components communicate through an external NATS
|
||||||
|
server and HTTP APIs, which incur considerable overhead. While this mode allows for more granular control of
|
||||||
|
resources dedicated toward individual processes, given the additional communications overhead, it is only
|
||||||
|
necessary for very large deployments.
|
||||||
|
|
||||||
|
Given our current state of development, **we recommend monolith mode** for all deployments.
|
||||||
|
|
||||||
## Databases
|
## Databases
|
||||||
|
|
||||||
Dendrite can run with either a PostgreSQL or a SQLite backend. There are considerable tradeoffs
|
Dendrite can run with either a PostgreSQL or a SQLite backend. There are considerable tradeoffs
|
||||||
|
|
@ -67,11 +83,17 @@ you should check (by running `go version`) that you are using a suitable version
|
||||||
|
|
||||||
If using the PostgreSQL database engine, you should install PostgreSQL 12 or later.
|
If using the PostgreSQL database engine, you should install PostgreSQL 12 or later.
|
||||||
|
|
||||||
|
### NATS Server
|
||||||
|
|
||||||
|
Dendrite comes with a built-in [NATS Server](https://github.com/nats-io/nats-server) and
|
||||||
|
therefore does not need this to be manually installed. If you are planning a monolith installation, you
|
||||||
|
do not need to do anything.
|
||||||
|
|
||||||
|
|
||||||
### Reverse proxy
|
### Reverse proxy
|
||||||
|
|
||||||
A reverse proxy such as [Caddy](https://caddyserver.com), [NGINX](https://www.nginx.com) or
|
A reverse proxy such as [Caddy](https://caddyserver.com), [NGINX](https://www.nginx.com) or
|
||||||
[HAProxy](http://www.haproxy.org) is recommended for monolith deployments.
|
[HAProxy](http://www.haproxy.org) is useful for deployments. Configuring those is not covered in this documentation, although sample configurations
|
||||||
Configuring those not covered in this documentation, although sample configurations
|
|
||||||
for [Caddy](https://github.com/matrix-org/dendrite/blob/main/docs/caddy) and
|
for [Caddy](https://github.com/matrix-org/dendrite/blob/main/docs/caddy) and
|
||||||
[NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx) are provided.
|
[NGINX](https://github.com/matrix-org/dendrite/blob/main/docs/nginx) are provided.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,10 @@ permalink: /installation/manual/configuration
|
||||||
|
|
||||||
# Configuring Dendrite
|
# Configuring Dendrite
|
||||||
|
|
||||||
A YAML configuration file is used to configure Dendrite. Sample configuration files are
|
A YAML configuration file is used to configure Dendrite. A sample configuration file is
|
||||||
present in the top level of the Dendrite repository:
|
present in the top level of the Dendrite repository:
|
||||||
|
|
||||||
* [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml)
|
* [`dendrite-sample.monolith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.monolith.yaml)
|
||||||
* [`dendrite-sample.polylith.yaml`](https://github.com/matrix-org/dendrite/blob/main/dendrite-sample.polylith.yaml)
|
|
||||||
|
|
||||||
You will need to duplicate the sample, calling it `dendrite.yaml` for example, and then
|
You will need to duplicate the sample, calling it `dendrite.yaml` for example, and then
|
||||||
tailor it to your installation. At a minimum, you will need to populate the following
|
tailor it to your installation. At a minimum, you will need to populate the following
|
||||||
|
|
@ -44,17 +43,42 @@ global:
|
||||||
private_key: /path/to/matrix_key.pem
|
private_key: /path/to/matrix_key.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## JetStream configuration
|
||||||
|
|
||||||
|
Dendrite deployments can use the built-in NATS Server rather than running a standalone
|
||||||
|
server. If you want to use a standalone NATS Server anyway, you can also configure that too.
|
||||||
|
|
||||||
### Built-in NATS Server
|
### Built-in NATS Server
|
||||||
|
|
||||||
In the `global` section, under the `jetstream` key, set a `storage_path` to a persistent folder on the filesystem:
|
In the `global` section, under the `jetstream` key, ensure that no server addresses are
|
||||||
|
configured and set a `storage_path` to a persistent folder on the filesystem:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
global:
|
global:
|
||||||
# ...
|
# ...
|
||||||
jetstream:
|
jetstream:
|
||||||
storage_path: /path/to/storage/folder
|
storage_path: /path/to/storage/folder
|
||||||
|
topic_prefix: Dendrite
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Standalone NATS Server
|
||||||
|
|
||||||
|
To use a standalone NATS Server instance, you will need to configure `addresses` field
|
||||||
|
to point to the port that your NATS Server is listening on:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
global:
|
||||||
|
# ...
|
||||||
|
jetstream:
|
||||||
|
addresses:
|
||||||
|
- localhost:4222
|
||||||
|
topic_prefix: Dendrite
|
||||||
|
```
|
||||||
|
|
||||||
|
You do not need to configure the `storage_path` when using a standalone NATS Server instance.
|
||||||
|
In the case that you are connecting to a multi-node NATS cluster, you can configure more than
|
||||||
|
one address in the `addresses` field.
|
||||||
|
|
||||||
## Database connections
|
## Database connections
|
||||||
|
|
||||||
Configuring database connections varies based on the [database configuration](database)
|
Configuring database connections varies based on the [database configuration](database)
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi/queue"
|
"github.com/matrix-org/dendrite/federationapi/queue"
|
||||||
"github.com/matrix-org/dendrite/federationapi/storage"
|
"github.com/matrix-org/dendrite/federationapi/storage"
|
||||||
"github.com/matrix-org/dendrite/federationapi/types"
|
"github.com/matrix-org/dendrite/federationapi/types"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
"github.com/matrix-org/dendrite/setup/process"
|
"github.com/matrix-org/dendrite/setup/process"
|
||||||
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyChangeConsumer consumes events that originate in key server.
|
// KeyChangeConsumer consumes events that originate in key server.
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,17 @@ package federationapi
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
"github.com/matrix-org/dendrite/federationapi/api"
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/federationapi/consumers"
|
"github.com/matrix-org/dendrite/federationapi/consumers"
|
||||||
"github.com/matrix-org/dendrite/federationapi/internal"
|
"github.com/matrix-org/dendrite/federationapi/internal"
|
||||||
"github.com/matrix-org/dendrite/federationapi/inthttp"
|
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
"github.com/matrix-org/dendrite/federationapi/queue"
|
"github.com/matrix-org/dendrite/federationapi/queue"
|
||||||
"github.com/matrix-org/dendrite/federationapi/statistics"
|
"github.com/matrix-org/dendrite/federationapi/statistics"
|
||||||
"github.com/matrix-org/dendrite/federationapi/storage"
|
"github.com/matrix-org/dendrite/federationapi/storage"
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
keyserverAPI "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
|
|
@ -41,21 +38,14 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi/routing"
|
"github.com/matrix-org/dendrite/federationapi/routing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddInternalRoutes registers HTTP handlers for the internal API. Invokes functions
|
|
||||||
// on the given input API.
|
|
||||||
func AddInternalRoutes(router *mux.Router, intAPI api.FederationInternalAPI, enableMetrics bool) {
|
|
||||||
inthttp.AddRoutes(intAPI, router, enableMetrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component.
|
// AddPublicRoutes sets up and registers HTTP handlers on the base API muxes for the FederationAPI component.
|
||||||
func AddPublicRoutes(
|
func AddPublicRoutes(
|
||||||
base *base.BaseDendrite,
|
base *base.BaseDendrite,
|
||||||
userAPI userapi.UserInternalAPI,
|
userAPI userapi.FederationUserAPI,
|
||||||
federation *gomatrixserverlib.FederationClient,
|
federation *gomatrixserverlib.FederationClient,
|
||||||
keyRing gomatrixserverlib.JSONVerifier,
|
keyRing gomatrixserverlib.JSONVerifier,
|
||||||
rsAPI roomserverAPI.FederationRoomserverAPI,
|
rsAPI roomserverAPI.FederationRoomserverAPI,
|
||||||
fedAPI federationAPI.FederationInternalAPI,
|
fedAPI federationAPI.FederationInternalAPI,
|
||||||
keyAPI keyserverAPI.FederationKeyAPI,
|
|
||||||
servers federationAPI.ServersInRoomProvider,
|
servers federationAPI.ServersInRoomProvider,
|
||||||
) {
|
) {
|
||||||
cfg := &base.Cfg.FederationAPI
|
cfg := &base.Cfg.FederationAPI
|
||||||
|
|
@ -87,7 +77,7 @@ func AddPublicRoutes(
|
||||||
routing.Setup(
|
routing.Setup(
|
||||||
base,
|
base,
|
||||||
rsAPI, f, keyRing,
|
rsAPI, f, keyRing,
|
||||||
federation, userAPI, keyAPI, mscCfg,
|
federation, userAPI, mscCfg,
|
||||||
servers, producer,
|
servers, producer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@ func TestMain(m *testing.M) {
|
||||||
// API to work.
|
// API to work.
|
||||||
cfg := &config.Dendrite{}
|
cfg := &config.Dendrite{}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: false,
|
||||||
})
|
})
|
||||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(s.name)
|
cfg.Global.ServerName = gomatrixserverlib.ServerName(s.name)
|
||||||
cfg.Global.PrivateKey = testPriv
|
cfg.Global.PrivateKey = testPriv
|
||||||
|
|
@ -109,7 +109,7 @@ func TestMain(m *testing.M) {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Finally, build the server key APIs.
|
// Finally, build the server key APIs.
|
||||||
sbase := base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics)
|
sbase := base.NewBaseDendrite(cfg, base.DisableMetrics)
|
||||||
s.api = NewInternalAPI(sbase, s.fedclient, nil, s.cache, nil, true)
|
s.api = NewInternalAPI(sbase, s.fedclient, nil, s.cache, nil, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi"
|
"github.com/matrix-org/dendrite/federationapi"
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
"github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/federationapi/internal"
|
"github.com/matrix-org/dendrite/federationapi/internal"
|
||||||
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
rsapi "github.com/matrix-org/dendrite/roomserver/api"
|
rsapi "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
"github.com/matrix-org/dendrite/test/testrig"
|
"github.com/matrix-org/dendrite/test/testrig"
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fedRoomserverAPI struct {
|
type fedRoomserverAPI struct {
|
||||||
|
|
@ -230,9 +230,9 @@ func testFederationAPIJoinThenKeyUpdate(t *testing.T, dbType test.DBType) {
|
||||||
// Inject a keyserver key change event and ensure we try to send it out. If we don't, then the
|
// Inject a keyserver key change event and ensure we try to send it out. If we don't, then the
|
||||||
// federationapi is incorrectly waiting for an output room event to arrive to update the joined
|
// federationapi is incorrectly waiting for an output room event to arrive to update the joined
|
||||||
// hosts table.
|
// hosts table.
|
||||||
key := keyapi.DeviceMessage{
|
key := userapi.DeviceMessage{
|
||||||
Type: keyapi.TypeDeviceKeyUpdate,
|
Type: userapi.TypeDeviceKeyUpdate,
|
||||||
DeviceKeys: &keyapi.DeviceKeys{
|
DeviceKeys: &userapi.DeviceKeys{
|
||||||
UserID: joiningUser.ID,
|
UserID: joiningUser.ID,
|
||||||
DeviceID: "MY_DEVICE",
|
DeviceID: "MY_DEVICE",
|
||||||
DisplayName: "BLARGLE",
|
DisplayName: "BLARGLE",
|
||||||
|
|
@ -266,18 +266,18 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
|
||||||
_, privKey, _ := ed25519.GenerateKey(nil)
|
_, privKey, _ := ed25519.GenerateKey(nil)
|
||||||
cfg := &config.Dendrite{}
|
cfg := &config.Dendrite{}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: false,
|
||||||
})
|
})
|
||||||
cfg.Global.KeyID = gomatrixserverlib.KeyID("ed25519:auto")
|
cfg.Global.KeyID = gomatrixserverlib.KeyID("ed25519:auto")
|
||||||
cfg.Global.ServerName = gomatrixserverlib.ServerName("localhost")
|
cfg.Global.ServerName = gomatrixserverlib.ServerName("localhost")
|
||||||
cfg.Global.PrivateKey = privKey
|
cfg.Global.PrivateKey = privKey
|
||||||
cfg.Global.JetStream.InMemory = true
|
cfg.Global.JetStream.InMemory = true
|
||||||
b := base.NewBaseDendrite(cfg, "Monolith", base.DisableMetrics)
|
b := base.NewBaseDendrite(cfg, base.DisableMetrics)
|
||||||
keyRing := &test.NopJSONVerifier{}
|
keyRing := &test.NopJSONVerifier{}
|
||||||
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
|
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
|
||||||
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.
|
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.
|
||||||
federationapi.AddPublicRoutes(b, nil, nil, keyRing, nil, &internal.FederationInternalAPI{}, nil, nil)
|
federationapi.AddPublicRoutes(b, nil, nil, keyRing, nil, &internal.FederationInternalAPI{}, nil)
|
||||||
baseURL, cancel := test.ListenAndServe(t, b.PublicFederationAPIMux, true)
|
baseURL, cancel := test.ListenAndServe(t, b.PublicFederationAPIMux, true)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://"))
|
serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://"))
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,6 @@ func (r *FederationInternalAPI) PerformJoin(
|
||||||
var httpErr gomatrix.HTTPError
|
var httpErr gomatrix.HTTPError
|
||||||
if ok := errors.As(lastErr, &httpErr); ok {
|
if ok := errors.As(lastErr, &httpErr); ok {
|
||||||
httpErr.Message = string(httpErr.Contents)
|
httpErr.Message = string(httpErr.Contents)
|
||||||
// Clear the wrapped error, else serialising to JSON (in polylith mode) will fail
|
|
||||||
httpErr.WrappedError = nil
|
|
||||||
response.LastError = &httpErr
|
response.LastError = &httpErr
|
||||||
} else {
|
} else {
|
||||||
response.LastError = &gomatrix.HTTPError{
|
response.LastError = &gomatrix.HTTPError{
|
||||||
|
|
@ -391,8 +389,6 @@ func (r *FederationInternalAPI) PerformOutboundPeek(
|
||||||
var httpErr gomatrix.HTTPError
|
var httpErr gomatrix.HTTPError
|
||||||
if ok := errors.As(lastErr, &httpErr); ok {
|
if ok := errors.As(lastErr, &httpErr); ok {
|
||||||
httpErr.Message = string(httpErr.Contents)
|
httpErr.Message = string(httpErr.Contents)
|
||||||
// Clear the wrapped error, else serialising to JSON (in polylith mode) will fail
|
|
||||||
httpErr.WrappedError = nil
|
|
||||||
response.LastError = &httpErr
|
response.LastError = &httpErr
|
||||||
} else {
|
} else {
|
||||||
response.LastError = &gomatrix.HTTPError{
|
response.LastError = &gomatrix.HTTPError{
|
||||||
|
|
|
||||||
|
|
@ -1,548 +0,0 @@
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
"github.com/matrix-org/gomatrix"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP paths for the internal HTTP API
|
|
||||||
const (
|
|
||||||
FederationAPIQueryJoinedHostServerNamesInRoomPath = "/federationapi/queryJoinedHostServerNamesInRoom"
|
|
||||||
FederationAPIQueryServerKeysPath = "/federationapi/queryServerKeys"
|
|
||||||
|
|
||||||
FederationAPIPerformDirectoryLookupRequestPath = "/federationapi/performDirectoryLookup"
|
|
||||||
FederationAPIPerformJoinRequestPath = "/federationapi/performJoinRequest"
|
|
||||||
FederationAPIPerformLeaveRequestPath = "/federationapi/performLeaveRequest"
|
|
||||||
FederationAPIPerformInviteRequestPath = "/federationapi/performInviteRequest"
|
|
||||||
FederationAPIPerformOutboundPeekRequestPath = "/federationapi/performOutboundPeekRequest"
|
|
||||||
FederationAPIPerformBroadcastEDUPath = "/federationapi/performBroadcastEDU"
|
|
||||||
FederationAPIPerformWakeupServers = "/federationapi/performWakeupServers"
|
|
||||||
FederationAPIQueryRelayServers = "/federationapi/queryRelayServers"
|
|
||||||
FederationAPIAddRelayServers = "/federationapi/addRelayServers"
|
|
||||||
FederationAPIRemoveRelayServers = "/federationapi/removeRelayServers"
|
|
||||||
|
|
||||||
FederationAPIGetUserDevicesPath = "/federationapi/client/getUserDevices"
|
|
||||||
FederationAPIClaimKeysPath = "/federationapi/client/claimKeys"
|
|
||||||
FederationAPIQueryKeysPath = "/federationapi/client/queryKeys"
|
|
||||||
FederationAPIBackfillPath = "/federationapi/client/backfill"
|
|
||||||
FederationAPILookupStatePath = "/federationapi/client/lookupState"
|
|
||||||
FederationAPILookupStateIDsPath = "/federationapi/client/lookupStateIDs"
|
|
||||||
FederationAPILookupMissingEventsPath = "/federationapi/client/lookupMissingEvents"
|
|
||||||
FederationAPIGetEventPath = "/federationapi/client/getEvent"
|
|
||||||
FederationAPILookupServerKeysPath = "/federationapi/client/lookupServerKeys"
|
|
||||||
FederationAPIEventRelationshipsPath = "/federationapi/client/msc2836eventRelationships"
|
|
||||||
FederationAPISpacesSummaryPath = "/federationapi/client/msc2946spacesSummary"
|
|
||||||
FederationAPIGetEventAuthPath = "/federationapi/client/getEventAuth"
|
|
||||||
|
|
||||||
FederationAPIInputPublicKeyPath = "/federationapi/inputPublicKey"
|
|
||||||
FederationAPIQueryPublicKeyPath = "/federationapi/queryPublicKey"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewFederationAPIClient creates a FederationInternalAPI implemented by talking to a HTTP POST API.
|
|
||||||
// If httpClient is nil an error is returned
|
|
||||||
func NewFederationAPIClient(federationSenderURL string, httpClient *http.Client, cache caching.ServerKeyCache) (api.FederationInternalAPI, error) {
|
|
||||||
if httpClient == nil {
|
|
||||||
return nil, errors.New("NewFederationInternalAPIHTTP: httpClient is <nil>")
|
|
||||||
}
|
|
||||||
return &httpFederationInternalAPI{
|
|
||||||
federationAPIURL: federationSenderURL,
|
|
||||||
httpClient: httpClient,
|
|
||||||
cache: cache,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type httpFederationInternalAPI struct {
|
|
||||||
federationAPIURL string
|
|
||||||
httpClient *http.Client
|
|
||||||
cache caching.ServerKeyCache
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an instruction to make_leave & send_leave with a remote server.
|
|
||||||
func (h *httpFederationInternalAPI) PerformLeave(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformLeaveRequest,
|
|
||||||
response *api.PerformLeaveResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformLeave", h.federationAPIURL+FederationAPIPerformLeaveRequestPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle sending an invite to a remote server.
|
|
||||||
func (h *httpFederationInternalAPI) PerformInvite(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformInviteRequest,
|
|
||||||
response *api.PerformInviteResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformInvite", h.federationAPIURL+FederationAPIPerformInviteRequestPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle starting a peek on a remote server.
|
|
||||||
func (h *httpFederationInternalAPI) PerformOutboundPeek(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformOutboundPeekRequest,
|
|
||||||
response *api.PerformOutboundPeekResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformOutboundPeek", h.federationAPIURL+FederationAPIPerformOutboundPeekRequestPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryJoinedHostServerNamesInRoom implements FederationInternalAPI
|
|
||||||
func (h *httpFederationInternalAPI) QueryJoinedHostServerNamesInRoom(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryJoinedHostServerNamesInRoomRequest,
|
|
||||||
response *api.QueryJoinedHostServerNamesInRoomResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryJoinedHostServerNamesInRoom", h.federationAPIURL+FederationAPIQueryJoinedHostServerNamesInRoomPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an instruction to make_join & send_join with a remote server.
|
|
||||||
func (h *httpFederationInternalAPI) PerformJoin(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformJoinRequest,
|
|
||||||
response *api.PerformJoinResponse,
|
|
||||||
) {
|
|
||||||
if err := httputil.CallInternalRPCAPI(
|
|
||||||
"PerformJoinRequest", h.federationAPIURL+FederationAPIPerformJoinRequestPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
); err != nil {
|
|
||||||
response.LastError = &gomatrix.HTTPError{
|
|
||||||
Message: err.Error(),
|
|
||||||
Code: 0,
|
|
||||||
WrappedError: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an instruction to make_join & send_join with a remote server.
|
|
||||||
func (h *httpFederationInternalAPI) PerformDirectoryLookup(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformDirectoryLookupRequest,
|
|
||||||
response *api.PerformDirectoryLookupResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformDirectoryLookup", h.federationAPIURL+FederationAPIPerformDirectoryLookupRequestPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an instruction to broadcast an EDU to all servers in rooms we are joined to.
|
|
||||||
func (h *httpFederationInternalAPI) PerformBroadcastEDU(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformBroadcastEDURequest,
|
|
||||||
response *api.PerformBroadcastEDUResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformBroadcastEDU", h.federationAPIURL+FederationAPIPerformBroadcastEDUPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an instruction to remove the respective servers from being blacklisted.
|
|
||||||
func (h *httpFederationInternalAPI) PerformWakeupServers(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformWakeupServersRequest,
|
|
||||||
response *api.PerformWakeupServersResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformWakeupServers", h.federationAPIURL+FederationAPIPerformWakeupServers,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type getUserDevices struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
UserID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) GetUserDevices(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, userID string,
|
|
||||||
) (gomatrixserverlib.RespUserDevices, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[getUserDevices, gomatrixserverlib.RespUserDevices, *api.FederationClientError](
|
|
||||||
"GetUserDevices", h.federationAPIURL+FederationAPIGetUserDevicesPath, h.httpClient,
|
|
||||||
ctx, &getUserDevices{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
UserID: userID,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type claimKeys struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
OneTimeKeys map[string]map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) ClaimKeys(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, oneTimeKeys map[string]map[string]string,
|
|
||||||
) (gomatrixserverlib.RespClaimKeys, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[claimKeys, gomatrixserverlib.RespClaimKeys, *api.FederationClientError](
|
|
||||||
"ClaimKeys", h.federationAPIURL+FederationAPIClaimKeysPath, h.httpClient,
|
|
||||||
ctx, &claimKeys{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
OneTimeKeys: oneTimeKeys,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type queryKeys struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
Keys map[string][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) QueryKeys(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, keys map[string][]string,
|
|
||||||
) (gomatrixserverlib.RespQueryKeys, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[queryKeys, gomatrixserverlib.RespQueryKeys, *api.FederationClientError](
|
|
||||||
"QueryKeys", h.federationAPIURL+FederationAPIQueryKeysPath, h.httpClient,
|
|
||||||
ctx, &queryKeys{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
Keys: keys,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type backfill struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
RoomID string
|
|
||||||
Limit int
|
|
||||||
EventIDs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) Backfill(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID string, limit int, eventIDs []string,
|
|
||||||
) (gomatrixserverlib.Transaction, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[backfill, gomatrixserverlib.Transaction, *api.FederationClientError](
|
|
||||||
"Backfill", h.federationAPIURL+FederationAPIBackfillPath, h.httpClient,
|
|
||||||
ctx, &backfill{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
RoomID: roomID,
|
|
||||||
Limit: limit,
|
|
||||||
EventIDs: eventIDs,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lookupState struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
RoomID string
|
|
||||||
EventID string
|
|
||||||
RoomVersion gomatrixserverlib.RoomVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) LookupState(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion,
|
|
||||||
) (gomatrixserverlib.RespState, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[lookupState, gomatrixserverlib.RespState, *api.FederationClientError](
|
|
||||||
"LookupState", h.federationAPIURL+FederationAPILookupStatePath, h.httpClient,
|
|
||||||
ctx, &lookupState{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
RoomID: roomID,
|
|
||||||
EventID: eventID,
|
|
||||||
RoomVersion: roomVersion,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lookupStateIDs struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
RoomID string
|
|
||||||
EventID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) LookupStateIDs(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID, eventID string,
|
|
||||||
) (gomatrixserverlib.RespStateIDs, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[lookupStateIDs, gomatrixserverlib.RespStateIDs, *api.FederationClientError](
|
|
||||||
"LookupStateIDs", h.federationAPIURL+FederationAPILookupStateIDsPath, h.httpClient,
|
|
||||||
ctx, &lookupStateIDs{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
RoomID: roomID,
|
|
||||||
EventID: eventID,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lookupMissingEvents struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
RoomID string
|
|
||||||
Missing gomatrixserverlib.MissingEvents
|
|
||||||
RoomVersion gomatrixserverlib.RoomVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) LookupMissingEvents(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, roomID string,
|
|
||||||
missing gomatrixserverlib.MissingEvents, roomVersion gomatrixserverlib.RoomVersion,
|
|
||||||
) (res gomatrixserverlib.RespMissingEvents, err error) {
|
|
||||||
return httputil.CallInternalProxyAPI[lookupMissingEvents, gomatrixserverlib.RespMissingEvents, *api.FederationClientError](
|
|
||||||
"LookupMissingEvents", h.federationAPIURL+FederationAPILookupMissingEventsPath, h.httpClient,
|
|
||||||
ctx, &lookupMissingEvents{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
RoomID: roomID,
|
|
||||||
Missing: missing,
|
|
||||||
RoomVersion: roomVersion,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type getEvent struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
EventID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) GetEvent(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, eventID string,
|
|
||||||
) (gomatrixserverlib.Transaction, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[getEvent, gomatrixserverlib.Transaction, *api.FederationClientError](
|
|
||||||
"GetEvent", h.federationAPIURL+FederationAPIGetEventPath, h.httpClient,
|
|
||||||
ctx, &getEvent{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
EventID: eventID,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type getEventAuth struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
RoomVersion gomatrixserverlib.RoomVersion
|
|
||||||
RoomID string
|
|
||||||
EventID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) GetEventAuth(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName,
|
|
||||||
roomVersion gomatrixserverlib.RoomVersion, roomID, eventID string,
|
|
||||||
) (gomatrixserverlib.RespEventAuth, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[getEventAuth, gomatrixserverlib.RespEventAuth, *api.FederationClientError](
|
|
||||||
"GetEventAuth", h.federationAPIURL+FederationAPIGetEventAuthPath, h.httpClient,
|
|
||||||
ctx, &getEventAuth{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
RoomVersion: roomVersion,
|
|
||||||
RoomID: roomID,
|
|
||||||
EventID: eventID,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) QueryServerKeys(
|
|
||||||
ctx context.Context, req *api.QueryServerKeysRequest, res *api.QueryServerKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryServerKeys", h.federationAPIURL+FederationAPIQueryServerKeysPath,
|
|
||||||
h.httpClient, ctx, req, res,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lookupServerKeys struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
KeyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) LookupServerKeys(
|
|
||||||
ctx context.Context, s gomatrixserverlib.ServerName, keyRequests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
|
|
||||||
) ([]gomatrixserverlib.ServerKeys, error) {
|
|
||||||
return httputil.CallInternalProxyAPI[lookupServerKeys, []gomatrixserverlib.ServerKeys, *api.FederationClientError](
|
|
||||||
"LookupServerKeys", h.federationAPIURL+FederationAPILookupServerKeysPath, h.httpClient,
|
|
||||||
ctx, &lookupServerKeys{
|
|
||||||
S: s,
|
|
||||||
KeyRequests: keyRequests,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type eventRelationships struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
Req gomatrixserverlib.MSC2836EventRelationshipsRequest
|
|
||||||
RoomVer gomatrixserverlib.RoomVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) MSC2836EventRelationships(
|
|
||||||
ctx context.Context, origin, s gomatrixserverlib.ServerName, r gomatrixserverlib.MSC2836EventRelationshipsRequest,
|
|
||||||
roomVersion gomatrixserverlib.RoomVersion,
|
|
||||||
) (res gomatrixserverlib.MSC2836EventRelationshipsResponse, err error) {
|
|
||||||
return httputil.CallInternalProxyAPI[eventRelationships, gomatrixserverlib.MSC2836EventRelationshipsResponse, *api.FederationClientError](
|
|
||||||
"MSC2836EventRelationships", h.federationAPIURL+FederationAPIEventRelationshipsPath, h.httpClient,
|
|
||||||
ctx, &eventRelationships{
|
|
||||||
S: s,
|
|
||||||
Origin: origin,
|
|
||||||
Req: r,
|
|
||||||
RoomVer: roomVersion,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type spacesReq struct {
|
|
||||||
S gomatrixserverlib.ServerName
|
|
||||||
Origin gomatrixserverlib.ServerName
|
|
||||||
SuggestedOnly bool
|
|
||||||
RoomID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) MSC2946Spaces(
|
|
||||||
ctx context.Context, origin, dst gomatrixserverlib.ServerName, roomID string, suggestedOnly bool,
|
|
||||||
) (res gomatrixserverlib.MSC2946SpacesResponse, err error) {
|
|
||||||
return httputil.CallInternalProxyAPI[spacesReq, gomatrixserverlib.MSC2946SpacesResponse, *api.FederationClientError](
|
|
||||||
"MSC2836EventRelationships", h.federationAPIURL+FederationAPISpacesSummaryPath, h.httpClient,
|
|
||||||
ctx, &spacesReq{
|
|
||||||
S: dst,
|
|
||||||
Origin: origin,
|
|
||||||
SuggestedOnly: suggestedOnly,
|
|
||||||
RoomID: roomID,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *httpFederationInternalAPI) KeyRing() *gomatrixserverlib.KeyRing {
|
|
||||||
// This is a bit of a cheat - we tell gomatrixserverlib that this API is
|
|
||||||
// both the key database and the key fetcher. While this does have the
|
|
||||||
// rather unfortunate effect of preventing gomatrixserverlib from handling
|
|
||||||
// key fetchers directly, we can at least reimplement this behaviour on
|
|
||||||
// the other end of the API.
|
|
||||||
return &gomatrixserverlib.KeyRing{
|
|
||||||
KeyDatabase: s,
|
|
||||||
KeyFetchers: []gomatrixserverlib.KeyFetcher{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *httpFederationInternalAPI) FetcherName() string {
|
|
||||||
return "httpServerKeyInternalAPI"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *httpFederationInternalAPI) StoreKeys(
|
|
||||||
_ context.Context,
|
|
||||||
results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult,
|
|
||||||
) error {
|
|
||||||
// Run in a background context - we don't want to stop this work just
|
|
||||||
// because the caller gives up waiting.
|
|
||||||
ctx := context.Background()
|
|
||||||
request := api.InputPublicKeysRequest{
|
|
||||||
Keys: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult),
|
|
||||||
}
|
|
||||||
response := api.InputPublicKeysResponse{}
|
|
||||||
for req, res := range results {
|
|
||||||
request.Keys[req] = res
|
|
||||||
s.cache.StoreServerKey(req, res)
|
|
||||||
}
|
|
||||||
return s.InputPublicKeys(ctx, &request, &response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *httpFederationInternalAPI) FetchKeys(
|
|
||||||
_ context.Context,
|
|
||||||
requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
|
|
||||||
) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) {
|
|
||||||
// Run in a background context - we don't want to stop this work just
|
|
||||||
// because the caller gives up waiting.
|
|
||||||
ctx := context.Background()
|
|
||||||
result := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult)
|
|
||||||
request := api.QueryPublicKeysRequest{
|
|
||||||
Requests: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp),
|
|
||||||
}
|
|
||||||
response := api.QueryPublicKeysResponse{
|
|
||||||
Results: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult),
|
|
||||||
}
|
|
||||||
for req, ts := range requests {
|
|
||||||
if res, ok := s.cache.GetServerKey(req, ts); ok {
|
|
||||||
result[req] = res
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
request.Requests[req] = ts
|
|
||||||
}
|
|
||||||
err := s.QueryPublicKeys(ctx, &request, &response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for req, res := range response.Results {
|
|
||||||
result[req] = res
|
|
||||||
s.cache.StoreServerKey(req, res)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) InputPublicKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.InputPublicKeysRequest,
|
|
||||||
response *api.InputPublicKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"InputPublicKey", h.federationAPIURL+FederationAPIInputPublicKeyPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) QueryPublicKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryPublicKeysRequest,
|
|
||||||
response *api.QueryPublicKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryPublicKeys", h.federationAPIURL+FederationAPIQueryPublicKeyPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) P2PQueryRelayServers(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.P2PQueryRelayServersRequest,
|
|
||||||
response *api.P2PQueryRelayServersResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryRelayServers", h.federationAPIURL+FederationAPIQueryRelayServers,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) P2PAddRelayServers(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.P2PAddRelayServersRequest,
|
|
||||||
response *api.P2PAddRelayServersResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"AddRelayServers", h.federationAPIURL+FederationAPIAddRelayServers,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpFederationInternalAPI) P2PRemoveRelayServers(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.P2PRemoveRelayServersRequest,
|
|
||||||
response *api.P2PRemoveRelayServersResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"RemoveRelayServers", h.federationAPIURL+FederationAPIRemoveRelayServers,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,257 +0,0 @@
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/matrix-org/gomatrix"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
"github.com/matrix-org/util"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/federationapi/api"
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddRoutes adds the FederationInternalAPI handlers to the http.ServeMux.
|
|
||||||
// nolint:gocyclo
|
|
||||||
func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router, enableMetrics bool) {
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIQueryJoinedHostServerNamesInRoomPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIQueryJoinedHostServerNamesInRoom", enableMetrics, intAPI.QueryJoinedHostServerNamesInRoom),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformInviteRequestPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIPerformInvite", enableMetrics, intAPI.PerformInvite),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformLeaveRequestPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIPerformLeave", enableMetrics, intAPI.PerformLeave),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformDirectoryLookupRequestPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIPerformDirectoryLookupRequest", enableMetrics, intAPI.PerformDirectoryLookup),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformBroadcastEDUPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIPerformBroadcastEDU", enableMetrics, intAPI.PerformBroadcastEDU),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformWakeupServers,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIPerformWakeupServers", enableMetrics, intAPI.PerformWakeupServers),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIPerformJoinRequestPath,
|
|
||||||
httputil.MakeInternalRPCAPI(
|
|
||||||
"FederationAPIPerformJoinRequest", enableMetrics,
|
|
||||||
func(ctx context.Context, req *api.PerformJoinRequest, res *api.PerformJoinResponse) error {
|
|
||||||
intAPI.PerformJoin(ctx, req, res)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIGetUserDevicesPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIGetUserDevices", enableMetrics,
|
|
||||||
func(ctx context.Context, req *getUserDevices) (*gomatrixserverlib.RespUserDevices, error) {
|
|
||||||
res, err := intAPI.GetUserDevices(ctx, req.Origin, req.S, req.UserID)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIClaimKeysPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIClaimKeys", enableMetrics,
|
|
||||||
func(ctx context.Context, req *claimKeys) (*gomatrixserverlib.RespClaimKeys, error) {
|
|
||||||
res, err := intAPI.ClaimKeys(ctx, req.Origin, req.S, req.OneTimeKeys)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIQueryKeysPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIQueryKeys", enableMetrics,
|
|
||||||
func(ctx context.Context, req *queryKeys) (*gomatrixserverlib.RespQueryKeys, error) {
|
|
||||||
res, err := intAPI.QueryKeys(ctx, req.Origin, req.S, req.Keys)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIBackfillPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIBackfill", enableMetrics,
|
|
||||||
func(ctx context.Context, req *backfill) (*gomatrixserverlib.Transaction, error) {
|
|
||||||
res, err := intAPI.Backfill(ctx, req.Origin, req.S, req.RoomID, req.Limit, req.EventIDs)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPILookupStatePath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPILookupState", enableMetrics,
|
|
||||||
func(ctx context.Context, req *lookupState) (*gomatrixserverlib.RespState, error) {
|
|
||||||
res, err := intAPI.LookupState(ctx, req.Origin, req.S, req.RoomID, req.EventID, req.RoomVersion)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPILookupStateIDsPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPILookupStateIDs", enableMetrics,
|
|
||||||
func(ctx context.Context, req *lookupStateIDs) (*gomatrixserverlib.RespStateIDs, error) {
|
|
||||||
res, err := intAPI.LookupStateIDs(ctx, req.Origin, req.S, req.RoomID, req.EventID)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPILookupMissingEventsPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPILookupMissingEvents", enableMetrics,
|
|
||||||
func(ctx context.Context, req *lookupMissingEvents) (*gomatrixserverlib.RespMissingEvents, error) {
|
|
||||||
res, err := intAPI.LookupMissingEvents(ctx, req.Origin, req.S, req.RoomID, req.Missing, req.RoomVersion)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIGetEventPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIGetEvent", enableMetrics,
|
|
||||||
func(ctx context.Context, req *getEvent) (*gomatrixserverlib.Transaction, error) {
|
|
||||||
res, err := intAPI.GetEvent(ctx, req.Origin, req.S, req.EventID)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIGetEventAuthPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIGetEventAuth", enableMetrics,
|
|
||||||
func(ctx context.Context, req *getEventAuth) (*gomatrixserverlib.RespEventAuth, error) {
|
|
||||||
res, err := intAPI.GetEventAuth(ctx, req.Origin, req.S, req.RoomVersion, req.RoomID, req.EventID)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIQueryServerKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("FederationAPIQueryServerKeys", enableMetrics, intAPI.QueryServerKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPILookupServerKeysPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPILookupServerKeys", enableMetrics,
|
|
||||||
func(ctx context.Context, req *lookupServerKeys) (*[]gomatrixserverlib.ServerKeys, error) {
|
|
||||||
res, err := intAPI.LookupServerKeys(ctx, req.S, req.KeyRequests)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPIEventRelationshipsPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIMSC2836EventRelationships", enableMetrics,
|
|
||||||
func(ctx context.Context, req *eventRelationships) (*gomatrixserverlib.MSC2836EventRelationshipsResponse, error) {
|
|
||||||
res, err := intAPI.MSC2836EventRelationships(ctx, req.Origin, req.S, req.Req, req.RoomVer)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
FederationAPISpacesSummaryPath,
|
|
||||||
httputil.MakeInternalProxyAPI(
|
|
||||||
"FederationAPIMSC2946SpacesSummary", enableMetrics,
|
|
||||||
func(ctx context.Context, req *spacesReq) (*gomatrixserverlib.MSC2946SpacesResponse, error) {
|
|
||||||
res, err := intAPI.MSC2946Spaces(ctx, req.Origin, req.S, req.RoomID, req.SuggestedOnly)
|
|
||||||
return &res, federationClientError(err)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Look at this shape
|
|
||||||
internalAPIMux.Handle(FederationAPIQueryPublicKeyPath,
|
|
||||||
httputil.MakeInternalAPI("FederationAPIQueryPublicKeys", enableMetrics, func(req *http.Request) util.JSONResponse {
|
|
||||||
request := api.QueryPublicKeysRequest{}
|
|
||||||
response := api.QueryPublicKeysResponse{}
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
|
||||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
keys, err := intAPI.FetchKeys(req.Context(), request.Requests)
|
|
||||||
if err != nil {
|
|
||||||
return util.ErrorResponse(err)
|
|
||||||
}
|
|
||||||
response.Results = keys
|
|
||||||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Look at this shape
|
|
||||||
internalAPIMux.Handle(FederationAPIInputPublicKeyPath,
|
|
||||||
httputil.MakeInternalAPI("FederationAPIInputPublicKeys", enableMetrics, func(req *http.Request) util.JSONResponse {
|
|
||||||
request := api.InputPublicKeysRequest{}
|
|
||||||
response := api.InputPublicKeysResponse{}
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
|
||||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
if err := intAPI.StoreKeys(req.Context(), request.Keys); err != nil {
|
|
||||||
return util.ErrorResponse(err)
|
|
||||||
}
|
|
||||||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func federationClientError(err error) error {
|
|
||||||
switch ferr := err.(type) {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
case api.FederationClientError:
|
|
||||||
return &ferr
|
|
||||||
case *api.FederationClientError:
|
|
||||||
return ferr
|
|
||||||
case gomatrix.HTTPError:
|
|
||||||
return &api.FederationClientError{
|
|
||||||
Code: ferr.Code,
|
|
||||||
}
|
|
||||||
case *url.Error: // e.g. certificate error, unable to connect
|
|
||||||
return &api.FederationClientError{
|
|
||||||
Err: ferr.Error(),
|
|
||||||
Code: 400,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// We don't know what exactly failed, but we probably don't
|
|
||||||
// want to retry the request immediately in the device list updater
|
|
||||||
return &api.FederationClientError{
|
|
||||||
Err: err.Error(),
|
|
||||||
Code: 400,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -41,7 +41,7 @@ type SyncAPIProducer struct {
|
||||||
TopicSigningKeyUpdate string
|
TopicSigningKeyUpdate string
|
||||||
JetStream nats.JetStreamContext
|
JetStream nats.JetStreamContext
|
||||||
Config *config.FederationAPI
|
Config *config.FederationAPI
|
||||||
UserAPI userapi.UserInternalAPI
|
UserAPI userapi.FederationUserAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SyncAPIProducer) SendReceipt(
|
func (p *SyncAPIProducer) SendReceipt(
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
@ -26,11 +26,11 @@ import (
|
||||||
// GetUserDevices for the given user id
|
// GetUserDevices for the given user id
|
||||||
func GetUserDevices(
|
func GetUserDevices(
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
keyAPI keyapi.FederationKeyAPI,
|
keyAPI api.FederationKeyAPI,
|
||||||
userID string,
|
userID string,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
var res keyapi.QueryDeviceMessagesResponse
|
var res api.QueryDeviceMessagesResponse
|
||||||
if err := keyAPI.QueryDeviceMessages(req.Context(), &keyapi.QueryDeviceMessagesRequest{
|
if err := keyAPI.QueryDeviceMessages(req.Context(), &api.QueryDeviceMessagesRequest{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
}, &res); err != nil {
|
}, &res); err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
|
|
@ -40,12 +40,12 @@ func GetUserDevices(
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
sigReq := &keyapi.QuerySignaturesRequest{
|
sigReq := &api.QuerySignaturesRequest{
|
||||||
TargetIDs: map[string][]gomatrixserverlib.KeyID{
|
TargetIDs: map[string][]gomatrixserverlib.KeyID{
|
||||||
userID: {},
|
userID: {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
sigRes := &keyapi.QuerySignaturesResponse{}
|
sigRes := &api.QuerySignaturesResponse{}
|
||||||
for _, dev := range res.Devices {
|
for _, dev := range res.Devices {
|
||||||
sigReq.TargetIDs[userID] = append(sigReq.TargetIDs[userID], gomatrixserverlib.KeyID(dev.DeviceID))
|
sigReq.TargetIDs[userID] = append(sigReq.TargetIDs[userID], gomatrixserverlib.KeyID(dev.DeviceID))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ import (
|
||||||
clienthttputil "github.com/matrix-org/dendrite/clientapi/httputil"
|
clienthttputil "github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func TestHandleQueryProfile(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("This is a programming error.")
|
panic("This is a programming error.")
|
||||||
}
|
}
|
||||||
routing.Setup(base, nil, r, keyRing, &fedClient, &userapi, nil, &base.Cfg.MSCs, nil, nil)
|
routing.Setup(base, nil, r, keyRing, &fedClient, &userapi, &base.Cfg.MSCs, nil, nil)
|
||||||
|
|
||||||
handler := fedMux.Get(routing.QueryProfileRouteName).GetHandler().ServeHTTP
|
handler := fedMux.Get(routing.QueryProfileRouteName).GetHandler().ServeHTTP
|
||||||
_, sk, _ := ed25519.GenerateKey(nil)
|
_, sk, _ := ed25519.GenerateKey(nil)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func TestHandleQueryDirectory(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("This is a programming error.")
|
panic("This is a programming error.")
|
||||||
}
|
}
|
||||||
routing.Setup(base, nil, r, keyRing, &fedClient, &userapi, nil, &base.Cfg.MSCs, nil, nil)
|
routing.Setup(base, nil, r, keyRing, &fedClient, &userapi, &base.Cfg.MSCs, nil, nil)
|
||||||
|
|
||||||
handler := fedMux.Get(routing.QueryDirectoryRouteName).GetHandler().ServeHTTP
|
handler := fedMux.Get(routing.QueryDirectoryRouteName).GetHandler().ServeHTTP
|
||||||
_, sk, _ := ed25519.GenerateKey(nil)
|
_, sk, _ := ed25519.GenerateKey(nil)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
keyserverAPI "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
"github.com/matrix-org/dendrite/setup/base"
|
||||||
|
|
@ -62,7 +61,6 @@ func Setup(
|
||||||
keys gomatrixserverlib.JSONVerifier,
|
keys gomatrixserverlib.JSONVerifier,
|
||||||
federation federationAPI.FederationClient,
|
federation federationAPI.FederationClient,
|
||||||
userAPI userapi.FederationUserAPI,
|
userAPI userapi.FederationUserAPI,
|
||||||
keyAPI keyserverAPI.FederationKeyAPI,
|
|
||||||
mscCfg *config.MSCs,
|
mscCfg *config.MSCs,
|
||||||
servers federationAPI.ServersInRoomProvider,
|
servers federationAPI.ServersInRoomProvider,
|
||||||
producer *producers.SyncAPIProducer,
|
producer *producers.SyncAPIProducer,
|
||||||
|
|
@ -141,7 +139,7 @@ func Setup(
|
||||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||||
return Send(
|
return Send(
|
||||||
httpReq, request, gomatrixserverlib.TransactionID(vars["txnID"]),
|
httpReq, request, gomatrixserverlib.TransactionID(vars["txnID"]),
|
||||||
cfg, rsAPI, keyAPI, keys, federation, mu, servers, producer,
|
cfg, rsAPI, userAPI, keys, federation, mu, servers, producer,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodPut, http.MethodOptions).Name(SendRouteName)
|
)).Methods(http.MethodPut, http.MethodOptions).Name(SendRouteName)
|
||||||
|
|
@ -269,7 +267,7 @@ func Setup(
|
||||||
"federation_user_devices", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
"federation_user_devices", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||||
return GetUserDevices(
|
return GetUserDevices(
|
||||||
httpReq, keyAPI, vars["userID"],
|
httpReq, userAPI, vars["userID"],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodGet)
|
)).Methods(http.MethodGet)
|
||||||
|
|
@ -494,14 +492,14 @@ func Setup(
|
||||||
v1fedmux.Handle("/user/keys/claim", MakeFedAPI(
|
v1fedmux.Handle("/user/keys/claim", MakeFedAPI(
|
||||||
"federation_keys_claim", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
"federation_keys_claim", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||||
return ClaimOneTimeKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
|
return ClaimOneTimeKeys(httpReq, request, userAPI, cfg.Matrix.ServerName)
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodPost)
|
)).Methods(http.MethodPost)
|
||||||
|
|
||||||
v1fedmux.Handle("/user/keys/query", MakeFedAPI(
|
v1fedmux.Handle("/user/keys/query", MakeFedAPI(
|
||||||
"federation_keys_query", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
"federation_keys_query", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||||
return QueryDeviceKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
|
return QueryDeviceKeys(httpReq, request, userAPI, cfg.Matrix.ServerName)
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodPost)
|
)).Methods(http.MethodPost)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ import (
|
||||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -59,7 +59,7 @@ func Send(
|
||||||
txnID gomatrixserverlib.TransactionID,
|
txnID gomatrixserverlib.TransactionID,
|
||||||
cfg *config.FederationAPI,
|
cfg *config.FederationAPI,
|
||||||
rsAPI api.FederationRoomserverAPI,
|
rsAPI api.FederationRoomserverAPI,
|
||||||
keyAPI keyapi.FederationKeyAPI,
|
keyAPI userAPI.FederationUserAPI,
|
||||||
keys gomatrixserverlib.JSONVerifier,
|
keys gomatrixserverlib.JSONVerifier,
|
||||||
federation federationAPI.FederationClient,
|
federation federationAPI.FederationClient,
|
||||||
mu *internal.MutexByRoom,
|
mu *internal.MutexByRoom,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func TestHandleSend(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("This is a programming error.")
|
panic("This is a programming error.")
|
||||||
}
|
}
|
||||||
routing.Setup(base, nil, r, keyRing, nil, nil, nil, &base.Cfg.MSCs, nil, nil)
|
routing.Setup(base, nil, r, keyRing, nil, nil, &base.Cfg.MSCs, nil, nil)
|
||||||
|
|
||||||
handler := fedMux.Get(routing.SendRouteName).GetHandler().ServeHTTP
|
handler := fedMux.Get(routing.SendRouteName).GetHandler().ServeHTTP
|
||||||
_, sk, _ := ed25519.GenerateKey(nil)
|
_, sk, _ := ed25519.GenerateKey(nil)
|
||||||
|
|
|
||||||
21
go.mod
21
go.mod
|
|
@ -23,7 +23,7 @@ require (
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230111184901-61850f0e63cb
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
||||||
github.com/mattn/go-sqlite3 v1.14.15
|
github.com/mattn/go-sqlite3 v1.14.15
|
||||||
github.com/nats-io/nats-server/v2 v2.9.8
|
github.com/nats-io/nats-server/v2 v2.9.8
|
||||||
|
|
@ -44,10 +44,9 @@ require (
|
||||||
github.com/yggdrasil-network/yggdrasil-go v0.4.6
|
github.com/yggdrasil-network/yggdrasil-go v0.4.6
|
||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
golang.org/x/crypto v0.5.0
|
golang.org/x/crypto v0.5.0
|
||||||
golang.org/x/image v0.1.0
|
golang.org/x/image v0.5.0
|
||||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
|
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/term v0.5.0
|
||||||
golang.org/x/term v0.4.0
|
|
||||||
gopkg.in/h2non/bimg.v1 v1.1.9
|
gopkg.in/h2non/bimg.v1 v1.1.9
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gotest.tools/v3 v3.4.0
|
gotest.tools/v3 v3.4.0
|
||||||
|
|
@ -95,9 +94,6 @@ require (
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/klauspost/compress v1.15.11 // indirect
|
github.com/klauspost/compress v1.15.11 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/lucas-clemente/quic-go v0.30.0 // indirect
|
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
github.com/minio/highwayhash v1.0.2 // indirect
|
github.com/minio/highwayhash v1.0.2 // indirect
|
||||||
|
|
@ -117,14 +113,19 @@ require (
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||||
|
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
||||||
|
github.com/quic-go/quic-go v0.32.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 // indirect
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||||
golang.org/x/mod v0.6.0 // indirect
|
golang.org/x/mod v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
|
golang.org/x/text v0.7.0 // indirect
|
||||||
golang.org/x/time v0.1.0 // indirect
|
golang.org/x/time v0.1.0 // indirect
|
||||||
golang.org/x/tools v0.2.0 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
|
|
||||||
43
go.sum
43
go.sum
|
|
@ -315,12 +315,6 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lucas-clemente/quic-go v0.30.0 h1:nwLW0h8ahVQ5EPTIM7uhl/stHqQDea15oRlYKZmw2O0=
|
|
||||||
github.com/lucas-clemente/quic-go v0.30.0/go.mod h1:ssOrRsOmdxa768Wr78vnh2B8JozgLsMzG/g+0qEC7uk=
|
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
|
||||||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e h1:DP5RC0Z3XdyBEW5dKt8YPeN6vZbm6OzVaGVp7f1BQRM=
|
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e h1:DP5RC0Z3XdyBEW5dKt8YPeN6vZbm6OzVaGVp7f1BQRM=
|
||||||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e/go.mod h1:NgPCr+UavRGH6n5jmdX8DuqFZ4JiCWIJoZiuhTRLSUg=
|
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e/go.mod h1:NgPCr+UavRGH6n5jmdX8DuqFZ4JiCWIJoZiuhTRLSUg=
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw2QV3YD/fRrzEDPNGgTlJlvXY0EHHnT87wF3OA=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw2QV3YD/fRrzEDPNGgTlJlvXY0EHHnT87wF3OA=
|
||||||
|
|
@ -329,8 +323,8 @@ github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1 h1:JSw0nmjMrgBmoM2aQsa78LTpI5BnuD9+vOiEQ4Qo0qw=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1 h1:JSw0nmjMrgBmoM2aQsa78LTpI5BnuD9+vOiEQ4Qo0qw=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230131183213-122f1e0e3fa1/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230111184901-61850f0e63cb h1:2L+ltfNKab56FoBBqAvbBLjoAbxwwoZie+B8d+Mp3JI=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230111184901-61850f0e63cb/go.mod h1:F3GHppRuHCTDeoOmmgjZMeJdbql91+RSGGsATWfC7oc=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4=
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
|
@ -424,6 +418,14 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
|
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||||
|
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||||
|
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||||
|
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||||
|
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||||
|
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY=
|
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
|
@ -517,13 +519,13 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 h1:QfTh0HpN6hlw6D3vu8DAwC8pBIwikq0AI1evdm+FksE=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
|
||||||
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
|
@ -583,8 +585,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
|
@ -656,12 +658,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
@ -669,9 +671,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: dendrite
|
name: dendrite
|
||||||
version: "0.11.1"
|
version: "0.11.1"
|
||||||
appVersion: "0.11.0"
|
appVersion: "0.11.1"
|
||||||
description: Dendrite Matrix Homeserver
|
description: Dendrite Matrix Homeserver
|
||||||
type: application
|
type: application
|
||||||
keywords:
|
keywords:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# dendrite
|
# dendrite
|
||||||
|
|
||||||
  
|
  
|
||||||
Dendrite Matrix Homeserver
|
Dendrite Matrix Homeserver
|
||||||
|
|
||||||
Status: **NOT PRODUCTION READY**
|
Status: **NOT PRODUCTION READY**
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package httputil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostJSON performs a POST request with JSON on an internal HTTP API.
|
|
||||||
// The error will match the errtype if returned from the remote API, or
|
|
||||||
// will be a different type if there was a problem reaching the API.
|
|
||||||
func PostJSON[reqtype, restype any, errtype error](
|
|
||||||
ctx context.Context, span opentracing.Span, httpClient *http.Client,
|
|
||||||
apiURL string, request *reqtype, response *restype,
|
|
||||||
) error {
|
|
||||||
jsonBytes, err := json.Marshal(request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedAPIURL, err := url.Parse(apiURL)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedAPIURL.Path = InternalPathPrefix + strings.TrimLeft(parsedAPIURL.Path, "/")
|
|
||||||
apiURL = parsedAPIURL.String()
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(jsonBytes))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the span as being an RPC client.
|
|
||||||
ext.SpanKindRPCClient.Set(span)
|
|
||||||
carrier := opentracing.HTTPHeadersCarrier(req.Header)
|
|
||||||
tracer := opentracing.GlobalTracer()
|
|
||||||
|
|
||||||
if err = tracer.Inject(span.Context(), opentracing.HTTPHeaders, carrier); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
res, err := httpClient.Do(req.WithContext(ctx))
|
|
||||||
if res != nil {
|
|
||||||
defer (func() { err = res.Body.Close() })()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var body []byte
|
|
||||||
body, err = io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
if len(body) == 0 {
|
|
||||||
return fmt.Errorf("HTTP %d from %s (no response body)", res.StatusCode, apiURL)
|
|
||||||
}
|
|
||||||
var reserr errtype
|
|
||||||
if err = json.Unmarshal(body, &reserr); err != nil {
|
|
||||||
return fmt.Errorf("HTTP %d from %s - %w", res.StatusCode, apiURL, err)
|
|
||||||
}
|
|
||||||
return reserr
|
|
||||||
}
|
|
||||||
if err = json.Unmarshal(body, response); err != nil {
|
|
||||||
return fmt.Errorf("json.Unmarshal: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package httputil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/matrix-org/util"
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type InternalAPIError struct {
|
|
||||||
Type string
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InternalAPIError) Error() string {
|
|
||||||
return fmt.Sprintf("internal API returned %q error: %s", e.Type, e.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeInternalRPCAPI[reqtype, restype any](metricsName string, enableMetrics bool, f func(context.Context, *reqtype, *restype) error) http.Handler {
|
|
||||||
return MakeInternalAPI(metricsName, enableMetrics, func(req *http.Request) util.JSONResponse {
|
|
||||||
var request reqtype
|
|
||||||
var response restype
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
|
||||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
if err := f(req.Context(), &request, &response); err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
JSON: &InternalAPIError{
|
|
||||||
Type: reflect.TypeOf(err).String(),
|
|
||||||
Message: fmt.Sprintf("%s", err),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusOK,
|
|
||||||
JSON: &response,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeInternalProxyAPI[reqtype, restype any](metricsName string, enableMetrics bool, f func(context.Context, *reqtype) (*restype, error)) http.Handler {
|
|
||||||
return MakeInternalAPI(metricsName, enableMetrics, func(req *http.Request) util.JSONResponse {
|
|
||||||
var request reqtype
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
|
||||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
response, err := f(req.Context(), &request)
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
JSON: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusOK,
|
|
||||||
JSON: response,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func CallInternalRPCAPI[reqtype, restype any](name, url string, client *http.Client, ctx context.Context, request *reqtype, response *restype) error {
|
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, name)
|
|
||||||
defer span.Finish()
|
|
||||||
|
|
||||||
return PostJSON[reqtype, restype, InternalAPIError](ctx, span, client, url, request, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CallInternalProxyAPI[reqtype, restype any, errtype error](name, url string, client *http.Client, ctx context.Context, request *reqtype) (restype, error) {
|
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, name)
|
|
||||||
defer span.Finish()
|
|
||||||
|
|
||||||
var response restype
|
|
||||||
return response, PostJSON[reqtype, restype, errtype](ctx, span, client, url, request, &response)
|
|
||||||
}
|
|
||||||
|
|
@ -21,7 +21,6 @@ const (
|
||||||
PublicMediaPathPrefix = "/_matrix/media/"
|
PublicMediaPathPrefix = "/_matrix/media/"
|
||||||
PublicStaticPath = "/_matrix/static/"
|
PublicStaticPath = "/_matrix/static/"
|
||||||
PublicWellKnownPrefix = "/.well-known/matrix/"
|
PublicWellKnownPrefix = "/.well-known/matrix/"
|
||||||
InternalPathPrefix = "/api/"
|
|
||||||
DendriteAdminPathPrefix = "/_dendrite/"
|
DendriteAdminPathPrefix = "/_dendrite/"
|
||||||
SynapseAdminPathPrefix = "/_synapse/"
|
SynapseAdminPathPrefix = "/_synapse/"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,9 @@ func checkFileHookParams(params map[string]interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new FSHook to the logger. Each component will log in its own file
|
// Add a new FSHook to the logger. Each component will log in its own file
|
||||||
func setupFileHook(hook config.LogrusHook, level logrus.Level, componentName string) {
|
func setupFileHook(hook config.LogrusHook, level logrus.Level) {
|
||||||
dirPath := (hook.Params["path"]).(string)
|
dirPath := (hook.Params["path"]).(string)
|
||||||
fullPath := filepath.Join(dirPath, componentName+".log")
|
fullPath := filepath.Join(dirPath, "dendrite.log")
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Dir(fullPath), os.ModePerm); err != nil {
|
if err := os.MkdirAll(path.Dir(fullPath), os.ModePerm); err != nil {
|
||||||
logrus.Fatalf("Couldn't create directory %s: %q", path.Dir(fullPath), err)
|
logrus.Fatalf("Couldn't create directory %s: %q", path.Dir(fullPath), err)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import (
|
||||||
// SetupHookLogging configures the logging hooks defined in the configuration.
|
// SetupHookLogging configures the logging hooks defined in the configuration.
|
||||||
// If something fails here it means that the logging was improperly configured,
|
// If something fails here it means that the logging was improperly configured,
|
||||||
// so we just exit with the error
|
// so we just exit with the error
|
||||||
func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
|
func SetupHookLogging(hooks []config.LogrusHook) {
|
||||||
levelLogAddedMu.Lock()
|
levelLogAddedMu.Lock()
|
||||||
defer levelLogAddedMu.Unlock()
|
defer levelLogAddedMu.Unlock()
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
|
|
@ -50,10 +50,10 @@ func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
|
||||||
switch hook.Type {
|
switch hook.Type {
|
||||||
case "file":
|
case "file":
|
||||||
checkFileHookParams(hook.Params)
|
checkFileHookParams(hook.Params)
|
||||||
setupFileHook(hook, level, componentName)
|
setupFileHook(hook, level)
|
||||||
case "syslog":
|
case "syslog":
|
||||||
checkSyslogHookParams(hook.Params)
|
checkSyslogHookParams(hook.Params)
|
||||||
setupSyslogHook(hook, level, componentName)
|
setupSyslogHook(hook, level)
|
||||||
case "std":
|
case "std":
|
||||||
setupStdLogHook(level)
|
setupStdLogHook(level)
|
||||||
default:
|
default:
|
||||||
|
|
@ -94,8 +94,8 @@ func setupStdLogHook(level logrus.Level) {
|
||||||
stdLevelLogAdded[level] = true
|
stdLevelLogAdded[level] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupSyslogHook(hook config.LogrusHook, level logrus.Level, componentName string) {
|
func setupSyslogHook(hook config.LogrusHook, level logrus.Level) {
|
||||||
syslogHook, err := lSyslog.NewSyslogHook(hook.Params["protocol"].(string), hook.Params["address"].(string), syslog.LOG_INFO, componentName)
|
syslogHook, err := lSyslog.NewSyslogHook(hook.Params["protocol"].(string), hook.Params["address"].(string), syslog.LOG_INFO, "dendrite")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.AddHook(&logLevelHook{level, syslogHook})
|
logrus.AddHook(&logLevelHook{level, syslogHook})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import (
|
||||||
// SetupHookLogging configures the logging hooks defined in the configuration.
|
// SetupHookLogging configures the logging hooks defined in the configuration.
|
||||||
// If something fails here it means that the logging was improperly configured,
|
// If something fails here it means that the logging was improperly configured,
|
||||||
// so we just exit with the error
|
// so we just exit with the error
|
||||||
func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
|
func SetupHookLogging(hooks []config.LogrusHook) {
|
||||||
logrus.SetReportCaller(true)
|
logrus.SetReportCaller(true)
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
// Check we received a proper logging level
|
// Check we received a proper logging level
|
||||||
|
|
@ -40,7 +40,7 @@ func SetupHookLogging(hooks []config.LogrusHook, componentName string) {
|
||||||
switch hook.Type {
|
switch hook.Type {
|
||||||
case "file":
|
case "file":
|
||||||
checkFileHookParams(hook.Params)
|
checkFileHookParams(hook.Params)
|
||||||
setupFileHook(hook, level, componentName)
|
setupFileHook(hook, level)
|
||||||
default:
|
default:
|
||||||
logrus.Fatalf("Unrecognised logging hook type: %s", hook.Type)
|
logrus.Fatalf("Unrecognised logging hook type: %s", hook.Type)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
"github.com/matrix-org/dendrite/federationapi/types"
|
"github.com/matrix-org/dendrite/federationapi/types"
|
||||||
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
syncTypes "github.com/matrix-org/dendrite/syncapi/types"
|
syncTypes "github.com/matrix-org/dendrite/syncapi/types"
|
||||||
|
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
@ -56,7 +56,7 @@ var (
|
||||||
type TxnReq struct {
|
type TxnReq struct {
|
||||||
gomatrixserverlib.Transaction
|
gomatrixserverlib.Transaction
|
||||||
rsAPI api.FederationRoomserverAPI
|
rsAPI api.FederationRoomserverAPI
|
||||||
keyAPI keyapi.FederationKeyAPI
|
userAPI userAPI.FederationUserAPI
|
||||||
ourServerName gomatrixserverlib.ServerName
|
ourServerName gomatrixserverlib.ServerName
|
||||||
keys gomatrixserverlib.JSONVerifier
|
keys gomatrixserverlib.JSONVerifier
|
||||||
roomsMu *MutexByRoom
|
roomsMu *MutexByRoom
|
||||||
|
|
@ -66,7 +66,7 @@ type TxnReq struct {
|
||||||
|
|
||||||
func NewTxnReq(
|
func NewTxnReq(
|
||||||
rsAPI api.FederationRoomserverAPI,
|
rsAPI api.FederationRoomserverAPI,
|
||||||
keyAPI keyapi.FederationKeyAPI,
|
userAPI userAPI.FederationUserAPI,
|
||||||
ourServerName gomatrixserverlib.ServerName,
|
ourServerName gomatrixserverlib.ServerName,
|
||||||
keys gomatrixserverlib.JSONVerifier,
|
keys gomatrixserverlib.JSONVerifier,
|
||||||
roomsMu *MutexByRoom,
|
roomsMu *MutexByRoom,
|
||||||
|
|
@ -80,7 +80,7 @@ func NewTxnReq(
|
||||||
) TxnReq {
|
) TxnReq {
|
||||||
t := TxnReq{
|
t := TxnReq{
|
||||||
rsAPI: rsAPI,
|
rsAPI: rsAPI,
|
||||||
keyAPI: keyAPI,
|
userAPI: userAPI,
|
||||||
ourServerName: ourServerName,
|
ourServerName: ourServerName,
|
||||||
keys: keys,
|
keys: keys,
|
||||||
roomsMu: roomsMu,
|
roomsMu: roomsMu,
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/federationapi/producers"
|
"github.com/matrix-org/dendrite/federationapi/producers"
|
||||||
keyAPI "github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
rsAPI "github.com/matrix-org/dendrite/roomserver/api"
|
rsAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||||
"github.com/matrix-org/dendrite/setup/process"
|
"github.com/matrix-org/dendrite/setup/process"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
|
keyAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -198,8 +198,8 @@ func TestProcessTransactionRequestPDUSendFail(t *testing.T) {
|
||||||
func createTransactionWithEDU(ctx *process.ProcessContext, edus []gomatrixserverlib.EDU) (TxnReq, nats.JetStreamContext, *config.Dendrite) {
|
func createTransactionWithEDU(ctx *process.ProcessContext, edus []gomatrixserverlib.EDU) (TxnReq, nats.JetStreamContext, *config.Dendrite) {
|
||||||
cfg := &config.Dendrite{}
|
cfg := &config.Dendrite{}
|
||||||
cfg.Defaults(config.DefaultOpts{
|
cfg.Defaults(config.DefaultOpts{
|
||||||
Generate: true,
|
Generate: true,
|
||||||
Monolithic: true,
|
SingleDatabase: true,
|
||||||
})
|
})
|
||||||
cfg.Global.JetStream.InMemory = true
|
cfg.Global.JetStream.InMemory = true
|
||||||
natsInstance := &jetstream.NATSInstance{}
|
natsInstance := &jetstream.NATSInstance{}
|
||||||
|
|
@ -647,7 +647,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testRoomserverAPI struct {
|
type testRoomserverAPI struct {
|
||||||
rsAPI.RoomserverInternalAPITrace
|
rsAPI.RoomserverInternalAPI
|
||||||
inputRoomEvents []rsAPI.InputRoomEvent
|
inputRoomEvents []rsAPI.InputRoomEvent
|
||||||
queryStateAfterEvents func(*rsAPI.QueryStateAfterEventsRequest) rsAPI.QueryStateAfterEventsResponse
|
queryStateAfterEvents func(*rsAPI.QueryStateAfterEventsRequest) rsAPI.QueryStateAfterEventsResponse
|
||||||
queryEventsByID func(req *rsAPI.QueryEventsByIDRequest) rsAPI.QueryEventsByIDResponse
|
queryEventsByID func(req *rsAPI.QueryEventsByIDRequest) rsAPI.QueryEventsByIDResponse
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ var build string
|
||||||
const (
|
const (
|
||||||
VersionMajor = 0
|
VersionMajor = 0
|
||||||
VersionMinor = 11
|
VersionMinor = 11
|
||||||
VersionPatch = 0
|
VersionPatch = 1
|
||||||
VersionTag = "" // example: "rc1"
|
VersionTag = "" // example: "rc1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
## Key Server
|
|
||||||
|
|
||||||
This is an internal component which manages E2E keys from clients. It handles all the [Key Management APIs](https://matrix.org/docs/spec/client_server/r0.6.1#key-management-api) with the exception of `/keys/changes` which is handled by Sync API. This component is designed to shard by user ID.
|
|
||||||
|
|
||||||
Keys are uploaded and stored in this component, and key changes are emitted to a Kafka topic for downstream components such as Sync API.
|
|
||||||
|
|
||||||
### Internal APIs
|
|
||||||
- `PerformUploadKeys` stores identity keys and one-time public keys for given user(s).
|
|
||||||
- `PerformClaimKeys` acquires one-time public keys for given user(s). This may involve outbound federation calls.
|
|
||||||
- `QueryKeys` returns identity keys for given user(s). This may involve outbound federation calls. This component may then cache federated identity keys to avoid repeatedly hitting remote servers.
|
|
||||||
- A topic which emits identity keys every time there is a change (addition or deletion).
|
|
||||||
|
|
||||||
### Endpoint mappings
|
|
||||||
- Client API maps `/keys/upload` to `PerformUploadKeys`.
|
|
||||||
- Client API maps `/keys/query` to `QueryKeys`.
|
|
||||||
- Client API maps `/keys/claim` to `PerformClaimKeys`.
|
|
||||||
- Federation API maps `/user/keys/query` to `QueryKeys`.
|
|
||||||
- Federation API maps `/user/keys/claim` to `PerformClaimKeys`.
|
|
||||||
- Sync API maps `/keys/changes` to consuming from the Kafka topic.
|
|
||||||
|
|
@ -1,346 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/types"
|
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KeyInternalAPI interface {
|
|
||||||
SyncKeyAPI
|
|
||||||
ClientKeyAPI
|
|
||||||
FederationKeyAPI
|
|
||||||
UserKeyAPI
|
|
||||||
|
|
||||||
// SetUserAPI assigns a user API to query when extracting device names.
|
|
||||||
SetUserAPI(i userapi.KeyserverUserAPI)
|
|
||||||
}
|
|
||||||
|
|
||||||
// API functions required by the clientapi
|
|
||||||
type ClientKeyAPI interface {
|
|
||||||
QueryKeys(ctx context.Context, req *QueryKeysRequest, res *QueryKeysResponse) error
|
|
||||||
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse) error
|
|
||||||
PerformUploadDeviceKeys(ctx context.Context, req *PerformUploadDeviceKeysRequest, res *PerformUploadDeviceKeysResponse) error
|
|
||||||
PerformUploadDeviceSignatures(ctx context.Context, req *PerformUploadDeviceSignaturesRequest, res *PerformUploadDeviceSignaturesResponse) error
|
|
||||||
// PerformClaimKeys claims one-time keys for use in pre-key messages
|
|
||||||
PerformClaimKeys(ctx context.Context, req *PerformClaimKeysRequest, res *PerformClaimKeysResponse) error
|
|
||||||
PerformMarkAsStaleIfNeeded(ctx context.Context, req *PerformMarkAsStaleRequest, res *struct{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// API functions required by the userapi
|
|
||||||
type UserKeyAPI interface {
|
|
||||||
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse) error
|
|
||||||
PerformDeleteKeys(ctx context.Context, req *PerformDeleteKeysRequest, res *PerformDeleteKeysResponse) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// API functions required by the syncapi
|
|
||||||
type SyncKeyAPI interface {
|
|
||||||
QueryKeyChanges(ctx context.Context, req *QueryKeyChangesRequest, res *QueryKeyChangesResponse) error
|
|
||||||
QueryOneTimeKeys(ctx context.Context, req *QueryOneTimeKeysRequest, res *QueryOneTimeKeysResponse) error
|
|
||||||
PerformMarkAsStaleIfNeeded(ctx context.Context, req *PerformMarkAsStaleRequest, res *struct{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type FederationKeyAPI interface {
|
|
||||||
QueryKeys(ctx context.Context, req *QueryKeysRequest, res *QueryKeysResponse) error
|
|
||||||
QuerySignatures(ctx context.Context, req *QuerySignaturesRequest, res *QuerySignaturesResponse) error
|
|
||||||
QueryDeviceMessages(ctx context.Context, req *QueryDeviceMessagesRequest, res *QueryDeviceMessagesResponse) error
|
|
||||||
PerformUploadDeviceKeys(ctx context.Context, req *PerformUploadDeviceKeysRequest, res *PerformUploadDeviceKeysResponse) error
|
|
||||||
PerformClaimKeys(ctx context.Context, req *PerformClaimKeysRequest, res *PerformClaimKeysResponse) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyError is returned if there was a problem performing/querying the server
|
|
||||||
type KeyError struct {
|
|
||||||
Err string `json:"error"`
|
|
||||||
IsInvalidSignature bool `json:"is_invalid_signature,omitempty"` // M_INVALID_SIGNATURE
|
|
||||||
IsMissingParam bool `json:"is_missing_param,omitempty"` // M_MISSING_PARAM
|
|
||||||
IsInvalidParam bool `json:"is_invalid_param,omitempty"` // M_INVALID_PARAM
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyError) Error() string {
|
|
||||||
return k.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeviceMessageType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
TypeDeviceKeyUpdate DeviceMessageType = iota
|
|
||||||
TypeCrossSigningUpdate
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeviceMessage represents the message produced into Kafka by the key server.
|
|
||||||
type DeviceMessage struct {
|
|
||||||
Type DeviceMessageType `json:"Type,omitempty"`
|
|
||||||
*DeviceKeys `json:"DeviceKeys,omitempty"`
|
|
||||||
*OutputCrossSigningKeyUpdate `json:"CrossSigningKeyUpdate,omitempty"`
|
|
||||||
// A monotonically increasing number which represents device changes for this user.
|
|
||||||
StreamID int64
|
|
||||||
DeviceChangeID int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// OutputCrossSigningKeyUpdate is an entry in the signing key update output kafka log
|
|
||||||
type OutputCrossSigningKeyUpdate struct {
|
|
||||||
CrossSigningKeyUpdate `json:"signing_keys"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CrossSigningKeyUpdate struct {
|
|
||||||
MasterKey *gomatrixserverlib.CrossSigningKey `json:"master_key,omitempty"`
|
|
||||||
SelfSigningKey *gomatrixserverlib.CrossSigningKey `json:"self_signing_key,omitempty"`
|
|
||||||
UserID string `json:"user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceKeysEqual returns true if the device keys updates contain the
|
|
||||||
// same display name and key JSON. This will return false if either of
|
|
||||||
// the updates is not a device keys update, or if the user ID/device ID
|
|
||||||
// differ between the two.
|
|
||||||
func (m1 *DeviceMessage) DeviceKeysEqual(m2 *DeviceMessage) bool {
|
|
||||||
if m1.DeviceKeys == nil || m2.DeviceKeys == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if m1.UserID != m2.UserID || m1.DeviceID != m2.DeviceID {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if m1.DisplayName != m2.DisplayName {
|
|
||||||
return false // different display names
|
|
||||||
}
|
|
||||||
if len(m1.KeyJSON) == 0 || len(m2.KeyJSON) == 0 {
|
|
||||||
return false // either is empty
|
|
||||||
}
|
|
||||||
return bytes.Equal(m1.KeyJSON, m2.KeyJSON)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceKeys represents a set of device keys for a single device
|
|
||||||
// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload
|
|
||||||
type DeviceKeys struct {
|
|
||||||
// The user who owns this device
|
|
||||||
UserID string
|
|
||||||
// The device ID of this device
|
|
||||||
DeviceID string
|
|
||||||
// The device display name
|
|
||||||
DisplayName string
|
|
||||||
// The raw device key JSON
|
|
||||||
KeyJSON []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithStreamID returns a copy of this device message with the given stream ID
|
|
||||||
func (k *DeviceKeys) WithStreamID(streamID int64) DeviceMessage {
|
|
||||||
return DeviceMessage{
|
|
||||||
DeviceKeys: k,
|
|
||||||
StreamID: streamID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OneTimeKeys represents a set of one-time keys for a single device
|
|
||||||
// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload
|
|
||||||
type OneTimeKeys struct {
|
|
||||||
// The user who owns this device
|
|
||||||
UserID string
|
|
||||||
// The device ID of this device
|
|
||||||
DeviceID string
|
|
||||||
// A map of algorithm:key_id => key JSON
|
|
||||||
KeyJSON map[string]json.RawMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split a key in KeyJSON into algorithm and key ID
|
|
||||||
func (k *OneTimeKeys) Split(keyIDWithAlgo string) (algo string, keyID string) {
|
|
||||||
segments := strings.Split(keyIDWithAlgo, ":")
|
|
||||||
return segments[0], segments[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// OneTimeKeysCount represents the counts of one-time keys for a single device
|
|
||||||
type OneTimeKeysCount struct {
|
|
||||||
// The user who owns this device
|
|
||||||
UserID string
|
|
||||||
// The device ID of this device
|
|
||||||
DeviceID string
|
|
||||||
// algorithm to count e.g:
|
|
||||||
// {
|
|
||||||
// "curve25519": 10,
|
|
||||||
// "signed_curve25519": 20
|
|
||||||
// }
|
|
||||||
KeyCount map[string]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// PerformUploadKeysRequest is the request to PerformUploadKeys
|
|
||||||
type PerformUploadKeysRequest struct {
|
|
||||||
UserID string // Required - User performing the request
|
|
||||||
DeviceID string // Optional - Device performing the request, for fetching OTK count
|
|
||||||
DeviceKeys []DeviceKeys
|
|
||||||
OneTimeKeys []OneTimeKeys
|
|
||||||
// OnlyDisplayNameUpdates should be `true` if ALL the DeviceKeys are present to update
|
|
||||||
// the display name for their respective device, and NOT to modify the keys. The key
|
|
||||||
// itself doesn't change but it's easier to pretend upload new keys and reuse the same code paths.
|
|
||||||
// Without this flag, requests to modify device display names would delete device keys.
|
|
||||||
OnlyDisplayNameUpdates bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// PerformUploadKeysResponse is the response to PerformUploadKeys
|
|
||||||
type PerformUploadKeysResponse struct {
|
|
||||||
// A fatal error when processing e.g database failures
|
|
||||||
Error *KeyError
|
|
||||||
// A map of user_id -> device_id -> Error for tracking failures.
|
|
||||||
KeyErrors map[string]map[string]*KeyError
|
|
||||||
OneTimeKeyCounts []OneTimeKeysCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// PerformDeleteKeysRequest asks the keyserver to forget about certain
|
|
||||||
// keys, and signatures related to those keys.
|
|
||||||
type PerformDeleteKeysRequest struct {
|
|
||||||
UserID string
|
|
||||||
KeyIDs []gomatrixserverlib.KeyID
|
|
||||||
}
|
|
||||||
|
|
||||||
// PerformDeleteKeysResponse is the response to PerformDeleteKeysRequest.
|
|
||||||
type PerformDeleteKeysResponse struct {
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyError sets a key error field on KeyErrors
|
|
||||||
func (r *PerformUploadKeysResponse) KeyError(userID, deviceID string, err *KeyError) {
|
|
||||||
if r.KeyErrors[userID] == nil {
|
|
||||||
r.KeyErrors[userID] = make(map[string]*KeyError)
|
|
||||||
}
|
|
||||||
r.KeyErrors[userID][deviceID] = err
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformClaimKeysRequest struct {
|
|
||||||
// Map of user_id to device_id to algorithm name
|
|
||||||
OneTimeKeys map[string]map[string]string
|
|
||||||
Timeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformClaimKeysResponse struct {
|
|
||||||
// Map of user_id to device_id to algorithm:key_id to key JSON
|
|
||||||
OneTimeKeys map[string]map[string]map[string]json.RawMessage
|
|
||||||
// Map of remote server domain to error JSON
|
|
||||||
Failures map[string]interface{}
|
|
||||||
// Set if there was a fatal error processing this action
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformUploadDeviceKeysRequest struct {
|
|
||||||
gomatrixserverlib.CrossSigningKeys
|
|
||||||
// The user that uploaded the key, should be populated by the clientapi.
|
|
||||||
UserID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformUploadDeviceKeysResponse struct {
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformUploadDeviceSignaturesRequest struct {
|
|
||||||
Signatures map[string]map[gomatrixserverlib.KeyID]gomatrixserverlib.CrossSigningForKeyOrDevice
|
|
||||||
// The user that uploaded the sig, should be populated by the clientapi.
|
|
||||||
UserID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformUploadDeviceSignaturesResponse struct {
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryKeysRequest struct {
|
|
||||||
// The user ID asking for the keys, e.g. if from a client API request.
|
|
||||||
// Will not be populated if the key request came from federation.
|
|
||||||
UserID string
|
|
||||||
// Maps user IDs to a list of devices
|
|
||||||
UserToDevices map[string][]string
|
|
||||||
Timeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryKeysResponse struct {
|
|
||||||
// Map of remote server domain to error JSON
|
|
||||||
Failures map[string]interface{}
|
|
||||||
// Map of user_id to device_id to device_key
|
|
||||||
DeviceKeys map[string]map[string]json.RawMessage
|
|
||||||
// Maps of user_id to cross signing key
|
|
||||||
MasterKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
SelfSigningKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
UserSigningKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
// Set if there was a fatal error processing this query
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryKeyChangesRequest struct {
|
|
||||||
// The offset of the last received key event, or sarama.OffsetOldest if this is from the beginning
|
|
||||||
Offset int64
|
|
||||||
// The inclusive offset where to track key changes up to. Messages with this offset are included in the response.
|
|
||||||
// Use types.OffsetNewest if the offset is unknown (then check the response Offset to avoid racing).
|
|
||||||
ToOffset int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryKeyChangesResponse struct {
|
|
||||||
// The set of users who have had their keys change.
|
|
||||||
UserIDs []string
|
|
||||||
// The latest offset represented in this response.
|
|
||||||
Offset int64
|
|
||||||
// Set if there was a problem handling the request.
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryOneTimeKeysRequest struct {
|
|
||||||
// The local user to query OTK counts for
|
|
||||||
UserID string
|
|
||||||
// The device to query OTK counts for
|
|
||||||
DeviceID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryOneTimeKeysResponse struct {
|
|
||||||
// OTK key counts, in the extended /sync form described by https://matrix.org/docs/spec/client_server/r0.6.1#id84
|
|
||||||
Count OneTimeKeysCount
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryDeviceMessagesRequest struct {
|
|
||||||
UserID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryDeviceMessagesResponse struct {
|
|
||||||
// The latest stream ID
|
|
||||||
StreamID int64
|
|
||||||
Devices []DeviceMessage
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type QuerySignaturesRequest struct {
|
|
||||||
// A map of target user ID -> target key/device IDs to retrieve signatures for
|
|
||||||
TargetIDs map[string][]gomatrixserverlib.KeyID `json:"target_ids"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type QuerySignaturesResponse struct {
|
|
||||||
// A map of target user ID -> target key/device ID -> origin user ID -> origin key/device ID -> signatures
|
|
||||||
Signatures map[string]map[gomatrixserverlib.KeyID]types.CrossSigningSigMap
|
|
||||||
// A map of target user ID -> cross-signing master key
|
|
||||||
MasterKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
// A map of target user ID -> cross-signing self-signing key
|
|
||||||
SelfSigningKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
// A map of target user ID -> cross-signing user-signing key
|
|
||||||
UserSigningKeys map[string]gomatrixserverlib.CrossSigningKey
|
|
||||||
// The request error, if any
|
|
||||||
Error *KeyError
|
|
||||||
}
|
|
||||||
|
|
||||||
type PerformMarkAsStaleRequest struct {
|
|
||||||
UserID string
|
|
||||||
Domain gomatrixserverlib.ServerName
|
|
||||||
DeviceID string
|
|
||||||
}
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP paths for the internal HTTP APIs
|
|
||||||
const (
|
|
||||||
InputDeviceListUpdatePath = "/keyserver/inputDeviceListUpdate"
|
|
||||||
PerformUploadKeysPath = "/keyserver/performUploadKeys"
|
|
||||||
PerformClaimKeysPath = "/keyserver/performClaimKeys"
|
|
||||||
PerformDeleteKeysPath = "/keyserver/performDeleteKeys"
|
|
||||||
PerformUploadDeviceKeysPath = "/keyserver/performUploadDeviceKeys"
|
|
||||||
PerformUploadDeviceSignaturesPath = "/keyserver/performUploadDeviceSignatures"
|
|
||||||
QueryKeysPath = "/keyserver/queryKeys"
|
|
||||||
QueryKeyChangesPath = "/keyserver/queryKeyChanges"
|
|
||||||
QueryOneTimeKeysPath = "/keyserver/queryOneTimeKeys"
|
|
||||||
QueryDeviceMessagesPath = "/keyserver/queryDeviceMessages"
|
|
||||||
QuerySignaturesPath = "/keyserver/querySignatures"
|
|
||||||
PerformMarkAsStalePath = "/keyserver/markAsStale"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewKeyServerClient creates a KeyInternalAPI implemented by talking to a HTTP POST API.
|
|
||||||
// If httpClient is nil an error is returned
|
|
||||||
func NewKeyServerClient(
|
|
||||||
apiURL string,
|
|
||||||
httpClient *http.Client,
|
|
||||||
) (api.KeyInternalAPI, error) {
|
|
||||||
if httpClient == nil {
|
|
||||||
return nil, errors.New("NewKeyServerClient: httpClient is <nil>")
|
|
||||||
}
|
|
||||||
return &httpKeyInternalAPI{
|
|
||||||
apiURL: apiURL,
|
|
||||||
httpClient: httpClient,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type httpKeyInternalAPI struct {
|
|
||||||
apiURL string
|
|
||||||
httpClient *http.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) SetUserAPI(i userapi.KeyserverUserAPI) {
|
|
||||||
// no-op: doesn't need it
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformClaimKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformClaimKeysRequest,
|
|
||||||
response *api.PerformClaimKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformClaimKeys", h.apiURL+PerformClaimKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformDeleteKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformDeleteKeysRequest,
|
|
||||||
response *api.PerformDeleteKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformDeleteKeys", h.apiURL+PerformDeleteKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformUploadKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformUploadKeysRequest,
|
|
||||||
response *api.PerformUploadKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformUploadKeys", h.apiURL+PerformUploadKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) QueryKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryKeysRequest,
|
|
||||||
response *api.QueryKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryKeys", h.apiURL+QueryKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) QueryOneTimeKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryOneTimeKeysRequest,
|
|
||||||
response *api.QueryOneTimeKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryOneTimeKeys", h.apiURL+QueryOneTimeKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) QueryDeviceMessages(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryDeviceMessagesRequest,
|
|
||||||
response *api.QueryDeviceMessagesResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryDeviceMessages", h.apiURL+QueryDeviceMessagesPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) QueryKeyChanges(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QueryKeyChangesRequest,
|
|
||||||
response *api.QueryKeyChangesResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QueryKeyChanges", h.apiURL+QueryKeyChangesPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformUploadDeviceKeys(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformUploadDeviceKeysRequest,
|
|
||||||
response *api.PerformUploadDeviceKeysResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformUploadDeviceKeys", h.apiURL+PerformUploadDeviceKeysPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformUploadDeviceSignatures(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformUploadDeviceSignaturesRequest,
|
|
||||||
response *api.PerformUploadDeviceSignaturesResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"PerformUploadDeviceSignatures", h.apiURL+PerformUploadDeviceSignaturesPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) QuerySignatures(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.QuerySignaturesRequest,
|
|
||||||
response *api.QuerySignaturesResponse,
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"QuerySignatures", h.apiURL+QuerySignaturesPath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformMarkAsStaleIfNeeded(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.PerformMarkAsStaleRequest,
|
|
||||||
response *struct{},
|
|
||||||
) error {
|
|
||||||
return httputil.CallInternalRPCAPI(
|
|
||||||
"MarkAsStale", h.apiURL+PerformMarkAsStalePath,
|
|
||||||
h.httpClient, ctx, request, response,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package inthttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AddRoutes(internalAPIMux *mux.Router, s api.KeyInternalAPI, enableMetrics bool) {
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformClaimKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverPerformClaimKeys", enableMetrics, s.PerformClaimKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformDeleteKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverPerformDeleteKeys", enableMetrics, s.PerformDeleteKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformUploadKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverPerformUploadKeys", enableMetrics, s.PerformUploadKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformUploadDeviceKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverPerformUploadDeviceKeys", enableMetrics, s.PerformUploadDeviceKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformUploadDeviceSignaturesPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverPerformUploadDeviceSignatures", enableMetrics, s.PerformUploadDeviceSignatures),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
QueryKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverQueryKeys", enableMetrics, s.QueryKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
QueryOneTimeKeysPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverQueryOneTimeKeys", enableMetrics, s.QueryOneTimeKeys),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
QueryDeviceMessagesPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverQueryDeviceMessages", enableMetrics, s.QueryDeviceMessages),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
QueryKeyChangesPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverQueryKeyChanges", enableMetrics, s.QueryKeyChanges),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
QuerySignaturesPath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverQuerySignatures", enableMetrics, s.QuerySignatures),
|
|
||||||
)
|
|
||||||
|
|
||||||
internalAPIMux.Handle(
|
|
||||||
PerformMarkAsStalePath,
|
|
||||||
httputil.MakeInternalRPCAPI("KeyserverMarkAsStale", enableMetrics, s.PerformMarkAsStaleIfNeeded),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package keyserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
rsapi "github.com/matrix-org/dendrite/roomserver/api"
|
|
||||||
|
|
||||||
fedsenderapi "github.com/matrix-org/dendrite/federationapi/api"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/consumers"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/internal"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/inthttp"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/producers"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddInternalRoutes registers HTTP handlers for the internal API. Invokes functions
|
|
||||||
// on the given input API.
|
|
||||||
func AddInternalRoutes(router *mux.Router, intAPI api.KeyInternalAPI, enableMetrics bool) {
|
|
||||||
inthttp.AddRoutes(router, intAPI, enableMetrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
|
||||||
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
|
||||||
func NewInternalAPI(
|
|
||||||
base *base.BaseDendrite, cfg *config.KeyServer, fedClient fedsenderapi.KeyserverFederationAPI,
|
|
||||||
rsAPI rsapi.KeyserverRoomserverAPI,
|
|
||||||
) api.KeyInternalAPI {
|
|
||||||
js, _ := base.NATS.Prepare(base.ProcessContext, &cfg.Matrix.JetStream)
|
|
||||||
|
|
||||||
db, err := storage.NewDatabase(base, &cfg.Database)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Panicf("failed to connect to key server database")
|
|
||||||
}
|
|
||||||
|
|
||||||
keyChangeProducer := &producers.KeyChange{
|
|
||||||
Topic: string(cfg.Matrix.JetStream.Prefixed(jetstream.OutputKeyChangeEvent)),
|
|
||||||
JetStream: js,
|
|
||||||
DB: db,
|
|
||||||
}
|
|
||||||
ap := &internal.KeyInternalAPI{
|
|
||||||
DB: db,
|
|
||||||
Cfg: cfg,
|
|
||||||
FedClient: fedClient,
|
|
||||||
Producer: keyChangeProducer,
|
|
||||||
}
|
|
||||||
updater := internal.NewDeviceListUpdater(base.ProcessContext, db, ap, keyChangeProducer, fedClient, 8, rsAPI, cfg.Matrix.ServerName) // 8 workers TODO: configurable
|
|
||||||
ap.Updater = updater
|
|
||||||
|
|
||||||
// Remove users which we don't share a room with anymore
|
|
||||||
if err := updater.CleanUp(); err != nil {
|
|
||||||
logrus.WithError(err).Error("failed to cleanup stale device lists")
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if err := updater.Start(); err != nil {
|
|
||||||
logrus.WithError(err).Panicf("failed to start device list updater")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
dlConsumer := consumers.NewDeviceListUpdateConsumer(
|
|
||||||
base.ProcessContext, cfg, js, updater,
|
|
||||||
)
|
|
||||||
if err := dlConsumer.Start(); err != nil {
|
|
||||||
logrus.WithError(err).Panic("failed to start device list consumer")
|
|
||||||
}
|
|
||||||
|
|
||||||
sigConsumer := consumers.NewSigningKeyUpdateConsumer(
|
|
||||||
base.ProcessContext, cfg, js, ap,
|
|
||||||
)
|
|
||||||
if err := sigConsumer.Start(); err != nil {
|
|
||||||
logrus.WithError(err).Panic("failed to start signing key consumer")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ap
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
package keyserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
roomserver "github.com/matrix-org/dendrite/roomserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/test"
|
|
||||||
"github.com/matrix-org/dendrite/test/testrig"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockKeyserverRoomserverAPI struct {
|
|
||||||
leftUsers []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockKeyserverRoomserverAPI) QueryLeftUsers(ctx context.Context, req *roomserver.QueryLeftUsersRequest, res *roomserver.QueryLeftUsersResponse) error {
|
|
||||||
res.LeftUsers = m.leftUsers
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merely tests that we can create an internal keyserver API
|
|
||||||
func Test_NewInternalAPI(t *testing.T) {
|
|
||||||
rsAPI := &mockKeyserverRoomserverAPI{}
|
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
base, closeBase := testrig.CreateBaseDendrite(t, dbType)
|
|
||||||
defer closeBase()
|
|
||||||
_ = NewInternalAPI(base, &base.Cfg.KeyServer, nil, rsAPI)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/types"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Database interface {
|
|
||||||
// ExistingOneTimeKeys returns a map of keyIDWithAlgorithm to key JSON for the given parameters. If no keys exist with this combination
|
|
||||||
// of user/device/key/algorithm 4-uple then it is omitted from the map. Returns an error when failing to communicate with the database.
|
|
||||||
ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error)
|
|
||||||
|
|
||||||
// StoreOneTimeKeys persists the given one-time keys.
|
|
||||||
StoreOneTimeKeys(ctx context.Context, keys api.OneTimeKeys) (*api.OneTimeKeysCount, error)
|
|
||||||
|
|
||||||
// OneTimeKeysCount returns a count of all OTKs for this device.
|
|
||||||
OneTimeKeysCount(ctx context.Context, userID, deviceID string) (*api.OneTimeKeysCount, error)
|
|
||||||
|
|
||||||
// DeviceKeysJSON populates the KeyJSON for the given keys. If any proided `keys` have a `KeyJSON` or `StreamID` already then it will be replaced.
|
|
||||||
DeviceKeysJSON(ctx context.Context, keys []api.DeviceMessage) error
|
|
||||||
|
|
||||||
// StoreLocalDeviceKeys persists the given keys. Keys with the same user ID and device ID will be replaced. An empty KeyJSON removes the key
|
|
||||||
// for this (user, device).
|
|
||||||
// The `StreamID` for each message is set on successful insertion. In the event the key already exists, the existing StreamID is set.
|
|
||||||
// Returns an error if there was a problem storing the keys.
|
|
||||||
StoreLocalDeviceKeys(ctx context.Context, keys []api.DeviceMessage) error
|
|
||||||
|
|
||||||
// StoreRemoteDeviceKeys persists the given keys. Keys with the same user ID and device ID will be replaced. An empty KeyJSON removes the key
|
|
||||||
// for this (user, device). Does not modify the stream ID for keys. User IDs in `clearUserIDs` will have all their device keys deleted prior
|
|
||||||
// to insertion - use this when you have a complete snapshot of a user's keys in order to track device deletions correctly.
|
|
||||||
StoreRemoteDeviceKeys(ctx context.Context, keys []api.DeviceMessage, clearUserIDs []string) error
|
|
||||||
|
|
||||||
// PrevIDsExists returns true if all prev IDs exist for this user.
|
|
||||||
PrevIDsExists(ctx context.Context, userID string, prevIDs []int64) (bool, error)
|
|
||||||
|
|
||||||
// DeviceKeysForUser returns the device keys for the device IDs given. If the length of deviceIDs is 0, all devices are selected.
|
|
||||||
// If there are some missing keys, they are omitted from the returned slice. There is no ordering on the returned slice.
|
|
||||||
DeviceKeysForUser(ctx context.Context, userID string, deviceIDs []string, includeEmpty bool) ([]api.DeviceMessage, error)
|
|
||||||
|
|
||||||
// DeleteDeviceKeys removes the device keys for a given user/device, and any accompanying
|
|
||||||
// cross-signing signatures relating to that device.
|
|
||||||
DeleteDeviceKeys(ctx context.Context, userID string, deviceIDs []gomatrixserverlib.KeyID) error
|
|
||||||
|
|
||||||
// ClaimKeys based on the 3-uple of user_id, device_id and algorithm name. Returns the keys claimed. Returns no error if a key
|
|
||||||
// cannot be claimed or if none exist for this (user, device, algorithm), instead it is omitted from the returned slice.
|
|
||||||
ClaimKeys(ctx context.Context, userToDeviceToAlgorithm map[string]map[string]string) ([]api.OneTimeKeys, error)
|
|
||||||
|
|
||||||
// StoreKeyChange stores key change metadata and returns the device change ID which represents the position in the /sync stream for this device change.
|
|
||||||
// `userID` is the the user who has changed their keys in some way.
|
|
||||||
StoreKeyChange(ctx context.Context, userID string) (int64, error)
|
|
||||||
|
|
||||||
// KeyChanges returns a list of user IDs who have modified their keys from the offset given (exclusive) to the offset given (inclusive).
|
|
||||||
// A to offset of types.OffsetNewest means no upper limit.
|
|
||||||
// Returns the offset of the latest key change.
|
|
||||||
KeyChanges(ctx context.Context, fromOffset, toOffset int64) (userIDs []string, latestOffset int64, err error)
|
|
||||||
|
|
||||||
// StaleDeviceLists returns a list of user IDs ending with the domains provided who have stale device lists.
|
|
||||||
// If no domains are given, all user IDs with stale device lists are returned.
|
|
||||||
StaleDeviceLists(ctx context.Context, domains []gomatrixserverlib.ServerName) ([]string, error)
|
|
||||||
|
|
||||||
// MarkDeviceListStale sets the stale bit for this user to isStale.
|
|
||||||
MarkDeviceListStale(ctx context.Context, userID string, isStale bool) error
|
|
||||||
|
|
||||||
CrossSigningKeysForUser(ctx context.Context, userID string) (map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey, error)
|
|
||||||
CrossSigningKeysDataForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error)
|
|
||||||
CrossSigningSigsForTarget(ctx context.Context, originUserID, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error)
|
|
||||||
|
|
||||||
StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error
|
|
||||||
StoreCrossSigningSigsForTarget(ctx context.Context, originUserID string, originKeyID gomatrixserverlib.KeyID, targetUserID string, targetKeyID gomatrixserverlib.KeyID, signature gomatrixserverlib.Base64Bytes) error
|
|
||||||
|
|
||||||
DeleteStaleDeviceLists(
|
|
||||||
ctx context.Context,
|
|
||||||
userIDs []string,
|
|
||||||
) error
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package postgres
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/shared"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDatabase creates a new sync server database
|
|
||||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions) (*shared.Database, error) {
|
|
||||||
var err error
|
|
||||||
db, writer, err := base.DatabaseConnection(dbProperties, sqlutil.NewDummyWriter())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
otk, err := NewPostgresOneTimeKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dk, err := NewPostgresDeviceKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
kc, err := NewPostgresKeyChangesTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sdl, err := NewPostgresStaleDeviceListsTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
csk, err := NewPostgresCrossSigningKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
css, err := NewPostgresCrossSigningSigsTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err = kc.Prepare(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
d := &shared.Database{
|
|
||||||
DB: db,
|
|
||||||
Writer: writer,
|
|
||||||
OneTimeKeysTable: otk,
|
|
||||||
DeviceKeysTable: dk,
|
|
||||||
KeyChangesTable: kc,
|
|
||||||
StaleDeviceListsTable: sdl,
|
|
||||||
CrossSigningKeysTable: csk,
|
|
||||||
CrossSigningSigsTable: css,
|
|
||||||
}
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,261 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package shared
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/tables"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/types"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Database struct {
|
|
||||||
DB *sql.DB
|
|
||||||
Writer sqlutil.Writer
|
|
||||||
OneTimeKeysTable tables.OneTimeKeys
|
|
||||||
DeviceKeysTable tables.DeviceKeys
|
|
||||||
KeyChangesTable tables.KeyChanges
|
|
||||||
StaleDeviceListsTable tables.StaleDeviceLists
|
|
||||||
CrossSigningKeysTable tables.CrossSigningKeys
|
|
||||||
CrossSigningSigsTable tables.CrossSigningSigs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) {
|
|
||||||
return d.OneTimeKeysTable.SelectOneTimeKeys(ctx, userID, deviceID, keyIDsWithAlgorithms)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) StoreOneTimeKeys(ctx context.Context, keys api.OneTimeKeys) (counts *api.OneTimeKeysCount, err error) {
|
|
||||||
_ = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
counts, err = d.OneTimeKeysTable.InsertOneTimeKeys(ctx, txn, keys)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) OneTimeKeysCount(ctx context.Context, userID, deviceID string) (*api.OneTimeKeysCount, error) {
|
|
||||||
return d.OneTimeKeysTable.CountOneTimeKeys(ctx, userID, deviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) DeviceKeysJSON(ctx context.Context, keys []api.DeviceMessage) error {
|
|
||||||
return d.DeviceKeysTable.SelectDeviceKeysJSON(ctx, keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) PrevIDsExists(ctx context.Context, userID string, prevIDs []int64) (bool, error) {
|
|
||||||
count, err := d.DeviceKeysTable.CountStreamIDsForUser(ctx, userID, prevIDs)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return count == len(prevIDs), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) StoreRemoteDeviceKeys(ctx context.Context, keys []api.DeviceMessage, clearUserIDs []string) error {
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
for _, userID := range clearUserIDs {
|
|
||||||
err := d.DeviceKeysTable.DeleteAllDeviceKeys(ctx, txn, userID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return d.DeviceKeysTable.InsertDeviceKeys(ctx, txn, keys)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) StoreLocalDeviceKeys(ctx context.Context, keys []api.DeviceMessage) error {
|
|
||||||
// work out the latest stream IDs for each user
|
|
||||||
userIDToStreamID := make(map[string]int64)
|
|
||||||
for _, k := range keys {
|
|
||||||
userIDToStreamID[k.UserID] = 0
|
|
||||||
}
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
for userID := range userIDToStreamID {
|
|
||||||
streamID, err := d.DeviceKeysTable.SelectMaxStreamIDForUser(ctx, txn, userID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
userIDToStreamID[userID] = streamID
|
|
||||||
}
|
|
||||||
// set the stream IDs for each key
|
|
||||||
for i := range keys {
|
|
||||||
k := keys[i]
|
|
||||||
userIDToStreamID[k.UserID]++ // start stream from 1
|
|
||||||
k.StreamID = userIDToStreamID[k.UserID]
|
|
||||||
keys[i] = k
|
|
||||||
}
|
|
||||||
return d.DeviceKeysTable.InsertDeviceKeys(ctx, txn, keys)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) DeviceKeysForUser(ctx context.Context, userID string, deviceIDs []string, includeEmpty bool) ([]api.DeviceMessage, error) {
|
|
||||||
return d.DeviceKeysTable.SelectBatchDeviceKeys(ctx, userID, deviceIDs, includeEmpty)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) ClaimKeys(ctx context.Context, userToDeviceToAlgorithm map[string]map[string]string) ([]api.OneTimeKeys, error) {
|
|
||||||
var result []api.OneTimeKeys
|
|
||||||
err := d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
for userID, deviceToAlgo := range userToDeviceToAlgorithm {
|
|
||||||
for deviceID, algo := range deviceToAlgo {
|
|
||||||
keyJSON, err := d.OneTimeKeysTable.SelectAndDeleteOneTimeKey(ctx, txn, userID, deviceID, algo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if keyJSON != nil {
|
|
||||||
result = append(result, api.OneTimeKeys{
|
|
||||||
UserID: userID,
|
|
||||||
DeviceID: deviceID,
|
|
||||||
KeyJSON: keyJSON,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) StoreKeyChange(ctx context.Context, userID string) (id int64, err error) {
|
|
||||||
err = d.Writer.Do(nil, nil, func(_ *sql.Tx) error {
|
|
||||||
id, err = d.KeyChangesTable.InsertKeyChange(ctx, userID)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Database) KeyChanges(ctx context.Context, fromOffset, toOffset int64) (userIDs []string, latestOffset int64, err error) {
|
|
||||||
return d.KeyChangesTable.SelectKeyChanges(ctx, fromOffset, toOffset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaleDeviceLists returns a list of user IDs ending with the domains provided who have stale device lists.
|
|
||||||
// If no domains are given, all user IDs with stale device lists are returned.
|
|
||||||
func (d *Database) StaleDeviceLists(ctx context.Context, domains []gomatrixserverlib.ServerName) ([]string, error) {
|
|
||||||
return d.StaleDeviceListsTable.SelectUserIDsWithStaleDeviceLists(ctx, domains)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkDeviceListStale sets the stale bit for this user to isStale.
|
|
||||||
func (d *Database) MarkDeviceListStale(ctx context.Context, userID string, isStale bool) error {
|
|
||||||
return d.Writer.Do(nil, nil, func(_ *sql.Tx) error {
|
|
||||||
return d.StaleDeviceListsTable.InsertStaleDeviceList(ctx, userID, isStale)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDeviceKeys removes the device keys for a given user/device, and any accompanying
|
|
||||||
// cross-signing signatures relating to that device.
|
|
||||||
func (d *Database) DeleteDeviceKeys(ctx context.Context, userID string, deviceIDs []gomatrixserverlib.KeyID) error {
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
for _, deviceID := range deviceIDs {
|
|
||||||
if err := d.CrossSigningSigsTable.DeleteCrossSigningSigsForTarget(ctx, txn, userID, deviceID); err != nil && err != sql.ErrNoRows {
|
|
||||||
return fmt.Errorf("d.CrossSigningSigsTable.DeleteCrossSigningSigsForTarget: %w", err)
|
|
||||||
}
|
|
||||||
if err := d.DeviceKeysTable.DeleteDeviceKeys(ctx, txn, userID, string(deviceID)); err != nil && err != sql.ErrNoRows {
|
|
||||||
return fmt.Errorf("d.DeviceKeysTable.DeleteDeviceKeys: %w", err)
|
|
||||||
}
|
|
||||||
if err := d.OneTimeKeysTable.DeleteOneTimeKeys(ctx, txn, userID, string(deviceID)); err != nil && err != sql.ErrNoRows {
|
|
||||||
return fmt.Errorf("d.OneTimeKeysTable.DeleteOneTimeKeys: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CrossSigningKeysForUser returns the latest known cross-signing keys for a user, if any.
|
|
||||||
func (d *Database) CrossSigningKeysForUser(ctx context.Context, userID string) (map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey, error) {
|
|
||||||
keyMap, err := d.CrossSigningKeysTable.SelectCrossSigningKeysForUser(ctx, nil, userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("d.CrossSigningKeysTable.SelectCrossSigningKeysForUser: %w", err)
|
|
||||||
}
|
|
||||||
results := map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey{}
|
|
||||||
for purpose, key := range keyMap {
|
|
||||||
keyID := gomatrixserverlib.KeyID("ed25519:" + key.Encode())
|
|
||||||
result := gomatrixserverlib.CrossSigningKey{
|
|
||||||
UserID: userID,
|
|
||||||
Usage: []gomatrixserverlib.CrossSigningKeyPurpose{purpose},
|
|
||||||
Keys: map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{
|
|
||||||
keyID: key,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
sigMap, err := d.CrossSigningSigsTable.SelectCrossSigningSigsForTarget(ctx, nil, userID, userID, keyID)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for sigUserID, forSigUserID := range sigMap {
|
|
||||||
if userID != sigUserID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if result.Signatures == nil {
|
|
||||||
result.Signatures = map[string]map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{}
|
|
||||||
}
|
|
||||||
if _, ok := result.Signatures[sigUserID]; !ok {
|
|
||||||
result.Signatures[sigUserID] = map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{}
|
|
||||||
}
|
|
||||||
for sigKeyID, sigBytes := range forSigUserID {
|
|
||||||
result.Signatures[sigUserID][sigKeyID] = sigBytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results[purpose] = result
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CrossSigningKeysForUser returns the latest known cross-signing keys for a user, if any.
|
|
||||||
func (d *Database) CrossSigningKeysDataForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error) {
|
|
||||||
return d.CrossSigningKeysTable.SelectCrossSigningKeysForUser(ctx, nil, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CrossSigningSigsForTarget returns the signatures for a given user's key ID, if any.
|
|
||||||
func (d *Database) CrossSigningSigsForTarget(ctx context.Context, originUserID, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error) {
|
|
||||||
return d.CrossSigningSigsTable.SelectCrossSigningSigsForTarget(ctx, nil, originUserID, targetUserID, targetKeyID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoreCrossSigningKeysForUser stores the latest known cross-signing keys for a user.
|
|
||||||
func (d *Database) StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error {
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
for keyType, keyData := range keyMap {
|
|
||||||
if err := d.CrossSigningKeysTable.UpsertCrossSigningKeysForUser(ctx, txn, userID, keyType, keyData); err != nil {
|
|
||||||
return fmt.Errorf("d.CrossSigningKeysTable.InsertCrossSigningKeysForUser: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoreCrossSigningSigsForTarget stores a signature for a target user ID and key/dvice.
|
|
||||||
func (d *Database) StoreCrossSigningSigsForTarget(
|
|
||||||
ctx context.Context,
|
|
||||||
originUserID string, originKeyID gomatrixserverlib.KeyID,
|
|
||||||
targetUserID string, targetKeyID gomatrixserverlib.KeyID,
|
|
||||||
signature gomatrixserverlib.Base64Bytes,
|
|
||||||
) error {
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
if err := d.CrossSigningSigsTable.UpsertCrossSigningSigsForTarget(ctx, nil, originUserID, originKeyID, targetUserID, targetKeyID, signature); err != nil {
|
|
||||||
return fmt.Errorf("d.CrossSigningSigsTable.InsertCrossSigningSigsForTarget: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteStaleDeviceLists deletes stale device list entries for users we don't share a room with anymore.
|
|
||||||
func (d *Database) DeleteStaleDeviceLists(
|
|
||||||
ctx context.Context,
|
|
||||||
userIDs []string,
|
|
||||||
) error {
|
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
|
||||||
return d.StaleDeviceListsTable.DeleteStaleDeviceLists(ctx, txn, userIDs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package sqlite3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/shared"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions) (*shared.Database, error) {
|
|
||||||
db, writer, err := base.DatabaseConnection(dbProperties, sqlutil.NewExclusiveWriter())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
otk, err := NewSqliteOneTimeKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dk, err := NewSqliteDeviceKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
kc, err := NewSqliteKeyChangesTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sdl, err := NewSqliteStaleDeviceListsTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
csk, err := NewSqliteCrossSigningKeysTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
css, err := NewSqliteCrossSigningSigsTable(db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = kc.Prepare(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
d := &shared.Database{
|
|
||||||
DB: db,
|
|
||||||
Writer: writer,
|
|
||||||
OneTimeKeysTable: otk,
|
|
||||||
DeviceKeysTable: dk,
|
|
||||||
KeyChangesTable: kc,
|
|
||||||
StaleDeviceListsTable: sdl,
|
|
||||||
CrossSigningKeysTable: csk,
|
|
||||||
CrossSigningSigsTable: css,
|
|
||||||
}
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build !wasm
|
|
||||||
// +build !wasm
|
|
||||||
|
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/postgres"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/sqlite3"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme)
|
|
||||||
// and sets postgres connection parameters
|
|
||||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions) (Database, error) {
|
|
||||||
switch {
|
|
||||||
case dbProperties.ConnectionString.IsSQLite():
|
|
||||||
return sqlite3.NewDatabase(base, dbProperties)
|
|
||||||
case dbProperties.ConnectionString.IsPostgres():
|
|
||||||
return postgres.NewDatabase(base, dbProperties)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unexpected database type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,197 +0,0 @@
|
||||||
package storage_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage"
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/types"
|
|
||||||
"github.com/matrix-org/dendrite/test"
|
|
||||||
"github.com/matrix-org/dendrite/test/testrig"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ctx = context.Background()
|
|
||||||
|
|
||||||
func MustCreateDatabase(t *testing.T, dbType test.DBType) (storage.Database, func()) {
|
|
||||||
base, close := testrig.CreateBaseDendrite(t, dbType)
|
|
||||||
db, err := storage.NewDatabase(base, &base.Cfg.KeyServer.Database)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create new database: %v", err)
|
|
||||||
}
|
|
||||||
return db, close
|
|
||||||
}
|
|
||||||
|
|
||||||
func MustNotError(t *testing.T, err error) {
|
|
||||||
t.Helper()
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Fatalf("operation failed: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKeyChanges(t *testing.T) {
|
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
db, clean := MustCreateDatabase(t, dbType)
|
|
||||||
defer clean()
|
|
||||||
_, err := db.StoreKeyChange(ctx, "@alice:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
deviceChangeIDB, err := db.StoreKeyChange(ctx, "@bob:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
deviceChangeIDC, err := db.StoreKeyChange(ctx, "@charlie:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
userIDs, latest, err := db.KeyChanges(ctx, deviceChangeIDB, types.OffsetNewest)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to KeyChanges: %s", err)
|
|
||||||
}
|
|
||||||
if latest != deviceChangeIDC {
|
|
||||||
t.Fatalf("KeyChanges: got latest=%d want %d", latest, deviceChangeIDC)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(userIDs, []string{"@charlie:localhost"}) {
|
|
||||||
t.Fatalf("KeyChanges: wrong user_ids: %v", userIDs)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKeyChangesNoDupes(t *testing.T) {
|
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
db, clean := MustCreateDatabase(t, dbType)
|
|
||||||
defer clean()
|
|
||||||
deviceChangeIDA, err := db.StoreKeyChange(ctx, "@alice:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
deviceChangeIDB, err := db.StoreKeyChange(ctx, "@alice:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
if deviceChangeIDA == deviceChangeIDB {
|
|
||||||
t.Fatalf("Expected change ID to be different even when inserting key change for the same user, got %d for both changes", deviceChangeIDA)
|
|
||||||
}
|
|
||||||
deviceChangeID, err := db.StoreKeyChange(ctx, "@alice:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
userIDs, latest, err := db.KeyChanges(ctx, 0, types.OffsetNewest)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to KeyChanges: %s", err)
|
|
||||||
}
|
|
||||||
if latest != deviceChangeID {
|
|
||||||
t.Fatalf("KeyChanges: got latest=%d want %d", latest, deviceChangeID)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(userIDs, []string{"@alice:localhost"}) {
|
|
||||||
t.Fatalf("KeyChanges: wrong user_ids: %v", userIDs)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKeyChangesUpperLimit(t *testing.T) {
|
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
db, clean := MustCreateDatabase(t, dbType)
|
|
||||||
defer clean()
|
|
||||||
deviceChangeIDA, err := db.StoreKeyChange(ctx, "@alice:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
deviceChangeIDB, err := db.StoreKeyChange(ctx, "@bob:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
_, err = db.StoreKeyChange(ctx, "@charlie:localhost")
|
|
||||||
MustNotError(t, err)
|
|
||||||
userIDs, latest, err := db.KeyChanges(ctx, deviceChangeIDA, deviceChangeIDB)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to KeyChanges: %s", err)
|
|
||||||
}
|
|
||||||
if latest != deviceChangeIDB {
|
|
||||||
t.Fatalf("KeyChanges: got latest=%d want %d", latest, deviceChangeIDB)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(userIDs, []string{"@bob:localhost"}) {
|
|
||||||
t.Fatalf("KeyChanges: wrong user_ids: %v", userIDs)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var dbLock sync.Mutex
|
|
||||||
var deviceArray = []string{"AAA", "another_device"}
|
|
||||||
|
|
||||||
// The purpose of this test is to make sure that the storage layer is generating sequential stream IDs per user,
|
|
||||||
// and that they are returned correctly when querying for device keys.
|
|
||||||
func TestDeviceKeysStreamIDGeneration(t *testing.T) {
|
|
||||||
var err error
|
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
db, clean := MustCreateDatabase(t, dbType)
|
|
||||||
defer clean()
|
|
||||||
alice := "@alice:TestDeviceKeysStreamIDGeneration"
|
|
||||||
bob := "@bob:TestDeviceKeysStreamIDGeneration"
|
|
||||||
msgs := []api.DeviceMessage{
|
|
||||||
{
|
|
||||||
Type: api.TypeDeviceKeyUpdate,
|
|
||||||
DeviceKeys: &api.DeviceKeys{
|
|
||||||
DeviceID: "AAA",
|
|
||||||
UserID: alice,
|
|
||||||
KeyJSON: []byte(`{"key":"v1"}`),
|
|
||||||
},
|
|
||||||
// StreamID: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: api.TypeDeviceKeyUpdate,
|
|
||||||
DeviceKeys: &api.DeviceKeys{
|
|
||||||
DeviceID: "AAA",
|
|
||||||
UserID: bob,
|
|
||||||
KeyJSON: []byte(`{"key":"v1"}`),
|
|
||||||
},
|
|
||||||
// StreamID: 1 as this is a different user
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: api.TypeDeviceKeyUpdate,
|
|
||||||
DeviceKeys: &api.DeviceKeys{
|
|
||||||
DeviceID: "another_device",
|
|
||||||
UserID: alice,
|
|
||||||
KeyJSON: []byte(`{"key":"v1"}`),
|
|
||||||
},
|
|
||||||
// StreamID: 2 as this is a 2nd device key
|
|
||||||
},
|
|
||||||
}
|
|
||||||
MustNotError(t, db.StoreLocalDeviceKeys(ctx, msgs))
|
|
||||||
if msgs[0].StreamID != 1 {
|
|
||||||
t.Fatalf("Expected StoreLocalDeviceKeys to set StreamID=1 but got %d", msgs[0].StreamID)
|
|
||||||
}
|
|
||||||
if msgs[1].StreamID != 1 {
|
|
||||||
t.Fatalf("Expected StoreLocalDeviceKeys to set StreamID=1 (different user) but got %d", msgs[1].StreamID)
|
|
||||||
}
|
|
||||||
if msgs[2].StreamID != 2 {
|
|
||||||
t.Fatalf("Expected StoreLocalDeviceKeys to set StreamID=2 (another device) but got %d", msgs[2].StreamID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// updating a device sets the next stream ID for that user
|
|
||||||
msgs = []api.DeviceMessage{
|
|
||||||
{
|
|
||||||
Type: api.TypeDeviceKeyUpdate,
|
|
||||||
DeviceKeys: &api.DeviceKeys{
|
|
||||||
DeviceID: "AAA",
|
|
||||||
UserID: alice,
|
|
||||||
KeyJSON: []byte(`{"key":"v2"}`),
|
|
||||||
},
|
|
||||||
// StreamID: 3
|
|
||||||
},
|
|
||||||
}
|
|
||||||
MustNotError(t, db.StoreLocalDeviceKeys(ctx, msgs))
|
|
||||||
if msgs[0].StreamID != 3 {
|
|
||||||
t.Fatalf("Expected StoreLocalDeviceKeys to set StreamID=3 (new key same device) but got %d", msgs[0].StreamID)
|
|
||||||
}
|
|
||||||
|
|
||||||
dbLock.Lock()
|
|
||||||
defer dbLock.Unlock()
|
|
||||||
// Querying for device keys returns the latest stream IDs
|
|
||||||
msgs, err = db.DeviceKeysForUser(ctx, alice, deviceArray, false)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("DeviceKeysForUser returned error: %s", err)
|
|
||||||
}
|
|
||||||
wantStreamIDs := map[string]int64{
|
|
||||||
"AAA": 3,
|
|
||||||
"another_device": 2,
|
|
||||||
}
|
|
||||||
if len(msgs) != len(wantStreamIDs) {
|
|
||||||
t.Fatalf("DeviceKeysForUser: wrong number of devices, got %d want %d", len(msgs), len(wantStreamIDs))
|
|
||||||
}
|
|
||||||
for _, m := range msgs {
|
|
||||||
if m.StreamID != wantStreamIDs[m.DeviceID] {
|
|
||||||
t.Errorf("DeviceKeysForUser: wrong returned stream ID for key, got %d want %d", m.StreamID, wantStreamIDs[m.DeviceID])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage/sqlite3"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions) (Database, error) {
|
|
||||||
switch {
|
|
||||||
case dbProperties.ConnectionString.IsSQLite():
|
|
||||||
return sqlite3.NewDatabase(base, dbProperties)
|
|
||||||
case dbProperties.ConnectionString.IsPostgres():
|
|
||||||
return nil, fmt.Errorf("can't use Postgres implementation")
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unexpected database type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue