mirror of
https://github.com/element-hq/dendrite.git
synced 2025-09-16 22:22:25 +03:00
Merge remote-tracking branch 'origin/main' into url-preview
Signed-off-by: adnull <d.lexand@gmail.com>
This commit is contained in:
commit
57b5def1d1
53 changed files with 993 additions and 637 deletions
4
.github/workflows/schedules.yaml
vendored
4
.github/workflows/schedules.yaml
vendored
|
@ -272,7 +272,7 @@ jobs:
|
|||
run: |
|
||||
sed -i '/HOMESERVER/c\ HOMESERVER: "dendrite",' cypress.config.ts
|
||||
- name: "Run cypress tests"
|
||||
uses: cypress-io/github-action@v6.7.10
|
||||
uses: cypress-io/github-action@v6.10.0
|
||||
with:
|
||||
browser: chrome
|
||||
start: npx serve -p 8080 ./element-web/webapp
|
||||
|
@ -312,7 +312,7 @@ jobs:
|
|||
run: |
|
||||
sed -i '/HOMESERVER/c\ HOMESERVER: "dendritePinecone",' cypress.config.ts
|
||||
- name: "Run cypress tests"
|
||||
uses: cypress-io/github-action@v6.7.10
|
||||
uses: cypress-io/github-action@v6.10.0
|
||||
with:
|
||||
browser: chrome
|
||||
start: npx serve -p 8080 ./element-web/webapp
|
||||
|
|
|
@ -28,7 +28,6 @@ run:
|
|||
# the dependency descriptions in go.mod.
|
||||
#modules-download-mode: (release|readonly|vendor)
|
||||
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||
|
@ -41,7 +40,6 @@ output:
|
|||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
errcheck:
|
||||
|
@ -72,22 +70,12 @@ linters-settings:
|
|||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
#local-prefixes: github.com/org/project
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 25
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
dupl:
|
||||
# tokens count to trigger issue, 150 by default
|
||||
threshold: 100
|
||||
|
@ -96,30 +84,17 @@ linters-settings:
|
|||
min-len: 3
|
||||
# minimal occurrences count to trigger, 3 by default
|
||||
min-occurrences: 3
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
include-go-root: false
|
||||
packages:
|
||||
# - github.com/davecgh/go-spew/spew
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: UK
|
||||
ignore-words:
|
||||
# - someword
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 96
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
unused:
|
||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
|
@ -167,7 +142,6 @@ linters:
|
|||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- megacheck
|
||||
- misspell # Check code comments, whereas misspell in CI checks *.md files
|
||||
- nakedret
|
||||
- staticcheck
|
||||
|
@ -182,22 +156,16 @@ linters:
|
|||
- gochecknoinits
|
||||
- gocritic
|
||||
- gofmt
|
||||
- golint
|
||||
- gosec # Should turn back on soon
|
||||
- interfacer
|
||||
- lll
|
||||
- maligned
|
||||
- prealloc # Should turn back on soon
|
||||
- scopelint
|
||||
- stylecheck
|
||||
- typecheck # Should turn back on soon
|
||||
- unconvert # Should turn back on soon
|
||||
- goconst # Slightly annoying, as it reports "issues" in SQL statements
|
||||
disable-all: false
|
||||
presets:
|
||||
fast: false
|
||||
|
||||
|
||||
issues:
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
|
@ -217,13 +185,6 @@ issues:
|
|||
- bin
|
||||
- docs
|
||||
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
exclude:
|
||||
# - abcdef
|
||||
|
||||
# Excluding configuration per-path, per-linter, per-text and per-source
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
|
|
34
CHANGES.md
34
CHANGES.md
|
@ -1,5 +1,39 @@
|
|||
# Changelog
|
||||
|
||||
## Dendrite 0.15.2 (2025-08-15)
|
||||
|
||||
### Bug fixes
|
||||
- Fixed an issue which could cause Dendrite to crash on startup if the room state lacked a create event.
|
||||
|
||||
## Dendrite 0.15.1 (2025-08-13)
|
||||
|
||||
### Bug fixes
|
||||
- Fixed an issue which could cause Dendrite to become unresponsive for minutes at a time. (contributed by [viviicat](https://github.com/viviicat))
|
||||
- Fixed an issue which prevented joining v12 rooms in some circumstances.
|
||||
- Fixed an issue which prevented sending invites to v12 rooms.
|
||||
- Fixed an issue which prevented some clients from syncing v12 rooms.
|
||||
- Fixed an issue where a single badly formed PDU would block entire transactions of PDUs being processed. See https://github.com/element-hq/synapse/issues/7543 for the related issue on Synapse.
|
||||
|
||||
## Dendrite 0.15.0 (2025-08-12)
|
||||
|
||||
### ⚠ Important
|
||||
|
||||
This is a security release, adding support for [room version 12](https://matrix.org/blog/2025/08/security-release/).
|
||||
|
||||
### Features
|
||||
- Add support for [MSC4163](https://github.com/matrix-org/matrix-spec-proposals/pull/4163).
|
||||
- Add support for [MSC3967](https://github.com/matrix-org/matrix-spec-proposals/pull/3967).
|
||||
- Add support for room version 12.
|
||||
|
||||
### Bug fixes
|
||||
- Refactored NATS JetStream code to gracefully handle more potential errors. (contributed by [neilalexander](https://github.com/neilalexander))
|
||||
- Refactored NATS startup and readiness checking. (contributed by [neilalexander](https://github.com/neilalexander))
|
||||
- Updated NATS to 2.11.7. (contributed by [neilalexander](https://github.com/neilalexander))
|
||||
- Fixed an issue which could cause Dendrite to become unresponsive for minutes at a time. (contributed by [viviicat](https://github.com/viviicat))
|
||||
- Order events when backfilling to reduce the amount of unecessary `/state_ids` requests.
|
||||
- Gracefully handle incorrect sync filter JSON.
|
||||
- Fixed an issue which prevented device deletion working correctly. (contributed by [robinsdan](https://github.com/robinsdan))
|
||||
|
||||
## Dendrite 0.14.1 (2025-01-16)
|
||||
|
||||
### ⚠ Important
|
||||
|
|
|
@ -8,7 +8,7 @@ This is the repository for Dendrite, a second-generation Matrix homeserver writt
|
|||
|
||||
We ask that everybody who contributes to this project signs off their contributions, as explained below.
|
||||
|
||||
We follow a simple 'inbound=outbound' model for contributions: the act of submitting an 'inbound' contribution means that the contributor agrees to license their contribution under the same terms as the project's overall 'outbound' license - in our case, this is Apache Software License v2 (see [LICENSE](./LICENSE)).
|
||||
We follow a simple 'inbound=outbound' model for contributions: the act of submitting an 'inbound' contribution means that the contributor agrees to license their contribution under the same terms as the project's overall 'outbound' license - in our case, this is GNU Affero General Public License v3 (see [LICENSE](./LICENSE)). Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
|
||||
|
||||
In order to have a concrete record that your contribution is intentional and you agree to license it under the same terms as the project's license, we've adopted the same lightweight approach used by the [Linux Kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html), [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other projects: the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). This is a simple declaration that you wrote the contribution or otherwise have the right to contribute it to Matrix:
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
# base installs required dependencies and runs go mod download to cache dependencies
|
||||
#
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.22-alpine AS base
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.24-alpine AS base
|
||||
RUN apk --update --no-cache add bash build-base curl git
|
||||
|
||||
#
|
||||
|
|
57
README.md
57
README.md
|
@ -2,14 +2,14 @@
|
|||
|
||||
[](https://github.com/element-hq/dendrite/actions/workflows/dendrite.yml) [](https://matrix.to/#/#dendrite:matrix.org) [](https://matrix.to/#/#dendrite-dev:matrix.org)
|
||||
|
||||
Dendrite is a second-generation Matrix homeserver written in Go.
|
||||
It intends to provide an **efficient**, **reliable** and **scalable** alternative to [Synapse](https://github.com/matrix-org/synapse):
|
||||
Dendrite is a second-generation Matrix homeserver written in Go. It is currently in maintenance mode,
|
||||
meaning only security fixes are being applied, for example [room version 12](https://matrix.org/blog/2025/08/security-release/).
|
||||
|
||||
It intends to provide an **efficient** and **reliable** alternative to [Synapse](https://github.com/matrix-org/synapse):
|
||||
|
||||
- Efficient: A small memory footprint with better baseline performance than an out-of-the-box Synapse.
|
||||
- Reliable: Implements the Matrix specification as written, using the
|
||||
[same test suite](https://github.com/matrix-org/sytest) as Synapse as well as
|
||||
a [brand new Go test suite](https://github.com/matrix-org/complement).
|
||||
- Scalable: can run on multiple machines and eventually scale to massive homeserver deployments.
|
||||
[same](https://github.com/matrix-org/sytest) test [suites](https://github.com/matrix-org/complement) as Synapse.
|
||||
|
||||
Dendrite is **beta** software, which means:
|
||||
|
||||
|
@ -31,9 +31,13 @@ If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or j
|
|||
- **[#dendrite-dev:matrix.org](https://matrix.to/#/#dendrite-dev:matrix.org)** - The place for developers, where all Dendrite development discussion happens
|
||||
- **[#dendrite-alerts:matrix.org](https://matrix.to/#/#dendrite-alerts:matrix.org)** - Release notifications and important info, highly recommended for all Dendrite server admins
|
||||
|
||||
Dendrite does not currently support the following MSCs, which impacts the ability to use Element X with Dendrite servers:
|
||||
- [MSC4186](https://github.com/matrix-org/matrix-spec-proposals/pull/4186): Simplified Sliding Sync
|
||||
- [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861): Next-gen auth OIDC
|
||||
|
||||
## Requirements
|
||||
|
||||
See the [Planning your Installation](https://matrix-org.github.io/dendrite/installation/planning) page for
|
||||
See the [Planning your Installation](https://element-hq.github.io/dendrite/installation/planning) page for
|
||||
more information on requirements.
|
||||
|
||||
To build Dendrite, you will need Go 1.21 or later.
|
||||
|
@ -53,7 +57,7 @@ The [Federation Tester](https://federationtester.matrix.org) can be used to veri
|
|||
|
||||
## Get started
|
||||
|
||||
If you wish to build a fully-federating Dendrite instance, see [the Installation documentation](https://matrix-org.github.io/dendrite/installation). For running in Docker, see [build/docker](build/docker).
|
||||
If you wish to build a fully-federating Dendrite instance, see [the Installation documentation](https://element-hq.github.io/dendrite/installation). For running in Docker, see [build/docker](build/docker).
|
||||
|
||||
The following instructions are enough to get Dendrite started as a non-federating test deployment using self-signed certificates and SQLite databases:
|
||||
|
||||
|
@ -83,36 +87,6 @@ $ ./bin/create-account --config dendrite.yaml --username alice
|
|||
|
||||
Then point your favourite Matrix client at `http://localhost:8008` or `https://localhost:8448`.
|
||||
|
||||
## Progress
|
||||
|
||||
We use a script called "Are We Synapse Yet" which checks Sytest compliance rates. Sytest is a black-box homeserver
|
||||
test rig with around 900 tests. The script works out how many of these tests are passing on Dendrite and it
|
||||
updates with CI. As of January 2023, we have 100% server-server parity with Synapse, and the client-server parity is at 93% , though check
|
||||
CI for the latest numbers. In practice, this means you can communicate locally and via federation with Synapse
|
||||
servers such as matrix.org reasonably well, although there are still some missing features (like SSO and Third-party ID APIs).
|
||||
|
||||
We are prioritising features that will benefit single-user homeservers first (e.g Receipts, E2E) rather
|
||||
than features that massive deployments may be interested in (OpenID, Guests, Admin APIs, AS API).
|
||||
This means Dendrite supports amongst others:
|
||||
|
||||
- Core room functionality (creating rooms, invites, auth rules)
|
||||
- Room versions 1 to 10 supported
|
||||
- Backfilling locally and via federation
|
||||
- Accounts, profiles and devices
|
||||
- Published room lists
|
||||
- Typing
|
||||
- Media APIs
|
||||
- Redaction
|
||||
- Tagging
|
||||
- Context
|
||||
- E2E keys and device lists
|
||||
- Receipts
|
||||
- Push
|
||||
- Guests
|
||||
- User Directory
|
||||
- Presence
|
||||
- Fulltext search
|
||||
|
||||
## Contributing
|
||||
|
||||
We would be grateful for any help on issues marked as
|
||||
|
@ -121,7 +95,7 @@ all have related Sytests which need to pass in order for the issue to be closed.
|
|||
code, you can quickly run Sytest to ensure that the test names are now passing.
|
||||
|
||||
If you're new to the project, see our
|
||||
[Contributing page](https://matrix-org.github.io/dendrite/development/contributing) to get up to speed, then
|
||||
[Contributing page](https://element-hq.github.io/dendrite/development/contributing) to get up to speed, then
|
||||
look for [Good First Issues](https://github.com/element-hq/dendrite/labels/good%20first%20issue). If you're
|
||||
familiar with the project, look for [Help Wanted](https://github.com/element-hq/dendrite/labels/help-wanted)
|
||||
issues.
|
||||
|
@ -130,12 +104,11 @@ issues.
|
|||
|
||||
Copyright 2017 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017-2025 New Vector Ltd
|
||||
Copyright 2017-2025 New Vector Ltd
|
||||
|
||||
This software is dual-licensed by New Vector Ltd (Element). It can be used either:
|
||||
|
||||
|
||||
(1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
|
||||
|
||||
|
||||
(2) under the terms of a paid-for Element Commercial License agreement between you and Element (the terms of which may vary depending on what you and Element have agreed to).
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#syntax=docker/dockerfile:1.2
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} ghcr.io/element-hq/dendrite-monolith:binaries AS build
|
||||
FROM --platform=${TARGETPLATFORM} ghcr.io/element-hq/dendrite-monolith:binaries AS build
|
||||
|
||||
FROM alpine:latest
|
||||
RUN apk --update --no-cache add curl
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#syntax=docker/dockerfile:1.2
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} ghcr.io/element-hq/dendrite-monolith:binaries AS build
|
||||
FROM --platform=${TARGETPLATFORM} ghcr.io/element-hq/dendrite-monolith:binaries AS build
|
||||
|
||||
FROM alpine:latest
|
||||
LABEL org.opencontainers.image.title="Dendrite (Yggdrasil demo)"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#syntax=docker/dockerfile:1.2
|
||||
|
||||
FROM golang:1.22-bookworm as build
|
||||
FROM golang:1.24-bookworm as build
|
||||
RUN apt-get update && apt-get install -y sqlite3
|
||||
WORKDIR /build
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#
|
||||
# Use these mounts to make use of this dockerfile:
|
||||
# COMPLEMENT_HOST_MOUNTS='/your/local/dendrite:/dendrite:ro;/your/go/path:/go:ro'
|
||||
FROM golang:1.22-bookworm
|
||||
FROM golang:1.24-bookworm
|
||||
RUN apt-get update && apt-get install -y sqlite3
|
||||
|
||||
ENV SERVER_NAME=localhost
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#syntax=docker/dockerfile:1.2
|
||||
|
||||
FROM golang:1.22-bookworm as build
|
||||
FROM golang:1.24-bookworm as build
|
||||
RUN apt-get update && apt-get install -y postgresql
|
||||
WORKDIR /build
|
||||
|
||||
|
|
|
@ -176,12 +176,6 @@ func createRoom(
|
|||
roomVersion = candidateVersion
|
||||
}
|
||||
|
||||
logger.WithFields(log.Fields{
|
||||
"userID": userID.String(),
|
||||
"roomID": roomID.String(),
|
||||
"roomVersion": roomVersion,
|
||||
}).Info("Creating new room")
|
||||
|
||||
profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID.String(), asAPI, profileAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
|
||||
|
@ -197,6 +191,49 @@ func createRoom(
|
|||
keyID := cfg.Matrix.KeyID
|
||||
privateKey := cfg.Matrix.PrivateKey
|
||||
|
||||
verImpl := gomatrixserverlib.MustGetRoomVersion(roomVersion)
|
||||
|
||||
var createEventJSON json.RawMessage
|
||||
if verImpl.DomainlessRoomIDs() {
|
||||
// make the create event up-front so the roomserver can calculate the room NID to store.
|
||||
var additionalCreators []string
|
||||
if createRequest.Preset == spec.PresetTrustedPrivateChat {
|
||||
additionalCreators = createRequest.Invite
|
||||
}
|
||||
createContent, err := roomserverAPI.GenerateCreateContent(ctx, createRequest.RoomVersion, userID.String(), createRequest.CreationContent, additionalCreators)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("GenerateCreateContent failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("invalid create content"),
|
||||
}
|
||||
}
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
|
||||
identity, err := cfg.Matrix.SigningIdentityFor(userID.Domain())
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to get signing identity")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
createEvent, jsonErr := roomserverAPI.GeneratePDU(
|
||||
ctx, gomatrixserverlib.MustGetRoomVersion(roomVersion),
|
||||
gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
},
|
||||
authEvents, 1, "", identity, evTime, userID.String(), "", rsAPI,
|
||||
)
|
||||
if jsonErr != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to make the create event")
|
||||
return *jsonErr
|
||||
}
|
||||
createEventJSON = createEvent.JSON()
|
||||
r := createEvent.RoomID()
|
||||
roomID = &r
|
||||
}
|
||||
|
||||
req := roomserverAPI.PerformCreateRoomRequest{
|
||||
InvitedUsers: createRequest.Invite,
|
||||
RoomName: createRequest.Name,
|
||||
|
@ -204,6 +241,7 @@ func createRoom(
|
|||
Topic: createRequest.Topic,
|
||||
StatePreset: createRequest.Preset,
|
||||
CreationContent: createRequest.CreationContent,
|
||||
CreateEvent: createEventJSON,
|
||||
InitialState: createRequest.InitialState,
|
||||
RoomAliasName: createRequest.RoomAliasName,
|
||||
RoomVersion: roomVersion,
|
||||
|
@ -217,6 +255,12 @@ func createRoom(
|
|||
EventTime: evTime,
|
||||
}
|
||||
|
||||
logger.WithFields(log.Fields{
|
||||
"userID": userID.String(),
|
||||
"roomID": roomID.String(),
|
||||
"roomVersion": roomVersion,
|
||||
}).Info("Creating new room")
|
||||
|
||||
roomAlias, createRes := rsAPI.PerformCreateRoom(ctx, *userID, *roomID, &req)
|
||||
if createRes != nil {
|
||||
return *createRes
|
||||
|
|
|
@ -411,10 +411,11 @@ func SetVisibility(
|
|||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
privileged := isPrivilegedCreator(req.Context(), rsAPI, roomID, *senderID)
|
||||
|
||||
// NOTSPEC: Check if the user's power is greater than power required to change m.room.canonical_alias event
|
||||
power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].PDU)
|
||||
if power.UserLevel(*senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) {
|
||||
if !privileged && power.UserLevel(*senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("userID doesn't have power level to change visibility"),
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"crypto/ed25519"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
appserviceAPI "github.com/element-hq/dendrite/appservice/api"
|
||||
|
@ -79,7 +80,8 @@ func SendBan(
|
|||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
allowedToBan := pl.UserLevel(*senderID) >= pl.Ban
|
||||
privileged := isPrivilegedCreator(req.Context(), rsAPI, roomID, *senderID)
|
||||
allowedToBan := privileged || pl.UserLevel(*senderID) >= pl.Ban
|
||||
if !allowedToBan {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
|
@ -118,6 +120,12 @@ func sendMembership(ctx context.Context, profileAPI userapi.ClientUserAPI, devic
|
|||
false,
|
||||
); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
|
||||
if err.Error() == api.InputWasRejected {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("the event was rejected"),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
|
@ -185,7 +193,8 @@ func SendKick(
|
|||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
allowedToKick := pl.UserLevel(*senderID) >= pl.Kick || bodyUserID.String() == deviceUserID.String()
|
||||
privileged := isPrivilegedCreator(req.Context(), rsAPI, roomID, *senderID)
|
||||
allowedToKick := privileged || pl.UserLevel(*senderID) >= pl.Kick || bodyUserID.String() == deviceUserID.String()
|
||||
if !allowedToKick {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
|
@ -680,3 +689,12 @@ func getPowerlevels(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI,
|
|||
}
|
||||
return pl, nil
|
||||
}
|
||||
|
||||
// Returns true if the room is a room which supports privileged creators and the sender is a creator, else false.
|
||||
func isPrivilegedCreator(ctx context.Context, rsAPI roomserverAPI.ClientRoomserverAPI, roomID string, senderID spec.SenderID) bool {
|
||||
createEvent := roomserverAPI.GetStateEvent(ctx, rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomCreate,
|
||||
StateKey: "",
|
||||
})
|
||||
return gomatrixserverlib.MustGetRoomVersion(createEvent.Version()).PrivilegedCreators() && slices.Contains(gomatrixserverlib.CreatorsFromCreateEvent(createEvent), string(senderID))
|
||||
}
|
||||
|
|
|
@ -98,10 +98,12 @@ func SendRedaction(
|
|||
}
|
||||
}
|
||||
|
||||
privileged := isPrivilegedCreator(req.Context(), rsAPI, roomID, *senderID)
|
||||
|
||||
// "Users may redact their own events, and any user with a power level greater than or equal
|
||||
// to the redact power level of the room may redact events there"
|
||||
// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid
|
||||
allowedToRedact := ev.SenderID() == *senderID
|
||||
allowedToRedact := ev.SenderID() == *senderID || privileged
|
||||
if !allowedToRedact {
|
||||
plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomPowerLevels,
|
||||
|
|
|
@ -77,7 +77,6 @@ func SendEvent(
|
|||
JSON: spec.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
if txnID != nil {
|
||||
// Try to fetch response from transactionsCache
|
||||
if res, ok := txnCache.FetchTransaction(device.AccessToken, *txnID, req.URL); ok {
|
||||
|
@ -367,6 +366,12 @@ func generateSendEvent(
|
|||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if proto.Type == spec.MRoomCreate && proto.StateKey != nil && *proto.StateKey == "" {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.InvalidParam("cannot resend m.room.create event"),
|
||||
}
|
||||
}
|
||||
|
||||
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID)
|
||||
if err != nil {
|
||||
|
@ -424,8 +429,13 @@ func generateSendEvent(
|
|||
if err = gomatrixserverlib.Allowed(e.PDU, provider, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return rsAPI.QueryUserIDForSender(ctx, *validRoomID, senderID)
|
||||
}); err != nil {
|
||||
code := 403
|
||||
validationErr, ok := err.(*gomatrixserverlib.EventValidationError)
|
||||
if ok {
|
||||
code = validationErr.Code
|
||||
}
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
Code: code,
|
||||
JSON: spec.Forbidden(err.Error()), // TODO: Is this error string comprehensible to the client?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/tokens"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
@ -100,7 +101,7 @@ func SendServerNotice(
|
|||
for _, membership := range []string{"join", "invite", "leave"} {
|
||||
userRooms, queryErr := rsAPI.QueryRoomsForUser(ctx, *userID, membership)
|
||||
if queryErr != nil {
|
||||
return util.ErrorResponse(err)
|
||||
return util.ErrorResponse(queryErr)
|
||||
}
|
||||
allUserRooms = append(allUserRooms, userRooms...)
|
||||
}
|
||||
|
@ -139,7 +140,7 @@ func SendServerNotice(
|
|||
|
||||
// create a new room for the user
|
||||
if len(commonRooms) == 0 {
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(senderUserID.String())
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(gomatrixserverlib.MustGetRoomVersion(roomVersion), senderUserID.String())
|
||||
powerLevelContent.Users[r.UserID] = -10 // taken from Synapse
|
||||
pl, err := json.Marshal(powerLevelContent)
|
||||
if err != nil {
|
||||
|
|
|
@ -23,7 +23,8 @@ import (
|
|||
)
|
||||
|
||||
type upgradeRoomRequest struct {
|
||||
NewVersion string `json:"new_version"`
|
||||
NewVersion string `json:"new_version"`
|
||||
AdditionalCreators []string `json:"additional_creators"`
|
||||
}
|
||||
|
||||
type upgradeRoomResponse struct {
|
||||
|
@ -43,6 +44,13 @@ func UpgradeRoom(
|
|||
return *rErr
|
||||
}
|
||||
|
||||
if r.NewVersion == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.InvalidParam("missing version to upgrade to"),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that the room version is supported
|
||||
if _, err := version.SupportedRoomVersion(gomatrixserverlib.RoomVersion(r.NewVersion)); err != nil {
|
||||
return util.JSONResponse{
|
||||
|
@ -59,7 +67,10 @@ func UpgradeRoom(
|
|||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
newRoomID, err := rsAPI.PerformRoomUpgrade(req.Context(), roomID, *userID, gomatrixserverlib.RoomVersion(r.NewVersion))
|
||||
newRoomID, err := rsAPI.PerformRoomUpgrade(req.Context(), roomID, *userID, gomatrixserverlib.RoomVersion(r.NewVersion), r.AdditionalCreators)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformRoomUpgrade failed")
|
||||
}
|
||||
switch e := err.(type) {
|
||||
case nil:
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
|
|
|
@ -55,7 +55,7 @@ var latest, _ = semver.NewVersion("v6.6.6") // Dummy version, used as "HEAD"
|
|||
// due to the error:
|
||||
// When using COPY with more than one source file, the destination must be a directory and end with a /
|
||||
// We need to run a postgres anyway, so use the dockerfile associated with Complement instead.
|
||||
const DockerfilePostgreSQL = `FROM golang:1.22-bookworm as build
|
||||
const DockerfilePostgreSQL = `FROM golang:1.24-bookworm as build
|
||||
RUN apt-get update && apt-get install -y postgresql
|
||||
WORKDIR /build
|
||||
ARG BINARY
|
||||
|
@ -99,7 +99,7 @@ ENV BINARY=dendrite
|
|||
EXPOSE 8008 8448
|
||||
CMD /build/run_dendrite.sh`
|
||||
|
||||
const DockerfileSQLite = `FROM golang:1.22-bookworm as build
|
||||
const DockerfileSQLite = `FROM golang:1.24-bookworm as build
|
||||
RUN apt-get update && apt-get install -y postgresql
|
||||
WORKDIR /build
|
||||
ARG BINARY
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
source "https://rubygems.org"
|
||||
gem "github-pages", "~> 226", group: :jekyll_plugins
|
||||
group :jekyll_plugins do
|
||||
gem "jekyll-feed", "~> 0.15.1"
|
||||
end
|
||||
gem "github-pages", "~> 232", group: :jekyll_plugins
|
||||
|
|
|
@ -1,66 +1,65 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.6.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
activesupport (8.0.2)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.2)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
coffee-script-source (1.12.2)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.23.10)
|
||||
concurrent-ruby (1.2.0)
|
||||
dnsruby (1.61.9)
|
||||
simpleidn (~> 0.1)
|
||||
commonmarker (0.23.11)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.3)
|
||||
csv (3.3.5)
|
||||
dnsruby (1.72.4)
|
||||
base64 (~> 0.2.0)
|
||||
logger (~> 1.6.5)
|
||||
simpleidn (~> 0.2.1)
|
||||
drb (2.2.3)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
ethon (0.15.0)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.8.1)
|
||||
faraday (1.10.0)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.3)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
ffi (1.15.5)
|
||||
execjs (2.10.0)
|
||||
faraday (2.13.4)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
json
|
||||
logger
|
||||
faraday-net_http (3.4.1)
|
||||
net-http (>= 0.5.0)
|
||||
ffi (1.17.2-arm64-darwin)
|
||||
ffi (1.17.2-x86_64-linux-gnu)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.1)
|
||||
github-pages (226)
|
||||
github-pages-health-check (= 1.17.9)
|
||||
jekyll (= 3.9.2)
|
||||
jekyll-avatar (= 0.7.0)
|
||||
jekyll-coffeescript (= 1.1.1)
|
||||
jekyll-commonmark-ghpages (= 0.2.0)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.15.1)
|
||||
gemoji (4.1.0)
|
||||
github-pages (232)
|
||||
github-pages-health-check (= 1.18.2)
|
||||
jekyll (= 3.10.0)
|
||||
jekyll-avatar (= 0.8.0)
|
||||
jekyll-coffeescript (= 1.2.2)
|
||||
jekyll-commonmark-ghpages (= 0.5.1)
|
||||
jekyll-default-layout (= 0.1.5)
|
||||
jekyll-feed (= 0.17.0)
|
||||
jekyll-gist (= 1.5.0)
|
||||
jekyll-github-metadata (= 2.13.0)
|
||||
jekyll-github-metadata (= 2.16.1)
|
||||
jekyll-include-cache (= 0.2.1)
|
||||
jekyll-mentions (= 1.6.0)
|
||||
jekyll-optional-front-matter (= 0.3.2)
|
||||
|
@ -87,32 +86,34 @@ GEM
|
|||
jekyll-theme-tactile (= 0.2.0)
|
||||
jekyll-theme-time-machine (= 0.2.0)
|
||||
jekyll-titles-from-headings (= 0.5.3)
|
||||
jemoji (= 0.12.0)
|
||||
kramdown (= 2.3.2)
|
||||
jemoji (= 0.13.0)
|
||||
kramdown (= 2.4.0)
|
||||
kramdown-parser-gfm (= 1.1.0)
|
||||
liquid (= 4.0.3)
|
||||
liquid (= 4.0.4)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.5.1)
|
||||
nokogiri (>= 1.13.4, < 2.0)
|
||||
rouge (= 3.26.0)
|
||||
nokogiri (>= 1.16.2, < 2.0)
|
||||
rouge (= 3.30.0)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.17.9)
|
||||
webrick (~> 1.8)
|
||||
github-pages-health-check (1.18.2)
|
||||
addressable (~> 2.3)
|
||||
dnsruby (~> 1.60)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (>= 3.0, < 5.0)
|
||||
octokit (>= 4, < 8)
|
||||
public_suffix (>= 3.0, < 6.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.14.1)
|
||||
html-pipeline (2.14.3)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (0.9.5)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (3.9.2)
|
||||
jekyll (3.10.0)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
csv (~> 3.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 0.7)
|
||||
i18n (>= 0.7, < 2)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (>= 1.17, < 3)
|
||||
|
@ -121,27 +122,28 @@ GEM
|
|||
pathutil (~> 0.9)
|
||||
rouge (>= 1.7, < 4)
|
||||
safe_yaml (~> 1.0)
|
||||
jekyll-avatar (0.7.0)
|
||||
webrick (>= 1.0)
|
||||
jekyll-avatar (0.8.0)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
jekyll-coffeescript (1.1.1)
|
||||
jekyll-coffeescript (1.2.2)
|
||||
coffee-script (~> 2.2)
|
||||
coffee-script-source (~> 1.11.1)
|
||||
coffee-script-source (~> 1.12)
|
||||
jekyll-commonmark (1.4.0)
|
||||
commonmarker (~> 0.22)
|
||||
jekyll-commonmark-ghpages (0.2.0)
|
||||
commonmarker (~> 0.23.4)
|
||||
jekyll (~> 3.9.0)
|
||||
jekyll-commonmark-ghpages (0.5.1)
|
||||
commonmarker (>= 0.23.7, < 1.1.0)
|
||||
jekyll (>= 3.9, < 4.0)
|
||||
jekyll-commonmark (~> 1.4.0)
|
||||
rouge (>= 2.0, < 4.0)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.15.1)
|
||||
rouge (>= 2.0, < 5.0)
|
||||
jekyll-default-layout (0.1.5)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
jekyll-feed (0.17.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-gist (1.5.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.13.0)
|
||||
jekyll-github-metadata (2.16.1)
|
||||
jekyll (>= 3.4, < 5.0)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
octokit (>= 4, < 7, != 4.4.0)
|
||||
jekyll-include-cache (0.2.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-mentions (1.6.0)
|
||||
|
@ -212,76 +214,71 @@ GEM
|
|||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
jemoji (0.12.0)
|
||||
gemoji (~> 3.0)
|
||||
jemoji (0.13.0)
|
||||
gemoji (>= 3, < 5)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
kramdown (2.3.2)
|
||||
json (2.13.1)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
liquid (4.0.4)
|
||||
listen (3.9.0)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.6.6)
|
||||
mercenary (0.3.6)
|
||||
minima (2.5.1)
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.17.0)
|
||||
multipart-post (2.1.1)
|
||||
nokogiri (1.16.2-arm64-darwin)
|
||||
minitest (5.25.5)
|
||||
net-http (0.6.0)
|
||||
uri
|
||||
nokogiri (1.18.9-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.16.2-x86_64-linux)
|
||||
nokogiri (1.18.9-x86_64-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
octokit (4.22.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
octokit (4.25.1)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (4.0.7)
|
||||
racc (1.7.3)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-inotify (0.10.1)
|
||||
public_suffix (5.1.1)
|
||||
racc (1.8.1)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.3.2)
|
||||
strscan
|
||||
rouge (3.26.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
rexml (3.4.1)
|
||||
rouge (3.30.0)
|
||||
rubyzip (2.4.1)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.7.4)
|
||||
sass-listen (~> 4.0.0)
|
||||
sass-listen (4.0.0)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
sawyer (0.8.2)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
simpleidn (0.2.1)
|
||||
unf (~> 0.1.4)
|
||||
strscan (3.1.0)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
securerandom (0.4.1)
|
||||
simpleidn (0.2.3)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (1.4.0)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.11)
|
||||
thread_safe (~> 0.1)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.1)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (1.8.0)
|
||||
zeitwerk (2.6.6)
|
||||
uri (1.0.3)
|
||||
webrick (1.9.1)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-21
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
github-pages (~> 226)
|
||||
jekyll-feed (~> 0.15.1)
|
||||
github-pages (~> 232)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.7
|
||||
|
|
|
@ -101,7 +101,7 @@ If successfully sent, the API will return the following response:
|
|||
|
||||
## GET `/_synapse/admin/v1/register`
|
||||
|
||||
Shared secret registration — please see the [user creation page](createusers) for
|
||||
Shared secret registration — please see the [user creation page](1_createusers.md) for
|
||||
guidance on configuring and using this endpoint.
|
||||
|
||||
## GET `/_matrix/client/v3/admin/whois/{userId}`
|
||||
|
|
85
go.mod
85
go.mod
|
@ -2,12 +2,12 @@ module github.com/element-hq/dendrite
|
|||
|
||||
require (
|
||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/MFAshby/stdemuxerhook v1.0.0
|
||||
github.com/Masterminds/semver/v3 v3.3.1
|
||||
github.com/blevesearch/bleve/v2 v2.4.4
|
||||
github.com/blevesearch/bleve/v2 v2.5.2
|
||||
github.com/codeclysm/extract v2.2.0+incompatible
|
||||
github.com/coder/websocket v1.8.12
|
||||
github.com/coder/websocket v1.8.13
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/dgraph-io/ristretto v0.2.0
|
||||
github.com/docker/docker v26.1.5+incompatible
|
||||
|
@ -17,7 +17,7 @@ require (
|
|||
github.com/foxcpp/go-mockdns v1.1.0
|
||||
github.com/getsentry/sentry-go v0.14.0
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
|
@ -26,17 +26,17 @@ 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-20250116181547-c4f1e01eab0d
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250815065806-6697d93cbcba
|
||||
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7
|
||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/nats-io/nats-server/v2 v2.10.25
|
||||
github.com/nats-io/nats.go v1.38.0
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/nats-io/nats-server/v2 v2.11.7
|
||||
github.com/nats-io/nats.go v1.44.0
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
|
@ -46,15 +46,15 @@ require (
|
|||
github.com/yggdrasil-network/yggdrasil-go v0.5.12
|
||||
github.com/yggdrasil-network/yggquic v0.0.0-20241212194307-0d495106021f
|
||||
go.uber.org/atomic v1.11.0
|
||||
golang.org/x/crypto v0.32.0
|
||||
golang.org/x/crypto v0.40.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
golang.org/x/image v0.23.0
|
||||
golang.org/x/image v0.27.0
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/term v0.28.0
|
||||
golang.org/x/sync v0.16.0
|
||||
golang.org/x/term v0.33.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gotest.tools/v3 v3.5.1
|
||||
gotest.tools/v3 v3.5.2
|
||||
maunium.net/go/mautrix v0.15.1
|
||||
modernc.org/sqlite v1.34.5
|
||||
)
|
||||
|
@ -63,27 +63,27 @@ require (
|
|||
github.com/Arceliar/ironwood v0.0.0-20241213013129-743fe2fccbd3 // indirect
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.9.3 // indirect
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
|
||||
github.com/blevesearch/geo v0.1.20 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.24 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
|
||||
github.com/blevesearch/geo v0.2.3 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
github.com/blevesearch/vellum v1.0.10 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.16 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.1.9-0.20241217210638-a0519e7caf3b // indirect
|
||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
|
@ -97,15 +97,16 @@ require (
|
|||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-tpm v0.9.5 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/h2non/filetype v1.1.3 // indirect
|
||||
github.com/hashicorp/go-set/v3 v3.0.0 // indirect
|
||||
github.com/hjson/hjson-go/v4 v4.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/juju/errors v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.57 // indirect
|
||||
|
@ -117,16 +118,17 @@ require (
|
|||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.3 // indirect
|
||||
github.com/nats-io/nkeys v0.4.9 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.4 // indirect
|
||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/oleiade/lane/v2 v2.0.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/quic-go/quic-go v0.48.2 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
|
@ -135,7 +137,7 @@ require (
|
|||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect
|
||||
|
@ -143,12 +145,13 @@ require (
|
|||
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.34.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/macaroon.v2 v2.1.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
maunium.net/go/maulogger/v2 v2.4.1 // indirect
|
||||
|
@ -158,6 +161,6 @@ require (
|
|||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
)
|
||||
|
||||
go 1.22
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.2
|
||||
toolchain go1.24.3
|
||||
|
|
177
go.sum
177
go.sum
|
@ -6,8 +6,8 @@ github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47
|
|||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/MFAshby/stdemuxerhook v1.0.0 h1:1XFGzakrsHMv76AeanPDL26NOgwjPl/OUxbGhJthwMc=
|
||||
|
@ -16,61 +16,63 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r
|
|||
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM=
|
||||
github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op h1:+OSa/t11TFhqfrX0EOSqQBDJ0YlpmK0rDSiB19dg9M0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
|
||||
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0 h1:VfknkqV4xI+PsaDIsoHueyxVDZrfvMn56jeWUzvzdls=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg=
|
||||
github.com/blevesearch/bleve/v2 v2.4.4 h1:RwwLGjUm54SwyyykbrZs4vc1qjzYic4ZnAnY9TwNl60=
|
||||
github.com/blevesearch/bleve/v2 v2.4.4/go.mod h1:fa2Eo6DP7JR+dMFpQe+WiZXINKSunh7WBtlDGbolKXk=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||
github.com/blevesearch/go-faiss v1.0.24 h1:K79IvKjoKHdi7FdiXEsAhxpMuns0x4fM0BO93bW5jLI=
|
||||
github.com/blevesearch/go-faiss v1.0.24/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
|
||||
github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
|
||||
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
|
||||
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
|
||||
github.com/blevesearch/geo v0.2.3/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
||||
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 h1:uGvKVvG7zvSxCwcm4/ehBa9cCEuZVE+/zvrSl57QUVY=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16/go.mod h1:VF5oHVbIFTu+znY1v30GjSpT5+9YFs9dV2hjvuh34F0=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 h1:Yqk0XD1mE0fDZAJXTjawJ8If/85JxnLd8v5vG/jWE/s=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A=
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ=
|
||||
github.com/blevesearch/vellum v1.0.10 h1:HGPJDT2bTva12hrHepVT3rOyIKFFF4t7Gf6yMxyMIPI=
|
||||
github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 h1:hvjgj9tZ9DeIqBCxKhi70TtSZYMdcFn7gDb71Xo/fvk=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 h1:yHfj3vXLSYmmsBleJFROXuO08mS3L1qDCdDK81jDl8s=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIqMGahDE8=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
||||
github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH48sb+FmE=
|
||||
github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||
github.com/blevesearch/zapx/v16 v16.1.9-0.20241217210638-a0519e7caf3b h1:ju9Az5YgrzCeK3M1QwvZIpxYhChkXp7/L0RhDYsxXoE=
|
||||
github.com/blevesearch/zapx/v16 v16.1.9-0.20241217210638-a0519e7caf3b/go.mod h1:BlrYNpOu4BvVRslmIG+rLtKhmjIaRhIbG8sb9scGTwI=
|
||||
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
||||
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
|
||||
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/codeclysm/extract v2.2.0+incompatible h1:q3wyckoA30bhUSiwdQezMqVhwd8+WGE64/GL//LtUhI=
|
||||
github.com/codeclysm/extract v2.2.0+incompatible/go.mod h1:2nhFMPHiU9At61hz+12bfrlpXSUrOnK+wR+KlGO4Uks=
|
||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
|
||||
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
|
@ -109,8 +111,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
|
|||
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
|
||||
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
|
||||
github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
|
||||
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
|
||||
github.com/getlantern/fdcount v0.0.0-20210503151800-5decd65b3731/go.mod h1:XZwE+iIlAgr64OFbXKFNCllBwV4wEipPx8Hlo2gZdbM=
|
||||
|
@ -166,8 +168,6 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
|
@ -181,8 +181,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
|
@ -199,6 +201,8 @@ github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
|||
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/go-set/v3 v3.0.0 h1:CaJBQvQCOWoftrBcDt7Nwgo0kdpmrKxar/x2o6pV9JA=
|
||||
github.com/hashicorp/go-set/v3 v3.0.0/go.mod h1:IEghM2MpE5IaNvL+D7X480dfNtxjRXZ6VMpK3C8s2ok=
|
||||
github.com/hjson/hjson-go/v4 v4.4.0 h1:D/NPvqOCH6/eisTb5/ztuIS8GUvmpHaLOcNk1Bjr298=
|
||||
github.com/hjson/hjson-go/v4 v4.4.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
|
@ -211,9 +215,10 @@ github.com/kardianos/minwinsvc v1.0.2 h1:JmZKFJQrmTGa/WiW+vkJXKmfzdjabuEW4Tirj5l
|
|||
github.com/kardianos/minwinsvc v1.0.2/go.mod h1:LUZNYhNmxujx2tR7FbdxqYJ9XDDoCd3MQcl1o//FWl4=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
|
@ -234,8 +239,8 @@ 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-20250116181547-c4f1e01eab0d h1:c3Dkci0GDH/6cGGt8zGIiJMP+UOdtX0DPY6dxiJvtZM=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250116181547-c4f1e01eab0d/go.mod h1:qil34SWn6VB6gO5312rzziCUcZtgROPjrLE+4ly/0os=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250815065806-6697d93cbcba h1:vUUjTOXZ/bYdF/SmJPH8HZ/UTmvw+ldngFKVLElmn+I=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250815065806-6697d93cbcba/go.mod h1:b6KVfDjXjA5Q7vhpOaMqIhFYvu5BuFVZixlNeTV/CLc=
|
||||
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7 h1:6t8kJr8i1/1I5nNttw6nn1ryQJgzVlBmSGgPiiaTdw4=
|
||||
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7/go.mod h1:ReWMS/LoVnOiRAdq9sNUC2NZnd1mZkMNB52QhpTRWjg=
|
||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||
|
@ -248,10 +253,11 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
|
|||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
||||
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
||||
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
|
||||
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
|
@ -270,14 +276,14 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
|||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/nats-io/jwt/v2 v2.7.3 h1:6bNPK+FXgBeAqdj4cYQ0F8ViHRbi7woQLq4W29nUAzE=
|
||||
github.com/nats-io/jwt/v2 v2.7.3/go.mod h1:GvkcbHhKquj3pkioy5put1wvPxs78UlZ7D/pY+BgZk4=
|
||||
github.com/nats-io/nats-server/v2 v2.10.25 h1:J0GWLDDXo5HId7ti/lTmBfs+lzhmu8RPkoKl0eSCqwc=
|
||||
github.com/nats-io/nats-server/v2 v2.10.25/go.mod h1:/YYYQO7cuoOBt+A7/8cVjuhWTaTUEAlZbJT+3sMAfFU=
|
||||
github.com/nats-io/nats.go v1.38.0 h1:A7P+g7Wjp4/NWqDOOP/K6hfhr54DvdDQUznt5JFg9XA=
|
||||
github.com/nats-io/nats.go v1.38.0/go.mod h1:IGUM++TwokGnXPs82/wCuiHS02/aKrdYUQkU8If6yjw=
|
||||
github.com/nats-io/nkeys v0.4.9 h1:qe9Faq2Gxwi6RZnZMXfmGMZkg3afLLOtrU+gDZJ35b0=
|
||||
github.com/nats-io/nkeys v0.4.9/go.mod h1:jcMqs+FLG+W5YO36OX6wFIFcmpdAns+w1Wm6D3I/evE=
|
||||
github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
|
||||
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
|
||||
github.com/nats-io/nats-server/v2 v2.11.7 h1:lINWQ/Hb3cnaoHmWTjj/7WppZnaSh9C/1cD//nHCbms=
|
||||
github.com/nats-io/nats-server/v2 v2.11.7/go.mod h1:DchDPVzAsAPqhqm7VLedX0L7hjnV/SYtlmsl9F8U53s=
|
||||
github.com/nats-io/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
|
||||
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
|
@ -285,6 +291,8 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm
|
|||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/oleiade/lane/v2 v2.0.0 h1:XW/ex/Inr+bPkLd3O240xrFOhUkTd4Wy176+Gv0E3Qw=
|
||||
github.com/oleiade/lane/v2 v2.0.0/go.mod h1:i5FBPFAYSWCgLh58UkUGCChjcCzef/MI7PlQm2TKCeg=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
|
||||
|
@ -306,12 +314,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||
|
@ -323,6 +331,8 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN
|
|||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc=
|
||||
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
|
||||
github.com/shoenig/test v1.11.0 h1:NoPa5GIoBwuqzIviCrnUJa+t5Xb4xi5Z+zODJnIDsEQ=
|
||||
github.com/shoenig/test v1.11.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
|
@ -367,8 +377,8 @@ github.com/yggdrasil-network/yggquic v0.0.0-20241212194307-0d495106021f/go.mod h
|
|||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
|
@ -399,8 +409,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
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-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -411,8 +421,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbR
|
|||
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.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
||||
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b h1:WX7nnnLfCEXg+FmdYZPai2XuP3VqCP1HZVMST0n9DF0=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b/go.mod h1:EiXZlVfUTaAyySFVJb9rsODuiO+WXu8HrUuySb7nYFw=
|
||||
|
@ -423,8 +433,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
|||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
@ -437,8 +447,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -447,8 +457,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -472,8 +482,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -481,8 +491,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
|
@ -492,11 +502,11 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -508,8 +518,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
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=
|
||||
|
@ -526,8 +536,8 @@ google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
|||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
@ -541,10 +551,11 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
|
||||
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
|
||||
maunium.net/go/mautrix v0.15.1 h1:pmCtMjYRpd83+2UL+KTRFYQo5to0373yulimvLK+1k0=
|
||||
|
|
|
@ -37,7 +37,7 @@ type CanonicalAlias struct {
|
|||
// if they have not been specified.
|
||||
// http://matrix.org/docs/spec/client_server/r0.2.0.html#m-room-power-levels
|
||||
// https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/handlers/room.py#L294
|
||||
func InitialPowerLevelsContent(roomCreator string) (c gomatrixserverlib.PowerLevelContent) {
|
||||
func InitialPowerLevelsContent(roomVersion gomatrixserverlib.IRoomVersion, roomCreator string) (c gomatrixserverlib.PowerLevelContent) {
|
||||
c.Defaults()
|
||||
c.Events = map[string]int64{
|
||||
"m.room.name": 50,
|
||||
|
@ -49,7 +49,12 @@ func InitialPowerLevelsContent(roomCreator string) (c gomatrixserverlib.PowerLev
|
|||
"m.room.encryption": 100,
|
||||
"m.room.server_acl": 100,
|
||||
}
|
||||
c.Users = map[string]int64{roomCreator: 100}
|
||||
c.Users = map[string]int64{}
|
||||
if roomVersion.PrivilegedCreators() {
|
||||
c.Events["m.room.tombstone"] = 150
|
||||
} else {
|
||||
c.Users[roomCreator] = 100
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
|
@ -67,16 +67,24 @@ func BuildEvent(
|
|||
identity *fclient.SigningIdentity, evTime time.Time,
|
||||
eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse,
|
||||
) (*types.HeaderedEvent, error) {
|
||||
if err := addPrevEventsToEvent(proto, eventsNeeded, queryRes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proto.Version = verImpl
|
||||
if err = addPrevEventsToEvent(proto, eventsNeeded, queryRes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builder := verImpl.NewEventBuilderFromProtoEvent(proto)
|
||||
|
||||
if verImpl.DomainlessRoomIDs() && builder.RoomID != "" && proto.Type == spec.MRoomCreate && proto.StateKey != nil && *proto.StateKey == "" {
|
||||
return nil, gomatrixserverlib.EventValidationError{
|
||||
Message: "cannot resend m.room.create event",
|
||||
Code: 400,
|
||||
}
|
||||
}
|
||||
|
||||
event, err := builder.Build(
|
||||
evTime, identity.ServerName, identity.KeyID,
|
||||
identity.PrivateKey,
|
||||
|
@ -136,8 +144,22 @@ func addPrevEventsToEvent(
|
|||
if err != nil {
|
||||
return fmt.Errorf("eventsNeeded.AuthEventReferences: %w", err)
|
||||
}
|
||||
var authEventIDs []string
|
||||
if builder.Version.DomainlessRoomIDs() && len(builder.RoomID) > 0 {
|
||||
// the room ID is the create event so we shouldn't set it in auth_events
|
||||
authEventIDs = make([]string, 0, len(refs))
|
||||
createEventID := fmt.Sprintf("$%s", builder.RoomID[1:])
|
||||
for _, id := range refs {
|
||||
if id == createEventID {
|
||||
continue
|
||||
}
|
||||
authEventIDs = append(authEventIDs, id)
|
||||
}
|
||||
} else {
|
||||
authEventIDs = refs
|
||||
}
|
||||
|
||||
builder.AuthEvents, builder.PrevEvents = truncateAuthAndPrevEvents(refs, queryRes.LatestEvents)
|
||||
builder.AuthEvents, builder.PrevEvents = truncateAuthAndPrevEvents(authEventIDs, queryRes.LatestEvents)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -134,6 +134,8 @@ func (t *TxnReq) ProcessTransaction(ctx context.Context) (*fclient.RespSend, *ut
|
|||
}
|
||||
event, err := verImpl.NewEventFromUntrustedJSON(pdu)
|
||||
if err != nil {
|
||||
/* Do not reject the entire transaction for a single bad PDU, that's dumb.
|
||||
|
||||
if _, ok := err.(gomatrixserverlib.BadJSONError); ok {
|
||||
// Room version 6 states that homeservers should strictly enforce canonical JSON
|
||||
// on PDUs.
|
||||
|
@ -146,7 +148,7 @@ func (t *TxnReq) ProcessTransaction(ctx context.Context) (*fclient.RespSend, *ut
|
|||
Code: 400,
|
||||
JSON: spec.BadJSON("PDU contains bad JSON"),
|
||||
}
|
||||
}
|
||||
} */
|
||||
util.GetLogger(ctx).WithError(err).Debugf("Transaction: Failed to parse event JSON of event %s", string(pdu))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ var build string
|
|||
|
||||
const (
|
||||
VersionMajor = 0
|
||||
VersionMinor = 14
|
||||
VersionPatch = 1
|
||||
VersionMinor = 15
|
||||
VersionPatch = 2
|
||||
VersionTag = "" // example: "rc1"
|
||||
|
||||
gitRevLen = 7 // 7 matches the displayed characters on github.com
|
||||
|
|
|
@ -243,7 +243,7 @@ type ClientRoomserverAPI interface {
|
|||
|
||||
PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *PerformCreateRoomRequest) (string, *util.JSONResponse)
|
||||
// PerformRoomUpgrade upgrades a room to a newer version
|
||||
PerformRoomUpgrade(ctx context.Context, roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion) (newRoomID string, err error)
|
||||
PerformRoomUpgrade(ctx context.Context, roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion, additionalCreators []string) (newRoomID string, err error)
|
||||
PerformAdminEvacuateRoom(ctx context.Context, roomID string) (affected []string, err error)
|
||||
PerformAdminEvacuateUser(ctx context.Context, userID string) (affected []string, err error)
|
||||
PerformAdminPurgeRoom(ctx context.Context, roomID string) error
|
||||
|
|
|
@ -15,6 +15,9 @@ import (
|
|||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// for detecting rejected events and returning 403 instead of 500ing
|
||||
const InputWasRejected = "InputWasRejected"
|
||||
|
||||
type Kind int
|
||||
|
||||
const (
|
||||
|
@ -108,5 +111,5 @@ func (r *InputRoomEventsResponse) Err() error {
|
|||
Message: r.ErrMsg,
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("InputRoomEventsResponse: %s", r.ErrMsg)
|
||||
return fmt.Errorf(r.ErrMsg)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ type PerformCreateRoomRequest struct {
|
|||
Topic string
|
||||
StatePreset string
|
||||
CreationContent json.RawMessage
|
||||
CreateEvent json.RawMessage
|
||||
InitialState []gomatrixserverlib.FledglingEvent
|
||||
RoomAliasName string
|
||||
RoomVersion gomatrixserverlib.RoomVersion
|
||||
|
|
|
@ -8,6 +8,10 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/element-hq/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
@ -216,3 +220,117 @@ func PopulatePublicRooms(ctx context.Context, roomIDs []string, rsAPI QueryBulkS
|
|||
}
|
||||
return chunk, nil
|
||||
}
|
||||
|
||||
func GenerateCreateContent(ctx context.Context, roomVer gomatrixserverlib.RoomVersion, senderID string, createContentJSON json.RawMessage, additionalCreators []string) (map[string]any, error) {
|
||||
createContent := map[string]any{}
|
||||
if len(createContentJSON) > 0 {
|
||||
if err := json.Unmarshal(createContentJSON, &createContent); err != nil {
|
||||
return nil, fmt.Errorf("invalid create content: %s", err)
|
||||
}
|
||||
}
|
||||
// TODO: Maybe, at some point, GMSL should return the events to create, so we can define the version
|
||||
// entirely there.
|
||||
switch roomVer {
|
||||
case gomatrixserverlib.RoomVersionV11:
|
||||
fallthrough
|
||||
case gomatrixserverlib.RoomVersionV12:
|
||||
// RoomVersionV11 removed the creator field from the create content: https://github.com/matrix-org/matrix-spec-proposals/pull/2175
|
||||
default:
|
||||
createContent["creator"] = senderID
|
||||
}
|
||||
createContent["room_version"] = string(roomVer)
|
||||
|
||||
verImpl := gomatrixserverlib.MustGetRoomVersion(roomVer)
|
||||
|
||||
if verImpl.PrivilegedCreators() {
|
||||
var finalAdditionalCreators []string
|
||||
creatorsSet := make(map[string]struct{})
|
||||
var unverifiedCreators []string
|
||||
unverifiedCreators = append(unverifiedCreators, additionalCreators...)
|
||||
// they get added to any additional creators specified already
|
||||
existingAdditionalCreators, ok := createContent["additional_creators"].([]any)
|
||||
if ok {
|
||||
for _, add := range existingAdditionalCreators {
|
||||
addStr, ok := add.(string)
|
||||
if ok {
|
||||
unverifiedCreators = append(unverifiedCreators, addStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, add := range unverifiedCreators {
|
||||
if _, exists := creatorsSet[add]; exists {
|
||||
continue
|
||||
}
|
||||
_, err := spec.NewUserID(add, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid additional creator: '%s': %s", add, err)
|
||||
}
|
||||
finalAdditionalCreators = append(finalAdditionalCreators, add)
|
||||
creatorsSet[add] = struct{}{}
|
||||
}
|
||||
if len(finalAdditionalCreators) > 0 {
|
||||
createContent["additional_creators"] = finalAdditionalCreators
|
||||
}
|
||||
}
|
||||
|
||||
return createContent, nil
|
||||
}
|
||||
|
||||
func GeneratePDU(
|
||||
ctx context.Context, verImpl gomatrixserverlib.IRoomVersion, e gomatrixserverlib.FledglingEvent, authEvents *gomatrixserverlib.AuthEvents, depth int, prevEventID string,
|
||||
identity *fclient.SigningIdentity, timestamp time.Time, senderID, roomID string, queryer QuerySenderIDAPI,
|
||||
) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||
builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
|
||||
SenderID: senderID,
|
||||
RoomID: roomID,
|
||||
Type: e.Type,
|
||||
StateKey: &e.StateKey,
|
||||
Depth: int64(depth),
|
||||
})
|
||||
err := builder.SetContent(e.Content)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if prevEventID != "" {
|
||||
builder.PrevEvents = []string{prevEventID}
|
||||
}
|
||||
var ev gomatrixserverlib.PDU
|
||||
if err = builder.AddAuthEvents(authEvents); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
ev, err = builder.Build(timestamp, identity.ServerName, identity.KeyID, identity.PrivateKey)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(ev, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return queryer.QueryUserIDForSender(ctx, roomID, senderID)
|
||||
}); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
|
||||
validationErr, ok := err.(*gomatrixserverlib.EventValidationError)
|
||||
if ok {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: validationErr.Code,
|
||||
JSON: spec.Forbidden(err.Error()),
|
||||
}
|
||||
}
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(err.Error()),
|
||||
}
|
||||
}
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
asAPI "github.com/element-hq/dendrite/appservice/api"
|
||||
|
@ -134,7 +135,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(ctx context.Context, senderID sp
|
|||
}
|
||||
|
||||
if spec.SenderID(creatorID) != senderID {
|
||||
var plEvent *types.HeaderedEvent
|
||||
var createEvent, plEvent *types.HeaderedEvent
|
||||
var pls *gomatrixserverlib.PowerLevelContent
|
||||
|
||||
plEvent, err = r.DB.GetStateEvent(ctx, roomID, spec.MRoomPowerLevels, "")
|
||||
|
@ -147,7 +148,14 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(ctx context.Context, senderID sp
|
|||
return true, false, fmt.Errorf("plEvent.PowerLevels: %w", err)
|
||||
}
|
||||
|
||||
if pls.UserLevel(senderID) < pls.EventLevel(spec.MRoomCanonicalAlias, true) {
|
||||
createEvent, err = r.DB.GetStateEvent(ctx, roomID, spec.MRoomCreate, "")
|
||||
if err != nil {
|
||||
return true, false, fmt.Errorf("r.DB.GetStateEvent: %w", err)
|
||||
}
|
||||
isPrivilegedCreator := gomatrixserverlib.MustGetRoomVersion(createEvent.Version()).PrivilegedCreators() &&
|
||||
slices.Contains(gomatrixserverlib.CreatorsFromCreateEvent(createEvent), string(senderID))
|
||||
|
||||
if !isPrivilegedCreator && pls.UserLevel(senderID) < pls.EventLevel(spec.MRoomCanonicalAlias, true) {
|
||||
return true, false, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,9 +101,12 @@ type worker struct {
|
|||
roomID string
|
||||
subscription *nats.Subscription
|
||||
sentryHub *sentry.Hub
|
||||
ephemeralSeq uint64
|
||||
// last seq we fully processed
|
||||
durableSeq uint64
|
||||
}
|
||||
|
||||
func (r *Inputer) startWorkerForRoom(roomID string) {
|
||||
func (r *Inputer) startWorkerForRoom(roomID string, seq uint64) {
|
||||
v, loaded := r.workers.LoadOrStore(roomID, &worker{
|
||||
r: r,
|
||||
roomID: roomID,
|
||||
|
@ -112,6 +115,9 @@ func (r *Inputer) startWorkerForRoom(roomID string) {
|
|||
w := v.(*worker)
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
|
||||
w.ephemeralSeq = seq
|
||||
|
||||
if !loaded || w.subscription == nil {
|
||||
streamName := r.Cfg.Matrix.JetStream.Prefixed(jetstream.InputRoomEvent)
|
||||
consumer := r.Cfg.Matrix.JetStream.Prefixed("RoomInput" + jetstream.Tokenise(w.roomID))
|
||||
|
@ -226,7 +232,8 @@ func (r *Inputer) Start() error {
|
|||
"", // This is blank because we specified it in BindStream.
|
||||
func(m *nats.Msg) {
|
||||
roomID := m.Header.Get(jetstream.RoomID)
|
||||
r.startWorkerForRoom(roomID)
|
||||
meta, _ := m.Metadata()
|
||||
r.startWorkerForRoom(roomID, meta.Sequence.Stream)
|
||||
_ = m.Ack()
|
||||
},
|
||||
nats.HeadersOnly(),
|
||||
|
@ -265,39 +272,61 @@ func (w *worker) _next() {
|
|||
msgs, err := w.subscription.Fetch(1, nats.Context(ctx))
|
||||
switch err {
|
||||
case nil:
|
||||
// Is the server shutting down? If so, stop processing.
|
||||
if w.r.ProcessContext.Context().Err() != nil {
|
||||
return
|
||||
}
|
||||
// Make sure that once we're done here, we queue up another call
|
||||
// to _next in the inbox.
|
||||
defer w.Act(nil, w._next)
|
||||
|
||||
// If no error was reported, but we didn't get exactly one message,
|
||||
// then skip over this and try again on the next iteration.
|
||||
if len(msgs) != 1 {
|
||||
case nats.ErrTimeout, context.DeadlineExceeded, context.Canceled:
|
||||
// Is the server shutting down? If so, stop processing.
|
||||
if w.r.ProcessContext.Context().Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
case context.DeadlineExceeded, context.Canceled:
|
||||
// The context exceeded, so we've been waiting for more than a
|
||||
// minute for activity in this room. At this point we will shut
|
||||
// down the subscriber to free up resources. It'll get started
|
||||
// again if new activity happens.
|
||||
w.Lock()
|
||||
// inside the lock, let's check if the ephemeral consumer saw something new!
|
||||
// If so, we do have new messages after all, they just came at a bad time.
|
||||
if w.ephemeralSeq > w.durableSeq {
|
||||
w.Unlock()
|
||||
w.Act(nil, w._next)
|
||||
return
|
||||
}
|
||||
|
||||
if err = w.subscription.Unsubscribe(); err != nil {
|
||||
logrus.WithError(err).Errorf("Failed to unsubscribe to stream for room %q", w.roomID)
|
||||
}
|
||||
w.Lock()
|
||||
w.subscription = nil
|
||||
w.Unlock()
|
||||
return
|
||||
|
||||
case nats.ErrConsumerDeleted, nats.ErrConsumerNotFound:
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
// The consumer is gone, therefore it's reached the inactivity
|
||||
// threshold. Clean up and stop processing at this point, if a
|
||||
// new event comes in for this room then the ordered consumer
|
||||
// over the entire stream will recreate this anyway.
|
||||
if err = w.subscription.Unsubscribe(); err != nil {
|
||||
logrus.WithError(err).Errorf("Failed to unsubscribe to stream for room %q", w.roomID)
|
||||
}
|
||||
w.subscription = nil
|
||||
return
|
||||
default:
|
||||
// Something went wrong while trying to fetch the next event
|
||||
// from the queue. In which case, we'll shut down the subscriber
|
||||
// and wait to be notified about new room activity again. Maybe
|
||||
// the problem will be corrected by then.
|
||||
// atomically clear the subscription and unsubscribe
|
||||
w.Lock()
|
||||
|
||||
logrus.WithError(err).Errorf("Failed to get next stream message for room %q", w.roomID)
|
||||
if err = w.subscription.Unsubscribe(); err != nil {
|
||||
logrus.WithError(err).Errorf("Failed to unsubscribe to stream for room %q", w.roomID)
|
||||
}
|
||||
w.Lock()
|
||||
w.subscription = nil
|
||||
w.Unlock()
|
||||
return
|
||||
|
@ -306,10 +335,19 @@ func (w *worker) _next() {
|
|||
// Since we either Ack() or Term() the message at this point, we can defer decrementing the room backpressure
|
||||
defer roomserverInputBackpressure.With(prometheus.Labels{"room_id": w.roomID}).Dec()
|
||||
|
||||
// If no error was reported, but we didn't get exactly one message,
|
||||
// then skip over this and try again on the next iteration.
|
||||
if len(msgs) != 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// Try to unmarshal the input room event. If the JSON unmarshalling
|
||||
// fails then we'll terminate the message — this notifies NATS that
|
||||
// we are done with the message and never want to see it again.
|
||||
msg := msgs[0]
|
||||
meta, _ := msg.Metadata()
|
||||
w.durableSeq = meta.Sequence.Stream
|
||||
|
||||
var inputRoomEvent api.InputRoomEvent
|
||||
if err = json.Unmarshal(msg.Data, &inputRoomEvent); err != nil {
|
||||
// using AckWait here makes the call synchronous; 5 seconds is the default value used by NATS
|
||||
|
@ -326,6 +364,7 @@ func (w *worker) _next() {
|
|||
// a string, because we might want to return that to the caller if
|
||||
// it was a synchronous request.
|
||||
var errString string
|
||||
wasRejected := false
|
||||
if err = w.r.processRoomEvent(
|
||||
w.r.ProcessContext.Context(),
|
||||
spec.ServerName(msg.Header.Get("virtual_host")),
|
||||
|
@ -339,6 +378,7 @@ func (w *worker) _next() {
|
|||
"event_id": inputRoomEvent.Event.EventID(),
|
||||
"type": inputRoomEvent.Event.Type(),
|
||||
}).Warn("Roomserver rejected event")
|
||||
wasRejected = true
|
||||
default:
|
||||
if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, context.Canceled) {
|
||||
w.sentryHub.CaptureException(err)
|
||||
|
@ -360,6 +400,10 @@ func (w *worker) _next() {
|
|||
_ = msg.AckSync()
|
||||
}
|
||||
|
||||
if wasRejected {
|
||||
errString = api.InputWasRejected
|
||||
}
|
||||
|
||||
// If it was a synchronous input request then the "sync" field
|
||||
// will be present in the message. That means that someone is
|
||||
// waiting for a response. The temporary inbox name is present in
|
||||
|
|
|
@ -128,9 +128,9 @@ func (r *Backfiller) backfillViaFederation(ctx context.Context, req *api.Perform
|
|||
logrus.WithError(err).WithField("room_id", req.RoomID).Infof("backfilled %d events", len(events))
|
||||
|
||||
// persist these new events - auth checks have already been done
|
||||
roomNID, backfilledEventMap := persistEvents(ctx, r.DB, r.Querier, events)
|
||||
roomNID, storedEvents := persistEvents(ctx, r.DB, r.Querier, events)
|
||||
|
||||
for _, ev := range backfilledEventMap {
|
||||
for _, ev := range storedEvents {
|
||||
// now add state for these events
|
||||
stateIDs, ok := requester.eventIDToBeforeStateIDs[ev.EventID()]
|
||||
if !ok {
|
||||
|
@ -591,10 +591,10 @@ func joinEventsFromHistoryVisibility(
|
|||
return evs, visibility, err
|
||||
}
|
||||
|
||||
func persistEvents(ctx context.Context, db storage.Database, querier api.QuerySenderIDAPI, events []gomatrixserverlib.PDU) (types.RoomNID, map[string]types.Event) {
|
||||
func persistEvents(ctx context.Context, db storage.Database, querier api.QuerySenderIDAPI, events []gomatrixserverlib.PDU) (types.RoomNID, []types.Event) {
|
||||
var roomNID types.RoomNID
|
||||
var eventNID types.EventNID
|
||||
backfilledEventMap := make(map[string]types.Event)
|
||||
storedEvents := make([]types.Event, 0, len(events))
|
||||
for j, ev := range events {
|
||||
nidMap, err := db.EventNIDs(ctx, ev.AuthEventIDs())
|
||||
if err != nil { // this shouldn't happen as RequestBackfill already found them
|
||||
|
@ -647,10 +647,10 @@ func persistEvents(ctx context.Context, db storage.Database, querier api.QuerySe
|
|||
ev = redactedEvent
|
||||
events[j] = ev
|
||||
}
|
||||
backfilledEventMap[ev.EventID()] = types.Event{
|
||||
storedEvents = append(storedEvents, types.Event{
|
||||
EventNID: eventNID,
|
||||
PDU: ev,
|
||||
}
|
||||
})
|
||||
}
|
||||
return roomNID, backfilledEventMap
|
||||
return roomNID, storedEvents
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ type Creator struct {
|
|||
// PerformCreateRoom handles all the steps necessary to create a new room.
|
||||
// nolint: gocyclo
|
||||
func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *api.PerformCreateRoomRequest) (string, *util.JSONResponse) {
|
||||
// Make sure we know the room version
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(createRequest.RoomVersion)
|
||||
if err != nil {
|
||||
return "", &util.JSONResponse{
|
||||
|
@ -47,17 +48,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
}
|
||||
}
|
||||
|
||||
createContent := map[string]interface{}{}
|
||||
if len(createRequest.CreationContent) > 0 {
|
||||
if err = json.Unmarshal(createRequest.CreationContent, &createContent); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for creation_content failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("invalid create content"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the room
|
||||
_, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID")
|
||||
|
@ -67,6 +58,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
}
|
||||
}
|
||||
|
||||
// Allocate the user
|
||||
var senderID spec.SenderID
|
||||
if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
// create user room key if needed
|
||||
|
@ -83,17 +75,73 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
senderID = spec.SenderID(userID.String())
|
||||
}
|
||||
|
||||
// TODO: Maybe, at some point, GMSL should return the events to create, so we can define the version
|
||||
// entirely there.
|
||||
switch createRequest.RoomVersion {
|
||||
case gomatrixserverlib.RoomVersionV11:
|
||||
// RoomVersionV11 removed the creator field from the create content: https://github.com/matrix-org/matrix-spec-proposals/pull/2175
|
||||
default:
|
||||
createContent["creator"] = senderID
|
||||
// get the signing identity
|
||||
identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
createContent["room_version"] = createRequest.RoomVersion
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(string(senderID))
|
||||
// Make the create event if we need to
|
||||
var (
|
||||
createEvent gomatrixserverlib.PDU
|
||||
jsonErr *util.JSONResponse
|
||||
)
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
|
||||
if createRequest.CreateEvent != nil {
|
||||
createEvent, err = verImpl.NewEventFromTrustedJSON(createRequest.CreateEvent, false)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.NewEventFromTrustedJSON failed to verify create event")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if err = authEvents.AddEvent(createEvent); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.AuthEvents.AddEvent failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var additionalCreators []string
|
||||
if createRequest.StatePreset == spec.PresetTrustedPrivateChat {
|
||||
additionalCreators = createRequest.InvitedUsers
|
||||
}
|
||||
createContent, contentErr := api.GenerateCreateContent(ctx, createRequest.RoomVersion, string(senderID), createRequest.CreationContent, additionalCreators)
|
||||
if contentErr != nil {
|
||||
util.GetLogger(ctx).WithError(contentErr).Error("GenerateCreateContent failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("invalid create content"),
|
||||
}
|
||||
}
|
||||
createEvent, jsonErr = api.GeneratePDU(
|
||||
ctx, verImpl,
|
||||
gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
},
|
||||
authEvents, 1, "", identity, createRequest.EventTime, string(senderID), roomID.String(), c.RSAPI,
|
||||
)
|
||||
if jsonErr != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to make the create event")
|
||||
return "", jsonErr
|
||||
}
|
||||
if err = authEvents.AddEvent(createEvent); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("authEvents.AddEvent failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(verImpl, string(senderID))
|
||||
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
||||
JoinRule: spec.Invite,
|
||||
}
|
||||
|
@ -122,8 +170,10 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
case spec.PresetTrustedPrivateChat:
|
||||
joinRuleContent.JoinRule = spec.Invite
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
for _, invitee := range createRequest.InvitedUsers {
|
||||
powerLevelContent.Users[invitee] = 100
|
||||
if !verImpl.PrivilegedCreators() {
|
||||
for _, invitee := range createRequest.InvitedUsers {
|
||||
powerLevelContent.Users[invitee] = 100
|
||||
}
|
||||
}
|
||||
guestsCanJoin = true
|
||||
case spec.PresetPublicChat:
|
||||
|
@ -131,10 +181,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
}
|
||||
|
||||
createEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
}
|
||||
powerLevelEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomPowerLevels,
|
||||
Content: powerLevelContent,
|
||||
|
@ -158,16 +204,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
AvatarURL: createRequest.UserAvatarURL,
|
||||
}
|
||||
|
||||
// get the signing identity
|
||||
identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// If we are creating a room with pseudo IDs, create and sign the MXIDMapping
|
||||
if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
var pseudoIDKey ed25519.PrivateKey
|
||||
|
@ -279,7 +315,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
switch createRequest.InitialState[i].Type {
|
||||
case spec.MRoomCreate:
|
||||
continue
|
||||
|
||||
case spec.MRoomPowerLevels:
|
||||
powerLevelEvent = createRequest.InitialState[i]
|
||||
|
||||
|
@ -321,7 +356,8 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
// harder to reason about, hence sticking to a strict static ordering.
|
||||
// TODO: Synapse has txn/token ID on each event. Do we need to do this here?
|
||||
eventsToMake := []gomatrixserverlib.FledglingEvent{
|
||||
createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
|
||||
// we made the create event already hence it isn't here.
|
||||
membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
|
||||
}
|
||||
if guestAccessEvent != nil {
|
||||
eventsToMake = append(eventsToMake, *guestAccessEvent)
|
||||
|
@ -342,61 +378,19 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
|||
// TODO: invite events
|
||||
// TODO: 3pid invite events
|
||||
|
||||
var builtEvents []*types.HeaderedEvent
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("rsapi.QuerySenderIDForUser failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
builtEvents := []*types.HeaderedEvent{
|
||||
{PDU: createEvent},
|
||||
}
|
||||
for i, e := range eventsToMake {
|
||||
depth := i + 1 // depth starts at 1
|
||||
depth := i + 2 // depth starts at 2 since we made the create event already
|
||||
|
||||
builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
|
||||
SenderID: string(senderID),
|
||||
RoomID: roomID.String(),
|
||||
Type: e.Type,
|
||||
StateKey: &e.StateKey,
|
||||
Depth: int64(depth),
|
||||
})
|
||||
err = builder.SetContent(e.Content)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if i > 0 {
|
||||
builder.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||
}
|
||||
var ev gomatrixserverlib.PDU
|
||||
if err = builder.AddAuthEvents(authEvents); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
ev, err = builder.Build(createRequest.EventTime, identity.ServerName, identity.KeyID, identity.PrivateKey)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(ev, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return c.RSAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||
}); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
ev, jsonErr := api.GeneratePDU(
|
||||
ctx, verImpl, e,
|
||||
authEvents, depth, builtEvents[len(builtEvents)-1].EventID(),
|
||||
identity, createRequest.EventTime, string(senderID), roomID.String(), c.RSAPI,
|
||||
)
|
||||
if jsonErr != nil {
|
||||
return "", jsonErr
|
||||
}
|
||||
|
||||
// Add the event to the list of auth events
|
||||
|
|
|
@ -31,7 +31,11 @@ type QueryState struct {
|
|||
}
|
||||
|
||||
func (q *QueryState) GetAuthEvents(ctx context.Context, event gomatrixserverlib.PDU) (gomatrixserverlib.AuthEventProvider, error) {
|
||||
return helpers.GetAuthEvents(ctx, q.Database, event.Version(), event, event.AuthEventIDs())
|
||||
authEventIDs := event.AuthEventIDs()
|
||||
if gomatrixserverlib.MustGetRoomVersion(event.Version()).DomainlessRoomIDs() {
|
||||
authEventIDs = append(authEventIDs, "$"+event.RoomID().String()[1:])
|
||||
}
|
||||
return helpers.GetAuthEvents(ctx, q.Database, event.Version(), event, authEventIDs)
|
||||
}
|
||||
|
||||
func (q *QueryState) GetState(ctx context.Context, roomID spec.RoomID, stateWanted []gomatrixserverlib.StateKeyTuple) ([]gomatrixserverlib.PDU, error) {
|
||||
|
|
|
@ -156,19 +156,11 @@ func (r *Joiner) performJoinRoomByID(
|
|||
}
|
||||
}
|
||||
|
||||
// Get the domain part of the room ID.
|
||||
roomID, err := spec.NewRoomID(req.RoomIDOrAlias)
|
||||
if err != nil {
|
||||
return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("room ID %q is invalid: %w", req.RoomIDOrAlias, err)}
|
||||
}
|
||||
|
||||
// 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 !r.Cfg.Matrix.IsLocalServerName(roomID.Domain()) {
|
||||
req.ServerNames = append(req.ServerNames, roomID.Domain())
|
||||
}
|
||||
|
||||
// Force a federated join if we aren't in the room and we've been
|
||||
// given some server names to try joining by.
|
||||
inRoomReq := &rsAPI.QueryServerJoinedToRoomRequest{
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/element-hq/dendrite/internal/eventutil"
|
||||
|
@ -30,14 +31,15 @@ type Upgrader struct {
|
|||
// PerformRoomUpgrade upgrades a room from one version to another
|
||||
func (r *Upgrader) PerformRoomUpgrade(
|
||||
ctx context.Context,
|
||||
roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion,
|
||||
roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion, additionalCreators []string,
|
||||
) (newRoomID string, err error) {
|
||||
return r.performRoomUpgrade(ctx, roomID, userID, roomVersion)
|
||||
return r.performRoomUpgrade(ctx, roomID, userID, roomVersion, additionalCreators)
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func (r *Upgrader) performRoomUpgrade(
|
||||
ctx context.Context,
|
||||
roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion,
|
||||
roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion, additionalCreators []string,
|
||||
) (string, error) {
|
||||
evTime := time.Now()
|
||||
|
||||
|
@ -64,35 +66,110 @@ func (r *Upgrader) performRoomUpgrade(
|
|||
return "", api.ErrNotAllowed{Err: fmt.Errorf("You don't have permission to upgrade the room, power level too low.")}
|
||||
}
|
||||
|
||||
// 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), userID.Domain())
|
||||
|
||||
// Get the existing room state for the old room.
|
||||
oldRoomReq := &api.QueryLatestEventsAndStateRequest{
|
||||
RoomID: roomID,
|
||||
}
|
||||
oldRoomRes := &api.QueryLatestEventsAndStateResponse{}
|
||||
if err := r.URSAPI.QueryLatestEventsAndState(ctx, oldRoomReq, oldRoomRes); err != nil {
|
||||
if err = r.URSAPI.QueryLatestEventsAndState(ctx, oldRoomReq, oldRoomRes); err != nil {
|
||||
return "", fmt.Errorf("Failed to get latest state: %s", err)
|
||||
}
|
||||
|
||||
// Make the tombstone event
|
||||
tombstoneEvent, pErr := r.makeTombstoneEvent(ctx, evTime, *senderID, userID.Domain(), roomID, newRoomID)
|
||||
if pErr != nil {
|
||||
return "", pErr
|
||||
var oldCreateEvent *types.HeaderedEvent
|
||||
for _, ev := range oldRoomRes.StateEvents {
|
||||
if ev.Type() == spec.MRoomCreate && ev.StateKeyEquals("") {
|
||||
oldCreateEvent = ev
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Make the create event and calculate the new room ID.
|
||||
var newRoomID string
|
||||
newRoomVerImpl := gomatrixserverlib.MustGetRoomVersion(roomVersion)
|
||||
var tombstoneEvent *types.HeaderedEvent
|
||||
var newCreateEvent gomatrixserverlib.PDU
|
||||
var pErr error
|
||||
if !newRoomVerImpl.DomainlessRoomIDs() {
|
||||
// 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), userID.Domain())
|
||||
|
||||
// Make the tombstone event
|
||||
tombstoneEvent, pErr = r.makeTombstoneEvent(ctx, evTime, *senderID, userID.Domain(), roomID, newRoomID)
|
||||
if pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
}
|
||||
content := struct {
|
||||
Federate *bool `json:"m.federate,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Predecessor struct {
|
||||
RoomID string `json:"room_id"`
|
||||
EventID string `json:"event_id,omitempty"`
|
||||
} `json:"predecessor"`
|
||||
}{}
|
||||
// keep existing values in old room e.g type/m.federate
|
||||
if err = json.Unmarshal(oldCreateEvent.Content(), &content); err != nil {
|
||||
return "", fmt.Errorf("failed to copy old create event content to new create event: %s", err)
|
||||
}
|
||||
content.Predecessor.RoomID = roomID
|
||||
content.Predecessor.EventID = ""
|
||||
if tombstoneEvent != nil {
|
||||
content.Predecessor.EventID = tombstoneEvent.EventID()
|
||||
}
|
||||
contentJSON, err := json.Marshal(content)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to make content for new create event: %s", err)
|
||||
}
|
||||
// make the create event up-front so the roomserver can calculate the room NID to store.
|
||||
createContent, err := api.GenerateCreateContent(ctx, roomVersion, userID.String(), contentJSON, additionalCreators)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("GenerateCreateContent failed")
|
||||
return "", fmt.Errorf("failed to GenerateCreateContent")
|
||||
}
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
|
||||
identity, err := r.Cfg.Matrix.SigningIdentityFor(userID.Domain())
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to get signing identity")
|
||||
return "", fmt.Errorf("No SigningIdentityFor domain %s", userID.Domain())
|
||||
}
|
||||
createEvent, jsonErr := api.GeneratePDU(
|
||||
ctx, gomatrixserverlib.MustGetRoomVersion(roomVersion),
|
||||
gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
},
|
||||
// newRoomID will be empty for domainless rooms
|
||||
authEvents, 1, "", identity, evTime, userID.String(), newRoomID, r.URSAPI,
|
||||
)
|
||||
if jsonErr != nil {
|
||||
util.GetLogger(ctx).Error("Failed to make the create event")
|
||||
return "", fmt.Errorf("failed to create new create event PDU")
|
||||
}
|
||||
newCreateEvent = createEvent
|
||||
if newRoomVerImpl.DomainlessRoomIDs() {
|
||||
newRoomID = newCreateEvent.RoomID().String()
|
||||
}
|
||||
|
||||
if tombstoneEvent == nil {
|
||||
// Make the tombstone event
|
||||
tombstoneEvent, pErr = r.makeTombstoneEvent(ctx, evTime, *senderID, userID.Domain(), roomID, newRoomID)
|
||||
if pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
}
|
||||
|
||||
creators := gomatrixserverlib.CreatorsFromCreateEvent(newCreateEvent)
|
||||
|
||||
// Generate the initial events we need to send into the new room. This includes copied state events and bans
|
||||
// as well as the power level events needed to set up the room
|
||||
eventsToMake, pErr := r.generateInitialEvents(ctx, oldRoomRes, *senderID, roomID, roomVersion, tombstoneEvent)
|
||||
eventsToMake, pErr := r.generateInitialEvents(ctx, oldRoomRes, *senderID, roomID, roomVersion, creators)
|
||||
if pErr != nil {
|
||||
return "", pErr
|
||||
}
|
||||
|
||||
// Send the setup events to the new room
|
||||
if pErr = r.sendInitialEvents(ctx, evTime, *senderID, userID.Domain(), newRoomID, roomVersion, eventsToMake); pErr != nil {
|
||||
return "", pErr
|
||||
if pErr = r.sendInitialEvents(ctx, evTime, *senderID, userID.Domain(), newRoomID, roomVersion, newCreateEvent, eventsToMake); pErr != nil {
|
||||
return "", fmt.Errorf("sendInitialEvents: %s", pErr)
|
||||
}
|
||||
|
||||
// 5. Send the tombstone event to the old room
|
||||
|
@ -296,13 +373,25 @@ func (r *Upgrader) userIsAuthorized(ctx context.Context, senderID spec.SenderID,
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
createEvent := api.GetStateEvent(ctx, r.URSAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomCreate,
|
||||
StateKey: "",
|
||||
})
|
||||
if gomatrixserverlib.MustGetRoomVersion(createEvent.Version()).PrivilegedCreators() &&
|
||||
slices.Contains(gomatrixserverlib.CreatorsFromCreateEvent(createEvent), string(senderID)) {
|
||||
return true
|
||||
}
|
||||
// Check for power level required to send tombstone event (marks the current room as obsolete),
|
||||
// if not found, use the StateDefault power level
|
||||
return pl.UserLevel(senderID) >= pl.EventLevel("m.room.tombstone", true)
|
||||
}
|
||||
|
||||
// Return the events to create AFTER the new create event
|
||||
// nolint:gocyclo
|
||||
func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, senderID spec.SenderID, roomID string, newVersion gomatrixserverlib.RoomVersion, tombstoneEvent *types.HeaderedEvent) ([]gomatrixserverlib.FledglingEvent, error) {
|
||||
func (r *Upgrader) generateInitialEvents(
|
||||
ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, senderID spec.SenderID, _ string, newVersion gomatrixserverlib.RoomVersion,
|
||||
creators []string) ([]gomatrixserverlib.FledglingEvent, error) {
|
||||
|
||||
state := make(map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent, len(oldRoom.StateEvents))
|
||||
for _, event := range oldRoom.StateEvents {
|
||||
if event.StateKey() == nil {
|
||||
|
@ -350,37 +439,10 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
|||
}
|
||||
}
|
||||
|
||||
oldCreateEvent := state[gomatrixserverlib.StateKeyTuple{EventType: spec.MRoomCreate, StateKey: ""}]
|
||||
oldMembershipEvent := state[gomatrixserverlib.StateKeyTuple{EventType: spec.MRoomMember, StateKey: string(senderID)}]
|
||||
oldPowerLevelsEvent := state[gomatrixserverlib.StateKeyTuple{EventType: spec.MRoomPowerLevels, StateKey: ""}]
|
||||
oldJoinRulesEvent := state[gomatrixserverlib.StateKeyTuple{EventType: spec.MRoomJoinRules, StateKey: ""}]
|
||||
|
||||
// Create the new room create event. Using a map here instead of CreateContent
|
||||
// means that we preserve any other interesting fields that might be present
|
||||
// in the create event (such as for the room types MSC).
|
||||
newCreateContent := map[string]interface{}{}
|
||||
_ = json.Unmarshal(oldCreateEvent.Content(), &newCreateContent)
|
||||
|
||||
switch newVersion {
|
||||
case gomatrixserverlib.RoomVersionV11:
|
||||
// RoomVersionV11 removed the creator field from the create content: https://github.com/matrix-org/matrix-spec-proposals/pull/2175
|
||||
// So if we are upgrading from pre v11, we need to remove the field.
|
||||
delete(newCreateContent, "creator")
|
||||
default:
|
||||
newCreateContent["creator"] = senderID
|
||||
}
|
||||
|
||||
newCreateContent["room_version"] = newVersion
|
||||
newCreateContent["predecessor"] = gomatrixserverlib.PreviousRoom{
|
||||
EventID: tombstoneEvent.EventID(),
|
||||
RoomID: roomID,
|
||||
}
|
||||
newCreateEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
StateKey: "",
|
||||
Content: newCreateContent,
|
||||
}
|
||||
|
||||
// Now create the new membership event. Same rules apply as above, so
|
||||
// that we preserve fields we don't otherwise know about. We'll always
|
||||
// set the membership to join though, because that is necessary to auth
|
||||
|
@ -405,7 +467,9 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
|||
return nil, fmt.Errorf("Power level event content was invalid")
|
||||
}
|
||||
|
||||
tempPowerLevelsEvent, powerLevelsOverridden := createTemporaryPowerLevels(powerLevelContent, senderID)
|
||||
verImpl := gomatrixserverlib.MustGetRoomVersion(newVersion)
|
||||
|
||||
tempPowerLevelsEvent, powerLevelsOverridden := createTemporaryPowerLevels(verImpl, powerLevelContent, senderID, creators)
|
||||
|
||||
// Now do the join rules event, same as the create and membership
|
||||
// events. We'll set a sane default of "invite" so that if the
|
||||
|
@ -423,7 +487,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
|||
|
||||
eventsToMake := make([]gomatrixserverlib.FledglingEvent, 0, len(state))
|
||||
eventsToMake = append(
|
||||
eventsToMake, newCreateEvent, newMembershipEvent,
|
||||
eventsToMake, newMembershipEvent,
|
||||
tempPowerLevelsEvent, newJoinRulesEvent,
|
||||
)
|
||||
|
||||
|
@ -467,12 +531,16 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
|||
return eventsToMake, nil
|
||||
}
|
||||
|
||||
func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, senderID spec.SenderID, userDomain spec.ServerName, newRoomID string, newVersion gomatrixserverlib.RoomVersion, eventsToMake []gomatrixserverlib.FledglingEvent) error {
|
||||
func (r *Upgrader) sendInitialEvents(
|
||||
ctx context.Context, evTime time.Time, senderID spec.SenderID, userDomain spec.ServerName, newRoomID string,
|
||||
newVersion gomatrixserverlib.RoomVersion, newCreateEvent gomatrixserverlib.PDU, eventsToMake []gomatrixserverlib.FledglingEvent) error {
|
||||
|
||||
var err error
|
||||
var builtEvents []*types.HeaderedEvent
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
|
||||
builtEvents = append(builtEvents, &types.HeaderedEvent{PDU: newCreateEvent})
|
||||
authEvents, _ := gomatrixserverlib.NewAuthEvents([]gomatrixserverlib.PDU{newCreateEvent})
|
||||
for i, e := range eventsToMake {
|
||||
depth := i + 1 // depth starts at 1
|
||||
depth := i + 2 // depth starts at 2 since we made the create event already.
|
||||
|
||||
proto := gomatrixserverlib.ProtoEvent{
|
||||
SenderID: string(senderID),
|
||||
|
@ -485,9 +553,7 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, send
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed to set content of new %q event: %w", proto.Type, err)
|
||||
}
|
||||
if i > 0 {
|
||||
proto.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||
}
|
||||
proto.PrevEvents = []string{builtEvents[i].EventID()}
|
||||
|
||||
var verImpl gomatrixserverlib.IRoomVersion
|
||||
verImpl, err = gomatrixserverlib.GetRoomVersion(newVersion)
|
||||
|
@ -503,13 +569,12 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, send
|
|||
event, err = builder.Build(evTime, userDomain, r.Cfg.Matrix.KeyID, r.Cfg.Matrix.PrivateKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build new %q event: %w", builder.Type, err)
|
||||
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(event, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return r.URSAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Failed to auth new %q event: %w", builder.Type, err)
|
||||
return fmt.Errorf("Failed to auth new initial %q event: %w", builder.Type, err)
|
||||
}
|
||||
|
||||
// Add the event to the list of auth events
|
||||
|
@ -599,7 +664,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, send
|
|||
return headeredEvent, nil
|
||||
}
|
||||
|
||||
func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, senderID spec.SenderID) (gomatrixserverlib.FledglingEvent, bool) {
|
||||
func createTemporaryPowerLevels(roomVersion gomatrixserverlib.IRoomVersion, powerLevelContent *gomatrixserverlib.PowerLevelContent, senderID spec.SenderID, creators []string) (gomatrixserverlib.FledglingEvent, bool) {
|
||||
// Work out what power level we need in order to be able to send events
|
||||
// of all types into the room.
|
||||
neededPowerLevel := powerLevelContent.StateDefault
|
||||
|
@ -619,14 +684,20 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC
|
|||
// so that we can modify them without modifying the original.
|
||||
tempPowerLevelContent.Users = make(map[string]int64, len(powerLevelContent.Users))
|
||||
for key, value := range powerLevelContent.Users {
|
||||
if roomVersion.PrivilegedCreators() && slices.Contains(creators, key) {
|
||||
continue // don't set the creator in the users map!
|
||||
}
|
||||
tempPowerLevelContent.Users[key] = value
|
||||
}
|
||||
|
||||
// If the user who is upgrading the room doesn't already have sufficient
|
||||
// power, then elevate their power levels.
|
||||
if tempPowerLevelContent.UserLevel(senderID) < neededPowerLevel {
|
||||
tempPowerLevelContent.Users[string(senderID)] = neededPowerLevel
|
||||
powerLevelsOverridden = true
|
||||
// the upgrader will be the creator so is guaranteed to have enough perms to do this.
|
||||
if !roomVersion.PrivilegedCreators() {
|
||||
// If the user who is upgrading the room doesn't already have sufficient
|
||||
// power, then elevate their power levels.
|
||||
if tempPowerLevelContent.UserLevel(senderID) < neededPowerLevel {
|
||||
tempPowerLevelContent.Users[string(senderID)] = neededPowerLevel
|
||||
powerLevelsOverridden = true
|
||||
}
|
||||
}
|
||||
|
||||
// Then return the temporary power levels event.
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
//"github.com/element-hq/dendrite/roomserver/internal"
|
||||
// "github.com/element-hq/dendrite/roomserver/internal"
|
||||
"github.com/element-hq/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
@ -747,7 +747,7 @@ func GetAuthChain(
|
|||
// from the database and the `eventsToFetch` will be updated with any new
|
||||
// events that we have learned about and need to find. When `eventsToFetch`
|
||||
// is eventually empty, we should have reached the end of the chain.
|
||||
eventsToFetch := authEventIDs
|
||||
eventsToFetch := append([]string{}, authEventIDs...)
|
||||
authEventsMap := make(map[string]gomatrixserverlib.PDU)
|
||||
|
||||
for len(eventsToFetch) > 0 {
|
||||
|
@ -779,7 +779,7 @@ func GetAuthChain(
|
|||
|
||||
// We've now retrieved all of the events we can. Flatten them down into an
|
||||
// array and return them.
|
||||
var authEvents []gomatrixserverlib.PDU
|
||||
authEvents := make([]gomatrixserverlib.PDU, 0, len(authEventsMap))
|
||||
for _, event := range authEventsMap {
|
||||
authEvents = append(authEvents, event)
|
||||
}
|
||||
|
|
|
@ -1075,7 +1075,7 @@ func TestUpgrade(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("upgrade userID is invalid")
|
||||
}
|
||||
newRoomID, err := rsAPI.PerformRoomUpgrade(processCtx.Context(), roomID, *userID, rsAPI.DefaultRoomVersion())
|
||||
newRoomID, err := rsAPI.PerformRoomUpgrade(processCtx.Context(), roomID, *userID, rsAPI.DefaultRoomVersion(), nil)
|
||||
if err != nil && tc.wantNewRoom {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -888,6 +888,8 @@ func (v *StateResolution) resolveConflicts(
|
|||
case gomatrixserverlib.StateResV1:
|
||||
return v.resolveConflictsV1(ctx, notConflicted, conflicted)
|
||||
case gomatrixserverlib.StateResV2:
|
||||
fallthrough
|
||||
case gomatrixserverlib.StateResV2_1:
|
||||
return v.resolveConflictsV2(ctx, notConflicted, conflicted)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported state resolution algorithm %v", stateResAlgo)
|
||||
|
|
|
@ -1052,6 +1052,7 @@ func (d *EventDatabase) MaybeRedactEvent(
|
|||
return err
|
||||
}
|
||||
|
||||
// TODO HYDRA: we need to load the create event here
|
||||
switch {
|
||||
case powerlevels.UserLevel(redactionEvent.SenderID()) >= powerlevels.Redact:
|
||||
// 1. The power level of the redaction event’s sender is greater than or equal to the redact level.
|
||||
|
|
|
@ -216,14 +216,6 @@ func OnIncomingMessagesRequest(
|
|||
|
||||
// TODO: Implement filtering (#587)
|
||||
|
||||
// Check the room ID's format.
|
||||
if _, _, err = gomatrixserverlib.SplitID('!', roomID); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.MissingParam("Bad room ID: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
// If the user already left the room, grep events from before that
|
||||
if membershipResp.Membership == spec.Leave {
|
||||
var token types.TopologyToken
|
||||
|
|
|
@ -92,6 +92,7 @@ func (s *accountDataStatements) SelectAccountDataInRange(
|
|||
accountDataEventFilter *synctypes.EventFilter,
|
||||
) (data map[string][]string, pos types.StreamPosition, err error) {
|
||||
data = make(map[string][]string)
|
||||
pos = r.Low()
|
||||
|
||||
rows, err := sqlutil.TxStmt(txn, s.selectAccountDataInRangeStmt).QueryContext(
|
||||
ctx, userID, r.Low(), r.High(),
|
||||
|
@ -122,7 +123,7 @@ func (s *accountDataStatements) SelectAccountDataInRange(
|
|||
pos = id
|
||||
}
|
||||
}
|
||||
if pos == 0 {
|
||||
if len(data) == 0 {
|
||||
pos = r.High()
|
||||
}
|
||||
return data, pos, rows.Err()
|
||||
|
|
|
@ -84,6 +84,8 @@ func (s *accountDataStatements) SelectAccountDataInRange(
|
|||
filter *synctypes.EventFilter,
|
||||
) (data map[string][]string, pos types.StreamPosition, err error) {
|
||||
data = make(map[string][]string)
|
||||
pos = r.Low()
|
||||
|
||||
stmt, params, err := prepareWithFilters(
|
||||
s.db, txn, selectAccountDataInRangeSQL,
|
||||
[]interface{}{
|
||||
|
@ -119,7 +121,7 @@ func (s *accountDataStatements) SelectAccountDataInRange(
|
|||
pos = id
|
||||
}
|
||||
}
|
||||
if pos == 0 {
|
||||
if len(data) == 0 {
|
||||
pos = r.High()
|
||||
}
|
||||
return data, pos, rows.Err()
|
||||
|
|
|
@ -46,7 +46,7 @@ func prepareWithFilters(
|
|||
params, offset = append(params, v), offset+1
|
||||
}
|
||||
} else {
|
||||
query += ` AND sender NOT = ""`
|
||||
query += ` AND sender != ""`
|
||||
}
|
||||
}
|
||||
if types != nil {
|
||||
|
@ -66,7 +66,7 @@ func prepareWithFilters(
|
|||
params, offset = append(params, v), offset+1
|
||||
}
|
||||
} else {
|
||||
query += ` AND type NOT = ""`
|
||||
query += ` AND type != ""`
|
||||
}
|
||||
}
|
||||
if containsURL != nil {
|
||||
|
|
|
@ -404,7 +404,9 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
|||
// "state" section and kept in "timeline".
|
||||
sEvents := gomatrixserverlib.HeaderedReverseTopologicalOrdering(
|
||||
gomatrixserverlib.ToPDUs(removeDuplicates(delta.StateEvents, events)),
|
||||
gomatrixserverlib.TopologicalOrderByAuthEvents,
|
||||
// sorting by auth events is not stable unless we know the create and historical PL events,
|
||||
// which we don't for deltas like this.
|
||||
gomatrixserverlib.TopologicalOrderByPrevEvents,
|
||||
)
|
||||
delta.StateEvents = make([]*rstypes.HeaderedEvent, len(sEvents))
|
||||
var skipped int
|
||||
|
|
|
@ -548,6 +548,13 @@ func testHistoryVisibility(t *testing.T, dbType test.DBType) {
|
|||
DisplayName: "BOB",
|
||||
}
|
||||
|
||||
filters := []string{
|
||||
// check that lazy loading doesn't break history visibility
|
||||
`{"lazy_load_members":true}`,
|
||||
// Test all kind of filters, including "bad" ones
|
||||
`{"lazy_load_members":true,"types":null,"not_types":[],"rooms":null,"not_rooms":[],"senders":null,"not_senders":[],"contains_url":null,"io.element.relation_senders":[],"io.element.relation_types":["io.element.thread"]}`,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
// check guest and normal user accounts
|
||||
for _, accType := range []userapi.AccountType{userapi.AccountTypeGuest, userapi.AccountTypeUser} {
|
||||
|
@ -614,79 +621,82 @@ func testHistoryVisibility(t *testing.T, dbType test.DBType) {
|
|||
for _, tc := range testCases {
|
||||
testname := fmt.Sprintf("%s - %s", tc.historyVisibility, userType)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
// create a room with the given visibility
|
||||
room := test.NewRoom(t, alice, test.RoomHistoryVisibility(tc.historyVisibility))
|
||||
for _, filter := range filters {
|
||||
t.Logf("Using filter: %s", filter)
|
||||
// create a room with the given visibility
|
||||
room := test.NewRoom(t, alice, test.RoomHistoryVisibility(tc.historyVisibility))
|
||||
|
||||
// send the events/messages to NATS to create the rooms
|
||||
beforeJoinBody := fmt.Sprintf("Before invite in a %s room", tc.historyVisibility)
|
||||
beforeJoinEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": beforeJoinBody})
|
||||
eventsToSend := append(room.Events(), beforeJoinEv)
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, eventsToSend, "test", "test", "test", nil, false); err != nil {
|
||||
t.Fatalf("failed to send events: %v", err)
|
||||
}
|
||||
syncUntil(t, routers, aliceDev.AccessToken, false,
|
||||
func(syncBody string) bool {
|
||||
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(content.body=="%s")`, room.ID, beforeJoinBody)
|
||||
return gjson.Get(syncBody, path).Exists()
|
||||
},
|
||||
)
|
||||
// send the events/messages to NATS to create the rooms
|
||||
beforeJoinBody := fmt.Sprintf("Before invite in a %s room", tc.historyVisibility)
|
||||
beforeJoinEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": beforeJoinBody})
|
||||
eventsToSend := append(room.Events(), beforeJoinEv)
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, eventsToSend, "test", "test", "test", nil, false); err != nil {
|
||||
t.Fatalf("failed to send events: %v", err)
|
||||
}
|
||||
syncUntil(t, routers, aliceDev.AccessToken, false,
|
||||
func(syncBody string) bool {
|
||||
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(content.body=="%s")`, room.ID, beforeJoinBody)
|
||||
return gjson.Get(syncBody, path).Exists()
|
||||
},
|
||||
)
|
||||
|
||||
// There is only one event, we expect only to be able to see this, if the room is world_readable
|
||||
w := httptest.NewRecorder()
|
||||
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
|
||||
"access_token": bobDev.AccessToken,
|
||||
"dir": "b",
|
||||
"filter": `{"lazy_load_members":true}`, // check that lazy loading doesn't break history visibility
|
||||
})))
|
||||
if w.Code != 200 {
|
||||
t.Logf("%s", w.Body.String())
|
||||
t.Fatalf("got HTTP %d want %d", w.Code, 200)
|
||||
}
|
||||
// We only care about the returned events at this point
|
||||
var res struct {
|
||||
Chunk []synctypes.ClientEvent `json:"chunk"`
|
||||
}
|
||||
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||
t.Errorf("failed to decode response body: %s", err)
|
||||
}
|
||||
// There is only one event, we expect only to be able to see this, if the room is world_readable
|
||||
w := httptest.NewRecorder()
|
||||
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
|
||||
"access_token": bobDev.AccessToken,
|
||||
"dir": "b",
|
||||
"filter": filter,
|
||||
})))
|
||||
if w.Code != 200 {
|
||||
t.Logf("%s", w.Body.String())
|
||||
t.Fatalf("got HTTP %d want %d", w.Code, 200)
|
||||
}
|
||||
// We only care about the returned events at this point
|
||||
var res struct {
|
||||
Chunk []synctypes.ClientEvent `json:"chunk"`
|
||||
}
|
||||
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||
t.Errorf("failed to decode response body: %s", err)
|
||||
}
|
||||
|
||||
verifyEventVisible(t, tc.wantResult.seeWithoutJoin, beforeJoinEv, res.Chunk)
|
||||
verifyEventVisible(t, tc.wantResult.seeWithoutJoin, beforeJoinEv, res.Chunk)
|
||||
|
||||
// Create invite, a message, join the room and create another message.
|
||||
inviteEv := room.CreateAndInsert(t, alice, "m.room.member", map[string]interface{}{"membership": "invite"}, test.WithStateKey(bob.ID))
|
||||
afterInviteEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": fmt.Sprintf("After invite in a %s room", tc.historyVisibility)})
|
||||
joinEv := room.CreateAndInsert(t, bob, "m.room.member", map[string]interface{}{"membership": "join"}, test.WithStateKey(bob.ID))
|
||||
afterJoinBody := fmt.Sprintf("After join in a %s room", tc.historyVisibility)
|
||||
msgEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": afterJoinBody})
|
||||
// Create invite, a message, join the room and create another message.
|
||||
inviteEv := room.CreateAndInsert(t, alice, "m.room.member", map[string]interface{}{"membership": "invite"}, test.WithStateKey(bob.ID))
|
||||
afterInviteEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": fmt.Sprintf("After invite in a %s room", tc.historyVisibility)})
|
||||
joinEv := room.CreateAndInsert(t, bob, "m.room.member", map[string]interface{}{"membership": "join"}, test.WithStateKey(bob.ID))
|
||||
afterJoinBody := fmt.Sprintf("After join in a %s room", tc.historyVisibility)
|
||||
msgEv := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": afterJoinBody})
|
||||
|
||||
eventsToSend = append([]*rstypes.HeaderedEvent{}, inviteEv, afterInviteEv, joinEv, msgEv)
|
||||
eventsToSend = append([]*rstypes.HeaderedEvent{}, inviteEv, afterInviteEv, joinEv, msgEv)
|
||||
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, eventsToSend, "test", "test", "test", nil, false); err != nil {
|
||||
t.Fatalf("failed to send events: %v", err)
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, eventsToSend, "test", "test", "test", nil, false); err != nil {
|
||||
t.Fatalf("failed to send events: %v", err)
|
||||
}
|
||||
syncUntil(t, routers, aliceDev.AccessToken, false,
|
||||
func(syncBody string) bool {
|
||||
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(content.body=="%s")`, room.ID, afterJoinBody)
|
||||
return gjson.Get(syncBody, path).Exists()
|
||||
},
|
||||
)
|
||||
|
||||
// Verify the messages after/before invite are visible or not
|
||||
w = httptest.NewRecorder()
|
||||
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
|
||||
"access_token": bobDev.AccessToken,
|
||||
"dir": "b",
|
||||
})))
|
||||
if w.Code != 200 {
|
||||
t.Logf("%s", w.Body.String())
|
||||
t.Fatalf("got HTTP %d want %d", w.Code, 200)
|
||||
}
|
||||
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||
t.Errorf("failed to decode response body: %s", err)
|
||||
}
|
||||
// verify results
|
||||
verifyEventVisible(t, tc.wantResult.seeBeforeJoin, beforeJoinEv, res.Chunk)
|
||||
verifyEventVisible(t, tc.wantResult.seeAfterInvite, afterInviteEv, res.Chunk)
|
||||
}
|
||||
syncUntil(t, routers, aliceDev.AccessToken, false,
|
||||
func(syncBody string) bool {
|
||||
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(content.body=="%s")`, room.ID, afterJoinBody)
|
||||
return gjson.Get(syncBody, path).Exists()
|
||||
},
|
||||
)
|
||||
|
||||
// Verify the messages after/before invite are visible or not
|
||||
w = httptest.NewRecorder()
|
||||
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
|
||||
"access_token": bobDev.AccessToken,
|
||||
"dir": "b",
|
||||
})))
|
||||
if w.Code != 200 {
|
||||
t.Logf("%s", w.Body.String())
|
||||
t.Fatalf("got HTTP %d want %d", w.Code, 200)
|
||||
}
|
||||
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||
t.Errorf("failed to decode response body: %s", err)
|
||||
}
|
||||
// verify results
|
||||
verifyEventVisible(t, tc.wantResult.seeBeforeJoin, beforeJoinEv, res.Chunk)
|
||||
verifyEventVisible(t, tc.wantResult.seeAfterInvite, afterInviteEv, res.Chunk)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,4 +21,8 @@ Guest users can accept invites to private rooms over federation
|
|||
|
||||
# Tests Synapse specific behavior
|
||||
/state returns M_NOT_FOUND for an outlier
|
||||
/state_ids returns M_NOT_FOUND for an outlier
|
||||
/state_ids returns M_NOT_FOUND for an outlier
|
||||
|
||||
# this is a silly restriction as it basically stops servers from communicating, so we relax it
|
||||
# see https://github.com/element-hq/synapse/issues/7543
|
||||
Server rejects invalid JSON in a version 6 room
|
|
@ -94,7 +94,7 @@ func (r *Room) insertCreateEvents(t *testing.T) {
|
|||
t.Helper()
|
||||
var joinRule gomatrixserverlib.JoinRuleContent
|
||||
var hisVis gomatrixserverlib.HistoryVisibilityContent
|
||||
plContent := eventutil.InitialPowerLevelsContent(r.creator.ID)
|
||||
plContent := eventutil.InitialPowerLevelsContent(gomatrixserverlib.MustGetRoomVersion(r.Version), r.creator.ID)
|
||||
switch r.preset {
|
||||
case PresetTrustedPrivateChat:
|
||||
fallthrough
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -604,7 +605,9 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
|||
// ordering guarantees we must provide.
|
||||
go func() {
|
||||
// This background processing cannot be tied to a request.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
// We're generous with the "global" timeout, each HTTP request gets its own context with
|
||||
// at most 30 seconds below.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
var rejected []*pushgateway.Device
|
||||
|
@ -621,7 +624,10 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
|||
// device, rather than per URL. For now, we must
|
||||
// notify each one separately.
|
||||
for _, dev := range devices {
|
||||
rej, err := s.notifyHTTP(ctx, event, url, format, []*pushgateway.Device{dev}, mem.Localpart, roomName, int(userNumUnreadNotifs))
|
||||
// Give each HTTP request its own context.
|
||||
httpCtx, httpCancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
rej, err := s.notifyHTTP(httpCtx, event, url, format, []*pushgateway.Device{dev}, mem.Localpart, roomName, int(userNumUnreadNotifs))
|
||||
httpCancel()
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"event_id": event.EventID(),
|
||||
|
@ -722,25 +728,34 @@ func (rse *ruleSetEvalContext) HasPowerLevel(senderID spec.SenderID, levelKey st
|
|||
req := &rsapi.QueryLatestEventsAndStateRequest{
|
||||
RoomID: rse.roomID,
|
||||
StateToFetch: []gomatrixserverlib.StateKeyTuple{
|
||||
{EventType: spec.MRoomPowerLevels},
|
||||
{EventType: spec.MRoomPowerLevels, StateKey: ""},
|
||||
{EventType: spec.MRoomCreate, StateKey: ""},
|
||||
},
|
||||
}
|
||||
var res rsapi.QueryLatestEventsAndStateResponse
|
||||
if err := rse.rsAPI.QueryLatestEventsAndState(rse.ctx, req, &res); err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, ev := range res.StateEvents {
|
||||
if ev.Type() != spec.MRoomPowerLevels {
|
||||
continue
|
||||
var createEvent, plEvent *rstypes.HeaderedEvent
|
||||
for i, ev := range res.StateEvents {
|
||||
if ev.Type() == spec.MRoomCreate {
|
||||
createEvent = res.StateEvents[i]
|
||||
} else if ev.Type() == spec.MRoomPowerLevels {
|
||||
plEvent = res.StateEvents[i]
|
||||
}
|
||||
|
||||
plc, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev.PDU)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return plc.UserLevel(senderID) >= plc.NotificationLevel(levelKey), nil
|
||||
}
|
||||
return true, nil
|
||||
verImpl := gomatrixserverlib.MustGetRoomVersion(createEvent.Version())
|
||||
if verImpl.PrivilegedCreators() && slices.Contains(gomatrixserverlib.CreatorsFromCreateEvent(createEvent), string(senderID)) {
|
||||
return true, nil
|
||||
}
|
||||
if plEvent == nil {
|
||||
return true, nil // unsure, but this is what we did before
|
||||
}
|
||||
plc, err := gomatrixserverlib.NewPowerLevelContentFromEvent(plEvent.PDU)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return plc.UserLevel(senderID) >= plc.NotificationLevel(levelKey), nil
|
||||
}
|
||||
|
||||
// localPushDevices pushes to the configured devices of a local
|
||||
|
|
|
@ -337,7 +337,7 @@ func (a *UserInternalAPI) PerformDeviceDeletion(ctx context.Context, req *api.Pe
|
|||
deleteReq := &api.PerformDeleteKeysRequest{
|
||||
UserID: req.UserID,
|
||||
}
|
||||
for _, keyID := range req.DeviceIDs {
|
||||
for _, keyID := range deletedDeviceIDs {
|
||||
deleteReq.KeyIDs = append(deleteReq.KeyIDs, gomatrixserverlib.KeyID(keyID))
|
||||
}
|
||||
deleteRes := &api.PerformDeleteKeysResponse{}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue