mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-07 15:03:09 -06:00
Merge pull request #49 from globekeeper/release/upstream-0.10.6
Release/upstream 0.10.6
This commit is contained in:
commit
610c73c1f5
18
.github/workflows/dendrite.yml
vendored
18
.github/workflows/dendrite.yml
vendored
|
|
@ -64,6 +64,11 @@ jobs:
|
|||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set up gotestfmt
|
||||
uses: gotesttools/gotestfmt-action@v2
|
||||
with:
|
||||
# Optional: pass GITHUB_TOKEN to avoid rate limiting.
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
|
@ -72,7 +77,7 @@ jobs:
|
|||
key: ${{ runner.os }}-go${{ matrix.go }}-test-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go${{ matrix.go }}-test-
|
||||
- run: go test ./...
|
||||
- run: go test -json -v ./... 2>&1 | gotestfmt
|
||||
env:
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_USER: postgres
|
||||
|
|
@ -266,14 +271,3 @@ jobs:
|
|||
uses: re-actors/alls-green@release/v1
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
||||
update-docker-images:
|
||||
name: Update Docker images
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
if: github.repository == 'matrix-org/dendrite' && github.ref_name == 'main'
|
||||
needs: [integration-tests-done]
|
||||
uses: matrix-org/dendrite/.github/workflows/docker.yml@main
|
||||
secrets:
|
||||
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
|
|
|||
199
.github/workflows/docker.yml
vendored
199
.github/workflows/docker.yml
vendored
|
|
@ -1,199 +0,0 @@
|
|||
# Based on https://github.com/docker/build-push-action
|
||||
|
||||
name: "Docker"
|
||||
|
||||
on:
|
||||
release: # A GitHub release was published
|
||||
types: [published]
|
||||
workflow_dispatch: # A build was manually requested
|
||||
workflow_call: # Another pipeline called us
|
||||
secrets:
|
||||
DOCKER_TOKEN:
|
||||
required: true
|
||||
|
||||
env:
|
||||
DOCKER_NAMESPACE: matrixdotorg
|
||||
DOCKER_HUB_USER: dendritegithub
|
||||
GHCR_NAMESPACE: matrix-org
|
||||
PLATFORMS: linux/amd64,linux/arm64,linux/arm/v7
|
||||
|
||||
jobs:
|
||||
monolith:
|
||||
name: Monolith image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Get release tag
|
||||
if: github.event_name == 'release' # Only for GitHub releases
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ env.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to GitHub Containers
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build main monolith image
|
||||
if: github.ref_name == 'main'
|
||||
id: docker_build_monolith
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.monolith
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-monolith:${{ github.ref_name }}
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-monolith:${{ github.ref_name }}
|
||||
|
||||
- name: Build release monolith image
|
||||
if: github.event_name == 'release' # Only for GitHub releases
|
||||
id: docker_build_monolith_release
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.monolith
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-monolith:latest
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-monolith:${{ env.RELEASE_VERSION }}
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-monolith:latest
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-monolith:${{ env.RELEASE_VERSION }}
|
||||
|
||||
polylith:
|
||||
name: Polylith image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Get release tag
|
||||
if: github.event_name == 'release' # Only for GitHub releases
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ env.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to GitHub Containers
|
||||
uses: docker/login-action@v1
|
||||
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@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.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@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.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 }}
|
||||
|
||||
demo-pinecone:
|
||||
name: Pinecone demo image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Get release tag
|
||||
if: github.event_name == 'release' # Only for GitHub releases
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ env.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to GitHub Containers
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build main pinecone demo image
|
||||
if: github.ref_name == 'main'
|
||||
id: docker_build_demo_pinecone
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.demo-pinecone
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-demo-pinecone:${{ github.ref_name }}
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-demo-pinecone:${{ github.ref_name }}
|
||||
|
||||
- name: Build release pinecone demo image
|
||||
if: github.event_name == 'release' # Only for GitHub releases
|
||||
id: docker_build_demo_pinecone_release
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
context: .
|
||||
file: ./build/docker/Dockerfile.demo-pinecone
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-demo-pinecone:latest
|
||||
${{ env.DOCKER_NAMESPACE }}/dendrite-demo-pinecone:${{ env.RELEASE_VERSION }}
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-demo-pinecone:latest
|
||||
ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-demo-pinecone:${{ env.RELEASE_VERSION }}
|
||||
128
.github/workflows/schedules.yaml
vendored
Normal file
128
.github/workflows/schedules.yaml
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
name: Scheduled
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # every day at midnight
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# run go test with different go versions
|
||||
test:
|
||||
timeout-minutes: 20
|
||||
name: Unit tests (Go ${{ matrix.go }})
|
||||
runs-on: ubuntu-latest
|
||||
# Service containers to run with `container-job`
|
||||
services:
|
||||
# Label used to access the service container
|
||||
postgres:
|
||||
# Docker Hub image
|
||||
image: postgres:13-alpine
|
||||
# Provide the password for postgres
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: dendrite
|
||||
ports:
|
||||
# Maps tcp port 5432 on service container to the host
|
||||
- 5432:5432
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go: ["1.18", "1.19"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go${{ matrix.go }}-test-race-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go${{ matrix.go }}-test-race-
|
||||
- run: go test -race ./...
|
||||
env:
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: dendrite
|
||||
|
||||
# Dummy step to gate other tests on without repeating the whole list
|
||||
initial-tests-done:
|
||||
name: Initial tests passed
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !cancelled() }} # Run this even if prior jobs were skipped
|
||||
steps:
|
||||
- name: Check initial tests passed
|
||||
uses: re-actors/alls-green@release/v1
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
||||
# run Sytest in different variations
|
||||
sytest:
|
||||
timeout-minutes: 60
|
||||
needs: initial-tests-done
|
||||
name: "Sytest (${{ matrix.label }})"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- label: SQLite
|
||||
|
||||
- label: SQLite, full HTTP APIs
|
||||
api: full-http
|
||||
|
||||
- label: PostgreSQL
|
||||
postgres: postgres
|
||||
|
||||
- label: PostgreSQL, full HTTP APIs
|
||||
postgres: postgres
|
||||
api: full-http
|
||||
container:
|
||||
image: matrixdotorg/sytest-dendrite:latest
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/src
|
||||
env:
|
||||
POSTGRES: ${{ matrix.postgres && 1}}
|
||||
API: ${{ matrix.api && 1 }}
|
||||
SYTEST_BRANCH: ${{ github.head_ref }}
|
||||
RACE_DETECTION: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run Sytest
|
||||
run: /bootstrap.sh dendrite
|
||||
working-directory: /src
|
||||
- name: Summarise results.tap
|
||||
if: ${{ always() }}
|
||||
run: /sytest/scripts/tap_to_gha.pl /logs/results.tap
|
||||
- name: Sytest List Maintenance
|
||||
if: ${{ always() }}
|
||||
run: /src/show-expected-fail-tests.sh /logs/results.tap /src/sytest-whitelist /src/sytest-blacklist
|
||||
continue-on-error: true # not fatal
|
||||
- name: Are We Synapse Yet?
|
||||
if: ${{ always() }}
|
||||
run: /src/are-we-synapse-yet.py /logs/results.tap -v
|
||||
continue-on-error: true # not fatal
|
||||
- name: Upload Sytest logs
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: Sytest Logs - ${{ job.status }} - (Dendrite, ${{ join(matrix.*, ', ') }})
|
||||
path: |
|
||||
/logs/results.tap
|
||||
/logs/**/*.log*
|
||||
34
CHANGES.md
34
CHANGES.md
|
|
@ -1,5 +1,39 @@
|
|||
# Changelog
|
||||
|
||||
## Dendrite 0.10.6 (2022-11-01)
|
||||
|
||||
### Features
|
||||
|
||||
* History visibility checks have been optimised, which should speed up response times on a variety of endpoints (including `/sync`, `/messages`, `/context` and others) and reduce database load
|
||||
* The built-in NATS Server has been updated to version 2.9.4
|
||||
* Some other minor dependencies have been updated
|
||||
|
||||
### Fixes
|
||||
|
||||
* A panic has been fixed in the sync API PDU stream which could cause requests to fail
|
||||
* The `/members` response now contains the `room_id` field, which may fix some E2EE problems with clients using the JS SDK (contributed by [ashkitten](https://github.com/ashkitten))
|
||||
* The auth difference calculation in state resolution v2 has been tweaked for clarity (and moved into gomatrixserverlib with the rest of the state resolution code)
|
||||
|
||||
## Dendrite 0.10.5 (2022-10-31)
|
||||
|
||||
### Features
|
||||
|
||||
* It is now possible to use hCaptcha instead of reCAPTCHA for protecting registration
|
||||
* A new `auto_join_rooms` configuration option has been added for automatically joining new users to a set of rooms
|
||||
* A new `/_dendrite/admin/downloadState/{serverName}/{roomID}` endpoint has been added, which allows a server administrator to attempt to repair a room with broken room state by downloading a state snapshot from another federated server in the room
|
||||
|
||||
### Fixes
|
||||
|
||||
* Querying cross-signing keys for users should now be considerably faster
|
||||
* A bug in state resolution where some events were not correctly selected for third-party invites has been fixed
|
||||
* A bug in state resolution which could result in `not in room` event rejections has been fixed
|
||||
* When accepting a DM invite, it should now be possible to see messages that were sent before the invite was accepted
|
||||
* Claiming remote E2EE one-time keys has been refactored and should be more reliable now
|
||||
* Various fixes have been made to the `/members` endpoint, which may help with E2EE reliability and clients rendering memberships
|
||||
* A race condition in the federation API destination queues has been fixed when associating queued events with remote server destinations
|
||||
* A bug in the sync API where too many events were selected resulting in high CPU usage has been fixed
|
||||
* Configuring the avatar URL for the Server Notices user should work correctly now
|
||||
|
||||
## Dendrite 0.10.4 (2022-10-21)
|
||||
|
||||
### Features
|
||||
|
|
|
|||
25
build/docker/Dockerfile.demo-yggdrasil
Normal file
25
build/docker/Dockerfile.demo-yggdrasil
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
FROM docker.io/golang:1.19-alpine AS base
|
||||
|
||||
RUN apk --update --no-cache add bash build-base
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY . /build
|
||||
|
||||
RUN mkdir -p bin
|
||||
RUN go build -trimpath -o bin/ ./cmd/dendrite-demo-yggdrasil
|
||||
RUN go build -trimpath -o bin/ ./cmd/create-account
|
||||
RUN go build -trimpath -o bin/ ./cmd/generate-keys
|
||||
|
||||
FROM alpine:latest
|
||||
LABEL org.opencontainers.image.title="Dendrite (Yggdrasil demo)"
|
||||
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.licenses="Apache-2.0"
|
||||
|
||||
COPY --from=base /build/bin/* /usr/bin/
|
||||
|
||||
VOLUME /etc/dendrite
|
||||
WORKDIR /etc/dendrite
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dendrite-demo-yggdrasil"]
|
||||
|
|
@ -101,18 +101,46 @@ func (m *DendriteMonolith) SessionCount() int {
|
|||
return len(m.PineconeQUIC.Protocol("matrix").Sessions())
|
||||
}
|
||||
|
||||
func (m *DendriteMonolith) RegisterNetworkInterface(name string, index int, mtu int, up bool, broadcast bool, loopback bool, pointToPoint bool, multicast bool, addrs string) {
|
||||
m.PineconeMulticast.RegisterInterface(pineconeMulticast.InterfaceInfo{
|
||||
Name: name,
|
||||
Index: index,
|
||||
Mtu: mtu,
|
||||
Up: up,
|
||||
Broadcast: broadcast,
|
||||
Loopback: loopback,
|
||||
PointToPoint: pointToPoint,
|
||||
Multicast: multicast,
|
||||
Addrs: addrs,
|
||||
})
|
||||
type InterfaceInfo struct {
|
||||
Name string
|
||||
Index int
|
||||
Mtu int
|
||||
Up bool
|
||||
Broadcast bool
|
||||
Loopback bool
|
||||
PointToPoint bool
|
||||
Multicast bool
|
||||
Addrs string
|
||||
}
|
||||
|
||||
type InterfaceRetriever interface {
|
||||
CacheCurrentInterfaces() int
|
||||
GetCachedInterface(index int) *InterfaceInfo
|
||||
}
|
||||
|
||||
func (m *DendriteMonolith) RegisterNetworkCallback(intfCallback InterfaceRetriever) {
|
||||
callback := func() []pineconeMulticast.InterfaceInfo {
|
||||
count := intfCallback.CacheCurrentInterfaces()
|
||||
intfs := []pineconeMulticast.InterfaceInfo{}
|
||||
for i := 0; i < count; i++ {
|
||||
iface := intfCallback.GetCachedInterface(i)
|
||||
if iface != nil {
|
||||
intfs = append(intfs, pineconeMulticast.InterfaceInfo{
|
||||
Name: iface.Name,
|
||||
Index: iface.Index,
|
||||
Mtu: iface.Mtu,
|
||||
Up: iface.Up,
|
||||
Broadcast: iface.Broadcast,
|
||||
Loopback: iface.Loopback,
|
||||
PointToPoint: iface.PointToPoint,
|
||||
Multicast: iface.Multicast,
|
||||
Addrs: iface.Addrs,
|
||||
})
|
||||
}
|
||||
}
|
||||
return intfs
|
||||
}
|
||||
m.PineconeMulticast.RegisterNetworkCallback(callback)
|
||||
}
|
||||
|
||||
func (m *DendriteMonolith) SetMulticastEnabled(enabled bool) {
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
|
|||
JSON: jsonerror.BadJSON("A password must be supplied."),
|
||||
}
|
||||
}
|
||||
localpart, err := userutil.ParseUsernameParam(username, &t.Config.Matrix.ServerName)
|
||||
localpart, _, err := userutil.ParseUsernameParam(username, t.Config.Matrix)
|
||||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func AdminEvacuateUser(req *http.Request, cfg *config.ClientAPI, device *userapi
|
|||
if err != nil {
|
||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("User ID must belong to this server."),
|
||||
|
|
@ -169,7 +169,7 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
|||
if err != nil {
|
||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
if domain == cfg.Matrix.ServerName {
|
||||
if cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("Can not mark local device list as stale"),
|
||||
|
|
@ -191,3 +191,43 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
|||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func AdminDownloadState(req *http.Request, cfg *config.ClientAPI, device *userapi.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
roomID, ok := vars["roomID"]
|
||||
if !ok {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Expecting room ID."),
|
||||
}
|
||||
}
|
||||
serverName, ok := vars["serverName"]
|
||||
if !ok {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Expecting remote server name."),
|
||||
}
|
||||
}
|
||||
res := &roomserverAPI.PerformAdminDownloadStateResponse{}
|
||||
if err := rsAPI.PerformAdminDownloadState(
|
||||
req.Context(),
|
||||
&roomserverAPI.PerformAdminDownloadStateRequest{
|
||||
UserID: device.UserID,
|
||||
RoomID: roomID,
|
||||
ServerName: gomatrixserverlib.ServerName(serverName),
|
||||
},
|
||||
res,
|
||||
); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if err := res.Error; err != nil {
|
||||
return err.JSONResponse()
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ const recaptchaTemplate = `
|
|||
<title>Authentication</title>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1,
|
||||
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
||||
<script src="https://www.google.com/recaptcha/api.js"
|
||||
async defer></script>
|
||||
<script src="{{.apiJsUrl}}" async defer></script>
|
||||
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
|
||||
<script>
|
||||
function captchaDone() {
|
||||
|
|
@ -51,8 +50,8 @@ function captchaDone() {
|
|||
Please verify that you're not a robot.
|
||||
</p>
|
||||
<input type="hidden" name="session" value="{{.session}}" />
|
||||
<div class="g-recaptcha"
|
||||
data-sitekey="{{.siteKey}}"
|
||||
<div class="{{.sitekeyClass}}"
|
||||
data-sitekey="{{.sitekey}}"
|
||||
data-callback="captchaDone">
|
||||
</div>
|
||||
<noscript>
|
||||
|
|
@ -114,9 +113,12 @@ func AuthFallback(
|
|||
|
||||
serveRecaptcha := func() {
|
||||
data := map[string]string{
|
||||
"myUrl": req.URL.String(),
|
||||
"session": sessionID,
|
||||
"siteKey": cfg.RecaptchaPublicKey,
|
||||
"myUrl": req.URL.String(),
|
||||
"session": sessionID,
|
||||
"apiJsUrl": cfg.RecaptchaApiJsUrl,
|
||||
"sitekey": cfg.RecaptchaPublicKey,
|
||||
"sitekeyClass": cfg.RecaptchaSitekeyClass,
|
||||
"formField": cfg.RecaptchaFormField,
|
||||
}
|
||||
serveTemplate(w, recaptchaTemplate, data)
|
||||
}
|
||||
|
|
@ -155,7 +157,7 @@ func AuthFallback(
|
|||
return &res
|
||||
}
|
||||
|
||||
response := req.Form.Get("g-recaptcha-response")
|
||||
response := req.Form.Get(cfg.RecaptchaFormField)
|
||||
if err := validateRecaptcha(cfg, response, clientIP); err != nil {
|
||||
util.GetLogger(req.Context()).Error(err)
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -169,9 +169,21 @@ func createRoom(
|
|||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
evTime time.Time,
|
||||
) util.JSONResponse {
|
||||
_, userDomain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if !cfg.Matrix.IsLocalServerName(userDomain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(fmt.Sprintf("User domain %q not configured locally", userDomain)),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (#267): Check room ID doesn't clash with an existing one, and we
|
||||
// probably shouldn't be using pseudo-random strings, maybe GUIDs?
|
||||
roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
|
||||
roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), userDomain)
|
||||
|
||||
logger := util.GetLogger(ctx)
|
||||
userID := device.UserID
|
||||
|
|
@ -314,7 +326,7 @@ func createRoom(
|
|||
|
||||
var roomAlias string
|
||||
if r.RoomAliasName != "" {
|
||||
roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName)
|
||||
roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, userDomain)
|
||||
// check it's free TODO: This races but is better than nothing
|
||||
hasAliasReq := roomserverAPI.GetRoomIDForAliasRequest{
|
||||
Alias: roomAlias,
|
||||
|
|
@ -436,7 +448,7 @@ func createRoom(
|
|||
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
||||
}
|
||||
var ev *gomatrixserverlib.Event
|
||||
ev, err = buildEvent(&builder, &authEvents, cfg, evTime, roomVersion)
|
||||
ev, err = buildEvent(&builder, userDomain, &authEvents, cfg, evTime, roomVersion)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
|
|
@ -461,7 +473,7 @@ func createRoom(
|
|||
inputs = append(inputs, roomserverAPI.InputRoomEvent{
|
||||
Kind: roomserverAPI.KindNew,
|
||||
Event: event,
|
||||
Origin: cfg.Matrix.ServerName,
|
||||
Origin: userDomain,
|
||||
SendAsServer: roomserverAPI.DoNotSendToOtherServers,
|
||||
})
|
||||
}
|
||||
|
|
@ -548,7 +560,7 @@ func createRoom(
|
|||
Event: event,
|
||||
InviteRoomState: inviteStrippedState,
|
||||
RoomVersion: event.RoomVersion,
|
||||
SendAsServer: string(cfg.Matrix.ServerName),
|
||||
SendAsServer: string(userDomain),
|
||||
}, &inviteRes); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
return util.JSONResponse{
|
||||
|
|
@ -591,6 +603,7 @@ func createRoom(
|
|||
// buildEvent fills out auth_events for the builder then builds the event
|
||||
func buildEvent(
|
||||
builder *gomatrixserverlib.EventBuilder,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
provider gomatrixserverlib.AuthEventProvider,
|
||||
cfg *config.ClientAPI,
|
||||
evTime time.Time,
|
||||
|
|
@ -606,7 +619,7 @@ func buildEvent(
|
|||
}
|
||||
builder.AuthEvents = refs
|
||||
event, err := builder.Build(
|
||||
evTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID,
|
||||
evTime, serverName, cfg.Matrix.KeyID,
|
||||
cfg.Matrix.PrivateKey, roomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -18,14 +18,15 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
type roomDirectoryResponse struct {
|
||||
|
|
@ -75,7 +76,7 @@ func DirectoryRoom(
|
|||
if res.RoomID == "" {
|
||||
// If we don't know it locally, do a federation query.
|
||||
// But don't send the query to ourselves.
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
fedRes, fedErr := federation.LookupRoomAlias(req.Context(), domain, roomAlias)
|
||||
if fedErr != nil {
|
||||
// TODO: Return 502 if the remote server errored.
|
||||
|
|
@ -127,7 +128,7 @@ func SetLocalAlias(
|
|||
}
|
||||
}
|
||||
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Alias must be on local homeserver"),
|
||||
|
|
@ -318,3 +319,43 @@ func SetVisibility(
|
|||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func SetVisibilityAS(
|
||||
req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI, dev *userapi.Device,
|
||||
networkID, roomID string,
|
||||
) util.JSONResponse {
|
||||
if dev.AccountType != userapi.AccountTypeAppService {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Only appservice may use this endpoint"),
|
||||
}
|
||||
}
|
||||
var v roomVisibility
|
||||
|
||||
// If the method is delete, we simply mark the visibility as private
|
||||
if req.Method == http.MethodDelete {
|
||||
v.Visibility = "private"
|
||||
} else {
|
||||
if reqErr := httputil.UnmarshalJSONRequest(req, &v); reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
}
|
||||
var publishRes roomserverAPI.PerformPublishResponse
|
||||
if err := rsAPI.PerformPublish(req.Context(), &roomserverAPI.PerformPublishRequest{
|
||||
RoomID: roomID,
|
||||
Visibility: v.Visibility,
|
||||
NetworkID: networkID,
|
||||
AppserviceID: dev.AppserviceID,
|
||||
}, &publishRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if publishRes.Error != nil {
|
||||
util.GetLogger(req.Context()).WithError(publishRes.Error).Error("PerformPublish failed")
|
||||
return publishRes.Error.JSONResponse()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,17 @@ var (
|
|||
)
|
||||
|
||||
type PublicRoomReq struct {
|
||||
Since string `json:"since,omitempty"`
|
||||
Limit int16 `json:"limit,omitempty"`
|
||||
Filter filter `json:"filter,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
Since string `json:"since,omitempty"`
|
||||
Limit int64 `json:"limit,omitempty"`
|
||||
Filter filter `json:"filter,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
IncludeAllNetworks bool `json:"include_all_networks,omitempty"`
|
||||
NetworkID string `json:"third_party_instance_id,omitempty"`
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
SearchTerms string `json:"generic_search_term,omitempty"`
|
||||
SearchTerms string `json:"generic_search_term,omitempty"`
|
||||
RoomTypes []string `json:"room_types,omitempty"` // TODO: Implement filter on this
|
||||
}
|
||||
|
||||
// GetPostPublicRooms implements GET and POST /publicRooms
|
||||
|
|
@ -61,9 +64,15 @@ func GetPostPublicRooms(
|
|||
return *fillErr
|
||||
}
|
||||
|
||||
serverName := gomatrixserverlib.ServerName(request.Server)
|
||||
if request.IncludeAllNetworks && request.NetworkID != "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("include_all_networks and third_party_instance_id can not be used together"),
|
||||
}
|
||||
}
|
||||
|
||||
if serverName != "" && serverName != cfg.Matrix.ServerName {
|
||||
serverName := gomatrixserverlib.ServerName(request.Server)
|
||||
if serverName != "" && !cfg.Matrix.IsLocalServerName(serverName) {
|
||||
res, err := federation.GetPublicRoomsFiltered(
|
||||
req.Context(), serverName,
|
||||
int(request.Limit), request.Since,
|
||||
|
|
@ -98,7 +107,7 @@ func publicRooms(
|
|||
response := gomatrixserverlib.RespPublicRooms{
|
||||
Chunk: []gomatrixserverlib.PublicRoom{},
|
||||
}
|
||||
var limit int16
|
||||
var limit int64
|
||||
var offset int64
|
||||
limit = request.Limit
|
||||
if limit == 0 {
|
||||
|
|
@ -115,7 +124,7 @@ func publicRooms(
|
|||
|
||||
var rooms []gomatrixserverlib.PublicRoom
|
||||
if request.Since == "" {
|
||||
rooms = refreshPublicRoomCache(ctx, rsAPI, extRoomsProvider)
|
||||
rooms = refreshPublicRoomCache(ctx, rsAPI, extRoomsProvider, request)
|
||||
} else {
|
||||
rooms = getPublicRoomsFromCache()
|
||||
}
|
||||
|
|
@ -177,7 +186,7 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
|||
JSON: jsonerror.BadJSON("limit param is not a number"),
|
||||
}
|
||||
}
|
||||
request.Limit = int16(limit)
|
||||
request.Limit = int64(limit)
|
||||
request.Since = httpReq.FormValue("since")
|
||||
request.Server = httpReq.FormValue("server")
|
||||
} else {
|
||||
|
|
@ -205,7 +214,7 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
|||
// limit=3&since=6 => G (prev='3', next='')
|
||||
//
|
||||
// A value of '-1' for prev/next indicates no position.
|
||||
func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int16) (subset []gomatrixserverlib.PublicRoom, prev, next int) {
|
||||
func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int64) (subset []gomatrixserverlib.PublicRoom, prev, next int) {
|
||||
prev = -1
|
||||
next = -1
|
||||
|
||||
|
|
@ -231,6 +240,7 @@ func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int16) (
|
|||
|
||||
func refreshPublicRoomCache(
|
||||
ctx context.Context, rsAPI roomserverAPI.ClientRoomserverAPI, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||
request PublicRoomReq,
|
||||
) []gomatrixserverlib.PublicRoom {
|
||||
cacheMu.Lock()
|
||||
defer cacheMu.Unlock()
|
||||
|
|
@ -239,8 +249,17 @@ func refreshPublicRoomCache(
|
|||
extraRooms = extRoomsProvider.Rooms()
|
||||
}
|
||||
|
||||
// TODO: this is only here to make Sytest happy, for now.
|
||||
ns := strings.Split(request.NetworkID, "|")
|
||||
if len(ns) == 2 {
|
||||
request.NetworkID = ns[1]
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryPublishedRoomsResponse
|
||||
err := rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{}, &queryRes)
|
||||
err := rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{
|
||||
NetworkID: request.NetworkID,
|
||||
IncludeAllNetworks: request.IncludeAllNetworks,
|
||||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("QueryPublishedRooms failed")
|
||||
return publicRoomsCache
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func TestSliceInto(t *testing.T) {
|
|||
slice := []gomatrixserverlib.PublicRoom{
|
||||
pubRoom("a"), pubRoom("b"), pubRoom("c"), pubRoom("d"), pubRoom("e"), pubRoom("f"), pubRoom("g"),
|
||||
}
|
||||
limit := int16(3)
|
||||
limit := int64(3)
|
||||
testCases := []struct {
|
||||
since int64
|
||||
wantPrev int
|
||||
|
|
|
|||
52
clientapi/routing/joined_rooms.go
Normal file
52
clientapi/routing/joined_rooms.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// 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 routing
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
||||
type getJoinedRoomsResponse struct {
|
||||
JoinedRooms []string `json:"joined_rooms"`
|
||||
}
|
||||
|
||||
func GetJoinedRooms(
|
||||
req *http.Request,
|
||||
device *userapi.Device,
|
||||
rsAPI api.ClientRoomserverAPI,
|
||||
) util.JSONResponse {
|
||||
var res api.QueryRoomsForUserResponse
|
||||
err := rsAPI.QueryRoomsForUser(req.Context(), &api.QueryRoomsForUserRequest{
|
||||
UserID: device.UserID,
|
||||
WantMembership: "join",
|
||||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryRoomsForUser failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if res.RoomIDs == nil {
|
||||
res.RoomIDs = []string{}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: getJoinedRoomsResponse{res.RoomIDs},
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,11 @@ func (r *queryKeysRequest) GetTimeout() time.Duration {
|
|||
if r.Timeout == 0 {
|
||||
return 10 * time.Second
|
||||
}
|
||||
return time.Duration(r.Timeout) * time.Millisecond
|
||||
timeout := time.Duration(r.Timeout) * time.Millisecond
|
||||
if timeout > time.Second*20 {
|
||||
timeout = time.Second * 20
|
||||
}
|
||||
return timeout
|
||||
}
|
||||
|
||||
func QueryKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *userapi.Device) util.JSONResponse {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func Login(
|
|||
}
|
||||
}
|
||||
// make a device/access token
|
||||
authErr2 := completeAuth(req.Context(), cfg.Matrix.ServerName, userAPI, login, req.RemoteAddr, req.UserAgent())
|
||||
authErr2 := completeAuth(req.Context(), cfg.Matrix, userAPI, login, req.RemoteAddr, req.UserAgent())
|
||||
cleanup(req.Context(), &authErr2)
|
||||
return authErr2
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ func Login(
|
|||
}
|
||||
|
||||
func completeAuth(
|
||||
ctx context.Context, serverName gomatrixserverlib.ServerName, userAPI userapi.ClientUserAPI, login *auth.Login,
|
||||
ctx context.Context, cfg *config.Global, userAPI userapi.ClientUserAPI, login *auth.Login,
|
||||
ipAddr, userAgent string,
|
||||
) util.JSONResponse {
|
||||
token, err := auth.GenerateAccessToken()
|
||||
|
|
@ -101,7 +101,7 @@ func completeAuth(
|
|||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
localpart, err := userutil.ParseUsernameParam(login.Username(), &serverName)
|
||||
localpart, serverName, err := userutil.ParseUsernameParam(login.Username(), cfg)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("auth.ParseUsernameParam failed")
|
||||
return jsonerror.InternalServerError()
|
||||
|
|
|
|||
|
|
@ -105,12 +105,13 @@ func sendMembership(ctx context.Context, profileAPI userapi.ClientUserAPI, devic
|
|||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
serverName := device.UserDomain()
|
||||
if err = roomserverAPI.SendEvents(
|
||||
ctx, rsAPI,
|
||||
roomserverAPI.KindNew,
|
||||
[]*gomatrixserverlib.HeaderedEvent{event.Event.Headered(roomVer)},
|
||||
cfg.Matrix.ServerName,
|
||||
cfg.Matrix.ServerName,
|
||||
serverName,
|
||||
serverName,
|
||||
nil,
|
||||
false,
|
||||
); err != nil {
|
||||
|
|
@ -271,7 +272,7 @@ func sendInvite(
|
|||
Event: event,
|
||||
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
|
||||
RoomVersion: event.RoomVersion,
|
||||
SendAsServer: string(cfg.Matrix.ServerName),
|
||||
SendAsServer: string(device.UserDomain()),
|
||||
}, &inviteRes); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
return util.JSONResponse{
|
||||
|
|
@ -341,7 +342,7 @@ func loadProfile(
|
|||
}
|
||||
|
||||
var profile *authtypes.Profile
|
||||
if serverName == cfg.Matrix.ServerName {
|
||||
if cfg.Matrix.IsLocalServerName(serverName) {
|
||||
profile, err = appserviceAPI.RetrieveUserProfile(ctx, userID, asAPI, profileAPI)
|
||||
} else {
|
||||
profile = &authtypes.Profile{}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func CreateOpenIDToken(
|
|||
JSON: openIDTokenResponse{
|
||||
AccessToken: response.Token.Token,
|
||||
TokenType: "Bearer",
|
||||
MatrixServerName: string(cfg.Matrix.ServerName),
|
||||
MatrixServerName: string(device.UserDomain()),
|
||||
ExpiresIn: response.Token.ExpiresAtMS / 1000, // convert ms to s
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,12 +107,19 @@ func SetAvatarURL(
|
|||
return *resErr
|
||||
}
|
||||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not belong to a locally configured domain"),
|
||||
}
|
||||
}
|
||||
|
||||
evTime, err := httputil.ParseTSParam(req)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -123,8 +130,9 @@ func SetAvatarURL(
|
|||
|
||||
setRes := &userapi.PerformSetAvatarURLResponse{}
|
||||
if err = profileAPI.SetAvatarURL(req.Context(), &userapi.PerformSetAvatarURLRequest{
|
||||
Localpart: localpart,
|
||||
AvatarURL: r.AvatarURL,
|
||||
Localpart: localpart,
|
||||
ServerName: domain,
|
||||
AvatarURL: r.AvatarURL,
|
||||
}, setRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("profileAPI.SetAvatarURL failed")
|
||||
return jsonerror.InternalServerError()
|
||||
|
|
@ -198,12 +206,19 @@ func SetDisplayName(
|
|||
}
|
||||
}
|
||||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not belong to a locally configured domain"),
|
||||
}
|
||||
}
|
||||
|
||||
evTime, err := httputil.ParseTSParam(req)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -215,6 +230,7 @@ func SetDisplayName(
|
|||
profileRes := &userapi.PerformUpdateDisplayNameResponse{}
|
||||
err = profileAPI.SetDisplayName(req.Context(), &userapi.PerformUpdateDisplayNameRequest{
|
||||
Localpart: localpart,
|
||||
ServerName: domain,
|
||||
DisplayName: r.DisplayName,
|
||||
}, profileRes)
|
||||
if err != nil {
|
||||
|
|
@ -255,6 +271,12 @@ func updateProfile(
|
|||
return jsonerror.InternalServerError(), err
|
||||
}
|
||||
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
}
|
||||
|
||||
events, err := buildMembershipEvents(
|
||||
ctx, res.RoomIDs, *profile, userID, cfg, evTime, rsAPI,
|
||||
)
|
||||
|
|
@ -270,7 +292,7 @@ func updateProfile(
|
|||
return jsonerror.InternalServerError(), e
|
||||
}
|
||||
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, events, cfg.Matrix.ServerName, cfg.Matrix.ServerName, nil, true); err != nil {
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, events, domain, domain, nil, true); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
}
|
||||
|
|
@ -292,7 +314,7 @@ func getProfile(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
profile, fedErr := federation.LookupProfile(ctx, domain, userID, "")
|
||||
if fedErr != nil {
|
||||
if x, ok := fedErr.(gomatrix.HTTPError); ok {
|
||||
|
|
|
|||
|
|
@ -131,7 +131,8 @@ func SendRedaction(
|
|||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
}
|
||||
}
|
||||
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, roomserverAPI.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, cfg.Matrix.ServerName, cfg.Matrix.ServerName, nil, false); err != nil {
|
||||
domain := device.UserDomain()
|
||||
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, roomserverAPI.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, domain, domain, nil, false); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Errorf("failed to SendEvents")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
|
|
@ -338,6 +339,7 @@ func validateRecaptcha(
|
|||
response string,
|
||||
clientip string,
|
||||
) *util.JSONResponse {
|
||||
ip, _, _ := net.SplitHostPort(clientip)
|
||||
if !cfg.RecaptchaEnabled {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusConflict,
|
||||
|
|
@ -357,7 +359,7 @@ func validateRecaptcha(
|
|||
url.Values{
|
||||
"secret": {cfg.RecaptchaPrivateKey},
|
||||
"response": {response},
|
||||
"remoteip": {clientip},
|
||||
"remoteip": {ip},
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -414,7 +416,7 @@ func UserIDIsWithinApplicationServiceNamespace(
|
|||
return false
|
||||
}
|
||||
|
||||
if domain != cfg.Matrix.ServerName {
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,12 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
dendriteAdminRouter.Handle("/admin/downloadState/{serverName}/{roomID}",
|
||||
httputil.MakeAdminAPI("admin_download_state", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return AdminDownloadState(req, cfg, device, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
dendriteAdminRouter.Handle("/admin/fulltext/reindex",
|
||||
httputil.MakeAdminAPI("admin_fultext_reindex", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return AdminReindex(req, cfg, device, natsClient)
|
||||
|
|
@ -493,7 +499,7 @@ func Setup(
|
|||
return GetVisibility(req, rsAPI, vars["roomID"])
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
// TODO: Add AS support
|
||||
|
||||
v3mux.Handle("/directory/list/room/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
|
@ -503,6 +509,27 @@ func Setup(
|
|||
return SetVisibility(req, rsAPI, device, vars["roomID"])
|
||||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
v3mux.Handle("/directory/list/appservice/{networkID}/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return SetVisibilityAS(req, rsAPI, device, vars["networkID"], vars["roomID"])
|
||||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
// Undocumented endpoint
|
||||
v3mux.Handle("/directory/list/appservice/{networkID}/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return SetVisibilityAS(req, rsAPI, device, vars["networkID"], vars["roomID"])
|
||||
}),
|
||||
).Methods(http.MethodDelete, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/publicRooms",
|
||||
httputil.MakeExternalAPI("public_rooms", func(req *http.Request) util.JSONResponse {
|
||||
return GetPostPublicRooms(req, rsAPI, extRoomsProvider, federation, cfg)
|
||||
|
|
@ -963,26 +990,6 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/rooms/{roomID}/members",
|
||||
httputil.MakeAuthAPI("rooms_members", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return GetMemberships(req, device, vars["roomID"], false, cfg, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/rooms/{roomID}/joined_members",
|
||||
httputil.MakeAuthAPI("rooms_members", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return GetMemberships(req, device, vars["roomID"], true, cfg, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/rooms/{roomID}/read_markers",
|
||||
httputil.MakeAuthAPI("rooms_read_markers", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ func SendEvent(
|
|||
// create a mutex for the specific user in the specific room
|
||||
// this avoids a situation where events that are received in quick succession are sent to the roomserver in a jumbled order
|
||||
userID := device.UserID
|
||||
domain := device.UserDomain()
|
||||
mutex, _ := userRoomSendMutexes.LoadOrStore(roomID+userID, &sync.Mutex{})
|
||||
mutex.(*sync.Mutex).Lock()
|
||||
defer mutex.(*sync.Mutex).Unlock()
|
||||
|
|
@ -185,8 +186,8 @@ func SendEvent(
|
|||
[]*gomatrixserverlib.HeaderedEvent{
|
||||
e.Headered(verRes.RoomVersion),
|
||||
},
|
||||
cfg.Matrix.ServerName,
|
||||
cfg.Matrix.ServerName,
|
||||
domain,
|
||||
domain,
|
||||
txnAndSessionID,
|
||||
false,
|
||||
); err != nil {
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ func queryIDServerStoreInvite(
|
|||
}
|
||||
|
||||
var profile *authtypes.Profile
|
||||
if serverName == cfg.Matrix.ServerName {
|
||||
if cfg.Matrix.IsLocalServerName(serverName) {
|
||||
res := &userapi.QueryProfileResponse{}
|
||||
err = userAPI.QueryProfile(ctx, &userapi.QueryProfileRequest{UserID: device.UserID}, res)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
|
|
@ -24,23 +25,23 @@ import (
|
|||
// usernameParam can either be a user ID or just the localpart/username.
|
||||
// If serverName is passed, it is verified against the domain obtained from usernameParam (if present)
|
||||
// Returns error in case of invalid usernameParam.
|
||||
func ParseUsernameParam(usernameParam string, expectedServerName *gomatrixserverlib.ServerName) (string, error) {
|
||||
func ParseUsernameParam(usernameParam string, cfg *config.Global) (string, gomatrixserverlib.ServerName, error) {
|
||||
localpart := usernameParam
|
||||
|
||||
if strings.HasPrefix(usernameParam, "@") {
|
||||
lp, domain, err := gomatrixserverlib.SplitID('@', usernameParam)
|
||||
|
||||
if err != nil {
|
||||
return "", errors.New("invalid username")
|
||||
return "", "", errors.New("invalid username")
|
||||
}
|
||||
|
||||
if expectedServerName != nil && domain != *expectedServerName {
|
||||
return "", errors.New("user ID does not belong to this server")
|
||||
if !cfg.IsLocalServerName(domain) {
|
||||
return "", "", errors.New("user ID does not belong to this server")
|
||||
}
|
||||
|
||||
localpart = lp
|
||||
return lp, domain, nil
|
||||
}
|
||||
return localpart, nil
|
||||
return localpart, cfg.ServerName, nil
|
||||
}
|
||||
|
||||
// MakeUserID generates user ID from localpart & server name
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ package userutil
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
|
|
@ -28,7 +29,11 @@ var (
|
|||
|
||||
// TestGoodUserID checks that correct localpart is returned for a valid user ID.
|
||||
func TestGoodUserID(t *testing.T) {
|
||||
lp, err := ParseUsernameParam(goodUserID, &serverName)
|
||||
cfg := &config.Global{
|
||||
ServerName: serverName,
|
||||
}
|
||||
|
||||
lp, _, err := ParseUsernameParam(goodUserID, cfg)
|
||||
|
||||
if err != nil {
|
||||
t.Error("User ID Parsing failed for ", goodUserID, " with error: ", err.Error())
|
||||
|
|
@ -41,7 +46,11 @@ func TestGoodUserID(t *testing.T) {
|
|||
|
||||
// TestWithLocalpartOnly checks that localpart is returned when usernameParam contains only localpart.
|
||||
func TestWithLocalpartOnly(t *testing.T) {
|
||||
lp, err := ParseUsernameParam(localpart, &serverName)
|
||||
cfg := &config.Global{
|
||||
ServerName: serverName,
|
||||
}
|
||||
|
||||
lp, _, err := ParseUsernameParam(localpart, cfg)
|
||||
|
||||
if err != nil {
|
||||
t.Error("User ID Parsing failed for ", localpart, " with error: ", err.Error())
|
||||
|
|
@ -54,7 +63,11 @@ func TestWithLocalpartOnly(t *testing.T) {
|
|||
|
||||
// TestIncorrectDomain checks for error when there's server name mismatch.
|
||||
func TestIncorrectDomain(t *testing.T) {
|
||||
_, err := ParseUsernameParam(goodUserID, &invalidServerName)
|
||||
cfg := &config.Global{
|
||||
ServerName: invalidServerName,
|
||||
}
|
||||
|
||||
_, _, err := ParseUsernameParam(goodUserID, cfg)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Invalid Domain should return an error")
|
||||
|
|
@ -63,7 +76,11 @@ func TestIncorrectDomain(t *testing.T) {
|
|||
|
||||
// TestBadUserID checks that ParseUsernameParam fails for invalid user ID
|
||||
func TestBadUserID(t *testing.T) {
|
||||
_, err := ParseUsernameParam(badUserID, &serverName)
|
||||
cfg := &config.Global{
|
||||
ServerName: serverName,
|
||||
}
|
||||
|
||||
_, _, err := ParseUsernameParam(badUserID, cfg)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Illegal User ID should return an error")
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -27,9 +28,9 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
|
||||
ironwoodtypes "github.com/Arceliar/ironwood/types"
|
||||
yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
yggdrasilcore "github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
yggdrasildefaults "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||
yggdrasilmulticast "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||
|
||||
gologme "github.com/gologme/log"
|
||||
|
|
@ -37,7 +38,6 @@ import (
|
|||
|
||||
type Node struct {
|
||||
core *yggdrasilcore.Core
|
||||
config *yggdrasilconfig.NodeConfig
|
||||
multicast *yggdrasilmulticast.Multicast
|
||||
log *gologme.Logger
|
||||
utpSocket *utp.Socket
|
||||
|
|
@ -57,43 +57,52 @@ func (n *Node) DialerContext(ctx context.Context, _, address string) (net.Conn,
|
|||
|
||||
func Setup(sk ed25519.PrivateKey, instanceName, storageDirectory, peerURI, listenURI string) (*Node, error) {
|
||||
n := &Node{
|
||||
core: &yggdrasilcore.Core{},
|
||||
config: yggdrasildefaults.GenerateConfig(),
|
||||
multicast: &yggdrasilmulticast.Multicast{},
|
||||
log: gologme.New(logrus.StandardLogger().Writer(), "", 0),
|
||||
incoming: make(chan net.Conn),
|
||||
log: gologme.New(logrus.StandardLogger().Writer(), "", 0),
|
||||
incoming: make(chan net.Conn),
|
||||
}
|
||||
|
||||
options := []yggdrasilcore.SetupOption{
|
||||
yggdrasilcore.AdminListenAddress("none"),
|
||||
}
|
||||
if listenURI != "" {
|
||||
options = append(options, yggdrasilcore.ListenAddress(listenURI))
|
||||
}
|
||||
if peerURI != "" {
|
||||
for _, uri := range strings.Split(peerURI, ",") {
|
||||
options = append(options, yggdrasilcore.Peer{
|
||||
URI: uri,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
if n.core, err = yggdrasilcore.New(sk, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n.log.EnableLevel("error")
|
||||
n.log.EnableLevel("warn")
|
||||
n.log.EnableLevel("info")
|
||||
n.core.SetLogger(n.log)
|
||||
if n.utpSocket, err = utp.NewSocketFromPacketConnNoClose(n.core); err != nil {
|
||||
panic(err)
|
||||
|
||||
{
|
||||
var err error
|
||||
options := []yggdrasilcore.SetupOption{}
|
||||
if listenURI != "" {
|
||||
options = append(options, yggdrasilcore.ListenAddress(listenURI))
|
||||
}
|
||||
if peerURI != "" {
|
||||
for _, uri := range strings.Split(peerURI, ",") {
|
||||
options = append(options, yggdrasilcore.Peer{
|
||||
URI: uri,
|
||||
})
|
||||
}
|
||||
}
|
||||
if n.core, err = core.New(sk[:], n.log, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n.core.SetLogger(n.log)
|
||||
|
||||
if n.utpSocket, err = utp.NewSocketFromPacketConnNoClose(n.core); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if err = n.multicast.Init(n.core, n.config, n.log, nil); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = n.multicast.Start(); err != nil {
|
||||
panic(err)
|
||||
|
||||
// Setup the multicast module.
|
||||
{
|
||||
var err error
|
||||
options := []multicast.SetupOption{
|
||||
multicast.MulticastInterface{
|
||||
Regex: regexp.MustCompile(".*"),
|
||||
Beacon: true,
|
||||
Listen: true,
|
||||
Port: 0,
|
||||
Priority: 0,
|
||||
},
|
||||
}
|
||||
if n.multicast, err = multicast.New(n.core, n.log, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
n.log.Printf("Public key: %x", n.core.PublicKey())
|
||||
|
|
@ -114,14 +123,7 @@ func (n *Node) DerivedServerName() string {
|
|||
}
|
||||
|
||||
func (n *Node) PrivateKey() ed25519.PrivateKey {
|
||||
sk := make(ed25519.PrivateKey, ed25519.PrivateKeySize)
|
||||
sb, err := hex.DecodeString(n.config.PrivateKey)
|
||||
if err == nil {
|
||||
copy(sk, sb[:])
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
return sk
|
||||
return n.core.PrivateKey()
|
||||
}
|
||||
|
||||
func (n *Node) PublicKey() ed25519.PublicKey {
|
||||
|
|
|
|||
|
|
@ -179,7 +179,13 @@ client_api:
|
|||
recaptcha_public_key: ""
|
||||
recaptcha_private_key: ""
|
||||
recaptcha_bypass_secret: ""
|
||||
recaptcha_siteverify_api: ""
|
||||
|
||||
# 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:
|
||||
|
|
@ -310,6 +316,14 @@ user_api:
|
|||
# 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.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,13 @@ client_api:
|
|||
recaptcha_public_key: ""
|
||||
recaptcha_private_key: ""
|
||||
recaptcha_bypass_secret: ""
|
||||
recaptcha_siteverify_api: ""
|
||||
|
||||
# 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:
|
||||
|
|
@ -375,6 +381,14 @@ user_api:
|
|||
# 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.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ matrix.example.com {
|
|||
# Change the end of each reverse_proxy line to the correct
|
||||
# address for your various services.
|
||||
@sync_api {
|
||||
path_regexp /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|context/.*?|relations/.*?|event/.*?))$
|
||||
path_regexp /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|.*?_?members|context/.*?|relations/.*?|event/.*?))$
|
||||
}
|
||||
reverse_proxy @sync_api sync_api:8073
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ VirtualHost {
|
|||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}
|
||||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}/{relType}
|
||||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}/{relType}/{eventType}
|
||||
# /_matrix/client/.*/rooms/{roomId}/members
|
||||
# /_matrix/client/.*/rooms/{roomId}/joined_members
|
||||
# to sync_api
|
||||
ReverseProxy = /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|context/.*?|relations/.*?|event/.*?))$ http://localhost:8073 600
|
||||
ReverseProxy = /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|.*?_?members|context/.*?|relations/.*?|event/.*?))$ http://localhost:8073 600
|
||||
ReverseProxy = /_matrix/client http://localhost:8071 600
|
||||
ReverseProxy = /_matrix/federation http://localhost:8072 600
|
||||
ReverseProxy = /_matrix/key http://localhost:8072 600
|
||||
|
|
|
|||
|
|
@ -33,8 +33,10 @@ server {
|
|||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}
|
||||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}/{relType}
|
||||
# /_matrix/client/.*/rooms/{roomId}/relations/{eventID}/{relType}/{eventType}
|
||||
# /_matrix/client/.*/rooms/{roomId}/members
|
||||
# /_matrix/client/.*/rooms/{roomId}/joined_members
|
||||
# to sync_api
|
||||
location ~ /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|context/.*?|relations/.*?|event/.*?))$ {
|
||||
location ~ /_matrix/client/.*?/(sync|user/.*?/filter/?.*|keys/changes|rooms/.*?/(messages|.*?_?members|context/.*?|relations/.*?|event/.*?))$ {
|
||||
proxy_pass http://sync_api:8073;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ import (
|
|||
|
||||
// KeyChangeConsumer consumes events that originate in key server.
|
||||
type KeyChangeConsumer struct {
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
serverName gomatrixserverlib.ServerName
|
||||
rsAPI roomserverAPI.FederationRoomserverAPI
|
||||
topic string
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
rsAPI roomserverAPI.FederationRoomserverAPI
|
||||
topic string
|
||||
}
|
||||
|
||||
// NewKeyChangeConsumer creates a new KeyChangeConsumer. Call Start() to begin consuming from key servers.
|
||||
|
|
@ -55,14 +55,14 @@ func NewKeyChangeConsumer(
|
|||
rsAPI roomserverAPI.FederationRoomserverAPI,
|
||||
) *KeyChangeConsumer {
|
||||
return &KeyChangeConsumer{
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
durable: cfg.Matrix.JetStream.Prefixed("FederationAPIKeyChangeConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputKeyChangeEvent),
|
||||
queues: queues,
|
||||
db: store,
|
||||
serverName: cfg.Matrix.ServerName,
|
||||
rsAPI: rsAPI,
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
durable: cfg.Matrix.JetStream.Prefixed("FederationAPIKeyChangeConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputKeyChangeEvent),
|
||||
queues: queues,
|
||||
db: store,
|
||||
isLocalServerName: cfg.Matrix.IsLocalServerName,
|
||||
rsAPI: rsAPI,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ func (t *KeyChangeConsumer) onDeviceKeyMessage(m api.DeviceMessage) bool {
|
|||
logger.WithError(err).Error("Failed to extract domain from key change event")
|
||||
return true
|
||||
}
|
||||
if originServerName != t.serverName {
|
||||
if !t.isLocalServerName(originServerName) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ func (t *KeyChangeConsumer) onDeviceKeyMessage(m api.DeviceMessage) bool {
|
|||
// Pack the EDU and marshal it
|
||||
edu := &gomatrixserverlib.EDU{
|
||||
Type: gomatrixserverlib.MDeviceListUpdate,
|
||||
Origin: string(t.serverName),
|
||||
Origin: string(originServerName),
|
||||
}
|
||||
event := gomatrixserverlib.DeviceListUpdateEvent{
|
||||
UserID: m.UserID,
|
||||
|
|
@ -159,7 +159,7 @@ func (t *KeyChangeConsumer) onDeviceKeyMessage(m api.DeviceMessage) bool {
|
|||
}
|
||||
|
||||
logger.Debugf("Sending device list update message to %q", destinations)
|
||||
err = t.queues.SendEDU(edu, t.serverName, destinations)
|
||||
err = t.queues.SendEDU(edu, originServerName, destinations)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ func (t *KeyChangeConsumer) onCrossSigningMessage(m api.DeviceMessage) bool {
|
|||
logrus.WithError(err).Errorf("fedsender key change consumer: user ID parse failure")
|
||||
return true
|
||||
}
|
||||
if host != gomatrixserverlib.ServerName(t.serverName) {
|
||||
if !t.isLocalServerName(host) {
|
||||
// Ignore any messages that didn't originate locally, otherwise we'll
|
||||
// end up parroting information we received from other servers.
|
||||
return true
|
||||
|
|
@ -203,7 +203,7 @@ func (t *KeyChangeConsumer) onCrossSigningMessage(m api.DeviceMessage) bool {
|
|||
// Pack the EDU and marshal it
|
||||
edu := &gomatrixserverlib.EDU{
|
||||
Type: types.MSigningKeyUpdate,
|
||||
Origin: string(t.serverName),
|
||||
Origin: string(host),
|
||||
}
|
||||
if edu.Content, err = json.Marshal(output); err != nil {
|
||||
sentry.CaptureException(err)
|
||||
|
|
@ -212,7 +212,7 @@ func (t *KeyChangeConsumer) onCrossSigningMessage(m api.DeviceMessage) bool {
|
|||
}
|
||||
|
||||
logger.Debugf("Sending cross-signing update message to %q", destinations)
|
||||
err = t.queues.SendEDU(edu, t.serverName, destinations)
|
||||
err = t.queues.SendEDU(edu, host, destinations)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type OutputPresenceConsumer struct {
|
|||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
topic string
|
||||
outboundPresenceEnabled bool
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ func NewOutputPresenceConsumer(
|
|||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
isLocalServerName: cfg.Matrix.IsLocalServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPIPresenceConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputPresenceEvent),
|
||||
outboundPresenceEnabled: cfg.Matrix.Presence.EnableOutbound,
|
||||
|
|
@ -85,7 +85,7 @@ func (t *OutputPresenceConsumer) onMessage(ctx context.Context, msgs []*nats.Msg
|
|||
log.WithError(err).WithField("user_id", userID).Error("failed to extract domain from receipt sender")
|
||||
return true
|
||||
}
|
||||
if serverName != t.ServerName {
|
||||
if !t.isLocalServerName(serverName) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ func (t *OutputPresenceConsumer) onMessage(ctx context.Context, msgs []*nats.Msg
|
|||
|
||||
edu := &gomatrixserverlib.EDU{
|
||||
Type: gomatrixserverlib.MPresence,
|
||||
Origin: string(t.ServerName),
|
||||
Origin: string(serverName),
|
||||
}
|
||||
if edu.Content, err = json.Marshal(content); err != nil {
|
||||
log.WithError(err).Error("failed to marshal EDU JSON")
|
||||
|
|
@ -135,7 +135,7 @@ func (t *OutputPresenceConsumer) onMessage(ctx context.Context, msgs []*nats.Msg
|
|||
}
|
||||
|
||||
log.Tracef("sending presence EDU to %d servers", len(joined))
|
||||
if err = t.queues.SendEDU(edu, t.ServerName, joined); err != nil {
|
||||
if err = t.queues.SendEDU(edu, serverName, joined); err != nil {
|
||||
log.WithError(err).Error("failed to send EDU")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ import (
|
|||
|
||||
// OutputReceiptConsumer consumes events that originate in the clientapi.
|
||||
type OutputReceiptConsumer struct {
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
topic string
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
topic string
|
||||
}
|
||||
|
||||
// NewOutputReceiptConsumer creates a new OutputReceiptConsumer. Call Start() to begin consuming typing events.
|
||||
|
|
@ -52,13 +52,13 @@ func NewOutputReceiptConsumer(
|
|||
store storage.Database,
|
||||
) *OutputReceiptConsumer {
|
||||
return &OutputReceiptConsumer{
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPIReceiptConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputReceiptEvent),
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
isLocalServerName: cfg.Matrix.IsLocalServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPIReceiptConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputReceiptEvent),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ func (t *OutputReceiptConsumer) onMessage(ctx context.Context, msgs []*nats.Msg)
|
|||
log.WithError(err).WithField("user_id", receipt.UserID).Error("failed to extract domain from receipt sender")
|
||||
return true
|
||||
}
|
||||
if receiptServerName != t.ServerName {
|
||||
if !t.isLocalServerName(receiptServerName) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -134,14 +134,14 @@ func (t *OutputReceiptConsumer) onMessage(ctx context.Context, msgs []*nats.Msg)
|
|||
|
||||
edu := &gomatrixserverlib.EDU{
|
||||
Type: gomatrixserverlib.MReceipt,
|
||||
Origin: string(t.ServerName),
|
||||
Origin: string(receiptServerName),
|
||||
}
|
||||
if edu.Content, err = json.Marshal(content); err != nil {
|
||||
log.WithError(err).Error("failed to marshal EDU JSON")
|
||||
return true
|
||||
}
|
||||
|
||||
if err := t.queues.SendEDU(edu, t.ServerName, names); err != nil {
|
||||
if err := t.queues.SendEDU(edu, receiptServerName, names); err != nil {
|
||||
log.WithError(err).Error("failed to send EDU")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ import (
|
|||
|
||||
// OutputSendToDeviceConsumer consumes events that originate in the clientapi.
|
||||
type OutputSendToDeviceConsumer struct {
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
topic string
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
topic string
|
||||
}
|
||||
|
||||
// NewOutputSendToDeviceConsumer creates a new OutputSendToDeviceConsumer. Call Start() to begin consuming send-to-device events.
|
||||
|
|
@ -52,13 +52,13 @@ func NewOutputSendToDeviceConsumer(
|
|||
store storage.Database,
|
||||
) *OutputSendToDeviceConsumer {
|
||||
return &OutputSendToDeviceConsumer{
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPIESendToDeviceConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputSendToDeviceEvent),
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
isLocalServerName: cfg.Matrix.IsLocalServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPIESendToDeviceConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputSendToDeviceEvent),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ func (t *OutputSendToDeviceConsumer) onMessage(ctx context.Context, msgs []*nats
|
|||
log.WithError(err).WithField("user_id", sender).Error("Failed to extract domain from send-to-device sender")
|
||||
return true
|
||||
}
|
||||
if originServerName != t.ServerName {
|
||||
if !t.isLocalServerName(originServerName) {
|
||||
return true
|
||||
}
|
||||
// Extract the send-to-device event from msg.
|
||||
|
|
@ -101,14 +101,14 @@ func (t *OutputSendToDeviceConsumer) onMessage(ctx context.Context, msgs []*nats
|
|||
}
|
||||
|
||||
// The SyncAPI is already handling sendToDevice for the local server
|
||||
if destServerName == t.ServerName {
|
||||
if t.isLocalServerName(destServerName) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Pack the EDU and marshal it
|
||||
edu := &gomatrixserverlib.EDU{
|
||||
Type: gomatrixserverlib.MDirectToDevice,
|
||||
Origin: string(t.ServerName),
|
||||
Origin: string(originServerName),
|
||||
}
|
||||
tdm := gomatrixserverlib.ToDeviceMessage{
|
||||
Sender: ote.Sender,
|
||||
|
|
@ -127,7 +127,7 @@ func (t *OutputSendToDeviceConsumer) onMessage(ctx context.Context, msgs []*nats
|
|||
}
|
||||
|
||||
log.Debugf("Sending send-to-device message into %q destination queue", destServerName)
|
||||
if err := t.queues.SendEDU(edu, t.ServerName, []gomatrixserverlib.ServerName{destServerName}); err != nil {
|
||||
if err := t.queues.SendEDU(edu, originServerName, []gomatrixserverlib.ServerName{destServerName}); err != nil {
|
||||
log.WithError(err).Error("failed to send EDU")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@ import (
|
|||
|
||||
// OutputTypingConsumer consumes events that originate in the clientapi.
|
||||
type OutputTypingConsumer struct {
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
topic string
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
db storage.Database
|
||||
queues *queue.OutgoingQueues
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
topic string
|
||||
}
|
||||
|
||||
// NewOutputTypingConsumer creates a new OutputTypingConsumer. Call Start() to begin consuming typing events.
|
||||
|
|
@ -49,13 +49,13 @@ func NewOutputTypingConsumer(
|
|||
store storage.Database,
|
||||
) *OutputTypingConsumer {
|
||||
return &OutputTypingConsumer{
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPITypingConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputTypingEvent),
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
queues: queues,
|
||||
db: store,
|
||||
isLocalServerName: cfg.Matrix.IsLocalServerName,
|
||||
durable: cfg.Matrix.JetStream.Durable("FederationAPITypingConsumer"),
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputTypingEvent),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ func (t *OutputTypingConsumer) onMessage(ctx context.Context, msgs []*nats.Msg)
|
|||
_ = msg.Ack()
|
||||
return true
|
||||
}
|
||||
if typingServerName != t.ServerName {
|
||||
if !t.isLocalServerName(typingServerName) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ func (t *OutputTypingConsumer) onMessage(ctx context.Context, msgs []*nats.Msg)
|
|||
log.WithError(err).Error("failed to marshal EDU JSON")
|
||||
return true
|
||||
}
|
||||
if err := t.queues.SendEDU(edu, t.ServerName, names); err != nil {
|
||||
if err := t.queues.SendEDU(edu, typingServerName, names); err != nil {
|
||||
log.WithError(err).Error("failed to send EDU")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func AddPublicRoutes(
|
|||
TopicPresenceEvent: cfg.Matrix.JetStream.Prefixed(jetstream.OutputPresenceEvent),
|
||||
TopicDeviceListUpdate: cfg.Matrix.JetStream.Prefixed(jetstream.InputDeviceListUpdate),
|
||||
TopicSigningKeyUpdate: cfg.Matrix.JetStream.Prefixed(jetstream.InputSigningKeyUpdate),
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
Config: cfg,
|
||||
UserAPI: userAPI,
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ func NewInternalAPI(
|
|||
) api.FederationInternalAPI {
|
||||
cfg := &base.Cfg.FederationAPI
|
||||
|
||||
federationDB, err := storage.NewDatabase(base, &cfg.Database, base.Caches, base.Cfg.Global.ServerName)
|
||||
federationDB, err := storage.NewDatabase(base, &cfg.Database, base.Caches, base.Cfg.Global.IsLocalServerName)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Panic("failed to connect to federation sender db")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ func TestMain(m *testing.M) {
|
|||
cfg.Global.JetStream.StoragePath = config.Path(d)
|
||||
cfg.Global.KeyID = serverKeyID
|
||||
cfg.Global.KeyValidityPeriod = s.validity
|
||||
cfg.FederationAPI.KeyPerspectives = nil
|
||||
f, err := os.CreateTemp(d, "federation_keys_test*.db")
|
||||
if err != nil {
|
||||
return -1
|
||||
|
|
@ -207,7 +208,6 @@ func TestRenewalBehaviour(t *testing.T) {
|
|||
// happy at this point that the key that we already have is from the past
|
||||
// then repeating a key fetch should cause us to try and renew the key.
|
||||
// If so, then the new key will end up in our cache.
|
||||
|
||||
serverC.renew()
|
||||
|
||||
res, err = serverA.api.FetchKeys(
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ func TestFederationAPIJoinThenKeyUpdate(t *testing.T) {
|
|||
func testFederationAPIJoinThenKeyUpdate(t *testing.T, dbType test.DBType) {
|
||||
base, close := testrig.CreateBaseDendrite(t, dbType)
|
||||
base.Cfg.FederationAPI.PreferDirectFetch = true
|
||||
base.Cfg.FederationAPI.KeyPerspectives = nil
|
||||
defer close()
|
||||
jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream)
|
||||
defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func (a *FederationInternalAPI) ClaimKeys(
|
|||
) (gomatrixserverlib.RespClaimKeys, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*30)
|
||||
defer cancel()
|
||||
ires, err := a.doRequestIfNotBackingOffOrBlacklisted(s, func() (interface{}, error) {
|
||||
ires, err := a.doRequestIfNotBlacklisted(s, func() (interface{}, error) {
|
||||
return a.federation.ClaimKeys(ctx, s, oneTimeKeys)
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ func (s *FederationInternalAPI) handleLocalKeys(
|
|||
results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult,
|
||||
) {
|
||||
for req := range requests {
|
||||
if req.ServerName != s.cfg.Matrix.ServerName {
|
||||
if !s.cfg.Matrix.IsLocalServerName(req.ServerName) {
|
||||
continue
|
||||
}
|
||||
if req.KeyID == s.cfg.Matrix.KeyID {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func (r *FederationInternalAPI) PerformJoin(
|
|||
seenSet := make(map[gomatrixserverlib.ServerName]bool)
|
||||
var uniqueList []gomatrixserverlib.ServerName
|
||||
for _, srv := range request.ServerNames {
|
||||
if seenSet[srv] || srv == r.cfg.Matrix.ServerName {
|
||||
if seenSet[srv] || r.cfg.Matrix.IsLocalServerName(srv) {
|
||||
continue
|
||||
}
|
||||
seenSet[srv] = true
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/nats-io/nats.go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/syncapi/types"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
|
|
@ -39,7 +40,7 @@ type SyncAPIProducer struct {
|
|||
TopicDeviceListUpdate string
|
||||
TopicSigningKeyUpdate string
|
||||
JetStream nats.JetStreamContext
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
Config *config.FederationAPI
|
||||
UserAPI userapi.UserInternalAPI
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ func (p *SyncAPIProducer) SendToDevice(
|
|||
// device. If the event isn't targeted locally then we can't expand the
|
||||
// wildcard as we don't know about the remote devices, so instead we leave it
|
||||
// as-is, so that the federation sender can send it on with the wildcard intact.
|
||||
if domain == p.ServerName && deviceID == "*" {
|
||||
if p.Config.Matrix.IsLocalServerName(domain) && deviceID == "*" {
|
||||
var res userapi.QueryDevicesResponse
|
||||
err = p.UserAPI.QueryDevices(context.TODO(), &userapi.QueryDevicesRequest{
|
||||
UserID: userID,
|
||||
|
|
|
|||
|
|
@ -76,21 +76,25 @@ func (oq *destinationQueue) sendEvent(event *gomatrixserverlib.HeaderedEvent, re
|
|||
return
|
||||
}
|
||||
|
||||
// If there's room in memory to hold the event then add it to the
|
||||
// list.
|
||||
oq.pendingMutex.Lock()
|
||||
if len(oq.pendingPDUs) < maxPDUsInMemory {
|
||||
oq.pendingPDUs = append(oq.pendingPDUs, &queuedPDU{
|
||||
pdu: event,
|
||||
receipt: receipt,
|
||||
})
|
||||
} else {
|
||||
oq.overflowed.Store(true)
|
||||
}
|
||||
oq.pendingMutex.Unlock()
|
||||
// Check if the destination is blacklisted. If it isn't then wake
|
||||
// up the queue.
|
||||
if !oq.statistics.Blacklisted() {
|
||||
// If there's room in memory to hold the event then add it to the
|
||||
// list.
|
||||
oq.pendingMutex.Lock()
|
||||
if len(oq.pendingPDUs) < maxPDUsInMemory {
|
||||
oq.pendingPDUs = append(oq.pendingPDUs, &queuedPDU{
|
||||
pdu: event,
|
||||
receipt: receipt,
|
||||
})
|
||||
} else {
|
||||
oq.overflowed.Store(true)
|
||||
}
|
||||
oq.pendingMutex.Unlock()
|
||||
|
||||
if !oq.backingOff.Load() {
|
||||
oq.wakeQueueAndNotify()
|
||||
if !oq.backingOff.Load() {
|
||||
oq.wakeQueueAndNotify()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,21 +107,25 @@ func (oq *destinationQueue) sendEDU(event *gomatrixserverlib.EDU, receipt *share
|
|||
return
|
||||
}
|
||||
|
||||
// If there's room in memory to hold the event then add it to the
|
||||
// list.
|
||||
oq.pendingMutex.Lock()
|
||||
if len(oq.pendingEDUs) < maxEDUsInMemory {
|
||||
oq.pendingEDUs = append(oq.pendingEDUs, &queuedEDU{
|
||||
edu: event,
|
||||
receipt: receipt,
|
||||
})
|
||||
} else {
|
||||
oq.overflowed.Store(true)
|
||||
}
|
||||
oq.pendingMutex.Unlock()
|
||||
// Check if the destination is blacklisted. If it isn't then wake
|
||||
// up the queue.
|
||||
if !oq.statistics.Blacklisted() {
|
||||
// If there's room in memory to hold the event then add it to the
|
||||
// list.
|
||||
oq.pendingMutex.Lock()
|
||||
if len(oq.pendingEDUs) < maxEDUsInMemory {
|
||||
oq.pendingEDUs = append(oq.pendingEDUs, &queuedEDU{
|
||||
edu: event,
|
||||
receipt: receipt,
|
||||
})
|
||||
} else {
|
||||
oq.overflowed.Store(true)
|
||||
}
|
||||
oq.pendingMutex.Unlock()
|
||||
|
||||
if !oq.backingOff.Load() {
|
||||
oq.wakeQueueAndNotify()
|
||||
if !oq.backingOff.Load() {
|
||||
oq.wakeQueueAndNotify()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,9 +247,10 @@ func (oqs *OutgoingQueues) SendEvent(
|
|||
return fmt.Errorf("sendevent: oqs.db.StoreJSON: %w", err)
|
||||
}
|
||||
|
||||
destQueues := make([]*destinationQueue, 0, len(destmap))
|
||||
for destination := range destmap {
|
||||
if queue := oqs.getQueue(destination); queue != nil && !queue.statistics.Blacklisted() {
|
||||
queue.sendEvent(ev, nid)
|
||||
if queue := oqs.getQueue(destination); queue != nil {
|
||||
destQueues = append(destQueues, queue)
|
||||
} else {
|
||||
delete(destmap, destination)
|
||||
}
|
||||
|
|
@ -267,6 +268,14 @@ func (oqs *OutgoingQueues) SendEvent(
|
|||
return err
|
||||
}
|
||||
|
||||
// NOTE : PDUs should be associated with destinations before sending
|
||||
// them, otherwise this is technically a race.
|
||||
// If the send completes before they are associated then they won't
|
||||
// get properly cleaned up in the database.
|
||||
for _, queue := range destQueues {
|
||||
queue.sendEvent(ev, nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -335,20 +344,21 @@ func (oqs *OutgoingQueues) SendEDU(
|
|||
return fmt.Errorf("sendevent: oqs.db.StoreJSON: %w", err)
|
||||
}
|
||||
|
||||
destQueues := make([]*destinationQueue, 0, len(destmap))
|
||||
for destination := range destmap {
|
||||
if queue := oqs.getQueue(destination); queue != nil && !queue.statistics.Blacklisted() {
|
||||
queue.sendEDU(e, nid)
|
||||
if queue := oqs.getQueue(destination); queue != nil {
|
||||
destQueues = append(destQueues, queue)
|
||||
} else {
|
||||
delete(destmap, destination)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a database entry that associates the given PDU NID with
|
||||
// this destination queue. We'll then be able to retrieve the PDU
|
||||
// these destination queues. We'll then be able to retrieve the PDU
|
||||
// later.
|
||||
if err := oqs.db.AssociateEDUWithDestinations(
|
||||
oqs.process.Context(),
|
||||
destmap, // the destination server name
|
||||
destmap, // the destination server names
|
||||
nid, // NIDs from federationapi_queue_json table
|
||||
e.Type,
|
||||
nil, // this will use the default expireEDUTypes map
|
||||
|
|
@ -357,6 +367,14 @@ func (oqs *OutgoingQueues) SendEDU(
|
|||
return err
|
||||
}
|
||||
|
||||
// NOTE : EDUs should be associated with destinations before sending
|
||||
// them, otherwise this is technically a race.
|
||||
// If the send completes before they are associated then they won't
|
||||
// get properly cleaned up in the database.
|
||||
for _, queue := range destQueues {
|
||||
queue.sendEDU(e, nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func mustCreateFederationDatabase(t *testing.T, dbType test.DBType, realDatabase
|
|||
connStr, dbClose := test.PrepareDBConnectionString(t, dbType)
|
||||
db, err := storage.NewDatabase(b, &config.DatabaseOptions{
|
||||
ConnectionString: config.DataSource(connStr),
|
||||
}, b.Caches, b.Cfg.Global.ServerName)
|
||||
}, b.Caches, b.Cfg.Global.IsLocalServerName)
|
||||
if err != nil {
|
||||
t.Fatalf("NewDatabase returned %s", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,29 @@ package routing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
type PublicRoomReq struct {
|
||||
Since string `json:"since,omitempty"`
|
||||
Limit int16 `json:"limit,omitempty"`
|
||||
Filter filter `json:"filter,omitempty"`
|
||||
Since string `json:"since,omitempty"`
|
||||
Limit int16 `json:"limit,omitempty"`
|
||||
Filter filter `json:"filter,omitempty"`
|
||||
IncludeAllNetworks bool `json:"include_all_networks,omitempty"`
|
||||
NetworkID string `json:"third_party_instance_id,omitempty"`
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
SearchTerms string `json:"generic_search_term,omitempty"`
|
||||
SearchTerms string `json:"generic_search_term,omitempty"`
|
||||
RoomTypes []string `json:"room_types,omitempty"`
|
||||
}
|
||||
|
||||
// GetPostPublicRooms implements GET and POST /publicRooms
|
||||
|
|
@ -57,8 +62,14 @@ func publicRooms(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if request.IncludeAllNetworks && request.NetworkID != "" {
|
||||
return nil, fmt.Errorf("include_all_networks and third_party_instance_id can not be used together")
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryPublishedRoomsResponse
|
||||
err = rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{}, &queryRes)
|
||||
err = rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{
|
||||
NetworkID: request.NetworkID,
|
||||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("QueryPublishedRooms failed")
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ func Setup(
|
|||
|
||||
mu := internal.NewMutexByRoom()
|
||||
v1fedmux.Handle("/send/{txnID}", MakeFedAPI(
|
||||
"federation_send", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_send", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
return Send(
|
||||
httpReq, request, gomatrixserverlib.TransactionID(vars["txnID"]),
|
||||
|
|
@ -134,7 +134,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
v1fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_invite", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -150,7 +150,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
v2fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_invite", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -172,7 +172,7 @@ func Setup(
|
|||
)).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
v1fedmux.Handle("/exchange_third_party_invite/{roomID}", MakeFedAPI(
|
||||
"exchange_third_party_invite", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"exchange_third_party_invite", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
return ExchangeThirdPartyInvite(
|
||||
httpReq, request, vars["roomID"], rsAPI, cfg, federation,
|
||||
|
|
@ -181,7 +181,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
v1fedmux.Handle("/event/{eventID}", MakeFedAPI(
|
||||
"federation_get_event", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_get_event", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
return GetEvent(
|
||||
httpReq.Context(), request, rsAPI, vars["eventID"], cfg.Matrix.ServerName,
|
||||
|
|
@ -190,7 +190,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/state/{roomID}", MakeFedAPI(
|
||||
"federation_get_state", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_get_state", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -205,7 +205,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/state_ids/{roomID}", MakeFedAPI(
|
||||
"federation_get_state_ids", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_get_state_ids", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -220,7 +220,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/event_auth/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_get_event_auth", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_get_event_auth", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -235,7 +235,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/query/directory", MakeFedAPI(
|
||||
"federation_query_room_alias", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_query_room_alias", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
return RoomAliasToID(
|
||||
httpReq, federation, cfg, rsAPI, fsAPI,
|
||||
|
|
@ -244,7 +244,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/query/profile", MakeFedAPI(
|
||||
"federation_query_profile", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_query_profile", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
return GetProfile(
|
||||
httpReq, userAPI, cfg,
|
||||
|
|
@ -253,7 +253,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/user/devices/{userID}", MakeFedAPI(
|
||||
"federation_user_devices", cfg.Matrix.ServerName, 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 {
|
||||
return GetUserDevices(
|
||||
httpReq, keyAPI, vars["userID"],
|
||||
|
|
@ -263,7 +263,7 @@ func Setup(
|
|||
|
||||
if mscCfg.Enabled("msc2444") {
|
||||
v1fedmux.Handle("/peek/{roomID}/{peekID}", MakeFedAPI(
|
||||
"federation_peek", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_peek", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -294,7 +294,7 @@ func Setup(
|
|||
}
|
||||
|
||||
v1fedmux.Handle("/make_join/{roomID}/{userID}", MakeFedAPI(
|
||||
"federation_make_join", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_make_join", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -325,7 +325,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_send_join", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -357,7 +357,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut)
|
||||
|
||||
v2fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_send_join", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -374,7 +374,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut)
|
||||
|
||||
v1fedmux.Handle("/make_leave/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_make_leave", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_make_leave", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -391,7 +391,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_send_leave", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -423,7 +423,7 @@ func Setup(
|
|||
)).Methods(http.MethodPut)
|
||||
|
||||
v2fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
|
||||
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_send_leave", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -447,7 +447,7 @@ func Setup(
|
|||
)).Methods(http.MethodGet)
|
||||
|
||||
v1fedmux.Handle("/get_missing_events/{roomID}", MakeFedAPI(
|
||||
"federation_get_missing_events", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_get_missing_events", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -460,7 +460,7 @@ func Setup(
|
|||
)).Methods(http.MethodPost)
|
||||
|
||||
v1fedmux.Handle("/backfill/{roomID}", MakeFedAPI(
|
||||
"federation_backfill", cfg.Matrix.ServerName, keys, wakeup,
|
||||
"federation_backfill", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
|
||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
||||
return util.JSONResponse{
|
||||
|
|
@ -479,14 +479,14 @@ func Setup(
|
|||
).Methods(http.MethodGet, http.MethodPost)
|
||||
|
||||
v1fedmux.Handle("/user/keys/claim", MakeFedAPI(
|
||||
"federation_keys_claim", cfg.Matrix.ServerName, 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 {
|
||||
return ClaimOneTimeKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
|
||||
},
|
||||
)).Methods(http.MethodPost)
|
||||
|
||||
v1fedmux.Handle("/user/keys/query", MakeFedAPI(
|
||||
"federation_keys_query", cfg.Matrix.ServerName, 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 {
|
||||
return QueryDeviceKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
|
||||
},
|
||||
|
|
@ -525,15 +525,15 @@ func ErrorIfLocalServerNotInRoom(
|
|||
|
||||
// MakeFedAPI makes an http.Handler that checks matrix federation authentication.
|
||||
func MakeFedAPI(
|
||||
metricsName string,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
metricsName string, serverName gomatrixserverlib.ServerName,
|
||||
isLocalServerName func(gomatrixserverlib.ServerName) bool,
|
||||
keyRing gomatrixserverlib.JSONVerifier,
|
||||
wakeup *FederationWakeups,
|
||||
f func(*http.Request, *gomatrixserverlib.FederationRequest, map[string]string) util.JSONResponse,
|
||||
) http.Handler {
|
||||
h := func(req *http.Request) util.JSONResponse {
|
||||
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
|
||||
req, time.Now(), serverName, keyRing,
|
||||
req, time.Now(), serverName, isLocalServerName, keyRing,
|
||||
)
|
||||
if fedReq == nil {
|
||||
return errResp
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ type Database struct {
|
|||
}
|
||||
|
||||
// NewDatabase opens a new database
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, isLocalServerName func(gomatrixserverlib.ServerName) bool) (*Database, error) {
|
||||
var d Database
|
||||
var err error
|
||||
if d.db, d.writer, err = base.DatabaseConnection(dbProperties, sqlutil.NewDummyWriter()); err != nil {
|
||||
|
|
@ -96,7 +96,7 @@ func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions,
|
|||
}
|
||||
d.Database = shared.Database{
|
||||
DB: d.db,
|
||||
ServerName: serverName,
|
||||
IsLocalServerName: isLocalServerName,
|
||||
Cache: cache,
|
||||
Writer: d.writer,
|
||||
FederationJoinedHosts: joinedHosts,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
|
||||
type Database struct {
|
||||
DB *sql.DB
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
IsLocalServerName func(gomatrixserverlib.ServerName) bool
|
||||
Cache caching.FederationCache
|
||||
Writer sqlutil.Writer
|
||||
FederationQueuePDUs tables.FederationQueuePDUs
|
||||
|
|
@ -124,7 +124,7 @@ func (d *Database) GetJoinedHostsForRooms(ctx context.Context, roomIDs []string,
|
|||
}
|
||||
if excludeSelf {
|
||||
for i, server := range servers {
|
||||
if server == d.ServerName {
|
||||
if d.IsLocalServerName(server) {
|
||||
servers = append(servers[:i], servers[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ type Database struct {
|
|||
}
|
||||
|
||||
// NewDatabase opens a new database
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, serverName gomatrixserverlib.ServerName) (*Database, error) {
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, isLocalServerName func(gomatrixserverlib.ServerName) bool) (*Database, error) {
|
||||
var d Database
|
||||
var err error
|
||||
if d.db, d.writer, err = base.DatabaseConnection(dbProperties, sqlutil.NewExclusiveWriter()); err != nil {
|
||||
|
|
@ -95,7 +95,7 @@ func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions,
|
|||
}
|
||||
d.Database = shared.Database{
|
||||
DB: d.db,
|
||||
ServerName: serverName,
|
||||
IsLocalServerName: isLocalServerName,
|
||||
Cache: cache,
|
||||
Writer: d.writer,
|
||||
FederationJoinedHosts: joinedHosts,
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ import (
|
|||
)
|
||||
|
||||
// NewDatabase opens a new database
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, serverName gomatrixserverlib.ServerName) (Database, error) {
|
||||
func NewDatabase(base *base.BaseDendrite, dbProperties *config.DatabaseOptions, cache caching.FederationCache, isLocalServerName func(gomatrixserverlib.ServerName) bool) (Database, error) {
|
||||
switch {
|
||||
case dbProperties.ConnectionString.IsSQLite():
|
||||
return sqlite3.NewDatabase(base, dbProperties, cache, serverName)
|
||||
return sqlite3.NewDatabase(base, dbProperties, cache, isLocalServerName)
|
||||
case dbProperties.ConnectionString.IsPostgres():
|
||||
return postgres.NewDatabase(base, dbProperties, cache, serverName)
|
||||
return postgres.NewDatabase(base, dbProperties, cache, isLocalServerName)
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected database type")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ func mustCreateFederationDatabase(t *testing.T, dbType test.DBType) (storage.Dat
|
|||
connStr, dbClose := test.PrepareDBConnectionString(t, dbType)
|
||||
db, err := storage.NewDatabase(b, &config.DatabaseOptions{
|
||||
ConnectionString: config.DataSource(connStr),
|
||||
}, b.Caches, b.Cfg.Global.ServerName)
|
||||
}, b.Caches, func(server gomatrixserverlib.ServerName) bool { return server == "localhost" })
|
||||
if err != nil {
|
||||
t.Fatalf("NewDatabase returned %s", err)
|
||||
}
|
||||
|
|
|
|||
38
go.mod
38
go.mod
|
|
@ -1,7 +1,7 @@
|
|||
module github.com/matrix-org/dendrite
|
||||
|
||||
require (
|
||||
github.com/Arceliar/ironwood v0.0.0-20220903132624-ee60c16bcfcf
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
|
|
@ -22,12 +22,12 @@ require (
|
|||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
||||
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/gomatrixserverlib v0.0.0-20221021091412-7c772f1b388a
|
||||
github.com/matrix-org/pinecone v0.0.0-20221007145426-3adc85477dd3
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20221101165746-0e4a8bb6db7e
|
||||
github.com/matrix-org/pinecone v0.0.0-20221026160848-639feeff74d6
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
|
||||
github.com/mattn/go-sqlite3 v1.14.15
|
||||
github.com/nats-io/nats-server/v2 v2.9.3
|
||||
github.com/nats-io/nats.go v1.18.0
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/nats-io/nats-server/v2 v2.9.4
|
||||
github.com/nats-io/nats.go v1.19.0
|
||||
github.com/neilalexander/utp v0.1.1-0.20210727203401-54ae7b1cd5f9
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79
|
||||
|
|
@ -36,18 +36,18 @@ require (
|
|||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tidwall/gjson v1.14.3
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.5-0.20220901155642-4f2abece817c
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.6
|
||||
go.uber.org/atomic v1.10.0
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/image v0.1.0
|
||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/term v0.1.0
|
||||
gopkg.in/h2non/bimg.v1 v1.1.9
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gotest.tools/v3 v3.4.0
|
||||
|
|
@ -120,12 +120,12 @@ require (
|
|||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/time v0.1.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/macaroon.v2 v2.1.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
|
|
|||
77
go.sum
77
go.sum
|
|
@ -38,8 +38,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
|||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/Arceliar/ironwood v0.0.0-20220903132624-ee60c16bcfcf h1:kjPkmDHUTWUma/4tqDl208bOk3jsUEqOJA6TsMZo5Jk=
|
||||
github.com/Arceliar/ironwood v0.0.0-20220903132624-ee60c16bcfcf/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk=
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2 h1:Usab30pNT2i/vZvpXcN9uOr5IO1RZPcUqoGH0DIAPnU=
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk=
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979 h1:WndgpSW13S32VLQ3ugUxx2EnnWmgba1kCqPkd4Gk1yQ=
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
|
|
@ -385,18 +385,18 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw
|
|||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20221021091412-7c772f1b388a h1:6rJFN5NBuzZ7h5meYkLtXKa6VFZfDc8oVXHd4SDXr5o=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20221021091412-7c772f1b388a/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4=
|
||||
github.com/matrix-org/pinecone v0.0.0-20221007145426-3adc85477dd3 h1:lzkSQvBv8TuqKJCPoVwOVvEnARTlua5rrNy/Qw2Vxeo=
|
||||
github.com/matrix-org/pinecone v0.0.0-20221007145426-3adc85477dd3/go.mod h1:K0N1ixHQxXoCyqolDqVxPM3ArrDtcMs8yegOx2Lfv9k=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20221101165746-0e4a8bb6db7e h1:6I34fdyiHMRCxL6GOb/G8ZyI1WWlb6ZxCF2hIGSMSCc=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20221101165746-0e4a8bb6db7e/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4=
|
||||
github.com/matrix-org/pinecone v0.0.0-20221026160848-639feeff74d6 h1:nAT5w41Q9uWTSnpKW55/hBwP91j2IFYPDRs0jJ8TyFI=
|
||||
github.com/matrix-org/pinecone v0.0.0-20221026160848-639feeff74d6/go.mod h1:K0N1ixHQxXoCyqolDqVxPM3ArrDtcMs8yegOx2Lfv9k=
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk=
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237/go.mod h1:UOnLAUmVG5paym8pD3C4B9BQylUDC2vXFJJpT7JrlEA=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
|
||||
|
|
@ -425,10 +425,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
|
||||
github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
|
||||
github.com/nats-io/nats-server/v2 v2.9.3 h1:HrfzA7G9LNetKkm1z+jU/e9kuAe+E6uaBuuq9EB5sQQ=
|
||||
github.com/nats-io/nats-server/v2 v2.9.3/go.mod h1:4sq8wvrpbvSzL1n3ZfEYnH4qeUuIl5W990j3kw13rRk=
|
||||
github.com/nats-io/nats.go v1.18.0 h1:o480Ao6kuSSFyJO75rGTXCEPj7LGkY84C1Ye+Uhm4c0=
|
||||
github.com/nats-io/nats.go v1.18.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
||||
github.com/nats-io/nats-server/v2 v2.9.4 h1:GvRgv1936J/zYUwMg/cqtYaJ6L+bgeIOIvPslbesdow=
|
||||
github.com/nats-io/nats-server/v2 v2.9.4/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
|
||||
github.com/nats-io/nats.go v1.19.0 h1:H6j8aBnTQFoVrTGB6Xjd903UMdE7jz6DS4YkmAqgZ9Q=
|
||||
github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
|
||||
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
|
|
@ -553,8 +553,9 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
|
@ -562,8 +563,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
|
||||
|
|
@ -592,8 +594,8 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
|||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.5-0.20220901155642-4f2abece817c h1:/cTmA6pV2Z20BT/FGSmnb5BmJ8eRbDP0HbCB5IO1aKw=
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.5-0.20220901155642-4f2abece817c/go.mod h1:cIwhYwX9yT9Bcei59O0oOBSaj+kQP+9aVQUMWHh5R00=
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.6 h1:GALUDV9QPz/5FVkbazpkTc9EABHufA556JwUJZr41j4=
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.6/go.mod h1:PBMoAOvQjA9geNEeGyMXA9QgCS6Bu+9V+1VkWM84wpw=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
|
@ -631,8 +633,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
|
|||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
|
@ -647,13 +649,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-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-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg=
|
||||
golang.org/x/exp v0.0.0-20221012211006-4de253d81b95/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 h1:QfTh0HpN6hlw6D3vu8DAwC8pBIwikq0AI1evdm+FksE=
|
||||
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326/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-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-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
||||
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/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=
|
||||
|
|
@ -668,8 +670,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
|
|||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
|
||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
|
||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
|
||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e h1:zSgtO19fpg781xknwqiQPmOHaASr6E7ZVlTseLd9Fx4=
|
||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
|
|
@ -677,8 +679,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
|||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -724,8 +727,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
|||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/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.0.0-20220728211354-c7608f3a8462/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
|
@ -748,7 +751,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -818,12 +820,12 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220730100132-1609e554cd39/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/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-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4=
|
||||
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w=
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -831,14 +833,14 @@ 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.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.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -888,8 +890,9 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ var build string
|
|||
const (
|
||||
VersionMajor = 0
|
||||
VersionMinor = 10
|
||||
VersionPatch = 4
|
||||
VersionPatch = 6
|
||||
VersionTag = "" // example: "rc1"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -128,58 +128,49 @@ func (a *KeyInternalAPI) PerformClaimKeys(ctx context.Context, req *api.PerformC
|
|||
func (a *KeyInternalAPI) claimRemoteKeys(
|
||||
ctx context.Context, timeout time.Duration, res *api.PerformClaimKeysResponse, domainToDeviceKeys map[string]map[string]map[string]string,
|
||||
) {
|
||||
resultCh := make(chan *gomatrixserverlib.RespClaimKeys, len(domainToDeviceKeys))
|
||||
// allows us to wait until all federation servers have been poked
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(domainToDeviceKeys))
|
||||
// mutex for failures
|
||||
var failMu sync.Mutex
|
||||
util.GetLogger(ctx).WithField("num_servers", len(domainToDeviceKeys)).Info("Claiming remote keys from servers")
|
||||
var wg sync.WaitGroup // Wait for fan-out goroutines to finish
|
||||
var mu sync.Mutex // Protects the response struct
|
||||
var claimed int // Number of keys claimed in total
|
||||
var failures int // Number of servers we failed to ask
|
||||
|
||||
util.GetLogger(ctx).Infof("Claiming remote keys from %d server(s)", len(domainToDeviceKeys))
|
||||
wg.Add(len(domainToDeviceKeys))
|
||||
|
||||
// fan out
|
||||
for d, k := range domainToDeviceKeys {
|
||||
go func(domain string, keysToClaim map[string]map[string]string) {
|
||||
defer wg.Done()
|
||||
fedCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
defer wg.Done()
|
||||
|
||||
claimKeyRes, err := a.FedClient.ClaimKeys(fedCtx, gomatrixserverlib.ServerName(domain), keysToClaim)
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).WithField("server", domain).Error("ClaimKeys failed")
|
||||
failMu.Lock()
|
||||
res.Failures[domain] = map[string]interface{}{
|
||||
"message": err.Error(),
|
||||
}
|
||||
failMu.Unlock()
|
||||
failures++
|
||||
return
|
||||
}
|
||||
resultCh <- &claimKeyRes
|
||||
|
||||
for userID, deviceIDToKeys := range claimKeyRes.OneTimeKeys {
|
||||
res.OneTimeKeys[userID] = make(map[string]map[string]json.RawMessage)
|
||||
for deviceID, keys := range deviceIDToKeys {
|
||||
res.OneTimeKeys[userID][deviceID] = keys
|
||||
claimed += len(keys)
|
||||
}
|
||||
}
|
||||
}(d, k)
|
||||
}
|
||||
|
||||
// Close the result channel when the goroutines have quit so the for .. range exits
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultCh)
|
||||
}()
|
||||
|
||||
keysClaimed := 0
|
||||
for result := range resultCh {
|
||||
for userID, nest := range result.OneTimeKeys {
|
||||
res.OneTimeKeys[userID] = make(map[string]map[string]json.RawMessage)
|
||||
for deviceID, nest2 := range nest {
|
||||
res.OneTimeKeys[userID][deviceID] = make(map[string]json.RawMessage)
|
||||
for keyIDWithAlgo, otk := range nest2 {
|
||||
keyJSON, err := json.Marshal(otk)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
res.OneTimeKeys[userID][deviceID][keyIDWithAlgo] = keyJSON
|
||||
keysClaimed++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
util.GetLogger(ctx).WithField("num_keys", keysClaimed).Info("Claimed remote keys")
|
||||
wg.Wait()
|
||||
util.GetLogger(ctx).WithFields(logrus.Fields{
|
||||
"num_keys": claimed,
|
||||
"num_failures": failures,
|
||||
}).Infof("Claimed remote keys from %d server(s)", len(domainToDeviceKeys))
|
||||
}
|
||||
|
||||
func (a *KeyInternalAPI) PerformDeleteKeys(ctx context.Context, req *api.PerformDeleteKeysRequest, res *api.PerformDeleteKeysResponse) error {
|
||||
|
|
@ -257,9 +248,6 @@ func (a *KeyInternalAPI) QueryKeys(ctx context.Context, req *api.QueryKeysReques
|
|||
res.UserSigningKeys = make(map[string]gomatrixserverlib.CrossSigningKey)
|
||||
res.Failures = make(map[string]interface{})
|
||||
|
||||
// get cross-signing keys from the database
|
||||
a.crossSigningKeysFromDatabase(ctx, req, res)
|
||||
|
||||
// make a map from domain to device keys
|
||||
domainToDeviceKeys := make(map[string]map[string][]string)
|
||||
domainToCrossSigningKeys := make(map[string]map[string]struct{})
|
||||
|
|
@ -336,6 +324,10 @@ func (a *KeyInternalAPI) QueryKeys(ctx context.Context, req *api.QueryKeysReques
|
|||
a.queryRemoteKeys(ctx, req.Timeout, res, domainToDeviceKeys, domainToCrossSigningKeys)
|
||||
}
|
||||
|
||||
// Now that we've done the potentially expensive work of asking the federation,
|
||||
// try filling the cross-signing keys from the database that we know about.
|
||||
a.crossSigningKeysFromDatabase(ctx, req, res)
|
||||
|
||||
// Finally, append signatures that we know about
|
||||
// TODO: This is horrible because we need to round-trip the signature from
|
||||
// JSON, add the signatures and marshal it again, for some reason?
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ CREATE INDEX IF NOT EXISTS keyserver_cross_signing_sigs_idx ON keyserver_cross_s
|
|||
|
||||
const selectCrossSigningSigsForTargetSQL = "" +
|
||||
"SELECT origin_user_id, origin_key_id, signature FROM keyserver_cross_signing_sigs" +
|
||||
" WHERE (origin_user_id = $1 OR origin_user_id = target_user_id) AND target_user_id = $2 AND target_key_id = $3"
|
||||
" WHERE (origin_user_id = $1 OR origin_user_id = $2) AND target_user_id = $2 AND target_key_id = $3"
|
||||
|
||||
const upsertCrossSigningSigsForTargetSQL = "" +
|
||||
"INSERT INTO keyserver_cross_signing_sigs (origin_user_id, origin_key_id, target_user_id, target_key_id, signature)" +
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ CREATE INDEX IF NOT EXISTS keyserver_cross_signing_sigs_idx ON keyserver_cross_s
|
|||
|
||||
const selectCrossSigningSigsForTargetSQL = "" +
|
||||
"SELECT origin_user_id, origin_key_id, signature FROM keyserver_cross_signing_sigs" +
|
||||
" WHERE (origin_user_id = $1 OR origin_user_id = target_user_id) AND target_user_id = $2 AND target_key_id = $3"
|
||||
" WHERE (origin_user_id = $1 OR origin_user_id = $2) AND target_user_id = $3 AND target_key_id = $4"
|
||||
|
||||
const upsertCrossSigningSigsForTargetSQL = "" +
|
||||
"INSERT OR REPLACE INTO keyserver_cross_signing_sigs (origin_user_id, origin_key_id, target_user_id, target_key_id, signature)" +
|
||||
|
|
@ -85,7 +85,7 @@ func NewSqliteCrossSigningSigsTable(db *sql.DB) (tables.CrossSigningSigs, error)
|
|||
func (s *crossSigningSigsStatements) SelectCrossSigningSigsForTarget(
|
||||
ctx context.Context, txn *sql.Tx, originUserID, targetUserID string, targetKeyID gomatrixserverlib.KeyID,
|
||||
) (r types.CrossSigningSigMap, err error) {
|
||||
rows, err := sqlutil.TxStmt(txn, s.selectCrossSigningSigsForTargetStmt).QueryContext(ctx, originUserID, targetUserID, targetKeyID)
|
||||
rows, err := sqlutil.TxStmt(txn, s.selectCrossSigningSigsForTargetStmt).QueryContext(ctx, originUserID, targetUserID, targetUserID, targetKeyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ type ClientRoomserverAPI interface {
|
|||
PerformRoomUpgrade(ctx context.Context, req *PerformRoomUpgradeRequest, resp *PerformRoomUpgradeResponse) error
|
||||
PerformAdminEvacuateRoom(ctx context.Context, req *PerformAdminEvacuateRoomRequest, res *PerformAdminEvacuateRoomResponse) error
|
||||
PerformAdminEvacuateUser(ctx context.Context, req *PerformAdminEvacuateUserRequest, res *PerformAdminEvacuateUserResponse) error
|
||||
PerformAdminDownloadState(ctx context.Context, req *PerformAdminDownloadStateRequest, res *PerformAdminDownloadStateResponse) error
|
||||
PerformPeek(ctx context.Context, req *PerformPeekRequest, res *PerformPeekResponse) error
|
||||
PerformUnpeek(ctx context.Context, req *PerformUnpeekRequest, res *PerformUnpeekResponse) error
|
||||
PerformInvite(ctx context.Context, req *PerformInviteRequest, res *PerformInviteResponse) error
|
||||
|
|
@ -167,6 +168,7 @@ type UserRoomserverAPI interface {
|
|||
QueryCurrentState(ctx context.Context, req *QueryCurrentStateRequest, res *QueryCurrentStateResponse) error
|
||||
QueryMembershipsForRoom(ctx context.Context, req *QueryMembershipsForRoomRequest, res *QueryMembershipsForRoomResponse) error
|
||||
PerformAdminEvacuateUser(ctx context.Context, req *PerformAdminEvacuateUserRequest, res *PerformAdminEvacuateUserResponse) error
|
||||
PerformJoin(ctx context.Context, req *PerformJoinRequest, res *PerformJoinResponse) error
|
||||
}
|
||||
|
||||
type FederationRoomserverAPI interface {
|
||||
|
|
|
|||
|
|
@ -131,6 +131,16 @@ func (t *RoomserverInternalAPITrace) PerformAdminEvacuateUser(
|
|||
return err
|
||||
}
|
||||
|
||||
func (t *RoomserverInternalAPITrace) PerformAdminDownloadState(
|
||||
ctx context.Context,
|
||||
req *PerformAdminDownloadStateRequest,
|
||||
res *PerformAdminDownloadStateResponse,
|
||||
) error {
|
||||
err := t.Impl.PerformAdminDownloadState(ctx, req, res)
|
||||
util.GetLogger(ctx).WithError(err).Infof("PerformAdminDownloadState req=%+v res=%+v", js(req), js(res))
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *RoomserverInternalAPITrace) PerformInboundPeek(
|
||||
ctx context.Context,
|
||||
req *PerformInboundPeekRequest,
|
||||
|
|
|
|||
|
|
@ -168,8 +168,10 @@ type PerformBackfillResponse struct {
|
|||
}
|
||||
|
||||
type PerformPublishRequest struct {
|
||||
RoomID string
|
||||
Visibility string
|
||||
RoomID string
|
||||
Visibility string
|
||||
AppserviceID string
|
||||
NetworkID string
|
||||
}
|
||||
|
||||
type PerformPublishResponse struct {
|
||||
|
|
@ -235,3 +237,13 @@ type PerformAdminEvacuateUserResponse struct {
|
|||
Affected []string `json:"affected"`
|
||||
Error *PerformError
|
||||
}
|
||||
|
||||
type PerformAdminDownloadStateRequest struct {
|
||||
RoomID string `json:"room_id"`
|
||||
UserID string `json:"user_id"`
|
||||
ServerName gomatrixserverlib.ServerName `json:"server_name"`
|
||||
}
|
||||
|
||||
type PerformAdminDownloadStateResponse struct {
|
||||
Error *PerformError `json:"error,omitempty"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
)
|
||||
|
||||
// QueryLatestEventsAndStateRequest is a request to QueryLatestEventsAndState
|
||||
|
|
@ -257,7 +258,9 @@ type QueryRoomVersionForRoomResponse struct {
|
|||
|
||||
type QueryPublishedRoomsRequest struct {
|
||||
// Optional. If specified, returns whether this room is published or not.
|
||||
RoomID string
|
||||
RoomID string
|
||||
NetworkID string
|
||||
IncludeAllNetworks bool
|
||||
}
|
||||
|
||||
type QueryPublishedRoomsResponse struct {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -159,7 +160,7 @@ func GetMembershipsAtState(
|
|||
ctx context.Context, db storage.Database, stateEntries []types.StateEntry, joinedOnly bool,
|
||||
) ([]types.Event, error) {
|
||||
|
||||
var eventNIDs []types.EventNID
|
||||
var eventNIDs types.EventNIDs
|
||||
for _, entry := range stateEntries {
|
||||
// Filter the events to retrieve to only keep the membership events
|
||||
if entry.EventTypeNID == types.MRoomMemberNID {
|
||||
|
|
@ -167,6 +168,14 @@ func GetMembershipsAtState(
|
|||
}
|
||||
}
|
||||
|
||||
// There are no events to get, don't bother asking the database
|
||||
if len(eventNIDs) == 0 {
|
||||
return []types.Event{}, nil
|
||||
}
|
||||
|
||||
sort.Sort(eventNIDs)
|
||||
util.Unique(eventNIDs)
|
||||
|
||||
// Get all of the events in this state
|
||||
stateEvents, err := db.Events(ctx, eventNIDs)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ func (r *Admin) PerformAdminEvacuateRoom(
|
|||
PrevEvents: prevEvents,
|
||||
}
|
||||
|
||||
_, senderDomain, err := gomatrixserverlib.SplitID('@', fledglingEvent.Sender)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if fledglingEvent.Content, err = json.Marshal(memberContent); err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
|
|
@ -146,8 +151,8 @@ func (r *Admin) PerformAdminEvacuateRoom(
|
|||
inputEvents = append(inputEvents, api.InputRoomEvent{
|
||||
Kind: api.KindNew,
|
||||
Event: event,
|
||||
Origin: r.Cfg.Matrix.ServerName,
|
||||
SendAsServer: string(r.Cfg.Matrix.ServerName),
|
||||
Origin: senderDomain,
|
||||
SendAsServer: string(senderDomain),
|
||||
})
|
||||
res.Affected = append(res.Affected, stateKey)
|
||||
prevEvents = []gomatrixserverlib.EventReference{
|
||||
|
|
@ -176,7 +181,7 @@ func (r *Admin) PerformAdminEvacuateUser(
|
|||
}
|
||||
return nil
|
||||
}
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: "Can only evacuate local users using this endpoint",
|
||||
|
|
@ -231,3 +236,145 @@ func (r *Admin) PerformAdminEvacuateUser(
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Admin) PerformAdminDownloadState(
|
||||
ctx context.Context,
|
||||
req *api.PerformAdminDownloadStateRequest,
|
||||
res *api.PerformAdminDownloadStateResponse,
|
||||
) error {
|
||||
roomInfo, err := r.DB.RoomInfo(ctx, req.RoomID)
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("r.DB.RoomInfo: %s", err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if roomInfo == nil || roomInfo.IsStub() {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("room %q not found", req.RoomID),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
fwdExtremities, _, depth, err := r.DB.LatestEventIDs(ctx, roomInfo.RoomNID)
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("r.DB.LatestEventIDs: %s", err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
authEventMap := map[string]*gomatrixserverlib.Event{}
|
||||
stateEventMap := map[string]*gomatrixserverlib.Event{}
|
||||
|
||||
for _, fwdExtremity := range fwdExtremities {
|
||||
var state gomatrixserverlib.RespState
|
||||
state, err = r.Inputer.FSAPI.LookupState(ctx, req.ServerName, req.RoomID, fwdExtremity.EventID, roomInfo.RoomVersion)
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("r.Inputer.FSAPI.LookupState (%q): %s", fwdExtremity.EventID, err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for _, authEvent := range state.AuthEvents.UntrustedEvents(roomInfo.RoomVersion) {
|
||||
if err = authEvent.VerifyEventSignatures(ctx, r.Inputer.KeyRing); err != nil {
|
||||
continue
|
||||
}
|
||||
authEventMap[authEvent.EventID()] = authEvent
|
||||
}
|
||||
for _, stateEvent := range state.StateEvents.UntrustedEvents(roomInfo.RoomVersion) {
|
||||
if err = stateEvent.VerifyEventSignatures(ctx, r.Inputer.KeyRing); err != nil {
|
||||
continue
|
||||
}
|
||||
stateEventMap[stateEvent.EventID()] = stateEvent
|
||||
}
|
||||
}
|
||||
|
||||
authEvents := make([]*gomatrixserverlib.HeaderedEvent, 0, len(authEventMap))
|
||||
stateEvents := make([]*gomatrixserverlib.HeaderedEvent, 0, len(stateEventMap))
|
||||
stateIDs := make([]string, 0, len(stateEventMap))
|
||||
|
||||
for _, authEvent := range authEventMap {
|
||||
authEvents = append(authEvents, authEvent.Headered(roomInfo.RoomVersion))
|
||||
}
|
||||
for _, stateEvent := range stateEventMap {
|
||||
stateEvents = append(stateEvents, stateEvent.Headered(roomInfo.RoomVersion))
|
||||
stateIDs = append(stateIDs, stateEvent.EventID())
|
||||
}
|
||||
|
||||
builder := &gomatrixserverlib.EventBuilder{
|
||||
Type: "org.matrix.dendrite.state_download",
|
||||
Sender: req.UserID,
|
||||
RoomID: req.RoomID,
|
||||
Content: gomatrixserverlib.RawJSON("{}"),
|
||||
}
|
||||
|
||||
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("gomatrixserverlib.StateNeededForEventBuilder: %s", err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
queryRes := &api.QueryLatestEventsAndStateResponse{
|
||||
RoomExists: true,
|
||||
RoomVersion: roomInfo.RoomVersion,
|
||||
LatestEvents: fwdExtremities,
|
||||
StateEvents: stateEvents,
|
||||
Depth: depth,
|
||||
}
|
||||
|
||||
ev, err := eventutil.BuildEvent(ctx, builder, r.Cfg.Matrix, time.Now(), &eventsNeeded, queryRes)
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("eventutil.BuildEvent: %s", err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
inputReq := &api.InputRoomEventsRequest{
|
||||
Asynchronous: false,
|
||||
}
|
||||
inputRes := &api.InputRoomEventsResponse{}
|
||||
|
||||
for _, authEvent := range append(authEvents, stateEvents...) {
|
||||
inputReq.InputRoomEvents = append(inputReq.InputRoomEvents, api.InputRoomEvent{
|
||||
Kind: api.KindOutlier,
|
||||
Event: authEvent,
|
||||
})
|
||||
}
|
||||
|
||||
inputReq.InputRoomEvents = append(inputReq.InputRoomEvents, api.InputRoomEvent{
|
||||
Kind: api.KindNew,
|
||||
Event: ev,
|
||||
Origin: r.Cfg.Matrix.ServerName,
|
||||
HasState: true,
|
||||
StateEventIDs: stateIDs,
|
||||
SendAsServer: string(r.Cfg.Matrix.ServerName),
|
||||
})
|
||||
|
||||
if err := r.Inputer.InputRoomEvents(ctx, inputReq, inputRes); err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("r.Inputer.InputRoomEvents: %s", err),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if inputRes.ErrMsg != "" {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: inputRes.ErrMsg,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ func (r *Inviter) PerformInvite(
|
|||
}
|
||||
return nil, nil
|
||||
}
|
||||
isTargetLocal := domain == r.Cfg.Matrix.ServerName
|
||||
isOriginLocal := senderDomain == r.Cfg.Matrix.ServerName
|
||||
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(domain)
|
||||
isOriginLocal := r.Cfg.Matrix.IsLocalServerName(senderDomain)
|
||||
if !isOriginLocal && !isTargetLocal {
|
||||
res.Error = &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (r *Joiner) performJoin(
|
|||
Msg: fmt.Sprintf("Supplied user ID %q in incorrect format", req.UserID),
|
||||
}
|
||||
}
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
return "", "", &rsAPI.PerformError{
|
||||
Code: rsAPI.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("User %q does not belong to this homeserver", req.UserID),
|
||||
|
|
@ -124,7 +124,7 @@ func (r *Joiner) performJoinRoomByAlias(
|
|||
// Check if this alias matches our own server configuration. If it
|
||||
// doesn't then we'll need to try a federated join.
|
||||
var roomID string
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
// The alias isn't owned by us, so we will need to try joining using
|
||||
// a remote server.
|
||||
dirReq := fsAPI.PerformDirectoryLookupRequest{
|
||||
|
|
@ -172,7 +172,7 @@ func (r *Joiner) performJoinRoomByID(
|
|||
// The original client request ?server_name=... may include this HS so filter that out so we
|
||||
// don't attempt to make_join with ourselves
|
||||
for i := 0; i < len(req.ServerNames); i++ {
|
||||
if req.ServerNames[i] == r.Cfg.Matrix.ServerName {
|
||||
if r.Cfg.Matrix.IsLocalServerName(req.ServerNames[i]) {
|
||||
// delete this entry
|
||||
req.ServerNames = append(req.ServerNames[:i], req.ServerNames[i+1:]...)
|
||||
i--
|
||||
|
|
@ -191,12 +191,19 @@ func (r *Joiner) performJoinRoomByID(
|
|||
// If the server name in the room ID isn't ours then it's a
|
||||
// possible candidate for finding the room via federation. Add
|
||||
// it to the list of servers to try.
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
req.ServerNames = append(req.ServerNames, domain)
|
||||
}
|
||||
|
||||
// Prepare the template for the join event.
|
||||
userID := req.UserID
|
||||
_, userDomain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return "", "", &rsAPI.PerformError{
|
||||
Code: rsAPI.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("User ID %q is invalid: %s", userID, err),
|
||||
}
|
||||
}
|
||||
eb := gomatrixserverlib.EventBuilder{
|
||||
Type: gomatrixserverlib.MRoomMember,
|
||||
Sender: userID,
|
||||
|
|
@ -247,7 +254,7 @@ func (r *Joiner) performJoinRoomByID(
|
|||
|
||||
// If we were invited by someone from another server then we can
|
||||
// assume they are in the room so we can join via them.
|
||||
if inviterDomain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(inviterDomain) {
|
||||
req.ServerNames = append(req.ServerNames, inviterDomain)
|
||||
forceFederatedJoin = true
|
||||
memberEvent := gjson.Parse(string(inviteEvent.JSON()))
|
||||
|
|
@ -300,7 +307,7 @@ func (r *Joiner) performJoinRoomByID(
|
|||
{
|
||||
Kind: rsAPI.KindNew,
|
||||
Event: event.Headered(buildRes.RoomVersion),
|
||||
SendAsServer: string(r.Cfg.Matrix.ServerName),
|
||||
SendAsServer: string(userDomain),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -323,7 +330,7 @@ func (r *Joiner) performJoinRoomByID(
|
|||
// The room doesn't exist locally. If the room ID looks like it should
|
||||
// be ours then this probably means that we've nuked our database at
|
||||
// some point.
|
||||
if domain == r.Cfg.Matrix.ServerName {
|
||||
if r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
// If there are no more server names to try then give up here.
|
||||
// Otherwise we'll try a federated join as normal, since it's quite
|
||||
// possible that the room still exists on other servers.
|
||||
|
|
@ -348,7 +355,7 @@ func (r *Joiner) performJoinRoomByID(
|
|||
// it will have been overwritten with a room ID by performJoinRoomByAlias.
|
||||
// We should now include this in the response so that the CS API can
|
||||
// return the right room ID.
|
||||
return req.RoomIDOrAlias, r.Cfg.Matrix.ServerName, nil
|
||||
return req.RoomIDOrAlias, userDomain, nil
|
||||
}
|
||||
|
||||
func (r *Joiner) performFederatedJoinRoomByID(
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func (r *Leaver) PerformLeave(
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("supplied user ID %q in incorrect format", req.UserID)
|
||||
}
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
return nil, fmt.Errorf("user %q does not belong to this homeserver", req.UserID)
|
||||
}
|
||||
logger := logrus.WithContext(ctx).WithFields(logrus.Fields{
|
||||
|
|
@ -85,7 +85,7 @@ func (r *Leaver) performLeaveRoomByID(
|
|||
if serr != nil {
|
||||
return nil, fmt.Errorf("sender %q is invalid", senderUser)
|
||||
}
|
||||
if senderDomain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(senderDomain) {
|
||||
return r.performFederatedRejectInvite(ctx, req, res, senderUser, eventID)
|
||||
}
|
||||
// check that this is not a "server notice room"
|
||||
|
|
@ -186,7 +186,7 @@ func (r *Leaver) performLeaveRoomByID(
|
|||
Kind: api.KindNew,
|
||||
Event: event.Headered(buildRes.RoomVersion),
|
||||
Origin: senderDomain,
|
||||
SendAsServer: string(r.Cfg.Matrix.ServerName),
|
||||
SendAsServer: string(senderDomain),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func (r *Peeker) performPeek(
|
|||
Msg: fmt.Sprintf("Supplied user ID %q in incorrect format", req.UserID),
|
||||
}
|
||||
}
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
return "", &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("User %q does not belong to this homeserver", req.UserID),
|
||||
|
|
@ -104,7 +104,7 @@ func (r *Peeker) performPeekRoomByAlias(
|
|||
// Check if this alias matches our own server configuration. If it
|
||||
// doesn't then we'll need to try a federated peek.
|
||||
var roomID string
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
// The alias isn't owned by us, so we will need to try peeking using
|
||||
// a remote server.
|
||||
dirReq := fsAPI.PerformDirectoryLookupRequest{
|
||||
|
|
@ -154,7 +154,7 @@ func (r *Peeker) performPeekRoomByID(
|
|||
|
||||
// handle federated peeks
|
||||
// FIXME: don't create an outbound peek if we already have one going.
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
// If the server name in the room ID isn't ours then it's a
|
||||
// possible candidate for finding the room via federation. Add
|
||||
// it to the list of servers to try.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ func (r *Publisher) PerformPublish(
|
|||
req *api.PerformPublishRequest,
|
||||
res *api.PerformPublishResponse,
|
||||
) error {
|
||||
err := r.DB.PublishRoom(ctx, req.RoomID, req.Visibility == "public")
|
||||
err := r.DB.PublishRoom(ctx, req.RoomID, req.AppserviceID, req.NetworkID, req.Visibility == "public")
|
||||
if err != nil {
|
||||
res.Error = &api.PerformError{
|
||||
Msg: err.Error(),
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func (r *Unpeeker) performUnpeek(
|
|||
Msg: fmt.Sprintf("Supplied user ID %q in incorrect format", req.UserID),
|
||||
}
|
||||
}
|
||||
if domain != r.Cfg.Matrix.ServerName {
|
||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||
return &api.PerformError{
|
||||
Code: api.PerformErrorBadRequest,
|
||||
Msg: fmt.Sprintf("User %q does not belong to this homeserver", req.UserID),
|
||||
|
|
|
|||
|
|
@ -60,6 +60,13 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
) (string, *api.PerformError) {
|
||||
roomID := req.RoomID
|
||||
userID := req.UserID
|
||||
_, userDomain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return "", &api.PerformError{
|
||||
Code: api.PerformErrorNotAllowed,
|
||||
Msg: "Error validating the user ID",
|
||||
}
|
||||
}
|
||||
evTime := time.Now()
|
||||
|
||||
// Return an immediate error if the room does not exist
|
||||
|
|
@ -80,7 +87,7 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
|
||||
// TODO (#267): Check room ID doesn't clash with an existing one, and we
|
||||
// probably shouldn't be using pseudo-random strings, maybe GUIDs?
|
||||
newRoomID := fmt.Sprintf("!%s:%s", util.RandomString(16), r.Cfg.Matrix.ServerName)
|
||||
newRoomID := fmt.Sprintf("!%s:%s", util.RandomString(16), userDomain)
|
||||
|
||||
// Get the existing room state for the old room.
|
||||
oldRoomReq := &api.QueryLatestEventsAndStateRequest{
|
||||
|
|
@ -107,12 +114,12 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
}
|
||||
|
||||
// Send the setup events to the new room
|
||||
if pErr = r.sendInitialEvents(ctx, evTime, userID, newRoomID, string(req.RoomVersion), eventsToMake); pErr != nil {
|
||||
if pErr = r.sendInitialEvents(ctx, evTime, userID, userDomain, newRoomID, string(req.RoomVersion), eventsToMake); pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
|
||||
// 5. Send the tombstone event to the old room
|
||||
if pErr = r.sendHeaderedEvent(ctx, tombstoneEvent, string(r.Cfg.Matrix.ServerName)); pErr != nil {
|
||||
if pErr = r.sendHeaderedEvent(ctx, userDomain, tombstoneEvent, string(userDomain)); pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +129,7 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
}
|
||||
|
||||
// If the old room had a canonical alias event, it should be deleted in the old room
|
||||
if pErr = r.clearOldCanonicalAliasEvent(ctx, oldRoomRes, evTime, userID, roomID); pErr != nil {
|
||||
if pErr = r.clearOldCanonicalAliasEvent(ctx, oldRoomRes, evTime, userID, userDomain, roomID); pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +139,7 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
}
|
||||
|
||||
// 6. Restrict power levels in the old room
|
||||
if pErr = r.restrictOldRoomPowerLevels(ctx, evTime, userID, roomID); pErr != nil {
|
||||
if pErr = r.restrictOldRoomPowerLevels(ctx, evTime, userID, userDomain, roomID); pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +161,7 @@ func (r *Upgrader) getRoomPowerLevels(ctx context.Context, roomID string) (*goma
|
|||
return powerLevelContent, nil
|
||||
}
|
||||
|
||||
func (r *Upgrader) restrictOldRoomPowerLevels(ctx context.Context, evTime time.Time, userID, roomID string) *api.PerformError {
|
||||
func (r *Upgrader) restrictOldRoomPowerLevels(ctx context.Context, evTime time.Time, userID string, userDomain gomatrixserverlib.ServerName, roomID string) *api.PerformError {
|
||||
restrictedPowerLevelContent, pErr := r.getRoomPowerLevels(ctx, roomID)
|
||||
if pErr != nil {
|
||||
return pErr
|
||||
|
|
@ -183,7 +190,7 @@ func (r *Upgrader) restrictOldRoomPowerLevels(ctx context.Context, evTime time.T
|
|||
return resErr
|
||||
}
|
||||
} else {
|
||||
if resErr = r.sendHeaderedEvent(ctx, restrictedPowerLevelsHeadered, api.DoNotSendToOtherServers); resErr != nil {
|
||||
if resErr = r.sendHeaderedEvent(ctx, userDomain, restrictedPowerLevelsHeadered, api.DoNotSendToOtherServers); resErr != nil {
|
||||
return resErr
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +230,7 @@ func moveLocalAliases(ctx context.Context,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Upgrader) clearOldCanonicalAliasEvent(ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, evTime time.Time, userID, roomID string) *api.PerformError {
|
||||
func (r *Upgrader) clearOldCanonicalAliasEvent(ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, evTime time.Time, userID string, userDomain gomatrixserverlib.ServerName, roomID string) *api.PerformError {
|
||||
for _, event := range oldRoom.StateEvents {
|
||||
if event.Type() != gomatrixserverlib.MRoomCanonicalAlias || !event.StateKeyEquals("") {
|
||||
continue
|
||||
|
|
@ -254,7 +261,7 @@ func (r *Upgrader) clearOldCanonicalAliasEvent(ctx context.Context, oldRoom *api
|
|||
return resErr
|
||||
}
|
||||
} else {
|
||||
if resErr = r.sendHeaderedEvent(ctx, emptyCanonicalAliasEvent, api.DoNotSendToOtherServers); resErr != nil {
|
||||
if resErr = r.sendHeaderedEvent(ctx, userDomain, emptyCanonicalAliasEvent, api.DoNotSendToOtherServers); resErr != nil {
|
||||
return resErr
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +502,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
|||
return eventsToMake, nil
|
||||
}
|
||||
|
||||
func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, userID, newRoomID, newVersion string, eventsToMake []fledglingEvent) *api.PerformError {
|
||||
func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, userID string, userDomain gomatrixserverlib.ServerName, newRoomID, newVersion string, eventsToMake []fledglingEvent) *api.PerformError {
|
||||
var err error
|
||||
var builtEvents []*gomatrixserverlib.HeaderedEvent
|
||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||
|
|
@ -519,7 +526,7 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user
|
|||
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
||||
}
|
||||
var event *gomatrixserverlib.Event
|
||||
event, err = r.buildEvent(&builder, &authEvents, evTime, gomatrixserverlib.RoomVersion(newVersion))
|
||||
event, err = r.buildEvent(&builder, userDomain, &authEvents, evTime, gomatrixserverlib.RoomVersion(newVersion))
|
||||
if err != nil {
|
||||
return &api.PerformError{
|
||||
Msg: fmt.Sprintf("Failed to build new %q event: %s", builder.Type, err),
|
||||
|
|
@ -547,7 +554,7 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user
|
|||
inputs = append(inputs, api.InputRoomEvent{
|
||||
Kind: api.KindNew,
|
||||
Event: event,
|
||||
Origin: r.Cfg.Matrix.ServerName,
|
||||
Origin: userDomain,
|
||||
SendAsServer: api.DoNotSendToOtherServers,
|
||||
})
|
||||
}
|
||||
|
|
@ -668,6 +675,7 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC
|
|||
|
||||
func (r *Upgrader) sendHeaderedEvent(
|
||||
ctx context.Context,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
headeredEvent *gomatrixserverlib.HeaderedEvent,
|
||||
sendAsServer string,
|
||||
) *api.PerformError {
|
||||
|
|
@ -675,7 +683,7 @@ func (r *Upgrader) sendHeaderedEvent(
|
|||
inputs = append(inputs, api.InputRoomEvent{
|
||||
Kind: api.KindNew,
|
||||
Event: headeredEvent,
|
||||
Origin: r.Cfg.Matrix.ServerName,
|
||||
Origin: serverName,
|
||||
SendAsServer: sendAsServer,
|
||||
})
|
||||
if err := api.SendInputRoomEvents(ctx, r.URSAPI, inputs, false); err != nil {
|
||||
|
|
@ -689,6 +697,7 @@ func (r *Upgrader) sendHeaderedEvent(
|
|||
|
||||
func (r *Upgrader) buildEvent(
|
||||
builder *gomatrixserverlib.EventBuilder,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
provider gomatrixserverlib.AuthEventProvider,
|
||||
evTime time.Time,
|
||||
roomVersion gomatrixserverlib.RoomVersion,
|
||||
|
|
@ -703,7 +712,7 @@ func (r *Upgrader) buildEvent(
|
|||
}
|
||||
builder.AuthEvents = refs
|
||||
event, err := builder.Build(
|
||||
evTime, r.Cfg.Matrix.ServerName, r.Cfg.Matrix.KeyID,
|
||||
evTime, serverName, r.Cfg.Matrix.KeyID,
|
||||
r.Cfg.Matrix.PrivateKey, roomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -245,16 +245,42 @@ func (r *Queryer) QueryMembershipAtEvent(
|
|||
return fmt.Errorf("unable to get state before event: %w", err)
|
||||
}
|
||||
|
||||
// If we only have one or less state entries, we can short circuit the below
|
||||
// loop and avoid hitting the database
|
||||
allStateEventNIDs := make(map[types.EventNID]types.StateEntry)
|
||||
for _, eventID := range request.EventIDs {
|
||||
stateEntry := stateEntries[eventID]
|
||||
for _, s := range stateEntry {
|
||||
allStateEventNIDs[s.EventNID] = s
|
||||
}
|
||||
}
|
||||
|
||||
var canShortCircuit bool
|
||||
if len(allStateEventNIDs) <= 1 {
|
||||
canShortCircuit = true
|
||||
}
|
||||
|
||||
var memberships []types.Event
|
||||
for _, eventID := range request.EventIDs {
|
||||
stateEntry, ok := stateEntries[eventID]
|
||||
if !ok {
|
||||
if !ok || len(stateEntry) == 0 {
|
||||
response.Memberships[eventID] = []*gomatrixserverlib.HeaderedEvent{}
|
||||
continue
|
||||
}
|
||||
memberships, err := helpers.GetMembershipsAtState(ctx, r.DB, stateEntry, false)
|
||||
|
||||
// If we can short circuit, e.g. we only have 0 or 1 membership events, we only get the memberships
|
||||
// once. If we have more than one membership event, we need to get the state for each state entry.
|
||||
if canShortCircuit {
|
||||
if len(memberships) == 0 {
|
||||
memberships, err = helpers.GetMembershipsAtState(ctx, r.DB, stateEntry, false)
|
||||
}
|
||||
} else {
|
||||
memberships, err = helpers.GetMembershipsAtState(ctx, r.DB, stateEntry, false)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get memberships at state: %w", err)
|
||||
}
|
||||
|
||||
res := make([]*gomatrixserverlib.HeaderedEvent, 0, len(memberships))
|
||||
|
||||
for i := range memberships {
|
||||
|
|
@ -708,7 +734,7 @@ func (r *Queryer) QueryPublishedRooms(
|
|||
}
|
||||
return err
|
||||
}
|
||||
rooms, err := r.DB.GetPublishedRooms(ctx)
|
||||
rooms, err := r.DB.GetPublishedRooms(ctx, req.NetworkID, req.IncludeAllNetworks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,18 +27,19 @@ const (
|
|||
RoomserverInputRoomEventsPath = "/roomserver/inputRoomEvents"
|
||||
|
||||
// Perform operations
|
||||
RoomserverPerformInvitePath = "/roomserver/performInvite"
|
||||
RoomserverPerformPeekPath = "/roomserver/performPeek"
|
||||
RoomserverPerformUnpeekPath = "/roomserver/performUnpeek"
|
||||
RoomserverPerformRoomUpgradePath = "/roomserver/performRoomUpgrade"
|
||||
RoomserverPerformJoinPath = "/roomserver/performJoin"
|
||||
RoomserverPerformLeavePath = "/roomserver/performLeave"
|
||||
RoomserverPerformBackfillPath = "/roomserver/performBackfill"
|
||||
RoomserverPerformPublishPath = "/roomserver/performPublish"
|
||||
RoomserverPerformInboundPeekPath = "/roomserver/performInboundPeek"
|
||||
RoomserverPerformForgetPath = "/roomserver/performForget"
|
||||
RoomserverPerformAdminEvacuateRoomPath = "/roomserver/performAdminEvacuateRoom"
|
||||
RoomserverPerformAdminEvacuateUserPath = "/roomserver/performAdminEvacuateUser"
|
||||
RoomserverPerformInvitePath = "/roomserver/performInvite"
|
||||
RoomserverPerformPeekPath = "/roomserver/performPeek"
|
||||
RoomserverPerformUnpeekPath = "/roomserver/performUnpeek"
|
||||
RoomserverPerformRoomUpgradePath = "/roomserver/performRoomUpgrade"
|
||||
RoomserverPerformJoinPath = "/roomserver/performJoin"
|
||||
RoomserverPerformLeavePath = "/roomserver/performLeave"
|
||||
RoomserverPerformBackfillPath = "/roomserver/performBackfill"
|
||||
RoomserverPerformPublishPath = "/roomserver/performPublish"
|
||||
RoomserverPerformInboundPeekPath = "/roomserver/performInboundPeek"
|
||||
RoomserverPerformForgetPath = "/roomserver/performForget"
|
||||
RoomserverPerformAdminEvacuateRoomPath = "/roomserver/performAdminEvacuateRoom"
|
||||
RoomserverPerformAdminEvacuateUserPath = "/roomserver/performAdminEvacuateUser"
|
||||
RoomserverPerformAdminDownloadStatePath = "/roomserver/performAdminDownloadState"
|
||||
|
||||
// Query operations
|
||||
RoomserverQueryLatestEventsAndStatePath = "/roomserver/queryLatestEventsAndState"
|
||||
|
|
@ -261,6 +262,17 @@ func (h *httpRoomserverInternalAPI) PerformAdminEvacuateRoom(
|
|||
)
|
||||
}
|
||||
|
||||
func (h *httpRoomserverInternalAPI) PerformAdminDownloadState(
|
||||
ctx context.Context,
|
||||
request *api.PerformAdminDownloadStateRequest,
|
||||
response *api.PerformAdminDownloadStateResponse,
|
||||
) error {
|
||||
return httputil.CallInternalRPCAPI(
|
||||
"PerformAdminDownloadState", h.roomserverURL+RoomserverPerformAdminDownloadStatePath,
|
||||
h.httpClient, ctx, request, response,
|
||||
)
|
||||
}
|
||||
|
||||
func (h *httpRoomserverInternalAPI) PerformAdminEvacuateUser(
|
||||
ctx context.Context,
|
||||
request *api.PerformAdminEvacuateUserRequest,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ func AddRoutes(r api.RoomserverInternalAPI, internalAPIMux *mux.Router) {
|
|||
httputil.MakeInternalRPCAPI("RoomserverPerformAdminEvacuateUser", r.PerformAdminEvacuateUser),
|
||||
)
|
||||
|
||||
internalAPIMux.Handle(
|
||||
RoomserverPerformAdminDownloadStatePath,
|
||||
httputil.MakeInternalRPCAPI("RoomserverPerformAdminDownloadState", r.PerformAdminDownloadState),
|
||||
)
|
||||
|
||||
internalAPIMux.Handle(
|
||||
RoomserverQueryPublishedRoomsPath,
|
||||
httputil.MakeInternalRPCAPI("RoomserverQueryPublishedRooms", r.QueryPublishedRooms),
|
||||
|
|
|
|||
|
|
@ -18,17 +18,17 @@ package state
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
)
|
||||
|
||||
type StateResolutionStorage interface {
|
||||
|
|
@ -37,6 +37,7 @@ type StateResolutionStorage interface {
|
|||
StateBlockNIDs(ctx context.Context, stateNIDs []types.StateSnapshotNID) ([]types.StateBlockNIDList, error)
|
||||
StateEntries(ctx context.Context, stateBlockNIDs []types.StateBlockNID) ([]types.StateEntryList, error)
|
||||
SnapshotNIDFromEventID(ctx context.Context, eventID string) (types.StateSnapshotNID, error)
|
||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||
StateEntriesForTuples(ctx context.Context, stateBlockNIDs []types.StateBlockNID, stateKeyTuples []types.StateKeyTuple) ([]types.StateEntryList, error)
|
||||
StateAtEventIDs(ctx context.Context, eventIDs []string) ([]types.StateAtEvent, error)
|
||||
AddState(ctx context.Context, roomNID types.RoomNID, stateBlockNIDs []types.StateBlockNID, state []types.StateEntry) (types.StateSnapshotNID, error)
|
||||
|
|
@ -130,21 +131,10 @@ func (v *StateResolution) LoadMembershipAtEvent(
|
|||
span, ctx := opentracing.StartSpanFromContext(ctx, "StateResolution.LoadMembershipAtEvent")
|
||||
defer span.Finish()
|
||||
|
||||
// De-dupe snapshotNIDs
|
||||
snapshotNIDMap := make(map[types.StateSnapshotNID][]string) // map from snapshot NID to eventIDs
|
||||
for i := range eventIDs {
|
||||
eventID := eventIDs[i]
|
||||
snapshotNID, err := v.db.SnapshotNIDFromEventID(ctx, eventID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, fmt.Errorf("LoadStateAtEvent.SnapshotNIDFromEventID failed for event %s : %w", eventID, err)
|
||||
}
|
||||
if snapshotNID == 0 {
|
||||
// If we don't know a state snapshot for this event then we can't calculate
|
||||
// memberships at the time of the event, so skip over it. This means that
|
||||
// it isn't guaranteed that the response map will contain every single event.
|
||||
continue
|
||||
}
|
||||
snapshotNIDMap[snapshotNID] = append(snapshotNIDMap[snapshotNID], eventID)
|
||||
// Get a mapping from snapshotNID -> eventIDs
|
||||
snapshotNIDMap, err := v.db.BulkSelectSnapshotsFromEventIDs(ctx, eventIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
snapshotNIDs := make([]types.StateSnapshotNID, 0, len(snapshotNIDMap))
|
||||
|
|
@ -157,24 +147,45 @@ func (v *StateResolution) LoadMembershipAtEvent(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var wantStateBlocks []types.StateBlockNID
|
||||
for _, x := range stateBlockNIDLists {
|
||||
wantStateBlocks = append(wantStateBlocks, x.StateBlockNIDs...)
|
||||
}
|
||||
|
||||
stateEntryLists, err := v.db.StateEntriesForTuples(ctx, uniqueStateBlockNIDs(wantStateBlocks), []types.StateKeyTuple{
|
||||
{
|
||||
EventTypeNID: types.MRoomMemberNID,
|
||||
EventStateKeyNID: stateKeyNID,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stateBlockNIDsMap := stateBlockNIDListMap(stateBlockNIDLists)
|
||||
stateEntriesMap := stateEntryListMap(stateEntryLists)
|
||||
|
||||
result := make(map[string][]types.StateEntry)
|
||||
for _, stateBlockNIDList := range stateBlockNIDLists {
|
||||
// Query the membership event for the user at the given stateblocks
|
||||
stateEntryLists, err := v.db.StateEntriesForTuples(ctx, stateBlockNIDList.StateBlockNIDs, []types.StateKeyTuple{
|
||||
{
|
||||
EventTypeNID: types.MRoomMemberNID,
|
||||
EventStateKeyNID: stateKeyNID,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
stateBlockNIDs, ok := stateBlockNIDsMap.lookup(stateBlockNIDList.StateSnapshotNID)
|
||||
if !ok {
|
||||
// This should only get hit if the database is corrupt.
|
||||
// It should be impossible for an event to reference a NID that doesn't exist
|
||||
return nil, fmt.Errorf("corrupt DB: Missing state snapshot numeric ID %d", stateBlockNIDList.StateSnapshotNID)
|
||||
}
|
||||
|
||||
evIDs := snapshotNIDMap[stateBlockNIDList.StateSnapshotNID]
|
||||
for _, stateBlockNID := range stateBlockNIDs {
|
||||
entries, ok := stateEntriesMap.lookup(stateBlockNID)
|
||||
if !ok {
|
||||
// This should only get hit if the database is corrupt.
|
||||
// It should be impossible for an event to reference a NID that doesn't exist
|
||||
return nil, fmt.Errorf("corrupt DB: Missing state block numeric ID %d", stateBlockNID)
|
||||
}
|
||||
|
||||
for _, evID := range evIDs {
|
||||
for _, x := range stateEntryLists {
|
||||
result[evID] = append(result[evID], x.StateEntries...)
|
||||
evIDs := snapshotNIDMap[stateBlockNIDList.StateSnapshotNID]
|
||||
|
||||
for _, evID := range evIDs {
|
||||
result[evID] = append(result[evID], entries...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -944,7 +955,6 @@ func (v *StateResolution) resolveConflictsV2(
|
|||
authSets := make(map[string][]*gomatrixserverlib.Event, len(conflicted))
|
||||
authEvents := make([]*gomatrixserverlib.Event, 0, estimate*3)
|
||||
gotAuthEvents := make(map[string]struct{}, estimate*3)
|
||||
authDifference := make([]*gomatrixserverlib.Event, 0, estimate)
|
||||
knownAuthEvents := make(map[string]types.Event, estimate*3)
|
||||
|
||||
// For each conflicted event, let's try and get the needed auth events.
|
||||
|
|
@ -992,41 +1002,6 @@ func (v *StateResolution) resolveConflictsV2(
|
|||
// longer need this after this point.
|
||||
gotAuthEvents = nil // nolint:ineffassign
|
||||
|
||||
// This function helps us to work out whether an event exists in one of the
|
||||
// auth sets.
|
||||
isInAuthList := func(k string, event *gomatrixserverlib.Event) bool {
|
||||
for _, e := range authSets[k] {
|
||||
if e.EventID() == event.EventID() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This function works out if an event exists in all of the auth sets.
|
||||
isInAllAuthLists := func(event *gomatrixserverlib.Event) bool {
|
||||
for k := range authSets {
|
||||
if !isInAuthList(k, event) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Look through all of the auth events that we've been given and work out if
|
||||
// there are any events which don't appear in all of the auth sets. If they
|
||||
// don't then we add them to the auth difference.
|
||||
func() {
|
||||
span, _ := opentracing.StartSpanFromContext(ctx, "isInAllAuthLists")
|
||||
defer span.Finish()
|
||||
|
||||
for _, event := range authEvents {
|
||||
if !isInAllAuthLists(event) {
|
||||
authDifference = append(authDifference, event)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Resolve the conflicts.
|
||||
resolvedEvents := func() []*gomatrixserverlib.Event {
|
||||
span, _ := opentracing.StartSpanFromContext(ctx, "gomatrixserverlib.ResolveStateConflictsV2")
|
||||
|
|
@ -1036,7 +1011,6 @@ func (v *StateResolution) resolveConflictsV2(
|
|||
conflictedEvents,
|
||||
nonConflictedEvents,
|
||||
authEvents,
|
||||
authDifference,
|
||||
)
|
||||
}()
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ type Database interface {
|
|||
Events(ctx context.Context, eventNIDs []types.EventNID) ([]types.Event, error)
|
||||
// Look up snapshot NID for an event ID string
|
||||
SnapshotNIDFromEventID(ctx context.Context, eventID string) (types.StateSnapshotNID, error)
|
||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||
// Stores a matrix room event in the database. Returns the room NID, the state snapshot and the redacted event ID if any, or an error.
|
||||
StoreEvent(
|
||||
ctx context.Context, event *gomatrixserverlib.Event, authEventNIDs []types.EventNID,
|
||||
|
|
@ -139,9 +140,9 @@ type Database interface {
|
|||
// Returns an error if the retrieval went wrong.
|
||||
EventsFromIDs(ctx context.Context, eventIDs []string) ([]types.Event, error)
|
||||
// Publish or unpublish a room from the room directory.
|
||||
PublishRoom(ctx context.Context, roomID string, publish bool) error
|
||||
PublishRoom(ctx context.Context, roomID, appserviceID, networkID string, publish bool) error
|
||||
// Returns a list of room IDs for rooms which are published.
|
||||
GetPublishedRooms(ctx context.Context) ([]string, error)
|
||||
GetPublishedRooms(ctx context.Context, networkID string, includeAllNetworks bool) ([]string, error)
|
||||
// Returns whether a given room is published or not.
|
||||
GetPublishedRoom(ctx context.Context, roomID string) (bool, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
// 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 deltas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func UpPulishedAppservice(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, `ALTER TABLE roomserver_published ADD COLUMN IF NOT EXISTS appservice_id TEXT NOT NULL DEFAULT '';`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_published ADD COLUMN IF NOT EXISTS network_id TEXT NOT NULL DEFAULT '';`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownPublishedAppservice(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, `ALTER TABLE roomserver_published DROP COLUMN IF EXISTS appservice_id;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute downgrade: %w", err)
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_published DROP COLUMN IF EXISTS network_id;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute downgrade: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -22,11 +22,12 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const eventsSchema = `
|
||||
|
|
@ -80,6 +81,9 @@ const insertEventSQL = "" +
|
|||
const selectEventSQL = "" +
|
||||
"SELECT event_nid, state_snapshot_nid FROM roomserver_events WHERE event_id = $1"
|
||||
|
||||
const bulkSelectSnapshotsForEventIDsSQL = "" +
|
||||
"SELECT event_id, state_snapshot_nid FROM roomserver_events WHERE event_id = ANY($1)"
|
||||
|
||||
// Bulk lookup of events by string ID.
|
||||
// Sort by the numeric IDs for event type and state key.
|
||||
// This means we can use binary search to lookup entries by type and state key.
|
||||
|
|
@ -150,6 +154,7 @@ const selectEventRejectedSQL = "" +
|
|||
type eventStatements struct {
|
||||
insertEventStmt *sql.Stmt
|
||||
selectEventStmt *sql.Stmt
|
||||
bulkSelectSnapshotsForEventIDsStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDExcludingRejectedStmt *sql.Stmt
|
||||
bulkSelectStateEventByNIDStmt *sql.Stmt
|
||||
|
|
@ -179,6 +184,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
|||
return s, sqlutil.StatementList{
|
||||
{&s.insertEventStmt, insertEventSQL},
|
||||
{&s.selectEventStmt, selectEventSQL},
|
||||
{&s.bulkSelectSnapshotsForEventIDsStmt, bulkSelectSnapshotsForEventIDsSQL},
|
||||
{&s.bulkSelectStateEventByIDStmt, bulkSelectStateEventByIDSQL},
|
||||
{&s.bulkSelectStateEventByIDExcludingRejectedStmt, bulkSelectStateEventByIDExcludingRejectedSQL},
|
||||
{&s.bulkSelectStateEventByNIDStmt, bulkSelectStateEventByNIDSQL},
|
||||
|
|
@ -230,6 +236,29 @@ func (s *eventStatements) SelectEvent(
|
|||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||
}
|
||||
|
||||
func (s *eventStatements) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, txn *sql.Tx, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.bulkSelectSnapshotsForEventIDsStmt)
|
||||
|
||||
rows, err := stmt.QueryContext(ctx, pq.Array(eventIDs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var eventID string
|
||||
var stateNID types.StateSnapshotNID
|
||||
result := make(map[types.StateSnapshotNID][]string)
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&eventID, &stateNID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[stateNID] = append(result[stateNID], eventID)
|
||||
}
|
||||
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If not excluding rejected events, and any of the requested events are missing from
|
||||
// the database it returns a types.MissingEventError. If excluding rejected events,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/postgres/deltas"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
)
|
||||
|
||||
|
|
@ -27,31 +28,48 @@ const publishedSchema = `
|
|||
-- Stores which rooms are published in the room directory
|
||||
CREATE TABLE IF NOT EXISTS roomserver_published (
|
||||
-- The room ID of the room
|
||||
room_id TEXT NOT NULL PRIMARY KEY,
|
||||
room_id TEXT NOT NULL,
|
||||
-- The appservice ID of the room
|
||||
appservice_id TEXT NOT NULL,
|
||||
-- The network_id of the room
|
||||
network_id TEXT NOT NULL,
|
||||
-- Whether it is published or not
|
||||
published BOOLEAN NOT NULL DEFAULT false
|
||||
published BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (room_id, appservice_id, network_id)
|
||||
);
|
||||
`
|
||||
|
||||
const upsertPublishedSQL = "" +
|
||||
"INSERT INTO roomserver_published (room_id, published) VALUES ($1, $2) " +
|
||||
"ON CONFLICT (room_id) DO UPDATE SET published=$2"
|
||||
"INSERT INTO roomserver_published (room_id, appservice_id, network_id, published) VALUES ($1, $2, $3, $4) " +
|
||||
"ON CONFLICT (room_id, appservice_id, network_id) DO UPDATE SET published=$4"
|
||||
|
||||
const selectAllPublishedSQL = "" +
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 ORDER BY room_id ASC"
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 AND CASE WHEN $2 THEN 1=1 ELSE network_id = '' END ORDER BY room_id ASC"
|
||||
|
||||
const selectNetworkPublishedSQL = "" +
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 AND network_id = $2 ORDER BY room_id ASC"
|
||||
|
||||
const selectPublishedSQL = "" +
|
||||
"SELECT published FROM roomserver_published WHERE room_id = $1"
|
||||
|
||||
type publishedStatements struct {
|
||||
upsertPublishedStmt *sql.Stmt
|
||||
selectAllPublishedStmt *sql.Stmt
|
||||
selectPublishedStmt *sql.Stmt
|
||||
upsertPublishedStmt *sql.Stmt
|
||||
selectAllPublishedStmt *sql.Stmt
|
||||
selectPublishedStmt *sql.Stmt
|
||||
selectNetworkPublishedStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func CreatePublishedTable(db *sql.DB) error {
|
||||
_, err := db.Exec(publishedSchema)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m := sqlutil.NewMigrator(db)
|
||||
m.AddMigrations(sqlutil.Migration{
|
||||
Version: "roomserver: published appservice",
|
||||
Up: deltas.UpPulishedAppservice,
|
||||
})
|
||||
return m.Up(context.Background())
|
||||
}
|
||||
|
||||
func PreparePublishedTable(db *sql.DB) (tables.Published, error) {
|
||||
|
|
@ -61,14 +79,15 @@ func PreparePublishedTable(db *sql.DB) (tables.Published, error) {
|
|||
{&s.upsertPublishedStmt, upsertPublishedSQL},
|
||||
{&s.selectAllPublishedStmt, selectAllPublishedSQL},
|
||||
{&s.selectPublishedStmt, selectPublishedSQL},
|
||||
{&s.selectNetworkPublishedStmt, selectNetworkPublishedSQL},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
func (s *publishedStatements) UpsertRoomPublished(
|
||||
ctx context.Context, txn *sql.Tx, roomID string, published bool,
|
||||
ctx context.Context, txn *sql.Tx, roomID, appserviceID, networkID string, published bool,
|
||||
) (err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.upsertPublishedStmt)
|
||||
_, err = stmt.ExecContext(ctx, roomID, published)
|
||||
_, err = stmt.ExecContext(ctx, roomID, appserviceID, networkID, published)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -84,10 +103,18 @@ func (s *publishedStatements) SelectPublishedFromRoomID(
|
|||
}
|
||||
|
||||
func (s *publishedStatements) SelectAllPublishedRooms(
|
||||
ctx context.Context, txn *sql.Tx, published bool,
|
||||
ctx context.Context, txn *sql.Tx, networkID string, published, includeAllNetworks bool,
|
||||
) ([]string, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectAllPublishedStmt)
|
||||
rows, err := stmt.QueryContext(ctx, published)
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
if networkID != "" {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectNetworkPublishedStmt)
|
||||
rows, err = stmt.QueryContext(ctx, published, networkID)
|
||||
} else {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectAllPublishedStmt)
|
||||
rows, err = stmt.QueryContext(ctx, published, includeAllNetworks)
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import (
|
|||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
)
|
||||
|
||||
type RoomUpdater struct {
|
||||
|
|
@ -186,6 +187,10 @@ func (u *RoomUpdater) EventIDs(
|
|||
return u.d.EventsTable.BulkSelectEventID(ctx, u.txn, eventNIDs)
|
||||
}
|
||||
|
||||
func (u *RoomUpdater) BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error) {
|
||||
return u.d.EventsTable.BulkSelectSnapshotsFromEventIDs(ctx, u.txn, eventIDs)
|
||||
}
|
||||
|
||||
func (u *RoomUpdater) StateAtEventIDs(
|
||||
ctx context.Context, eventIDs []string,
|
||||
) ([]types.StateAtEvent, error) {
|
||||
|
|
|
|||
|
|
@ -469,6 +469,23 @@ func (d *Database) events(
|
|||
eventNIDs = append(eventNIDs, nid)
|
||||
}
|
||||
}
|
||||
// If we don't need to get any events from the database, short circuit now
|
||||
if len(eventNIDs) == 0 {
|
||||
results := make([]types.Event, 0, len(inputEventNIDs))
|
||||
for _, nid := range inputEventNIDs {
|
||||
event, ok := events[nid]
|
||||
if !ok || event == nil {
|
||||
return nil, fmt.Errorf("event %d missing", nid)
|
||||
}
|
||||
results = append(results, types.Event{
|
||||
EventNID: nid,
|
||||
Event: event,
|
||||
})
|
||||
}
|
||||
if !redactionsArePermanent {
|
||||
d.applyRedactions(results)
|
||||
}
|
||||
}
|
||||
eventJSONs, err := d.EventJSONTable.BulkSelectEventJSON(ctx, txn, eventNIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -534,6 +551,12 @@ func (d *Database) events(
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func (d *Database) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
return d.EventsTable.BulkSelectSnapshotsFromEventIDs(ctx, nil, eventIDs)
|
||||
}
|
||||
|
||||
func (d *Database) MembershipUpdater(
|
||||
ctx context.Context, roomID, targetUserID string,
|
||||
targetLocal bool, roomVersion gomatrixserverlib.RoomVersion,
|
||||
|
|
@ -722,9 +745,9 @@ func (d *Database) storeEvent(
|
|||
}, redactionEvent, redactedEventID, err
|
||||
}
|
||||
|
||||
func (d *Database) PublishRoom(ctx context.Context, roomID string, publish bool) error {
|
||||
func (d *Database) PublishRoom(ctx context.Context, roomID, appserviceID, networkID string, publish bool) error {
|
||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
||||
return d.PublishedTable.UpsertRoomPublished(ctx, txn, roomID, publish)
|
||||
return d.PublishedTable.UpsertRoomPublished(ctx, txn, roomID, appserviceID, networkID, publish)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -732,8 +755,8 @@ func (d *Database) GetPublishedRoom(ctx context.Context, roomID string) (bool, e
|
|||
return d.PublishedTable.SelectPublishedFromRoomID(ctx, nil, roomID)
|
||||
}
|
||||
|
||||
func (d *Database) GetPublishedRooms(ctx context.Context) ([]string, error) {
|
||||
return d.PublishedTable.SelectAllPublishedRooms(ctx, nil, true)
|
||||
func (d *Database) GetPublishedRooms(ctx context.Context, networkID string, includeAllNetworks bool) ([]string, error) {
|
||||
return d.PublishedTable.SelectAllPublishedRooms(ctx, nil, networkID, true, includeAllNetworks)
|
||||
}
|
||||
|
||||
func (d *Database) MissingAuthPrevEvents(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
// 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 deltas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func UpPulishedAppservice(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, ` ALTER TABLE roomserver_published RENAME TO roomserver_published_tmp;
|
||||
CREATE TABLE IF NOT EXISTS roomserver_published (
|
||||
room_id TEXT NOT NULL,
|
||||
appservice_id TEXT NOT NULL DEFAULT '',
|
||||
network_id TEXT NOT NULL DEFAULT '',
|
||||
published BOOLEAN NOT NULL DEFAULT false,
|
||||
CONSTRAINT unique_published_idx PRIMARY KEY (room_id, appservice_id, network_id)
|
||||
);
|
||||
INSERT
|
||||
INTO roomserver_published (
|
||||
room_id, published
|
||||
) SELECT
|
||||
room_id, published
|
||||
FROM roomserver_published_tmp
|
||||
;
|
||||
DROP TABLE roomserver_published_tmp;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownPublishedAppservice(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, ` ALTER TABLE roomserver_published RENAME TO roomserver_published_tmp;
|
||||
CREATE TABLE IF NOT EXISTS roomserver_published (
|
||||
room_id TEXT NOT NULL PRIMARY KEY,
|
||||
published BOOLEAN NOT NULL DEFAULT false
|
||||
);
|
||||
INSERT
|
||||
INTO roomserver_published (
|
||||
room_id, published
|
||||
) SELECT
|
||||
room_id, published
|
||||
FROM roomserver_published_tmp
|
||||
;
|
||||
DROP TABLE roomserver_published_tmp;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -23,11 +23,12 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const eventsSchema = `
|
||||
|
|
@ -57,6 +58,9 @@ const insertEventSQL = `
|
|||
const selectEventSQL = "" +
|
||||
"SELECT event_nid, state_snapshot_nid FROM roomserver_events WHERE event_id = $1"
|
||||
|
||||
const bulkSelectSnapshotsForEventIDsSQL = "" +
|
||||
"SELECT event_id, state_snapshot_nid FROM roomserver_events WHERE event_id IN ($1)"
|
||||
|
||||
// Bulk lookup of events by string ID.
|
||||
// Sort by the numeric IDs for event type and state key.
|
||||
// This means we can use binary search to lookup entries by type and state key.
|
||||
|
|
@ -124,6 +128,7 @@ type eventStatements struct {
|
|||
db *sql.DB
|
||||
insertEventStmt *sql.Stmt
|
||||
selectEventStmt *sql.Stmt
|
||||
bulkSelectSnapshotsForEventIDsStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDExcludingRejectedStmt *sql.Stmt
|
||||
bulkSelectStateAtEventByIDStmt *sql.Stmt
|
||||
|
|
@ -153,6 +158,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
|||
return s, sqlutil.StatementList{
|
||||
{&s.insertEventStmt, insertEventSQL},
|
||||
{&s.selectEventStmt, selectEventSQL},
|
||||
{&s.bulkSelectSnapshotsForEventIDsStmt, bulkSelectSnapshotsForEventIDsSQL},
|
||||
{&s.bulkSelectStateEventByIDStmt, bulkSelectStateEventByIDSQL},
|
||||
{&s.bulkSelectStateEventByIDExcludingRejectedStmt, bulkSelectStateEventByIDExcludingRejectedSQL},
|
||||
{&s.bulkSelectStateAtEventByIDStmt, bulkSelectStateAtEventByIDSQL},
|
||||
|
|
@ -203,6 +209,40 @@ func (s *eventStatements) SelectEvent(
|
|||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||
}
|
||||
|
||||
func (s *eventStatements) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, txn *sql.Tx, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
qry := strings.Replace(bulkSelectSnapshotsForEventIDsSQL, "($1)", sqlutil.QueryVariadic(len(eventIDs)), 1)
|
||||
stmt, err := s.db.Prepare(qry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, stmt, "BulkSelectSnapshotsFromEventIDs: stmt.close() failed")
|
||||
|
||||
params := make([]interface{}, len(eventIDs))
|
||||
for i := range eventIDs {
|
||||
params[i] = eventIDs[i]
|
||||
}
|
||||
|
||||
rows, err := stmt.QueryContext(ctx, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, rows, "BulkSelectSnapshotsFromEventIDs: rows.close() failed")
|
||||
|
||||
var eventID string
|
||||
var stateNID types.StateSnapshotNID
|
||||
result := make(map[types.StateSnapshotNID][]string)
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&eventID, &stateNID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[stateNID] = append(result[stateNID], eventID)
|
||||
}
|
||||
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If not excluding rejected events, and any of the requested events are missing from
|
||||
// the database it returns a types.MissingEventError. If excluding rejected events,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3/deltas"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
)
|
||||
|
||||
|
|
@ -27,31 +28,49 @@ const publishedSchema = `
|
|||
-- Stores which rooms are published in the room directory
|
||||
CREATE TABLE IF NOT EXISTS roomserver_published (
|
||||
-- The room ID of the room
|
||||
room_id TEXT NOT NULL PRIMARY KEY,
|
||||
room_id TEXT NOT NULL,
|
||||
-- The appservice ID of the room
|
||||
appservice_id TEXT NOT NULL,
|
||||
-- The network_id of the room
|
||||
network_id TEXT NOT NULL,
|
||||
-- Whether it is published or not
|
||||
published BOOLEAN NOT NULL DEFAULT false
|
||||
published BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (room_id, appservice_id, network_id)
|
||||
);
|
||||
`
|
||||
|
||||
const upsertPublishedSQL = "" +
|
||||
"INSERT OR REPLACE INTO roomserver_published (room_id, published) VALUES ($1, $2)"
|
||||
"INSERT INTO roomserver_published (room_id, appservice_id, network_id, published) VALUES ($1, $2, $3, $4)" +
|
||||
" ON CONFLICT (room_id, appservice_id, network_id) DO UPDATE SET published = $4"
|
||||
|
||||
const selectAllPublishedSQL = "" +
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 ORDER BY room_id ASC"
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 AND CASE WHEN $2 THEN 1=1 ELSE network_id = '' END ORDER BY room_id ASC"
|
||||
|
||||
const selectNetworkPublishedSQL = "" +
|
||||
"SELECT room_id FROM roomserver_published WHERE published = $1 AND network_id = $2 ORDER BY room_id ASC"
|
||||
|
||||
const selectPublishedSQL = "" +
|
||||
"SELECT published FROM roomserver_published WHERE room_id = $1"
|
||||
|
||||
type publishedStatements struct {
|
||||
db *sql.DB
|
||||
upsertPublishedStmt *sql.Stmt
|
||||
selectAllPublishedStmt *sql.Stmt
|
||||
selectPublishedStmt *sql.Stmt
|
||||
db *sql.DB
|
||||
upsertPublishedStmt *sql.Stmt
|
||||
selectAllPublishedStmt *sql.Stmt
|
||||
selectPublishedStmt *sql.Stmt
|
||||
selectNetworkPublishedStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func CreatePublishedTable(db *sql.DB) error {
|
||||
_, err := db.Exec(publishedSchema)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m := sqlutil.NewMigrator(db)
|
||||
m.AddMigrations(sqlutil.Migration{
|
||||
Version: "roomserver: published appservice",
|
||||
Up: deltas.UpPulishedAppservice,
|
||||
})
|
||||
return m.Up(context.Background())
|
||||
}
|
||||
|
||||
func PreparePublishedTable(db *sql.DB) (tables.Published, error) {
|
||||
|
|
@ -63,14 +82,15 @@ func PreparePublishedTable(db *sql.DB) (tables.Published, error) {
|
|||
{&s.upsertPublishedStmt, upsertPublishedSQL},
|
||||
{&s.selectAllPublishedStmt, selectAllPublishedSQL},
|
||||
{&s.selectPublishedStmt, selectPublishedSQL},
|
||||
{&s.selectNetworkPublishedStmt, selectNetworkPublishedSQL},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
func (s *publishedStatements) UpsertRoomPublished(
|
||||
ctx context.Context, txn *sql.Tx, roomID string, published bool,
|
||||
ctx context.Context, txn *sql.Tx, roomID, appserviceID, networkID string, published bool,
|
||||
) error {
|
||||
stmt := sqlutil.TxStmt(txn, s.upsertPublishedStmt)
|
||||
_, err := stmt.ExecContext(ctx, roomID, published)
|
||||
_, err := stmt.ExecContext(ctx, roomID, appserviceID, networkID, published)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -86,10 +106,17 @@ func (s *publishedStatements) SelectPublishedFromRoomID(
|
|||
}
|
||||
|
||||
func (s *publishedStatements) SelectAllPublishedRooms(
|
||||
ctx context.Context, txn *sql.Tx, published bool,
|
||||
ctx context.Context, txn *sql.Tx, networkID string, published, includeAllNetworks bool,
|
||||
) ([]string, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectAllPublishedStmt)
|
||||
rows, err := stmt.QueryContext(ctx, published)
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
if networkID != "" {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectNetworkPublishedStmt)
|
||||
rows, err = stmt.QueryContext(ctx, published, networkID)
|
||||
} else {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectAllPublishedStmt)
|
||||
rows, err = stmt.QueryContext(ctx, published, includeAllNetworks)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ type Events interface {
|
|||
referenceSHA256 []byte, authEventNIDs []types.EventNID, depth int64, isRejected bool,
|
||||
) (types.EventNID, types.StateSnapshotNID, error)
|
||||
SelectEvent(ctx context.Context, txn *sql.Tx, eventID string) (types.EventNID, types.StateSnapshotNID, error)
|
||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, txn *sql.Tx, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If any of the requested events are missing from the database it returns a types.MissingEventError
|
||||
BulkSelectStateEventByID(ctx context.Context, txn *sql.Tx, eventIDs []string, excludeRejected bool) ([]types.StateEntry, error)
|
||||
|
|
@ -146,9 +147,9 @@ type Membership interface {
|
|||
}
|
||||
|
||||
type Published interface {
|
||||
UpsertRoomPublished(ctx context.Context, txn *sql.Tx, roomID string, published bool) (err error)
|
||||
UpsertRoomPublished(ctx context.Context, txn *sql.Tx, roomID, appserviceID, networkID string, published bool) (err error)
|
||||
SelectPublishedFromRoomID(ctx context.Context, txn *sql.Tx, roomID string) (published bool, err error)
|
||||
SelectAllPublishedRooms(ctx context.Context, txn *sql.Tx, published bool) ([]string, error)
|
||||
SelectAllPublishedRooms(ctx context.Context, txn *sql.Tx, networkdID string, published, includeAllNetworks bool) ([]string, error)
|
||||
}
|
||||
|
||||
type RedactionInfo struct {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,18 @@ package tables_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/postgres"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func mustCreatePublishedTable(t *testing.T, dbType test.DBType) (tab tables.Published, close func()) {
|
||||
|
|
@ -46,10 +48,12 @@ func TestPublishedTable(t *testing.T) {
|
|||
|
||||
// Publish some rooms
|
||||
publishedRooms := []string{}
|
||||
asID := ""
|
||||
nwID := ""
|
||||
for i := 0; i < 10; i++ {
|
||||
room := test.NewRoom(t, alice)
|
||||
published := i%2 == 0
|
||||
err := tab.UpsertRoomPublished(ctx, nil, room.ID, published)
|
||||
err := tab.UpsertRoomPublished(ctx, nil, room.ID, asID, nwID, published)
|
||||
assert.NoError(t, err)
|
||||
if published {
|
||||
publishedRooms = append(publishedRooms, room.ID)
|
||||
|
|
@ -61,19 +65,36 @@ func TestPublishedTable(t *testing.T) {
|
|||
sort.Strings(publishedRooms)
|
||||
|
||||
// check that we get the expected published rooms
|
||||
roomIDs, err := tab.SelectAllPublishedRooms(ctx, nil, true)
|
||||
roomIDs, err := tab.SelectAllPublishedRooms(ctx, nil, "", true, true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, publishedRooms, roomIDs)
|
||||
|
||||
// test an actual upsert
|
||||
room := test.NewRoom(t, alice)
|
||||
err = tab.UpsertRoomPublished(ctx, nil, room.ID, true)
|
||||
err = tab.UpsertRoomPublished(ctx, nil, room.ID, asID, nwID, true)
|
||||
assert.NoError(t, err)
|
||||
err = tab.UpsertRoomPublished(ctx, nil, room.ID, false)
|
||||
err = tab.UpsertRoomPublished(ctx, nil, room.ID, asID, nwID, false)
|
||||
assert.NoError(t, err)
|
||||
// should now be false, due to the upsert
|
||||
publishedRes, err := tab.SelectPublishedFromRoomID(ctx, nil, room.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, publishedRes)
|
||||
assert.False(t, publishedRes, fmt.Sprintf("expected room %s to be unpublished", room.ID))
|
||||
|
||||
// network specific test
|
||||
nwID = "irc"
|
||||
room = test.NewRoom(t, alice)
|
||||
err = tab.UpsertRoomPublished(ctx, nil, room.ID, asID, nwID, true)
|
||||
assert.NoError(t, err)
|
||||
publishedRooms = append(publishedRooms, room.ID)
|
||||
sort.Strings(publishedRooms)
|
||||
// should only return the room for network "irc"
|
||||
allNWPublished, err := tab.SelectAllPublishedRooms(ctx, nil, nwID, true, true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{room.ID}, allNWPublished)
|
||||
|
||||
// check that we still get all published rooms regardless networkID
|
||||
roomIDs, err = tab.SelectAllPublishedRooms(ctx, nil, "", true, true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, publishedRooms, roomIDs)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ type ClientAPI struct {
|
|||
// Boolean stating whether catpcha registration is enabled
|
||||
// and required
|
||||
RecaptchaEnabled bool `yaml:"enable_registration_captcha"`
|
||||
// Recaptcha api.js Url, for compatible with hcaptcha.com, etc.
|
||||
RecaptchaApiJsUrl string `yaml:"recaptcha_api_js_url"`
|
||||
// Recaptcha div class for sitekey, for compatible with hcaptcha.com, etc.
|
||||
RecaptchaSitekeyClass string `yaml:"recaptcha_sitekey_class"`
|
||||
// Recaptcha form field, for compatible with hcaptcha.com, etc.
|
||||
RecaptchaFormField string `yaml:"recaptcha_form_field"`
|
||||
// This Home Server's ReCAPTCHA public key.
|
||||
RecaptchaPublicKey string `yaml:"recaptcha_public_key"`
|
||||
// This Home Server's ReCAPTCHA private key.
|
||||
|
|
@ -92,6 +98,18 @@ func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
|||
checkNotEmpty(configErrs, "client_api.recaptcha_public_key", c.RecaptchaPublicKey)
|
||||
checkNotEmpty(configErrs, "client_api.recaptcha_private_key", c.RecaptchaPrivateKey)
|
||||
checkNotEmpty(configErrs, "client_api.recaptcha_siteverify_api", c.RecaptchaSiteVerifyAPI)
|
||||
if c.RecaptchaSiteVerifyAPI == "" {
|
||||
c.RecaptchaSiteVerifyAPI = "https://www.google.com/recaptcha/api/siteverify"
|
||||
}
|
||||
if c.RecaptchaApiJsUrl == "" {
|
||||
c.RecaptchaApiJsUrl = "https://www.google.com/recaptcha/api.js"
|
||||
}
|
||||
if c.RecaptchaFormField == "" {
|
||||
c.RecaptchaFormField = "g-recaptcha"
|
||||
}
|
||||
if c.RecaptchaSitekeyClass == "" {
|
||||
c.RecaptchaSitekeyClass = "g-recaptcha-response"
|
||||
}
|
||||
}
|
||||
// Ensure there is any spam counter measure when enabling registration
|
||||
if !c.RegistrationDisabled && !c.OpenRegistrationWithoutVerificationEnabled {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ type Global struct {
|
|||
// The name of the server. This is usually the domain name, e.g 'matrix.org', 'localhost'.
|
||||
ServerName gomatrixserverlib.ServerName `yaml:"server_name"`
|
||||
|
||||
// The secondary server names, used for virtual hosting.
|
||||
SecondaryServerNames []gomatrixserverlib.ServerName `yaml:"-"`
|
||||
|
||||
// Path to the private key which will be used to sign requests and events.
|
||||
PrivateKeyPath Path `yaml:"private_key"`
|
||||
|
||||
|
|
@ -120,6 +123,18 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
|||
c.Cache.Verify(configErrs, isMonolith)
|
||||
}
|
||||
|
||||
func (c *Global) IsLocalServerName(serverName gomatrixserverlib.ServerName) bool {
|
||||
if c.ServerName == serverName {
|
||||
return true
|
||||
}
|
||||
for _, secondaryName := range c.SecondaryServerNames {
|
||||
if secondaryName == serverName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type OldVerifyKeys struct {
|
||||
// Path to the private key.
|
||||
PrivateKeyPath Path `yaml:"private_key"`
|
||||
|
|
@ -170,7 +185,7 @@ type ServerNotices struct {
|
|||
// The displayname to be used when sending notices
|
||||
DisplayName string `yaml:"display_name"`
|
||||
// The avatar of this user
|
||||
AvatarURL string `yaml:"avatar"`
|
||||
AvatarURL string `yaml:"avatar_url"`
|
||||
// The roomname to be used when creating messages
|
||||
RoomName string `yaml:"room_name"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ type UserAPI struct {
|
|||
// The Account database stores the login details and account information
|
||||
// for local users. It is accessed by the UserAPI.
|
||||
AccountDatabase DatabaseOptions `yaml:"account_database,omitempty"`
|
||||
|
||||
// Users who register on this homeserver will automatically
|
||||
// be joined to the rooms listed under this option.
|
||||
AutoJoinRooms []string `yaml:"auto_join_rooms"`
|
||||
}
|
||||
|
||||
const DefaultOpenIDTokenLifetimeMS = 3600000 // 60 minutes
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ func Enable(
|
|||
base.PublicFederationAPIMux.Handle("/unstable/event_relationships", httputil.MakeExternalAPI(
|
||||
"msc2836_event_relationships", func(req *http.Request) util.JSONResponse {
|
||||
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
|
||||
req, time.Now(), base.Cfg.Global.ServerName, keyRing,
|
||||
req, time.Now(), base.Cfg.Global.ServerName, base.Cfg.Global.IsLocalServerName, keyRing,
|
||||
)
|
||||
if fedReq == nil {
|
||||
return errResp
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func Enable(
|
|||
fedAPI := httputil.MakeExternalAPI(
|
||||
"msc2946_fed_spaces", func(req *http.Request) util.JSONResponse {
|
||||
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
|
||||
req, time.Now(), base.Cfg.Global.ServerName, keyRing,
|
||||
req, time.Now(), base.Cfg.Global.ServerName, base.Cfg.Global.IsLocalServerName, keyRing,
|
||||
)
|
||||
if fedReq == nil {
|
||||
return errResp
|
||||
|
|
|
|||
|
|
@ -18,22 +18,20 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/syncapi/storage"
|
||||
"github.com/matrix-org/dendrite/syncapi/types"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
||||
type getMembershipResponse struct {
|
||||
Chunk []gomatrixserverlib.ClientEvent `json:"chunk"`
|
||||
}
|
||||
|
||||
type getJoinedRoomsResponse struct {
|
||||
JoinedRooms []string `json:"joined_rooms"`
|
||||
}
|
||||
|
||||
// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members
|
||||
type getJoinedMembersResponse struct {
|
||||
Joined map[string]joinedMember `json:"joined"`
|
||||
|
|
@ -51,19 +49,22 @@ type databaseJoinedMember struct {
|
|||
AvatarURL string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
// GetMemberships implements GET /rooms/{roomId}/members
|
||||
// GetMemberships implements
|
||||
//
|
||||
// GET /rooms/{roomId}/members
|
||||
// GET /rooms/{roomId}/joined_members
|
||||
func GetMemberships(
|
||||
req *http.Request, device *userapi.Device, roomID string, joinedOnly bool,
|
||||
_ *config.ClientAPI,
|
||||
rsAPI api.ClientRoomserverAPI,
|
||||
req *http.Request, device *userapi.Device, roomID string,
|
||||
syncDB storage.Database, rsAPI api.SyncRoomserverAPI,
|
||||
joinedOnly bool, membership, notMembership *string, at string,
|
||||
) util.JSONResponse {
|
||||
queryReq := api.QueryMembershipsForRoomRequest{
|
||||
JoinedOnly: joinedOnly,
|
||||
RoomID: roomID,
|
||||
Sender: device.UserID,
|
||||
queryReq := api.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: device.UserID,
|
||||
}
|
||||
var queryRes api.QueryMembershipsForRoomResponse
|
||||
if err := rsAPI.QueryMembershipsForRoom(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
|
||||
var queryRes api.QueryMembershipForUserResponse
|
||||
if err := rsAPI.QueryMembershipForUser(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryMembershipsForRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
|
@ -75,16 +76,57 @@ func GetMemberships(
|
|||
}
|
||||
}
|
||||
|
||||
if joinedOnly && !queryRes.IsInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("You aren't a member of the room and weren't previously a member of the room."),
|
||||
}
|
||||
}
|
||||
|
||||
db, err := syncDB.NewDatabaseSnapshot(req.Context())
|
||||
if err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
atToken, err := types.NewTopologyTokenFromString(at)
|
||||
if err != nil {
|
||||
if queryRes.HasBeenInRoom && !queryRes.IsInRoom {
|
||||
// If you have left the room then this will be the members of the room when you left.
|
||||
atToken, err = db.EventPositionInTopology(req.Context(), queryRes.EventID)
|
||||
} else {
|
||||
// If you are joined to the room then this will be the current members of the room.
|
||||
atToken, err = db.MaxTopologicalPosition(req.Context(), roomID)
|
||||
}
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("unable to get 'atToken'")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
}
|
||||
|
||||
eventIDs, err := db.SelectMemberships(req.Context(), roomID, atToken, membership, notMembership)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("db.SelectMemberships failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
qryRes := &api.QueryEventsByIDResponse{}
|
||||
if err := rsAPI.QueryEventsByID(req.Context(), &api.QueryEventsByIDRequest{EventIDs: eventIDs}, qryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryEventsByID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
result := qryRes.Events
|
||||
|
||||
if joinedOnly {
|
||||
var res getJoinedMembersResponse
|
||||
res.Joined = make(map[string]joinedMember)
|
||||
for _, ev := range queryRes.JoinEvents {
|
||||
for _, ev := range result {
|
||||
var content databaseJoinedMember
|
||||
if err := json.Unmarshal(ev.Content, &content); err != nil {
|
||||
if err := json.Unmarshal(ev.Content(), &content); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("failed to unmarshal event content")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
res.Joined[ev.Sender] = joinedMember(content)
|
||||
res.Joined[ev.Sender()] = joinedMember(content)
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -93,29 +135,6 @@ func GetMemberships(
|
|||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: getMembershipResponse{queryRes.JoinEvents},
|
||||
}
|
||||
}
|
||||
|
||||
func GetJoinedRooms(
|
||||
req *http.Request,
|
||||
device *userapi.Device,
|
||||
rsAPI api.ClientRoomserverAPI,
|
||||
) util.JSONResponse {
|
||||
var res api.QueryRoomsForUserResponse
|
||||
err := rsAPI.QueryRoomsForUser(req.Context(), &api.QueryRoomsForUserRequest{
|
||||
UserID: device.UserID,
|
||||
WantMembership: "join",
|
||||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryRoomsForUser failed")
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if res.RoomIDs == nil {
|
||||
res.RoomIDs = []string{}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: getJoinedRoomsResponse{res.RoomIDs},
|
||||
JSON: getMembershipResponse{gomatrixserverlib.HeaderedToClientEvents(result, gomatrixserverlib.FormatAll)},
|
||||
}
|
||||
}
|
||||
|
|
@ -83,18 +83,18 @@ func OnIncomingMessagesRequest(
|
|||
defer sqlutil.EndTransactionWithCheck(snapshot, &succeeded, &err)
|
||||
|
||||
// check if the user has already forgotten about this room
|
||||
isForgotten, roomExists, err := checkIsRoomForgotten(req.Context(), roomID, device.UserID, rsAPI)
|
||||
membershipResp, err := getMembershipForUser(req.Context(), roomID, device.UserID, rsAPI)
|
||||
if err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if !roomExists {
|
||||
if !membershipResp.RoomExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("room does not exist"),
|
||||
}
|
||||
}
|
||||
|
||||
if isForgotten {
|
||||
if membershipResp.IsRoomForgotten {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("user already forgot about this room"),
|
||||
|
|
@ -195,6 +195,20 @@ func OnIncomingMessagesRequest(
|
|||
}
|
||||
}
|
||||
|
||||
// If the user already left the room, grep events from before that
|
||||
if membershipResp.Membership == gomatrixserverlib.Leave {
|
||||
var token types.TopologyToken
|
||||
token, err = snapshot.EventPositionInTopology(req.Context(), membershipResp.EventID)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
if backwardOrdering {
|
||||
from = token
|
||||
}
|
||||
}
|
||||
|
||||
mReq := messagesReq{
|
||||
ctx: req.Context(),
|
||||
db: db,
|
||||
|
|
@ -283,17 +297,16 @@ func (m *messagesResp) applyLazyLoadMembers(
|
|||
}
|
||||
}
|
||||
|
||||
func checkIsRoomForgotten(ctx context.Context, roomID, userID string, rsAPI api.SyncRoomserverAPI) (forgotten bool, exists bool, err error) {
|
||||
func getMembershipForUser(ctx context.Context, roomID, userID string, rsAPI api.SyncRoomserverAPI) (resp api.QueryMembershipForUserResponse, err error) {
|
||||
req := api.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: userID,
|
||||
}
|
||||
resp := api.QueryMembershipForUserResponse{}
|
||||
if err := rsAPI.QueryMembershipForUser(ctx, &req, &resp); err != nil {
|
||||
return false, false, err
|
||||
return api.QueryMembershipForUserResponse{}, err
|
||||
}
|
||||
|
||||
return resp.IsRoomForgotten, resp.RoomExists, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// retrieveEvents retrieves events from the local database for a request on
|
||||
|
|
@ -313,7 +326,11 @@ func (r *messagesReq) retrieveEvents() (
|
|||
}
|
||||
|
||||
var events []*gomatrixserverlib.HeaderedEvent
|
||||
util.GetLogger(r.ctx).WithField("start", start).WithField("end", end).Infof("Fetched %d events locally", len(streamEvents))
|
||||
util.GetLogger(r.ctx).WithFields(logrus.Fields{
|
||||
"start": r.from,
|
||||
"end": r.to,
|
||||
"backwards": r.backwardOrdering,
|
||||
}).Infof("Fetched %d events locally", len(streamEvents))
|
||||
|
||||
// There can be two reasons for streamEvents to be empty: either we've
|
||||
// reached the oldest event in the room (or the most recent one, depending
|
||||
|
|
|
|||
|
|
@ -172,4 +172,37 @@ func Setup(
|
|||
return Search(req, device, syncDB, fts, nextBatch)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/rooms/{roomID}/members",
|
||||
httputil.MakeAuthAPI("rooms_members", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
var membership, notMembership *string
|
||||
if req.URL.Query().Has("membership") {
|
||||
m := req.URL.Query().Get("membership")
|
||||
membership = &m
|
||||
}
|
||||
if req.URL.Query().Has("not_membership") {
|
||||
m := req.URL.Query().Get("not_membership")
|
||||
notMembership = &m
|
||||
}
|
||||
|
||||
at := req.URL.Query().Get("at")
|
||||
return GetMemberships(req, device, vars["roomID"], syncDB, rsAPI, false, membership, notMembership, at)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
v3mux.Handle("/rooms/{roomID}/joined_members",
|
||||
httputil.MakeAuthAPI("rooms_members", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
at := req.URL.Query().Get("at")
|
||||
membership := gomatrixserverlib.Join
|
||||
return GetMemberships(req, device, vars["roomID"], syncDB, rsAPI, true, &membership, nil, at)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,6 +179,11 @@ type Database interface {
|
|||
ReIndex(ctx context.Context, limit, afterID int64) (map[int64]gomatrixserverlib.HeaderedEvent, error)
|
||||
UpdateRelations(ctx context.Context, event *gomatrixserverlib.HeaderedEvent) error
|
||||
RedactRelations(ctx context.Context, roomID, redactedEventID string) error
|
||||
SelectMemberships(
|
||||
ctx context.Context,
|
||||
roomID string, pos types.TopologyToken,
|
||||
membership, notMembership *string,
|
||||
) (eventIDs []string, err error)
|
||||
}
|
||||
|
||||
type Presence interface {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/syncapi/storage/tables"
|
||||
"github.com/matrix-org/dendrite/syncapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
// The memberships table is designed to track the last time that
|
||||
|
|
@ -69,11 +70,20 @@ const selectHeroesSQL = "" +
|
|||
const selectMembershipBeforeSQL = "" +
|
||||
"SELECT membership, topological_pos FROM syncapi_memberships WHERE room_id = $1 and user_id = $2 AND topological_pos <= $3 ORDER BY topological_pos DESC LIMIT 1"
|
||||
|
||||
const selectMembersSQL = `
|
||||
SELECT event_id FROM (
|
||||
SELECT DISTINCT ON (room_id, user_id) room_id, user_id, event_id, membership FROM syncapi_memberships WHERE room_id = $1 AND topological_pos <= $2 ORDER BY room_id, user_id, stream_pos DESC
|
||||
) t
|
||||
WHERE ($3::text IS NULL OR t.membership = $3)
|
||||
AND ($4::text IS NULL OR t.membership <> $4)
|
||||
`
|
||||
|
||||
type membershipsStatements struct {
|
||||
upsertMembershipStmt *sql.Stmt
|
||||
selectMembershipCountStmt *sql.Stmt
|
||||
selectHeroesStmt *sql.Stmt
|
||||
selectMembershipForUserStmt *sql.Stmt
|
||||
selectMembersStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func NewPostgresMembershipsTable(db *sql.DB) (tables.Memberships, error) {
|
||||
|
|
@ -87,6 +97,7 @@ func NewPostgresMembershipsTable(db *sql.DB) (tables.Memberships, error) {
|
|||
{&s.selectMembershipCountStmt, selectMembershipCountSQL},
|
||||
{&s.selectHeroesStmt, selectHeroesSQL},
|
||||
{&s.selectMembershipForUserStmt, selectMembershipBeforeSQL},
|
||||
{&s.selectMembersStmt, selectMembersSQL},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
|
|
@ -154,3 +165,25 @@ func (s *membershipsStatements) SelectMembershipForUser(
|
|||
}
|
||||
return membership, topologyPos, nil
|
||||
}
|
||||
|
||||
func (s *membershipsStatements) SelectMemberships(
|
||||
ctx context.Context, txn *sql.Tx,
|
||||
roomID string, pos types.TopologyToken,
|
||||
membership, notMembership *string,
|
||||
) (eventIDs []string, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectMembersStmt)
|
||||
rows, err := stmt.QueryContext(ctx, roomID, pos.Depth, membership, notMembership)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var (
|
||||
eventID string
|
||||
)
|
||||
for rows.Next() {
|
||||
if err = rows.Scan(&eventID); err != nil {
|
||||
return
|
||||
}
|
||||
eventIDs = append(eventIDs, eventID)
|
||||
}
|
||||
return eventIDs, rows.Err()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,6 +629,14 @@ func (d *Database) RedactRelations(ctx context.Context, roomID, redactedEventID
|
|||
})
|
||||
}
|
||||
|
||||
func (d *Database) SelectMemberships(
|
||||
ctx context.Context,
|
||||
roomID string, pos types.TopologyToken,
|
||||
membership, notMembership *string,
|
||||
) (eventIDs []string, err error) {
|
||||
return d.Memberships.SelectMemberships(ctx, nil, roomID, pos, membership, notMembership)
|
||||
}
|
||||
|
||||
func (s *Database) ExpirePresence(ctx context.Context) ([]types.PresenceNotify, error) {
|
||||
return s.Presence.ExpirePresence(ctx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/syncapi/storage/tables"
|
||||
"github.com/matrix-org/dendrite/syncapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
// The memberships table is designed to track the last time that
|
||||
|
|
@ -69,12 +70,20 @@ const selectHeroesSQL = "" +
|
|||
const selectMembershipBeforeSQL = "" +
|
||||
"SELECT membership, topological_pos FROM syncapi_memberships WHERE room_id = $1 and user_id = $2 AND topological_pos <= $3 ORDER BY topological_pos DESC LIMIT 1"
|
||||
|
||||
const selectMembersSQL = `
|
||||
SELECT event_id FROM
|
||||
( SELECT event_id, membership FROM syncapi_memberships WHERE room_id = $1 AND topological_pos <= $2 GROUP BY user_id HAVING(max(stream_pos))) t
|
||||
WHERE ($3 IS NULL OR t.membership = $3)
|
||||
AND ($4 IS NULL OR t.membership <> $4)
|
||||
`
|
||||
|
||||
type membershipsStatements struct {
|
||||
db *sql.DB
|
||||
upsertMembershipStmt *sql.Stmt
|
||||
selectMembershipCountStmt *sql.Stmt
|
||||
//selectHeroesStmt *sql.Stmt - prepared at runtime due to variadic
|
||||
selectMembershipForUserStmt *sql.Stmt
|
||||
selectMembersStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func NewSqliteMembershipsTable(db *sql.DB) (tables.Memberships, error) {
|
||||
|
|
@ -89,6 +98,7 @@ func NewSqliteMembershipsTable(db *sql.DB) (tables.Memberships, error) {
|
|||
{&s.upsertMembershipStmt, upsertMembershipSQL},
|
||||
{&s.selectMembershipCountStmt, selectMembershipCountSQL},
|
||||
{&s.selectMembershipForUserStmt, selectMembershipBeforeSQL},
|
||||
{&s.selectMembersStmt, selectMembersSQL},
|
||||
// {&s.selectHeroesStmt, selectHeroesSQL}, - prepared at runtime due to variadic
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
|
@ -170,3 +180,23 @@ func (s *membershipsStatements) SelectMembershipForUser(
|
|||
}
|
||||
return membership, topologyPos, nil
|
||||
}
|
||||
|
||||
func (s *membershipsStatements) SelectMemberships(
|
||||
ctx context.Context, txn *sql.Tx,
|
||||
roomID string, pos types.TopologyToken,
|
||||
membership, notMembership *string,
|
||||
) (eventIDs []string, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.selectMembersStmt)
|
||||
rows, err := stmt.QueryContext(ctx, roomID, pos.Depth, membership, notMembership)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var eventID string
|
||||
for rows.Next() {
|
||||
if err = rows.Scan(&eventID); err != nil {
|
||||
return
|
||||
}
|
||||
eventIDs = append(eventIDs, eventID)
|
||||
}
|
||||
return eventIDs, rows.Err()
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue