Merge branch 'main' of github.com:matrix-org/dendrite into gh-pages
This commit is contained in:
commit
b5312d1421
4
.github/workflows/dendrite.yml
vendored
4
.github/workflows/dendrite.yml
vendored
|
@ -280,6 +280,8 @@ jobs:
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
cache: true
|
cache: true
|
||||||
|
- name: Docker version
|
||||||
|
run: docker version
|
||||||
- name: Build upgrade-tests
|
- name: Build upgrade-tests
|
||||||
run: go build ./cmd/dendrite-upgrade-tests
|
run: go build ./cmd/dendrite-upgrade-tests
|
||||||
- name: Test upgrade (PostgreSQL)
|
- name: Test upgrade (PostgreSQL)
|
||||||
|
@ -300,6 +302,8 @@ jobs:
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
cache: true
|
cache: true
|
||||||
|
- name: Docker version
|
||||||
|
run: docker version
|
||||||
- name: Build upgrade-tests
|
- name: Build upgrade-tests
|
||||||
run: go build ./cmd/dendrite-upgrade-tests
|
run: go build ./cmd/dendrite-upgrade-tests
|
||||||
- name: Test upgrade (PostgreSQL)
|
- name: Test upgrade (PostgreSQL)
|
||||||
|
|
2
.github/workflows/helm.yml
vendored
2
.github/workflows/helm.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
||||||
version: v3.10.0
|
version: v3.10.0
|
||||||
|
|
||||||
- name: Run chart-releaser
|
- name: Run chart-releaser
|
||||||
uses: helm/chart-releaser-action@v1.4.1
|
uses: helm/chart-releaser-action@ed43eb303604cbc0eeec8390544f7748dc6c790d # specific commit, since `mark_as_latest` is not yet in a release
|
||||||
env:
|
env:
|
||||||
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
with:
|
with:
|
||||||
|
|
2
.github/workflows/schedules.yaml
vendored
2
.github/workflows/schedules.yaml
vendored
|
@ -128,7 +128,7 @@ jobs:
|
||||||
# See https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md specifically GOROOT_1_17_X64
|
# See https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md specifically GOROOT_1_17_X64
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
|
sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
|
||||||
go get -v github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
|
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
|
||||||
- name: Run actions/checkout@v3 for dendrite
|
- name: Run actions/checkout@v3 for dendrite
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
|
19
CHANGES.md
19
CHANGES.md
|
@ -1,5 +1,24 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Dendrite 0.13.3 (2023-09-28)
|
||||||
|
|
||||||
|
### Fixes:
|
||||||
|
|
||||||
|
- The `user_id` query parameter when authenticating is now used correctly (contributed by [tulir](https://github.com/tulir))
|
||||||
|
- Invitations are now correctly pushed to devices
|
||||||
|
- A bug which could result in the corruption of `m.direct` account data has been fixed
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- [Sliding Sync proxy](https://github.com/matrix-org/sliding-sync) can be configured in the `/.well-known/matrix/client` response
|
||||||
|
- Room version 11 is now supported
|
||||||
|
- Clients can request the `federation` `event_format` when creating filters
|
||||||
|
- Many under the hood improvements for [MSC4014: Pseudonymous Identities](https://github.com/matrix-org/matrix-spec-proposals/blob/kegan/pseudo-ids/proposals/4014-pseudonymous-identities.md)
|
||||||
|
|
||||||
|
### Other
|
||||||
|
|
||||||
|
- Dendrite now requires Go 1.20 if building from source
|
||||||
|
|
||||||
## Dendrite 0.13.2 (2023-08-23)
|
## Dendrite 0.13.2 (2023-08-23)
|
||||||
|
|
||||||
### Fixes:
|
### Fixes:
|
||||||
|
|
|
@ -36,7 +36,7 @@ If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or j
|
||||||
See the [Planning your Installation](https://matrix-org.github.io/dendrite/installation/planning) page for
|
See the [Planning your Installation](https://matrix-org.github.io/dendrite/installation/planning) page for
|
||||||
more information on requirements.
|
more information on requirements.
|
||||||
|
|
||||||
To build Dendrite, you will need Go 1.18 or later.
|
To build Dendrite, you will need Go 1.20 or later.
|
||||||
|
|
||||||
For a usable federating Dendrite deployment, you will also need:
|
For a usable federating Dendrite deployment, you will also need:
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (s *OutputRoomEventConsumer) onMessage(
|
||||||
if len(output.NewRoomEvent.AddsStateEventIDs) > 0 {
|
if len(output.NewRoomEvent.AddsStateEventIDs) > 0 {
|
||||||
newEventID := output.NewRoomEvent.Event.EventID()
|
newEventID := output.NewRoomEvent.Event.EventID()
|
||||||
eventsReq := &api.QueryEventsByIDRequest{
|
eventsReq := &api.QueryEventsByIDRequest{
|
||||||
RoomID: output.NewRoomEvent.Event.RoomID(),
|
RoomID: output.NewRoomEvent.Event.RoomID().String(),
|
||||||
EventIDs: make([]string, 0, len(output.NewRoomEvent.AddsStateEventIDs)),
|
EventIDs: make([]string, 0, len(output.NewRoomEvent.AddsStateEventIDs)),
|
||||||
}
|
}
|
||||||
eventsRes := &api.QueryEventsByIDResponse{}
|
eventsRes := &api.QueryEventsByIDResponse{}
|
||||||
|
@ -236,11 +236,7 @@ func (s *appserviceState) backoffAndPause(err error) error {
|
||||||
// TODO: This should be cached, see https://github.com/matrix-org/dendrite/issues/1682
|
// TODO: This should be cached, see https://github.com/matrix-org/dendrite/issues/1682
|
||||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *types.HeaderedEvent, appservice *config.ApplicationService) bool {
|
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *types.HeaderedEvent, appservice *config.ApplicationService) bool {
|
||||||
user := ""
|
user := ""
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
userID, err := s.rsAPI.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
user = userID.String()
|
user = userID.String()
|
||||||
}
|
}
|
||||||
|
@ -250,7 +246,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
||||||
return false
|
return false
|
||||||
case appservice.IsInterestedInUserID(user):
|
case appservice.IsInterestedInUserID(user):
|
||||||
return true
|
return true
|
||||||
case appservice.IsInterestedInRoomID(event.RoomID()):
|
case appservice.IsInterestedInRoomID(event.RoomID().String()):
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +257,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all known room aliases of the room the event came from
|
// Check all known room aliases of the room the event came from
|
||||||
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID()}
|
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID().String()}
|
||||||
var queryRes api.GetAliasesForRoomIDResponse
|
var queryRes api.GetAliasesForRoomIDResponse
|
||||||
if err := s.rsAPI.GetAliasesForRoomID(ctx, &queryReq, &queryRes); err == nil {
|
if err := s.rsAPI.GetAliasesForRoomID(ctx, &queryReq, &queryRes); err == nil {
|
||||||
for _, alias := range queryRes.Aliases {
|
for _, alias := range queryRes.Aliases {
|
||||||
|
@ -272,7 +268,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
||||||
} else {
|
} else {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
}).WithError(err).Errorf("Unable to get aliases for room")
|
}).WithError(err).Errorf("Unable to get aliases for room")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +284,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
|
||||||
// until we have a lighter way of checking the state before the event that
|
// until we have a lighter way of checking the state before the event that
|
||||||
// doesn't involve state res, then this is probably OK.
|
// doesn't involve state res, then this is probably OK.
|
||||||
membershipReq := &api.QueryMembershipsForRoomRequest{
|
membershipReq := &api.QueryMembershipsForRoomRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
JoinedOnly: true,
|
JoinedOnly: true,
|
||||||
}
|
}
|
||||||
membershipRes := &api.QueryMembershipsForRoomResponse{}
|
membershipRes := &api.QueryMembershipsForRoomResponse{}
|
||||||
|
@ -317,7 +313,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
|
||||||
} else {
|
} else {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
}).WithError(err).Errorf("Unable to get membership for room")
|
}).WithError(err).Errorf("Unable to get membership for room")
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -944,4 +944,12 @@ rmv remote user can join room with version 10
|
||||||
rmv User can invite remote user to room with version 10
|
rmv User can invite remote user to room with version 10
|
||||||
rmv Remote user can backfill in a room with version 10
|
rmv Remote user can backfill in a room with version 10
|
||||||
rmv Can reject invites over federation for rooms with version 10
|
rmv Can reject invites over federation for rooms with version 10
|
||||||
rmv Can receive redactions from regular users over federation in room version 10
|
rmv Can receive redactions from regular users over federation in room version 10
|
||||||
|
rmv User can create and send/receive messages in a room with version 11
|
||||||
|
rmv local user can join room with version 11
|
||||||
|
rmv User can invite local user to room with version 11
|
||||||
|
rmv remote user can join room with version 11
|
||||||
|
rmv User can invite remote user to room with version 11
|
||||||
|
rmv Remote user can backfill in a room with version 11
|
||||||
|
rmv Can reject invites over federation for rooms with version 11
|
||||||
|
rmv Can receive redactions from regular users over federation in room version 11
|
|
@ -34,7 +34,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type redactionContent struct {
|
type redactionContent struct {
|
||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
|
Redacts string `json:"redacts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type redactionResponse struct {
|
type redactionResponse struct {
|
||||||
|
@ -98,7 +99,7 @@ func SendRedaction(
|
||||||
JSON: spec.NotFound("unknown event ID"), // TODO: is it ok to leak existence?
|
JSON: spec.NotFound("unknown event ID"), // TODO: is it ok to leak existence?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ev.RoomID() != roomID {
|
if ev.RoomID().String() != roomID {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: 400,
|
Code: 400,
|
||||||
JSON: spec.NotFound("cannot redact event in another room"),
|
JSON: spec.NotFound("cannot redact event in another room"),
|
||||||
|
@ -151,6 +152,11 @@ func SendRedaction(
|
||||||
Type: spec.MRoomRedaction,
|
Type: spec.MRoomRedaction,
|
||||||
Redacts: eventID,
|
Redacts: eventID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Room version 11 expects the "redacts" field on the
|
||||||
|
// content field, so add it here as well
|
||||||
|
r.Redacts = eventID
|
||||||
|
|
||||||
err = proto.SetContent(r)
|
err = proto.SetContent(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("proto.SetContent failed")
|
util.GetLogger(req.Context()).WithError(err).Error("proto.SetContent failed")
|
||||||
|
|
|
@ -263,7 +263,11 @@ func SendEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID string, rsAPI api.ClientRoomserverAPI) error {
|
func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID string, rsAPI api.ClientRoomserverAPI) error {
|
||||||
userMap := r["users"].(map[string]interface{})
|
users, ok := r["users"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
userMap := users.(map[string]interface{})
|
||||||
validRoomID, err := spec.NewRoomID(roomID)
|
validRoomID, err := spec.NewRoomID(roomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -277,7 +281,8 @@ func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID strin
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if senderID == nil {
|
} else if senderID == nil {
|
||||||
return fmt.Errorf("sender ID not found for %s in %s", uID, *validRoomID)
|
util.GetLogger(req.Context()).Warnf("sender ID not found for %s in %s", uID, *validRoomID)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
userMap[string(*senderID)] = level
|
userMap[string(*senderID)] = level
|
||||||
delete(userMap, user)
|
delete(userMap, user)
|
||||||
|
@ -437,7 +442,7 @@ func generateSendEvent(
|
||||||
JSON: spec.BadJSON("Cannot unmarshal the event content."),
|
JSON: spec.BadJSON("Cannot unmarshal the event content."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if content["replacement_room"] == e.RoomID() {
|
if content["replacement_room"] == e.RoomID().String() {
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
JSON: spec.InvalidParam("Cannot send tombstone event that points to the same room."),
|
JSON: spec.InvalidParam("Cannot send tombstone event that points to the same room."),
|
||||||
|
|
|
@ -172,28 +172,16 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, ev := range stateAfterRes.StateEvents {
|
for _, ev := range stateAfterRes.StateEvents {
|
||||||
sender := spec.UserID{}
|
clientEvent, err := synctypes.ToClientEvent(ev, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
evRoomID, err := spec.NewRoomID(ev.RoomID())
|
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).WithError(err).Error("Event roomID is invalid")
|
util.GetLogger(ctx).WithError(err).Error("Failed converting to ClientEvent")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
userID, err := rsAPI.QueryUserIDForSender(ctx, *evRoomID, ev.SenderID())
|
|
||||||
if err == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := ev.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := rsAPI.QueryUserIDForSender(ctx, *evRoomID, spec.SenderID(*ev.StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateEvents = append(
|
stateEvents = append(
|
||||||
stateEvents,
|
stateEvents,
|
||||||
synctypes.ToClientEvent(ev, synctypes.FormatAll, sender, sk),
|
*clientEvent,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Yggdrasil Demo
|
# Yggdrasil Demo
|
||||||
|
|
||||||
This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.18 or later.
|
This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.20 or later.
|
||||||
|
|
||||||
To run the homeserver, start at the root of the Dendrite repository and run:
|
To run the homeserver, start at the root of the Dendrite repository and run:
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -55,7 +54,7 @@ var latest, _ = semver.NewVersion("v6.6.6") // Dummy version, used as "HEAD"
|
||||||
// due to the error:
|
// due to the error:
|
||||||
// When using COPY with more than one source file, the destination must be a directory and end with a /
|
// 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.
|
// We need to run a postgres anyway, so use the dockerfile associated with Complement instead.
|
||||||
const DockerfilePostgreSQL = `FROM golang:1.18-buster as build
|
const DockerfilePostgreSQL = `FROM golang:1.20-bookworm as build
|
||||||
RUN apt-get update && apt-get install -y postgresql
|
RUN apt-get update && apt-get install -y postgresql
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
ARG BINARY
|
ARG BINARY
|
||||||
|
@ -74,16 +73,16 @@ RUN ./generate-keys --private-key matrix_key.pem --tls-cert server.crt --tls-key
|
||||||
# Replace the connection string with a single postgres DB, using user/db = 'postgres' and no password
|
# Replace the connection string with a single postgres DB, using user/db = 'postgres' and no password
|
||||||
RUN sed -i "s%connection_string:.*$%connection_string: postgresql://postgres@localhost/postgres?sslmode=disable%g" dendrite.yaml
|
RUN sed -i "s%connection_string:.*$%connection_string: postgresql://postgres@localhost/postgres?sslmode=disable%g" dendrite.yaml
|
||||||
# No password when connecting over localhost
|
# No password when connecting over localhost
|
||||||
RUN sed -i "s%127.0.0.1/32 md5%127.0.0.1/32 trust%g" /etc/postgresql/11/main/pg_hba.conf
|
RUN sed -i "s%127.0.0.1/32 scram-sha-256%127.0.0.1/32 trust%g" /etc/postgresql/15/main/pg_hba.conf
|
||||||
# Bump up max conns for moar concurrency
|
# Bump up max conns for moar concurrency
|
||||||
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/11/main/postgresql.conf
|
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/15/main/postgresql.conf
|
||||||
RUN sed -i 's/max_open_conns:.*$/max_open_conns: 100/g' dendrite.yaml
|
RUN sed -i 's/max_open_conns:.*$/max_open_conns: 100/g' dendrite.yaml
|
||||||
|
|
||||||
# This entry script starts postgres, waits for it to be up then starts dendrite
|
# This entry script starts postgres, waits for it to be up then starts dendrite
|
||||||
RUN echo '\
|
RUN echo '\
|
||||||
#!/bin/bash -eu \n\
|
#!/bin/bash -eu \n\
|
||||||
pg_lsclusters \n\
|
pg_lsclusters \n\
|
||||||
pg_ctlcluster 11 main start \n\
|
pg_ctlcluster 15 main start \n\
|
||||||
\n\
|
\n\
|
||||||
until pg_isready \n\
|
until pg_isready \n\
|
||||||
do \n\
|
do \n\
|
||||||
|
@ -101,7 +100,7 @@ ENV BINARY=dendrite
|
||||||
EXPOSE 8008 8448
|
EXPOSE 8008 8448
|
||||||
CMD /build/run_dendrite.sh`
|
CMD /build/run_dendrite.sh`
|
||||||
|
|
||||||
const DockerfileSQLite = `FROM golang:1.18-buster as build
|
const DockerfileSQLite = `FROM golang:1.20-bookworm as build
|
||||||
RUN apt-get update && apt-get install -y postgresql
|
RUN apt-get update && apt-get install -y postgresql
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
ARG BINARY
|
ARG BINARY
|
||||||
|
@ -119,7 +118,7 @@ RUN ./generate-keys --private-key matrix_key.pem --tls-cert server.crt --tls-key
|
||||||
|
|
||||||
# Make sure the SQLite databases are in a persistent location, we're already mapping
|
# Make sure the SQLite databases are in a persistent location, we're already mapping
|
||||||
# the postgresql folder so let's just use that for simplicity
|
# the postgresql folder so let's just use that for simplicity
|
||||||
RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postgresql\/11\/main\/%g" dendrite.yaml
|
RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postgresql\/15\/main\/%g" dendrite.yaml
|
||||||
|
|
||||||
# This entry script starts postgres, waits for it to be up then starts dendrite
|
# This entry script starts postgres, waits for it to be up then starts dendrite
|
||||||
RUN echo '\
|
RUN echo '\
|
||||||
|
@ -402,7 +401,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
|
||||||
{
|
{
|
||||||
Type: mount.TypeVolume,
|
Type: mount.TypeVolume,
|
||||||
Source: volumeName,
|
Source: volumeName,
|
||||||
Target: "/var/lib/postgresql/11/main",
|
Target: "/var/lib/postgresql/15/main",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil, nil, "dendrite_upgrade_test_"+branchName)
|
}, nil, nil, "dendrite_upgrade_test_"+branchName)
|
||||||
|
@ -515,7 +514,7 @@ func testCreateAccount(dockerClient *client.Client, version *semver.Version, con
|
||||||
}
|
}
|
||||||
defer response.Close()
|
defer response.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(response.Reader)
|
data, err := io.ReadAll(response.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -557,8 +556,8 @@ func cleanup(dockerClient *client.Client) {
|
||||||
})
|
})
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
log.Printf("Removing container: %v %v\n", c.ID, c.Names)
|
log.Printf("Removing container: %v %v\n", c.ID, c.Names)
|
||||||
s := time.Second
|
timeout := 1
|
||||||
_ = dockerClient.ContainerStop(context.Background(), c.ID, &s)
|
_ = dockerClient.ContainerStop(context.Background(), c.ID, container.StopOptions{Timeout: &timeout})
|
||||||
_ = dockerClient.ContainerRemove(context.Background(), c.ID, types.ContainerRemoveOptions{
|
_ = dockerClient.ContainerRemove(context.Background(), c.ID, types.ContainerRemoveOptions{
|
||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
|
@ -592,7 +591,7 @@ func main() {
|
||||||
branchToImageID := buildDendriteImages(httpClient, dockerClient, *flagTempDir, *flagBuildConcurrency, versions)
|
branchToImageID := buildDendriteImages(httpClient, dockerClient, *flagTempDir, *flagBuildConcurrency, versions)
|
||||||
|
|
||||||
// make a shared postgres volume
|
// make a shared postgres volume
|
||||||
volume, err := dockerClient.VolumeCreate(context.Background(), volume.VolumeCreateBody{
|
volume, err := dockerClient.VolumeCreate(context.Background(), volume.CreateOptions{
|
||||||
Name: "dendrite_upgrade_test",
|
Name: "dendrite_upgrade_test",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
dendriteUpgradeTestLabel: "yes",
|
dendriteUpgradeTestLabel: "yes",
|
||||||
|
|
|
@ -14,7 +14,7 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.11.1)
|
coffee-script-source (1.11.1)
|
||||||
colorator (1.1.0)
|
colorator (1.1.0)
|
||||||
commonmarker (0.23.9)
|
commonmarker (0.23.10)
|
||||||
concurrent-ruby (1.2.0)
|
concurrent-ruby (1.2.0)
|
||||||
dnsruby (1.61.9)
|
dnsruby (1.61.9)
|
||||||
simpleidn (~> 0.1)
|
simpleidn (~> 0.1)
|
||||||
|
|
|
@ -95,7 +95,7 @@ Consider enabling the DNS cache by modifying the `global` section of your config
|
||||||
## Time synchronisation
|
## Time synchronisation
|
||||||
|
|
||||||
Matrix relies heavily on TLS which requires the system time to be correct. If the clock
|
Matrix relies heavily on TLS which requires the system time to be correct. If the clock
|
||||||
drifts then you may find that federation no works reliably (or at all) and clients may
|
drifts then you may find that federation will not work reliably (or at all) and clients may
|
||||||
struggle to connect to your Dendrite server.
|
struggle to connect to your Dendrite server.
|
||||||
|
|
||||||
Ensure that the time is synchronised on your system by enabling NTP sync.
|
Ensure that the time is synchronised on your system by enabling NTP sync.
|
||||||
|
|
|
@ -59,7 +59,7 @@ In order to install Dendrite, you will need to satisfy the following dependencie
|
||||||
|
|
||||||
### Go
|
### Go
|
||||||
|
|
||||||
At this time, Dendrite supports being built with Go 1.18 or later. We do not support building
|
At this time, Dendrite supports being built with Go 1.20 or later. We do not support building
|
||||||
Dendrite with older versions of Go than this. If you are installing Go using a package manager,
|
Dendrite with older versions of Go than this. If you are installing Go using a package manager,
|
||||||
you should check (by running `go version`) that you are using a suitable version before you start.
|
you should check (by running `go version`) that you are using a suitable version before you start.
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent, rew
|
||||||
// Finally, work out if there are any more events missing.
|
// Finally, work out if there are any more events missing.
|
||||||
if len(missingEventIDs) > 0 {
|
if len(missingEventIDs) > 0 {
|
||||||
eventsReq := &api.QueryEventsByIDRequest{
|
eventsReq := &api.QueryEventsByIDRequest{
|
||||||
RoomID: ore.Event.RoomID(),
|
RoomID: ore.Event.RoomID().String(),
|
||||||
EventIDs: missingEventIDs,
|
EventIDs: missingEventIDs,
|
||||||
}
|
}
|
||||||
eventsRes := &api.QueryEventsByIDResponse{}
|
eventsRes := &api.QueryEventsByIDResponse{}
|
||||||
|
@ -205,7 +205,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent, rew
|
||||||
// talking to the roomserver
|
// talking to the roomserver
|
||||||
oldJoinedHosts, err := s.db.UpdateRoom(
|
oldJoinedHosts, err := s.db.UpdateRoom(
|
||||||
s.ctx,
|
s.ctx,
|
||||||
ore.Event.RoomID(),
|
ore.Event.RoomID().String(),
|
||||||
addsJoinedHosts,
|
addsJoinedHosts,
|
||||||
ore.RemovesStateEventIDs,
|
ore.RemovesStateEventIDs,
|
||||||
rewritesState, // if we're re-writing state, nuke all joined hosts before adding
|
rewritesState, // if we're re-writing state, nuke all joined hosts before adding
|
||||||
|
@ -218,7 +218,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent, rew
|
||||||
if s.cfg.Matrix.Presence.EnableOutbound && len(addsJoinedHosts) > 0 && ore.Event.Type() == spec.MRoomMember && ore.Event.StateKey() != nil {
|
if s.cfg.Matrix.Presence.EnableOutbound && len(addsJoinedHosts) > 0 && ore.Event.Type() == spec.MRoomMember && ore.Event.StateKey() != nil {
|
||||||
membership, _ := ore.Event.Membership()
|
membership, _ := ore.Event.Membership()
|
||||||
if membership == spec.Join {
|
if membership == spec.Join {
|
||||||
s.sendPresence(ore.Event.RoomID(), addsJoinedHosts)
|
s.sendPresence(ore.Event.RoomID().String(), addsJoinedHosts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ func (s *OutputRoomEventConsumer) joinedHostsAtEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle peeking hosts
|
// handle peeking hosts
|
||||||
inboundPeeks, err := s.db.GetInboundPeeks(s.ctx, ore.Event.PDU.RoomID())
|
inboundPeeks, err := s.db.GetInboundPeeks(s.ctx, ore.Event.PDU.RoomID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -409,12 +409,8 @@ func JoinedHostsFromEvents(ctx context.Context, evs []gomatrixserverlib.PDU, rsA
|
||||||
if membership != spec.Join {
|
if membership != spec.Join {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var domain spec.ServerName
|
var domain spec.ServerName
|
||||||
userID, err := rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*ev.StateKey()))
|
userID, err := rsAPI.QueryUserIDForSender(ctx, ev.RoomID(), spec.SenderID(*ev.StateKey()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.As(err, new(base64.CorruptInputError)) {
|
if errors.As(err, new(base64.CorruptInputError)) {
|
||||||
// Fallback to using the "old" way of getting the user domain, avoids
|
// Fallback to using the "old" way of getting the user domain, avoids
|
||||||
|
@ -510,7 +506,7 @@ func (s *OutputRoomEventConsumer) lookupStateEvents(
|
||||||
// At this point the missing events are neither the event itself nor are
|
// At this point the missing events are neither the event itself nor are
|
||||||
// they present in our local database. Our only option is to fetch them
|
// they present in our local database. Our only option is to fetch them
|
||||||
// from the roomserver using the query API.
|
// from the roomserver using the query API.
|
||||||
eventReq := api.QueryEventsByIDRequest{EventIDs: missing, RoomID: event.RoomID()}
|
eventReq := api.QueryEventsByIDRequest{EventIDs: missing, RoomID: event.RoomID().String()}
|
||||||
var eventResp api.QueryEventsByIDResponse
|
var eventResp api.QueryEventsByIDResponse
|
||||||
if err := s.rsAPI.QueryEventsByID(s.ctx, &eventReq, &eventResp); err != nil {
|
if err := s.rsAPI.QueryEventsByID(s.ctx, &eventReq, &eventResp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -146,7 +146,7 @@ func (f *fedClient) SendJoin(ctx context.Context, origin, s spec.ServerName, eve
|
||||||
f.fedClientMutex.Lock()
|
f.fedClientMutex.Lock()
|
||||||
defer f.fedClientMutex.Unlock()
|
defer f.fedClientMutex.Unlock()
|
||||||
for _, r := range f.allowJoins {
|
for _, r := range f.allowJoins {
|
||||||
if r.ID == event.RoomID() {
|
if r.ID == event.RoomID().String() {
|
||||||
r.InsertEvent(f.t, &types.HeaderedEvent{PDU: event})
|
r.InsertEvent(f.t, &types.HeaderedEvent{PDU: event})
|
||||||
f.t.Logf("Join event: %v", event.EventID())
|
f.t.Logf("Join event: %v", event.EventID())
|
||||||
res.StateEvents = types.NewEventJSONsFromHeaderedEvents(r.CurrentState())
|
res.StateEvents = types.NewEventJSONsFromHeaderedEvents(r.CurrentState())
|
||||||
|
|
|
@ -548,11 +548,7 @@ func (r *FederationInternalAPI) SendInvite(
|
||||||
event gomatrixserverlib.PDU,
|
event gomatrixserverlib.PDU,
|
||||||
strippedState []gomatrixserverlib.InviteStrippedState,
|
strippedState []gomatrixserverlib.InviteStrippedState,
|
||||||
) (gomatrixserverlib.PDU, error) {
|
) (gomatrixserverlib.PDU, error) {
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
inviter, err := r.rsAPI.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
inviter, err := r.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -575,7 +571,7 @@ func (r *FederationInternalAPI) SendInvite(
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"user_id": *event.StateKey(),
|
"user_id": *event.StateKey(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"room_version": event.Version(),
|
"room_version": event.Version(),
|
||||||
"destination": destination,
|
"destination": destination,
|
||||||
}).Info("Sending invite")
|
}).Info("Sending invite")
|
||||||
|
|
|
@ -218,7 +218,7 @@ func (oqs *OutgoingQueues) SendEvent(
|
||||||
if api.IsServerBannedFromRoom(
|
if api.IsServerBannedFromRoom(
|
||||||
oqs.process.Context(),
|
oqs.process.Context(),
|
||||||
oqs.rsAPI,
|
oqs.rsAPI,
|
||||||
ev.RoomID(),
|
ev.RoomID().String(),
|
||||||
destination,
|
destination,
|
||||||
) {
|
) {
|
||||||
delete(destmap, destination)
|
delete(destmap, destination)
|
||||||
|
|
|
@ -104,7 +104,7 @@ func (f *stubFederationClient) P2PSendTransactionToRelay(ctx context.Context, u
|
||||||
|
|
||||||
func mustCreatePDU(t *testing.T) *types.HeaderedEvent {
|
func mustCreatePDU(t *testing.T) *types.HeaderedEvent {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
content := `{"type":"m.room.message"}`
|
content := `{"type":"m.room.message", "room_id":"!room:a"}`
|
||||||
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV10).NewEventFromTrustedJSON([]byte(content), false)
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV10).NewEventFromTrustedJSON([]byte(content), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create event: %v", err)
|
t.Fatalf("failed to create event: %v", err)
|
||||||
|
|
|
@ -109,7 +109,7 @@ func Backfill(
|
||||||
|
|
||||||
var ev *types.HeaderedEvent
|
var ev *types.HeaderedEvent
|
||||||
for _, ev = range res.Events {
|
for _, ev = range res.Events {
|
||||||
if ev.RoomID() == roomID {
|
if ev.RoomID().String() == roomID {
|
||||||
evs = append(evs, ev.PDU)
|
evs = append(evs, ev.PDU)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,10 @@ func GetEventAuth(
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.RoomID() != roomID {
|
if event.RoomID().String() != roomID {
|
||||||
return util.JSONResponse{Code: http.StatusNotFound, JSON: spec.NotFound("event does not belong to this room")}
|
return util.JSONResponse{Code: http.StatusNotFound, JSON: spec.NotFound("event does not belong to this room")}
|
||||||
}
|
}
|
||||||
resErr = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID())
|
resErr = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID().String())
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ func GetEvent(
|
||||||
return *err
|
return *err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID())
|
err = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return *err
|
return *err
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@ func SendLeave(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the room ID is correct.
|
// Check that the room ID is correct.
|
||||||
if event.RoomID() != roomID {
|
if event.RoomID().String() != roomID {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusBadRequest,
|
Code: http.StatusBadRequest,
|
||||||
JSON: spec.BadJSON("The room ID in the request path must match the room ID in the leave event JSON"),
|
JSON: spec.BadJSON("The room ID in the request path must match the room ID in the leave event JSON"),
|
||||||
|
@ -242,14 +242,7 @@ func SendLeave(
|
||||||
// Check that the sender belongs to the server that is sending us
|
// Check that the sender belongs to the server that is sending us
|
||||||
// the request. By this point we've already asserted that the sender
|
// the request. By this point we've already asserted that the sender
|
||||||
// and the state key are equal so we don't need to check both.
|
// and the state key are equal so we don't need to check both.
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
sender, err := rsAPI.QueryUserIDForSender(httpReq.Context(), event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("Room ID is invalid."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sender, err := rsAPI.QueryUserIDForSender(httpReq.Context(), *validRoomID, event.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusForbidden,
|
Code: http.StatusForbidden,
|
||||||
|
|
|
@ -87,7 +87,7 @@ func filterEvents(
|
||||||
) []*types.HeaderedEvent {
|
) []*types.HeaderedEvent {
|
||||||
ref := events[:0]
|
ref := events[:0]
|
||||||
for _, ev := range events {
|
for _, ev := range events {
|
||||||
if ev.RoomID() == roomID {
|
if ev.RoomID().String() == roomID {
|
||||||
ref = append(ref, ev)
|
ref = append(ref, ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,10 +113,10 @@ func getState(
|
||||||
return nil, nil, resErr
|
return nil, nil, resErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.RoomID() != roomID {
|
if event.RoomID().String() != roomID {
|
||||||
return nil, nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: spec.NotFound("event does not belong to this room")}
|
return nil, nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: spec.NotFound("event does not belong to this room")}
|
||||||
}
|
}
|
||||||
resErr = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID())
|
resErr = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID, event.RoomID().String())
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
return nil, nil, resErr
|
return nil, nil, resErr
|
||||||
}
|
}
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -9,7 +9,7 @@ require (
|
||||||
github.com/blevesearch/bleve/v2 v2.3.8
|
github.com/blevesearch/bleve/v2 v2.3.8
|
||||||
github.com/codeclysm/extract v2.2.0+incompatible
|
github.com/codeclysm/extract v2.2.0+incompatible
|
||||||
github.com/dgraph-io/ristretto v0.1.1
|
github.com/dgraph-io/ristretto v0.1.1
|
||||||
github.com/docker/docker v20.10.24+incompatible
|
github.com/docker/docker v24.0.5+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/getsentry/sentry-go v0.14.0
|
github.com/getsentry/sentry-go v0.14.0
|
||||||
github.com/gologme/log v1.3.0
|
github.com/gologme/log v1.3.0
|
||||||
|
@ -22,7 +22,7 @@ require (
|
||||||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
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/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230823153616-484e7693bb8d
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7
|
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
||||||
github.com/mattn/go-sqlite3 v1.14.17
|
github.com/mattn/go-sqlite3 v1.14.17
|
||||||
|
@ -36,18 +36,18 @@ require (
|
||||||
github.com/prometheus/client_golang v1.16.0
|
github.com/prometheus/client_golang v1.16.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/tidwall/gjson v1.16.0
|
github.com/tidwall/gjson v1.17.0
|
||||||
github.com/tidwall/sjson v1.2.5
|
github.com/tidwall/sjson v1.2.5
|
||||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||||
github.com/uber/jaeger-lib v2.4.1+incompatible
|
github.com/uber/jaeger-lib v2.4.1+incompatible
|
||||||
github.com/yggdrasil-network/yggdrasil-go v0.4.6
|
github.com/yggdrasil-network/yggdrasil-go v0.4.6
|
||||||
go.uber.org/atomic v1.10.0
|
go.uber.org/atomic v1.10.0
|
||||||
golang.org/x/crypto v0.12.0
|
golang.org/x/crypto v0.13.0
|
||||||
golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819
|
golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819
|
||||||
golang.org/x/image v0.5.0
|
golang.org/x/image v0.5.0
|
||||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
|
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e
|
||||||
golang.org/x/sync v0.3.0
|
golang.org/x/sync v0.3.0
|
||||||
golang.org/x/term v0.11.0
|
golang.org/x/term v0.12.0
|
||||||
gopkg.in/h2non/bimg.v1 v1.1.9
|
gopkg.in/h2non/bimg.v1 v1.1.9
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gotest.tools/v3 v3.4.0
|
gotest.tools/v3 v3.4.0
|
||||||
|
@ -124,8 +124,8 @@ require (
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/net v0.14.0 // indirect
|
golang.org/x/net v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.11.0 // indirect
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.12.0 // indirect
|
golang.org/x/tools v0.12.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
|
@ -143,4 +143,4 @@ require (
|
||||||
modernc.org/token v1.0.1 // indirect
|
modernc.org/token v1.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.18
|
go 1.20
|
||||||
|
|
28
go.sum
28
go.sum
|
@ -89,8 +89,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC
|
||||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE=
|
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
|
||||||
github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
@ -208,8 +208,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/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 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230823153616-484e7693bb8d h1:yFoT2nyjD4TFrgYMJGgrotFbTLjaYKfZbRmnsj7lvZE=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4 h1:UuXfC7b29RBDfMdLmggeF3opu3XuGi8bNT9SKZtZc3I=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230823153616-484e7693bb8d/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
||||||
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 h1:6t8kJr8i1/1I5nNttw6nn1ryQJgzVlBmSGgPiiaTdw4=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7/go.mod h1:ReWMS/LoVnOiRAdq9sNUC2NZnd1mZkMNB52QhpTRWjg=
|
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=
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||||
|
@ -318,8 +318,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
|
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
|
||||||
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
@ -354,8 +354,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -418,19 +418,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: dendrite
|
name: dendrite
|
||||||
version: "0.13.2"
|
version: "0.13.4"
|
||||||
appVersion: "0.13.2"
|
appVersion: "0.13.3"
|
||||||
description: Dendrite Matrix Homeserver
|
description: Dendrite Matrix Homeserver
|
||||||
type: application
|
type: application
|
||||||
keywords:
|
keywords:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
# dendrite
|
# dendrite
|
||||||
|
|
||||||
![Version: 0.13.2](https://img.shields.io/badge/Version-0.13.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.13.2](https://img.shields.io/badge/AppVersion-0.13.2-informational?style=flat-square)
|
![Version: 0.13.4](https://img.shields.io/badge/Version-0.13.4-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.13.3](https://img.shields.io/badge/AppVersion-0.13.3-informational?style=flat-square)
|
||||||
Dendrite Matrix Homeserver
|
Dendrite Matrix Homeserver
|
||||||
|
|
||||||
Status: **NOT PRODUCTION READY**
|
Status: **NOT PRODUCTION READY**
|
||||||
|
@ -63,9 +63,6 @@ Create a folder `appservices` and place your configurations in there. The confi
|
||||||
| strategy.type | string | `"RollingUpdate"` | Strategy to use for rolling updates (e.g. Recreate, RollingUpdate) If you are using ReadWriteOnce volumes, you should probably use Recreate |
|
| strategy.type | string | `"RollingUpdate"` | Strategy to use for rolling updates (e.g. Recreate, RollingUpdate) If you are using ReadWriteOnce volumes, you should probably use Recreate |
|
||||||
| strategy.rollingUpdate.maxUnavailable | string | `"25%"` | Maximum number of pods that can be unavailable during the update process |
|
| strategy.rollingUpdate.maxUnavailable | string | `"25%"` | Maximum number of pods that can be unavailable during the update process |
|
||||||
| strategy.rollingUpdate.maxSurge | string | `"25%"` | Maximum number of pods that can be scheduled above the desired number of pods |
|
| strategy.rollingUpdate.maxSurge | string | `"25%"` | Maximum number of pods that can be scheduled above the desired number of pods |
|
||||||
| strategy.type | string | `"RollingUpdate"` | Strategy to use for rolling updates (e.g. Recreate, RollingUpdate) If you are using ReadWriteOnce volumes, you should probably use Recreate |
|
|
||||||
| strategy.rollingUpdate.maxUnavailable | string | `"25%"` | Maximum number of pods that can be unavailable during the update process |
|
|
||||||
| strategy.rollingUpdate.maxSurge | string | `"25%"` | Maximum number of pods that can be scheduled above the desired number of pods |
|
|
||||||
| dendrite_config.version | int | `2` | |
|
| dendrite_config.version | int | `2` | |
|
||||||
| dendrite_config.global.server_name | string | `""` | **REQUIRED** Servername for this Dendrite deployment. |
|
| dendrite_config.global.server_name | string | `""` | **REQUIRED** Servername for this Dendrite deployment. |
|
||||||
| dendrite_config.global.private_key | string | `"/etc/dendrite/secrets/signing.key"` | The private key to use. (**NOTE**: This is overriden in Helm) |
|
| dendrite_config.global.private_key | string | `"/etc/dendrite/secrets/signing.key"` | The private key to use. (**NOTE**: This is overriden in Helm) |
|
||||||
|
|
|
@ -26,13 +26,6 @@ spec:
|
||||||
annotations:
|
annotations:
|
||||||
confighash: secret-{{ .Values.dendrite_config | toYaml | sha256sum | trunc 32 }}
|
confighash: secret-{{ .Values.dendrite_config | toYaml | sha256sum | trunc 32 }}
|
||||||
spec:
|
spec:
|
||||||
strategy:
|
|
||||||
type: {{ $.Values.strategy.type }}
|
|
||||||
{{- if eq $.Values.strategy.type "RollingUpdate" }}
|
|
||||||
rollingUpdate:
|
|
||||||
maxSurge: {{ $.Values.strategy.rollingUpdate.maxSurge }}
|
|
||||||
maxUnavailable: {{ $.Values.strategy.rollingUpdate.maxUnavailable }}
|
|
||||||
{{- end }}
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: {{ include "dendrite.fullname" . }}-conf-vol
|
- name: {{ include "dendrite.fullname" . }}-conf-vol
|
||||||
secret:
|
secret:
|
||||||
|
@ -116,4 +109,4 @@ spec:
|
||||||
failureThreshold: 10
|
failureThreshold: 10
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /_dendrite/monitor/up
|
path: /_dendrite/monitor/up
|
||||||
port: http
|
port: http
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{{- if .Values.ingress.enabled -}}
|
{{- if .Values.ingress.enabled -}}
|
||||||
{{- $fullName := include "dendrite.fullname" . -}}
|
{{- $fullName := include "dendrite.fullname" . -}}
|
||||||
{{- $serverNameHost := .Values.dendrite_config.global.server_name -}}
|
{{- $serverNameHost := .Values.dendrite_config.global.server_name -}}
|
||||||
{{- $wellKnownServerHost := default $serverNameHost (regexFind "^[^:]+" .Values.dendrite_config.global.well_known_server_name) -}}
|
{{- $wellKnownServerHost := default $serverNameHost (regexFind "^(\\[.+\\])?[^:]*" .Values.dendrite_config.global.well_known_server_name) -}}
|
||||||
{{- $wellKnownClientHost := default $serverNameHost (regexFind "^[^:]+" .Values.dendrite_config.global.well_known_client_name) -}}
|
{{- $wellKnownClientHost := default $serverNameHost (regexFind "//(\\[.+\\])?[^:/]*" .Values.dendrite_config.global.well_known_client_name | trimAll "/") -}}
|
||||||
{{- $allHosts := list $serverNameHost $wellKnownServerHost $wellKnownClientHost | uniq -}}
|
{{- $allHosts := list $serverNameHost $wellKnownServerHost $wellKnownClientHost | uniq -}}
|
||||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
|
|
|
@ -65,16 +65,6 @@ extraVolumeMounts: []
|
||||||
# - mountPath: /etc/dendrite/extra-config
|
# - mountPath: /etc/dendrite/extra-config
|
||||||
# name: extra-config
|
# name: extra-config
|
||||||
|
|
||||||
strategy:
|
|
||||||
# -- Strategy to use for rolling updates (e.g. Recreate, RollingUpdate)
|
|
||||||
# If you are using ReadWriteOnce volumes, you should probably use Recreate
|
|
||||||
type: RollingUpdate
|
|
||||||
rollingUpdate:
|
|
||||||
# -- Maximum number of pods that can be unavailable during the update process
|
|
||||||
maxUnavailable: 25%
|
|
||||||
# -- Maximum number of pods that can be scheduled above the desired number of pods
|
|
||||||
maxSurge: 25%
|
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
# -- Strategy to use for rolling updates (e.g. Recreate, RollingUpdate)
|
# -- Strategy to use for rolling updates (e.g. Recreate, RollingUpdate)
|
||||||
# If you are using ReadWriteOnce volumes, you should probably use Recreate
|
# If you are using ReadWriteOnce volumes, you should probably use Recreate
|
||||||
|
|
|
@ -176,15 +176,13 @@ func RedactEvent(ctx context.Context, redactionEvent, redactedEvent gomatrixserv
|
||||||
return fmt.Errorf("RedactEvent: redactionEvent isn't a redaction event, is '%s'", redactionEvent.Type())
|
return fmt.Errorf("RedactEvent: redactionEvent isn't a redaction event, is '%s'", redactionEvent.Type())
|
||||||
}
|
}
|
||||||
redactedEvent.Redact()
|
redactedEvent.Redact()
|
||||||
validRoomID, err := spec.NewRoomID(redactionEvent.RoomID())
|
clientEvent, err := synctypes.ToClientEvent(redactionEvent, synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return querier.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
senderID, err := querier.QueryUserIDForSender(ctx, *validRoomID, redactionEvent.SenderID())
|
redactedBecause := clientEvent
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
redactedBecause := synctypes.ToClientEvent(redactionEvent, synctypes.FormatSync, *senderID, redactionEvent.StateKey())
|
|
||||||
if err := redactedEvent.SetUnsignedField("redacted_because", redactedBecause); err != nil {
|
if err := redactedEvent.SetUnsignedField("redacted_because", redactedBecause); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,15 +111,11 @@ func ruleMatches(rule *Rule, kind Kind, event gomatrixserverlib.PDU, ec Evaluati
|
||||||
return patternMatches("content.body", *rule.Pattern, event)
|
return patternMatches("content.body", *rule.Pattern, event)
|
||||||
|
|
||||||
case RoomKind:
|
case RoomKind:
|
||||||
return rule.RuleID == event.RoomID(), nil
|
return rule.RuleID == event.RoomID().String(), nil
|
||||||
|
|
||||||
case SenderKind:
|
case SenderKind:
|
||||||
userID := ""
|
userID := ""
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
sender, err := userIDForSender(event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
sender, err := userIDForSender(*validRoomID, event.SenderID())
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
userID = sender.String()
|
userID = sender.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ func UserIDForSender(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRuleSetEvaluatorMatchEvent(t *testing.T) {
|
func TestRuleSetEvaluatorMatchEvent(t *testing.T) {
|
||||||
ev := mustEventFromJSON(t, `{}`)
|
ev := mustEventFromJSON(t, `{"room_id":"!room:a"}`)
|
||||||
defaultEnabled := &Rule{
|
defaultEnabled := &Rule{
|
||||||
RuleID: ".default.enabled",
|
RuleID: ".default.enabled",
|
||||||
Default: true,
|
Default: true,
|
||||||
|
@ -44,8 +44,8 @@ func TestRuleSetEvaluatorMatchEvent(t *testing.T) {
|
||||||
{"overrideRoom", RuleSet{Override: []*Rule{userEnabled}, Room: []*Rule{userEnabled2}}, userEnabled, ev},
|
{"overrideRoom", RuleSet{Override: []*Rule{userEnabled}, Room: []*Rule{userEnabled2}}, userEnabled, ev},
|
||||||
{"overrideSender", RuleSet{Override: []*Rule{userEnabled}, Sender: []*Rule{userEnabled2}}, userEnabled, ev},
|
{"overrideSender", RuleSet{Override: []*Rule{userEnabled}, Sender: []*Rule{userEnabled2}}, userEnabled, ev},
|
||||||
{"overrideUnderride", RuleSet{Override: []*Rule{userEnabled}, Underride: []*Rule{userEnabled2}}, userEnabled, ev},
|
{"overrideUnderride", RuleSet{Override: []*Rule{userEnabled}, Underride: []*Rule{userEnabled2}}, userEnabled, ev},
|
||||||
{"reactions don't notify", *defaultRuleset, &mRuleReactionDefinition, mustEventFromJSON(t, `{"type":"m.reaction"}`)},
|
{"reactions don't notify", *defaultRuleset, &mRuleReactionDefinition, mustEventFromJSON(t, `{"room_id":"!room:a","type":"m.reaction"}`)},
|
||||||
{"receipts don't notify", *defaultRuleset, nil, mustEventFromJSON(t, `{"type":"m.receipt"}`)},
|
{"receipts don't notify", *defaultRuleset, nil, mustEventFromJSON(t, `{"room_id":"!room:a","type":"m.receipt"}`)},
|
||||||
}
|
}
|
||||||
for _, tst := range tsts {
|
for _, tst := range tsts {
|
||||||
t.Run(tst.Name, func(t *testing.T) {
|
t.Run(tst.Name, func(t *testing.T) {
|
||||||
|
@ -70,28 +70,27 @@ func TestRuleMatches(t *testing.T) {
|
||||||
EventJSON string
|
EventJSON string
|
||||||
Want bool
|
Want bool
|
||||||
}{
|
}{
|
||||||
{"emptyOverride", OverrideKind, emptyRule, `{}`, true},
|
{"emptyOverride", OverrideKind, emptyRule, `{"room_id":"!room:example.com"}`, true},
|
||||||
{"emptyContent", ContentKind, emptyRule, `{}`, false},
|
{"emptyContent", ContentKind, emptyRule, `{"room_id":"!room:example.com"}`, false},
|
||||||
{"emptyRoom", RoomKind, emptyRule, `{}`, true},
|
|
||||||
{"emptySender", SenderKind, emptyRule, `{"room_id":"!room:example.com"}`, true},
|
{"emptySender", SenderKind, emptyRule, `{"room_id":"!room:example.com"}`, true},
|
||||||
{"emptyUnderride", UnderrideKind, emptyRule, `{}`, true},
|
{"emptyUnderride", UnderrideKind, emptyRule, `{"room_id":"!room:example.com"}`, true},
|
||||||
|
|
||||||
{"disabled", OverrideKind, Rule{}, `{}`, false},
|
{"disabled", OverrideKind, Rule{}, `{"room_id":"!room:example.com"}`, false},
|
||||||
|
|
||||||
{"overrideConditionMatch", OverrideKind, Rule{Enabled: true}, `{}`, true},
|
{"overrideConditionMatch", OverrideKind, Rule{Enabled: true}, `{"room_id":"!room:example.com"}`, true},
|
||||||
{"overrideConditionNoMatch", OverrideKind, Rule{Enabled: true, Conditions: []*Condition{{}}}, `{}`, false},
|
{"overrideConditionNoMatch", OverrideKind, Rule{Enabled: true, Conditions: []*Condition{{}}}, `{"room_id":"!room:example.com"}`, false},
|
||||||
|
|
||||||
{"underrideConditionMatch", UnderrideKind, Rule{Enabled: true}, `{}`, true},
|
{"underrideConditionMatch", UnderrideKind, Rule{Enabled: true}, `{"room_id":"!room:example.com"}`, true},
|
||||||
{"underrideConditionNoMatch", UnderrideKind, Rule{Enabled: true, Conditions: []*Condition{{}}}, `{}`, false},
|
{"underrideConditionNoMatch", UnderrideKind, Rule{Enabled: true, Conditions: []*Condition{{}}}, `{"room_id":"!room:example.com"}`, false},
|
||||||
|
|
||||||
{"contentMatch", ContentKind, Rule{Enabled: true, Pattern: pointer("b")}, `{"content":{"body":"abc"}}`, true},
|
{"contentMatch", ContentKind, Rule{Enabled: true, Pattern: pointer("b")}, `{"room_id":"!room:example.com","content":{"body":"abc"}}`, true},
|
||||||
{"contentNoMatch", ContentKind, Rule{Enabled: true, Pattern: pointer("d")}, `{"content":{"body":"abc"}}`, false},
|
{"contentNoMatch", ContentKind, Rule{Enabled: true, Pattern: pointer("d")}, `{"room_id":"!room:example.com","content":{"body":"abc"}}`, false},
|
||||||
|
|
||||||
{"roomMatch", RoomKind, Rule{Enabled: true, RuleID: "!room:example.com"}, `{"room_id":"!room:example.com"}`, true},
|
{"roomMatch", RoomKind, Rule{Enabled: true, RuleID: "!room:example.com"}, `{"room_id":"!room:example.com"}`, true},
|
||||||
{"roomNoMatch", RoomKind, Rule{Enabled: true, RuleID: "!room:example.com"}, `{"room_id":"!otherroom:example.com"}`, false},
|
{"roomNoMatch", RoomKind, Rule{Enabled: true, RuleID: "!room:example.com"}, `{"room_id":"!otherroom:example.com"}`, false},
|
||||||
|
|
||||||
{"senderMatch", SenderKind, Rule{Enabled: true, RuleID: "@user:example.com"}, `{"sender":"@user:example.com","room_id":"!room:example.com"}`, true},
|
{"senderMatch", SenderKind, Rule{Enabled: true, RuleID: "@user:example.com"}, `{"room_id":"!room:example.com","sender":"@user:example.com","room_id":"!room:example.com"}`, true},
|
||||||
{"senderNoMatch", SenderKind, Rule{Enabled: true, RuleID: "@user:example.com"}, `{"sender":"@otheruser:example.com","room_id":"!room:example.com"}`, false},
|
{"senderNoMatch", SenderKind, Rule{Enabled: true, RuleID: "@user:example.com"}, `{"room_id":"!room:example.com","sender":"@otheruser:example.com","room_id":"!room:example.com"}`, false},
|
||||||
}
|
}
|
||||||
for _, tst := range tsts {
|
for _, tst := range tsts {
|
||||||
t.Run(tst.Name, func(t *testing.T) {
|
t.Run(tst.Name, func(t *testing.T) {
|
||||||
|
@ -114,32 +113,32 @@ func TestConditionMatches(t *testing.T) {
|
||||||
WantMatch bool
|
WantMatch bool
|
||||||
WantErr bool
|
WantErr bool
|
||||||
}{
|
}{
|
||||||
{Name: "empty", Cond: Condition{}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "empty", Cond: Condition{}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "empty", Cond: Condition{Kind: "unknownstring"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "empty", Cond: Condition{Kind: "unknownstring"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
|
|
||||||
// Neither of these should match because `content` is not a full string match,
|
// Neither of these should match because `content` is not a full string match,
|
||||||
// and `content.body` is not a string value.
|
// and `content.body` is not a string value.
|
||||||
{Name: "eventMatch", Cond: Condition{Kind: EventMatchCondition, Key: "content", Pattern: pointer("")}, EventJSON: `{"content":{}}`, WantMatch: false, WantErr: false},
|
{Name: "eventMatch", Cond: Condition{Kind: EventMatchCondition, Key: "content", Pattern: pointer("")}, EventJSON: `{"room_id":"!room:example.com","content":{}}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "eventBodyMatch", Cond: Condition{Kind: EventMatchCondition, Key: "content.body", Is: "3", Pattern: pointer("")}, EventJSON: `{"content":{"body": "3"}}`, WantMatch: false, WantErr: false},
|
{Name: "eventBodyMatch", Cond: Condition{Kind: EventMatchCondition, Key: "content.body", Is: "3", Pattern: pointer("")}, EventJSON: `{"room_id":"!room:example.com","content":{"body": "3"}}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "eventBodyMatch matches", Cond: Condition{Kind: EventMatchCondition, Key: "content.body", Pattern: pointer("world")}, EventJSON: `{"content":{"body": "hello world!"}}`, WantMatch: true, WantErr: false},
|
{Name: "eventBodyMatch matches", Cond: Condition{Kind: EventMatchCondition, Key: "content.body", Pattern: pointer("world")}, EventJSON: `{"room_id":"!room:example.com","content":{"body": "hello world!"}}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "EventMatch missing pattern", Cond: Condition{Kind: EventMatchCondition, Key: "content.body"}, EventJSON: `{"content":{"body": "hello world!"}}`, WantMatch: false, WantErr: true},
|
{Name: "EventMatch missing pattern", Cond: Condition{Kind: EventMatchCondition, Key: "content.body"}, EventJSON: `{"room_id":"!room:example.com","content":{"body": "hello world!"}}`, WantMatch: false, WantErr: true},
|
||||||
|
|
||||||
{Name: "displayNameNoMatch", Cond: Condition{Kind: ContainsDisplayNameCondition}, EventJSON: `{"content":{"body":"something without displayname"}}`, WantMatch: false, WantErr: false},
|
{Name: "displayNameNoMatch", Cond: Condition{Kind: ContainsDisplayNameCondition}, EventJSON: `{"room_id":"!room:example.com","content":{"body":"something without displayname"}}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "displayNameMatch", Cond: Condition{Kind: ContainsDisplayNameCondition}, EventJSON: `{"content":{"body":"hello Dear User, how are you?"}}`, WantMatch: true, WantErr: false},
|
{Name: "displayNameMatch", Cond: Condition{Kind: ContainsDisplayNameCondition}, EventJSON: `{"room_id":"!room:example.com","content":{"body":"hello Dear User, how are you?"}}`, WantMatch: true, WantErr: false},
|
||||||
|
|
||||||
{Name: "roomMemberCountLessNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<2"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "roomMemberCountLessNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<2"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "roomMemberCountLessMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<3"}, EventJSON: `{}`, WantMatch: true, WantErr: false},
|
{Name: "roomMemberCountLessMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<3"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "roomMemberCountLessEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<=1"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "roomMemberCountLessEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<=1"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "roomMemberCountLessEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<=2"}, EventJSON: `{}`, WantMatch: true, WantErr: false},
|
{Name: "roomMemberCountLessEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "<=2"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "roomMemberCountEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "==1"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "roomMemberCountEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "==1"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "roomMemberCountEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "==2"}, EventJSON: `{}`, WantMatch: true, WantErr: false},
|
{Name: "roomMemberCountEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: "==2"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "roomMemberCountGreaterEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">=3"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "roomMemberCountGreaterEqualNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">=3"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "roomMemberCountGreaterEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">=2"}, EventJSON: `{}`, WantMatch: true, WantErr: false},
|
{Name: "roomMemberCountGreaterEqualMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">=2"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "roomMemberCountGreaterNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">2"}, EventJSON: `{}`, WantMatch: false, WantErr: false},
|
{Name: "roomMemberCountGreaterNoMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">2"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
{Name: "roomMemberCountGreaterMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">1"}, EventJSON: `{}`, WantMatch: true, WantErr: false},
|
{Name: "roomMemberCountGreaterMatch", Cond: Condition{Kind: RoomMemberCountCondition, Is: ">1"}, EventJSON: `{"room_id":"!room:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
|
|
||||||
{Name: "senderNotificationPermissionMatch", Cond: Condition{Kind: SenderNotificationPermissionCondition, Key: "powerlevel"}, EventJSON: `{"sender":"@poweruser:example.com"}`, WantMatch: true, WantErr: false},
|
{Name: "senderNotificationPermissionMatch", Cond: Condition{Kind: SenderNotificationPermissionCondition, Key: "powerlevel"}, EventJSON: `{"room_id":"!room:example.com","sender":"@poweruser:example.com"}`, WantMatch: true, WantErr: false},
|
||||||
{Name: "senderNotificationPermissionNoMatch", Cond: Condition{Kind: SenderNotificationPermissionCondition, Key: "powerlevel"}, EventJSON: `{"sender":"@nobody:example.com"}`, WantMatch: false, WantErr: false},
|
{Name: "senderNotificationPermissionNoMatch", Cond: Condition{Kind: SenderNotificationPermissionCondition, Key: "powerlevel"}, EventJSON: `{"room_id":"!room:example.com","sender":"@nobody:example.com"}`, WantMatch: false, WantErr: false},
|
||||||
}
|
}
|
||||||
for _, tst := range tsts {
|
for _, tst := range tsts {
|
||||||
t.Run(tst.Name, func(t *testing.T) {
|
t.Run(tst.Name, func(t *testing.T) {
|
||||||
|
@ -170,15 +169,15 @@ func TestPatternMatches(t *testing.T) {
|
||||||
EventJSON string
|
EventJSON string
|
||||||
Want bool
|
Want bool
|
||||||
}{
|
}{
|
||||||
{"empty", "", "", `{}`, false},
|
{"empty", "", "", `{"room_id":"!room:a"}`, false},
|
||||||
|
|
||||||
{"patternEmpty", "content", "", `{"content":{}}`, false},
|
{"patternEmpty", "content", "", `{"room_id":"!room:a","content":{}}`, false},
|
||||||
|
|
||||||
{"literal", "content.creator", "acreator", `{"content":{"creator":"acreator"}}`, true},
|
{"literal", "content.creator", "acreator", `{"room_id":"!room:a","content":{"creator":"acreator"}}`, true},
|
||||||
{"substring", "content.creator", "reat", `{"content":{"creator":"acreator"}}`, true},
|
{"substring", "content.creator", "reat", `{"room_id":"!room:a","content":{"creator":"acreator"}}`, true},
|
||||||
{"singlePattern", "content.creator", "acr?ator", `{"content":{"creator":"acreator"}}`, true},
|
{"singlePattern", "content.creator", "acr?ator", `{"room_id":"!room:a","content":{"creator":"acreator"}}`, true},
|
||||||
{"multiPattern", "content.creator", "a*ea*r", `{"content":{"creator":"acreator"}}`, true},
|
{"multiPattern", "content.creator", "a*ea*r", `{"room_id":"!room:a","content":{"creator":"acreator"}}`, true},
|
||||||
{"patternNoSubstring", "content.creator", "r*t", `{"content":{"creator":"acreator"}}`, false},
|
{"patternNoSubstring", "content.creator", "r*t", `{"room_id":"!room:a","content":{"creator":"acreator"}}`, false},
|
||||||
}
|
}
|
||||||
for _, tst := range tsts {
|
for _, tst := range tsts {
|
||||||
t.Run(tst.Name, func(t *testing.T) {
|
t.Run(tst.Name, func(t *testing.T) {
|
||||||
|
|
|
@ -161,7 +161,7 @@ func (t *TxnReq) ProcessTransaction(ctx context.Context) (*fclient.RespSend, *ut
|
||||||
if event.Type() == spec.MRoomCreate && event.StateKeyEquals("") {
|
if event.Type() == spec.MRoomCreate && event.StateKeyEquals("") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if api.IsServerBannedFromRoom(ctx, t.rsAPI, event.RoomID(), t.Origin) {
|
if api.IsServerBannedFromRoom(ctx, t.rsAPI, event.RoomID().String(), t.Origin) {
|
||||||
results[event.EventID()] = fclient.PDUResult{
|
results[event.EventID()] = fclient.PDUResult{
|
||||||
Error: "Forbidden by server ACLs",
|
Error: "Forbidden by server ACLs",
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ var build string
|
||||||
const (
|
const (
|
||||||
VersionMajor = 0
|
VersionMajor = 0
|
||||||
VersionMinor = 13
|
VersionMinor = 13
|
||||||
VersionPatch = 2
|
VersionPatch = 3
|
||||||
VersionTag = "" // example: "rc1"
|
VersionTag = "" // example: "rc1"
|
||||||
|
|
||||||
gitRevLen = 7 // 7 matches the displayed characters on github.com
|
gitRevLen = 7 // 7 matches the displayed characters on github.com
|
||||||
|
|
|
@ -119,7 +119,7 @@ func (s *ServerACLs) OnServerACLUpdate(state gomatrixserverlib.PDU) {
|
||||||
}).Debugf("Updating server ACLs for %q", state.RoomID())
|
}).Debugf("Updating server ACLs for %q", state.RoomID())
|
||||||
s.aclsMutex.Lock()
|
s.aclsMutex.Lock()
|
||||||
defer s.aclsMutex.Unlock()
|
defer s.aclsMutex.Unlock()
|
||||||
s.acls[state.RoomID()] = acls
|
s.acls[state.RoomID().String()] = acls
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerACLs) IsServerBannedFromRoom(serverName spec.ServerName, roomID string) bool {
|
func (s *ServerACLs) IsServerBannedFromRoom(serverName spec.ServerName, roomID string) bool {
|
||||||
|
|
|
@ -75,7 +75,7 @@ func SendEventWithState(
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
logrus.WithContext(ctx).WithFields(logrus.Fields{
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"outliers": len(ires),
|
"outliers": len(ires),
|
||||||
"state_ids": len(stateEventIDs),
|
"state_ids": len(stateEventIDs),
|
||||||
|
|
|
@ -85,11 +85,7 @@ func IsAnyUserOnServerWithMembership(ctx context.Context, querier api.QuerySende
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
userID, err := querier.QueryUserIDForSender(ctx, ev.RoomID(), spec.SenderID(*stateKey))
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
userID, err := querier.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*stateKey))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(ctx context.Context, senderID sp
|
||||||
|
|
||||||
proto := &gomatrixserverlib.ProtoEvent{
|
proto := &gomatrixserverlib.ProtoEvent{
|
||||||
SenderID: string(canonicalSenderID),
|
SenderID: string(canonicalSenderID),
|
||||||
RoomID: ev.RoomID(),
|
RoomID: ev.RoomID().String(),
|
||||||
Type: ev.Type(),
|
Type: ev.Type(),
|
||||||
StateKey: ev.StateKey(),
|
StateKey: ev.StateKey(),
|
||||||
Content: res,
|
Content: res,
|
||||||
|
|
|
@ -239,7 +239,7 @@ func (r *RoomserverInternalAPI) HandleInvite(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return r.OutputProducer.ProduceRoomEvents(inviteEvent.RoomID(), outputEvents)
|
return r.OutputProducer.ProduceRoomEvents(inviteEvent.RoomID().String(), outputEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RoomserverInternalAPI) PerformCreateRoom(
|
func (r *RoomserverInternalAPI) PerformCreateRoom(
|
||||||
|
|
|
@ -218,9 +218,9 @@ func loadAuthEvents(
|
||||||
roomID := ""
|
roomID := ""
|
||||||
for _, ev := range result.events {
|
for _, ev := range result.events {
|
||||||
if roomID == "" {
|
if roomID == "" {
|
||||||
roomID = ev.RoomID()
|
roomID = ev.RoomID().String()
|
||||||
}
|
}
|
||||||
if ev.RoomID() != roomID {
|
if ev.RoomID().String() != roomID {
|
||||||
result.valid = false
|
result.valid = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func UpdateToInviteMembership(
|
||||||
Type: api.OutputTypeRetireInviteEvent,
|
Type: api.OutputTypeRetireInviteEvent,
|
||||||
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
||||||
EventID: eventID,
|
EventID: eventID,
|
||||||
RoomID: add.RoomID(),
|
RoomID: add.RoomID().String(),
|
||||||
Membership: spec.Join,
|
Membership: spec.Join,
|
||||||
RetiredByEventID: add.EventID(),
|
RetiredByEventID: add.EventID(),
|
||||||
TargetSenderID: spec.SenderID(*add.StateKey()),
|
TargetSenderID: spec.SenderID(*add.StateKey()),
|
||||||
|
@ -396,7 +396,7 @@ BFSLoop:
|
||||||
// It's nasty that we have to extract the room ID from an event, but many federation requests
|
// It's nasty that we have to extract the room ID from an event, but many federation requests
|
||||||
// only talk in event IDs, no room IDs at all (!!!)
|
// only talk in event IDs, no room IDs at all (!!!)
|
||||||
ev := events[0]
|
ev := events[0]
|
||||||
isServerInRoom, err = IsServerCurrentlyInRoom(ctx, db, querier, serverName, ev.RoomID())
|
isServerInRoom, err = IsServerCurrentlyInRoom(ctx, db, querier, serverName, ev.RoomID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).WithError(err).Error("Failed to check if server is currently in room, assuming not.")
|
util.GetLogger(ctx).WithError(err).Error("Failed to check if server is currently in room, assuming not.")
|
||||||
}
|
}
|
||||||
|
@ -419,7 +419,7 @@ BFSLoop:
|
||||||
// hasn't been seen before.
|
// hasn't been seen before.
|
||||||
if !visited[pre] {
|
if !visited[pre] {
|
||||||
visited[pre] = true
|
visited[pre] = true
|
||||||
allowed, err = CheckServerAllowedToSeeEvent(ctx, db, info, ev.RoomID(), pre, serverName, isServerInRoom, querier)
|
allowed, err = CheckServerAllowedToSeeEvent(ctx, db, info, ev.RoomID().String(), pre, serverName, isServerInRoom, querier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).WithError(err).Error(
|
util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).WithError(err).Error(
|
||||||
"Error checking if allowed to see event",
|
"Error checking if allowed to see event",
|
||||||
|
|
|
@ -358,7 +358,7 @@ func (r *Inputer) queueInputRoomEvents(
|
||||||
// For each event, marshal the input room event and then
|
// For each event, marshal the input room event and then
|
||||||
// send it into the input queue.
|
// send it into the input queue.
|
||||||
for _, e := range request.InputRoomEvents {
|
for _, e := range request.InputRoomEvents {
|
||||||
roomID := e.Event.RoomID()
|
roomID := e.Event.RoomID().String()
|
||||||
subj := r.Cfg.Matrix.JetStream.Prefixed(jetstream.InputRoomEventSubj(roomID))
|
subj := r.Cfg.Matrix.JetStream.Prefixed(jetstream.InputRoomEventSubj(roomID))
|
||||||
msg := &nats.Msg{
|
msg := &nats.Msg{
|
||||||
Subject: subj,
|
Subject: subj,
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
trace, ctx := internal.StartRegion(ctx, "processRoomEvent")
|
trace, ctx := internal.StartRegion(ctx, "processRoomEvent")
|
||||||
trace.SetTag("room_id", input.Event.RoomID())
|
trace.SetTag("room_id", input.Event.RoomID().String())
|
||||||
trace.SetTag("event_id", input.Event.EventID())
|
trace.SetTag("event_id", input.Event.EventID())
|
||||||
defer trace.EndRegion()
|
defer trace.EndRegion()
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
defer func() {
|
defer func() {
|
||||||
timetaken := time.Since(started)
|
timetaken := time.Since(started)
|
||||||
processRoomEventDuration.With(prometheus.Labels{
|
processRoomEventDuration.With(prometheus.Labels{
|
||||||
"room_id": input.Event.RoomID(),
|
"room_id": input.Event.RoomID().String(),
|
||||||
}).Observe(float64(timetaken.Milliseconds()))
|
}).Observe(float64(timetaken.Milliseconds()))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
event := headered.PDU
|
event := headered.PDU
|
||||||
logger := util.GetLogger(ctx).WithFields(logrus.Fields{
|
logger := util.GetLogger(ctx).WithFields(logrus.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"kind": input.Kind,
|
"kind": input.Kind,
|
||||||
"origin": input.Origin,
|
"origin": input.Origin,
|
||||||
"type": event.Type(),
|
"type": event.Type(),
|
||||||
|
@ -120,19 +120,15 @@ func (r *Inputer) processRoomEvent(
|
||||||
// Don't waste time processing the event if the room doesn't exist.
|
// Don't waste time processing the event if the room doesn't exist.
|
||||||
// A room entry locally will only be created in response to a create
|
// A room entry locally will only be created in response to a create
|
||||||
// event.
|
// event.
|
||||||
roomInfo, rerr := r.DB.RoomInfo(ctx, event.RoomID())
|
roomInfo, rerr := r.DB.RoomInfo(ctx, event.RoomID().String())
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
return fmt.Errorf("r.DB.RoomInfo: %w", rerr)
|
return fmt.Errorf("r.DB.RoomInfo: %w", rerr)
|
||||||
}
|
}
|
||||||
isCreateEvent := event.Type() == spec.MRoomCreate && event.StateKeyEquals("")
|
isCreateEvent := event.Type() == spec.MRoomCreate && event.StateKeyEquals("")
|
||||||
if roomInfo == nil && !isCreateEvent {
|
if roomInfo == nil && !isCreateEvent {
|
||||||
return fmt.Errorf("room %s does not exist for event %s", event.RoomID(), event.EventID())
|
return fmt.Errorf("room %s does not exist for event %s", event.RoomID().String(), event.EventID())
|
||||||
}
|
}
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
sender, err := r.Queryer.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sender, err := r.Queryer.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed getting userID for sender %q. %w", event.SenderID(), err)
|
return fmt.Errorf("failed getting userID for sender %q. %w", event.SenderID(), err)
|
||||||
}
|
}
|
||||||
|
@ -179,7 +175,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
// If we have missing events (auth or prev), we build a list of servers to ask
|
// If we have missing events (auth or prev), we build a list of servers to ask
|
||||||
if missingAuth || missingPrev {
|
if missingAuth || missingPrev {
|
||||||
serverReq := &fedapi.QueryJoinedHostServerNamesInRoomRequest{
|
serverReq := &fedapi.QueryJoinedHostServerNamesInRoomRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
ExcludeSelf: true,
|
ExcludeSelf: true,
|
||||||
ExcludeBlacklisted: true,
|
ExcludeBlacklisted: true,
|
||||||
}
|
}
|
||||||
|
@ -395,12 +391,12 @@ func (r *Inputer) processRoomEvent(
|
||||||
|
|
||||||
// Request the room info again — it's possible that the room has been
|
// Request the room info again — it's possible that the room has been
|
||||||
// created by now if it didn't exist already.
|
// created by now if it didn't exist already.
|
||||||
roomInfo, err = r.DB.RoomInfo(ctx, event.RoomID())
|
roomInfo, err = r.DB.RoomInfo(ctx, event.RoomID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("updater.RoomInfo: %w", err)
|
return fmt.Errorf("updater.RoomInfo: %w", err)
|
||||||
}
|
}
|
||||||
if roomInfo == nil {
|
if roomInfo == nil {
|
||||||
return fmt.Errorf("updater.RoomInfo missing for room %s", event.RoomID())
|
return fmt.Errorf("updater.RoomInfo missing for room %s", event.RoomID().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.HasState || (!missingPrev && stateAtEvent.BeforeStateSnapshotNID == 0) {
|
if input.HasState || (!missingPrev && stateAtEvent.BeforeStateSnapshotNID == 0) {
|
||||||
|
@ -459,7 +455,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
if userErr != nil {
|
if userErr != nil {
|
||||||
return userErr
|
return userErr
|
||||||
}
|
}
|
||||||
err = r.RSAPI.StoreUserRoomPublicKey(ctx, mapping.MXIDMapping.UserRoomKey, *storeUserID, *validRoomID)
|
err = r.RSAPI.StoreUserRoomPublicKey(ctx, mapping.MXIDMapping.UserRoomKey, *storeUserID, event.RoomID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed storing user room public key: %w", err)
|
return fmt.Errorf("failed storing user room public key: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -481,7 +477,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
return fmt.Errorf("r.updateLatestEvents: %w", err)
|
return fmt.Errorf("r.updateLatestEvents: %w", err)
|
||||||
}
|
}
|
||||||
case api.KindOld:
|
case api.KindOld:
|
||||||
err = r.OutputProducer.ProduceRoomEvents(event.RoomID(), []api.OutputEvent{
|
err = r.OutputProducer.ProduceRoomEvents(event.RoomID().String(), []api.OutputEvent{
|
||||||
{
|
{
|
||||||
Type: api.OutputTypeOldRoomEvent,
|
Type: api.OutputTypeOldRoomEvent,
|
||||||
OldRoomEvent: &api.OutputOldRoomEvent{
|
OldRoomEvent: &api.OutputOldRoomEvent{
|
||||||
|
@ -507,7 +503,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
// so notify downstream components to redact this event - they should have it if they've
|
// so notify downstream components to redact this event - they should have it if they've
|
||||||
// been tracking our output log.
|
// been tracking our output log.
|
||||||
if redactedEventID != "" {
|
if redactedEventID != "" {
|
||||||
err = r.OutputProducer.ProduceRoomEvents(event.RoomID(), []api.OutputEvent{
|
err = r.OutputProducer.ProduceRoomEvents(event.RoomID().String(), []api.OutputEvent{
|
||||||
{
|
{
|
||||||
Type: api.OutputTypeRedactedEvent,
|
Type: api.OutputTypeRedactedEvent,
|
||||||
RedactedEvent: &api.OutputRedactedEvent{
|
RedactedEvent: &api.OutputRedactedEvent{
|
||||||
|
@ -536,7 +532,7 @@ func (r *Inputer) processRoomEvent(
|
||||||
|
|
||||||
// handleRemoteRoomUpgrade updates published rooms and room aliases
|
// handleRemoteRoomUpgrade updates published rooms and room aliases
|
||||||
func (r *Inputer) handleRemoteRoomUpgrade(ctx context.Context, event gomatrixserverlib.PDU) error {
|
func (r *Inputer) handleRemoteRoomUpgrade(ctx context.Context, event gomatrixserverlib.PDU) error {
|
||||||
oldRoomID := event.RoomID()
|
oldRoomID := event.RoomID().String()
|
||||||
newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str
|
newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str
|
||||||
return r.DB.UpgradeRoom(ctx, oldRoomID, newRoomID, string(event.SenderID()))
|
return r.DB.UpgradeRoom(ctx, oldRoomID, newRoomID, string(event.SenderID()))
|
||||||
}
|
}
|
||||||
|
@ -596,7 +592,7 @@ func (r *Inputer) processStateBefore(
|
||||||
StateKey: "",
|
StateKey: "",
|
||||||
})
|
})
|
||||||
stateBeforeReq := &api.QueryStateAfterEventsRequest{
|
stateBeforeReq := &api.QueryStateAfterEventsRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
PrevEventIDs: event.PrevEventIDs(),
|
PrevEventIDs: event.PrevEventIDs(),
|
||||||
StateToFetch: tuplesNeeded,
|
StateToFetch: tuplesNeeded,
|
||||||
}
|
}
|
||||||
|
@ -606,7 +602,7 @@ func (r *Inputer) processStateBefore(
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case !stateBeforeRes.RoomExists:
|
case !stateBeforeRes.RoomExists:
|
||||||
rejectionErr = fmt.Errorf("room %q does not exist", event.RoomID())
|
rejectionErr = fmt.Errorf("room %q does not exist", event.RoomID().String())
|
||||||
return
|
return
|
||||||
case !stateBeforeRes.PrevEventsExist:
|
case !stateBeforeRes.PrevEventsExist:
|
||||||
rejectionErr = fmt.Errorf("prev events of %q are not known", event.EventID())
|
rejectionErr = fmt.Errorf("prev events of %q are not known", event.EventID())
|
||||||
|
@ -707,7 +703,7 @@ func (r *Inputer) fetchAuthEvents(
|
||||||
// Request the entire auth chain for the event in question. This should
|
// Request the entire auth chain for the event in question. This should
|
||||||
// contain all of the auth events — including ones that we already know —
|
// contain all of the auth events — including ones that we already know —
|
||||||
// so we'll need to filter through those in the next section.
|
// so we'll need to filter through those in the next section.
|
||||||
res, err = r.FSAPI.GetEventAuth(ctx, virtualHost, serverName, event.Version(), event.RoomID(), event.EventID())
|
res, err = r.FSAPI.GetEventAuth(ctx, virtualHost, serverName, event.Version(), event.RoomID().String(), event.EventID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Warnf("Failed to get event auth from federation for %q: %s", event.EventID(), err)
|
logger.WithError(err).Warnf("Failed to get event auth from federation for %q: %s", event.EventID(), err)
|
||||||
continue
|
continue
|
||||||
|
@ -866,25 +862,20 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
|
||||||
|
|
||||||
inputEvents := make([]api.InputRoomEvent, 0, len(memberEvents))
|
inputEvents := make([]api.InputRoomEvent, 0, len(memberEvents))
|
||||||
latestReq := &api.QueryLatestEventsAndStateRequest{
|
latestReq := &api.QueryLatestEventsAndStateRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
}
|
}
|
||||||
latestRes := &api.QueryLatestEventsAndStateResponse{}
|
latestRes := &api.QueryLatestEventsAndStateResponse{}
|
||||||
if err = r.Queryer.QueryLatestEventsAndState(ctx, latestReq, latestRes); err != nil {
|
if err = r.Queryer.QueryLatestEventsAndState(ctx, latestReq, latestRes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
prevEvents := latestRes.LatestEvents
|
prevEvents := latestRes.LatestEvents
|
||||||
for _, memberEvent := range memberEvents {
|
for _, memberEvent := range memberEvents {
|
||||||
if memberEvent.StateKey() == nil {
|
if memberEvent.StateKey() == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
memberUserID, err := r.Queryer.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*memberEvent.StateKey()))
|
memberUserID, err := r.Queryer.QueryUserIDForSender(ctx, event.RoomID(), spec.SenderID(*memberEvent.StateKey()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -912,7 +903,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
|
||||||
|
|
||||||
stateKey := *memberEvent.StateKey()
|
stateKey := *memberEvent.StateKey()
|
||||||
fledglingEvent := &gomatrixserverlib.ProtoEvent{
|
fledglingEvent := &gomatrixserverlib.ProtoEvent{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
Type: spec.MRoomMember,
|
Type: spec.MRoomMember,
|
||||||
StateKey: &stateKey,
|
StateKey: &stateKey,
|
||||||
SenderID: stateKey,
|
SenderID: stateKey,
|
||||||
|
@ -928,12 +919,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
signingIdentity, err := r.SigningIdentity(ctx, event.RoomID(), *memberUserID)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
signingIdentity, err := r.SigningIdentity(ctx, *validRoomID, *memberUserID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ func (u *latestEventsUpdater) doUpdateLatestEvents() error {
|
||||||
// send the event asynchronously but we would need to ensure that 1) the events are written to the log in
|
// send the event asynchronously but we would need to ensure that 1) the events are written to the log in
|
||||||
// the correct order, 2) that pending writes are resent across restarts. In order to avoid writing all the
|
// the correct order, 2) that pending writes are resent across restarts. In order to avoid writing all the
|
||||||
// necessary bookkeeping we'll keep the event sending synchronous for now.
|
// necessary bookkeeping we'll keep the event sending synchronous for now.
|
||||||
if err = u.api.OutputProducer.ProduceRoomEvents(u.event.RoomID(), updates); err != nil {
|
if err = u.api.OutputProducer.ProduceRoomEvents(u.event.RoomID().String(), updates); err != nil {
|
||||||
return fmt.Errorf("u.api.WriteOutputEvents: %w", err)
|
return fmt.Errorf("u.api.WriteOutputEvents: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ func (u *latestEventsUpdater) latestState() error {
|
||||||
if removed := len(u.removed) - len(u.added); !u.rewritesState && removed > 0 {
|
if removed := len(u.removed) - len(u.added); !u.rewritesState && removed > 0 {
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"event_id": u.event.EventID(),
|
"event_id": u.event.EventID(),
|
||||||
"room_id": u.event.RoomID(),
|
"room_id": u.event.RoomID().String(),
|
||||||
"old_state_nid": u.oldStateNID,
|
"old_state_nid": u.oldStateNID,
|
||||||
"new_state_nid": u.newStateNID,
|
"new_state_nid": u.newStateNID,
|
||||||
"old_latest": u.oldLatest.EventIDs(),
|
"old_latest": u.oldLatest.EventIDs(),
|
||||||
|
|
|
@ -139,11 +139,7 @@ func (r *Inputer) updateMembership(
|
||||||
func (r *Inputer) isLocalTarget(ctx context.Context, event *types.Event) bool {
|
func (r *Inputer) isLocalTarget(ctx context.Context, event *types.Event) bool {
|
||||||
isTargetLocalUser := false
|
isTargetLocalUser := false
|
||||||
if statekey := event.StateKey(); statekey != nil {
|
if statekey := event.StateKey(); statekey != nil {
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
userID, err := r.Queryer.QueryUserIDForSender(ctx, event.RoomID(), spec.SenderID(*statekey))
|
||||||
if err != nil {
|
|
||||||
return isTargetLocalUser
|
|
||||||
}
|
|
||||||
userID, err := r.Queryer.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*statekey))
|
|
||||||
if err != nil || userID == nil {
|
if err != nil || userID == nil {
|
||||||
return isTargetLocalUser
|
return isTargetLocalUser
|
||||||
}
|
}
|
||||||
|
@ -168,7 +164,7 @@ func updateToJoinMembership(
|
||||||
Type: api.OutputTypeRetireInviteEvent,
|
Type: api.OutputTypeRetireInviteEvent,
|
||||||
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
||||||
EventID: eventID,
|
EventID: eventID,
|
||||||
RoomID: add.RoomID(),
|
RoomID: add.RoomID().String(),
|
||||||
Membership: spec.Join,
|
Membership: spec.Join,
|
||||||
RetiredByEventID: add.EventID(),
|
RetiredByEventID: add.EventID(),
|
||||||
TargetSenderID: spec.SenderID(*add.StateKey()),
|
TargetSenderID: spec.SenderID(*add.StateKey()),
|
||||||
|
@ -195,7 +191,7 @@ func updateToLeaveMembership(
|
||||||
Type: api.OutputTypeRetireInviteEvent,
|
Type: api.OutputTypeRetireInviteEvent,
|
||||||
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
RetireInviteEvent: &api.OutputRetireInviteEvent{
|
||||||
EventID: eventID,
|
EventID: eventID,
|
||||||
RoomID: add.RoomID(),
|
RoomID: add.RoomID().String(),
|
||||||
Membership: newMembership,
|
Membership: newMembership,
|
||||||
RetiredByEventID: add.EventID(),
|
RetiredByEventID: add.EventID(),
|
||||||
TargetSenderID: spec.SenderID(*add.StateKey()),
|
TargetSenderID: spec.SenderID(*add.StateKey()),
|
||||||
|
|
|
@ -84,7 +84,7 @@ func (t *missingStateReq) processEventWithMissingState(
|
||||||
// need to fallback to /state.
|
// need to fallback to /state.
|
||||||
t.log = util.GetLogger(ctx).WithFields(map[string]interface{}{
|
t.log = util.GetLogger(ctx).WithFields(map[string]interface{}{
|
||||||
"txn_event": e.EventID(),
|
"txn_event": e.EventID(),
|
||||||
"room_id": e.RoomID(),
|
"room_id": e.RoomID().String(),
|
||||||
"txn_prev_events": e.PrevEventIDs(),
|
"txn_prev_events": e.PrevEventIDs(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ func (t *missingStateReq) lookupResolvedStateBeforeEvent(ctx context.Context, e
|
||||||
// Look up what the state is after the backward extremity. This will either
|
// Look up what the state is after the backward extremity. This will either
|
||||||
// come from the roomserver, if we know all the required events, or it will
|
// come from the roomserver, if we know all the required events, or it will
|
||||||
// come from a remote server via /state_ids if not.
|
// come from a remote server via /state_ids if not.
|
||||||
prevState, trustworthy, err := t.lookupStateAfterEvent(ctx, roomVersion, e.RoomID(), prevEventID)
|
prevState, trustworthy, err := t.lookupStateAfterEvent(ctx, roomVersion, e.RoomID().String(), prevEventID)
|
||||||
switch err2 := err.(type) {
|
switch err2 := err.(type) {
|
||||||
case gomatrixserverlib.EventValidationError:
|
case gomatrixserverlib.EventValidationError:
|
||||||
if !err2.Persistable {
|
if !err2.Persistable {
|
||||||
|
@ -316,9 +316,9 @@ func (t *missingStateReq) lookupResolvedStateBeforeEvent(ctx context.Context, e
|
||||||
}
|
}
|
||||||
// There's more than one previous state - run them all through state res
|
// There's more than one previous state - run them all through state res
|
||||||
var err error
|
var err error
|
||||||
t.roomsMu.Lock(e.RoomID())
|
t.roomsMu.Lock(e.RoomID().String())
|
||||||
resolvedState, err = t.resolveStatesAndCheck(ctx, roomVersion, respStates, e)
|
resolvedState, err = t.resolveStatesAndCheck(ctx, roomVersion, respStates, e)
|
||||||
t.roomsMu.Unlock(e.RoomID())
|
t.roomsMu.Unlock(e.RoomID().String())
|
||||||
switch err2 := err.(type) {
|
switch err2 := err.(type) {
|
||||||
case gomatrixserverlib.EventValidationError:
|
case gomatrixserverlib.EventValidationError:
|
||||||
if !err2.Persistable {
|
if !err2.Persistable {
|
||||||
|
@ -510,7 +510,7 @@ retryAllowedState:
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
switch missing := err.(type) {
|
switch missing := err.(type) {
|
||||||
case gomatrixserverlib.MissingAuthEventError:
|
case gomatrixserverlib.MissingAuthEventError:
|
||||||
h, err2 := t.lookupEvent(ctx, roomVersion, backwardsExtremity.RoomID(), missing.AuthEventID, true)
|
h, err2 := t.lookupEvent(ctx, roomVersion, backwardsExtremity.RoomID().String(), missing.AuthEventID, true)
|
||||||
switch e := err2.(type) {
|
switch e := err2.(type) {
|
||||||
case gomatrixserverlib.EventValidationError:
|
case gomatrixserverlib.EventValidationError:
|
||||||
if !e.Persistable {
|
if !e.Persistable {
|
||||||
|
@ -546,7 +546,7 @@ func (t *missingStateReq) getMissingEvents(ctx context.Context, e gomatrixserver
|
||||||
trace, ctx := internal.StartRegion(ctx, "getMissingEvents")
|
trace, ctx := internal.StartRegion(ctx, "getMissingEvents")
|
||||||
defer trace.EndRegion()
|
defer trace.EndRegion()
|
||||||
|
|
||||||
logger := t.log.WithField("event_id", e.EventID()).WithField("room_id", e.RoomID())
|
logger := t.log.WithField("event_id", e.EventID()).WithField("room_id", e.RoomID().String())
|
||||||
latest, _, _, err := t.db.LatestEventIDs(ctx, t.roomInfo.RoomNID)
|
latest, _, _, err := t.db.LatestEventIDs(ctx, t.roomInfo.RoomNID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, fmt.Errorf("t.DB.LatestEventIDs: %w", err)
|
return nil, false, false, fmt.Errorf("t.DB.LatestEventIDs: %w", err)
|
||||||
|
@ -560,7 +560,7 @@ func (t *missingStateReq) getMissingEvents(ctx context.Context, e gomatrixserver
|
||||||
var missingResp *fclient.RespMissingEvents
|
var missingResp *fclient.RespMissingEvents
|
||||||
for _, server := range t.servers {
|
for _, server := range t.servers {
|
||||||
var m fclient.RespMissingEvents
|
var m fclient.RespMissingEvents
|
||||||
if m, err = t.federation.LookupMissingEvents(ctx, t.virtualHost, server, e.RoomID(), fclient.MissingEvents{
|
if m, err = t.federation.LookupMissingEvents(ctx, t.virtualHost, server, e.RoomID().String(), fclient.MissingEvents{
|
||||||
Limit: 20,
|
Limit: 20,
|
||||||
// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of latest_events.
|
// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of latest_events.
|
||||||
EarliestEvents: latestEvents,
|
EarliestEvents: latestEvents,
|
||||||
|
|
|
@ -301,7 +301,7 @@ func (b *backfillRequester) StateIDsBeforeEvent(ctx context.Context, targetEvent
|
||||||
return ids, nil
|
return ids, nil
|
||||||
}
|
}
|
||||||
if len(targetEvent.PrevEventIDs()) == 0 && targetEvent.Type() == "m.room.create" && targetEvent.StateKeyEquals("") {
|
if len(targetEvent.PrevEventIDs()) == 0 && targetEvent.Type() == "m.room.create" && targetEvent.StateKeyEquals("") {
|
||||||
util.GetLogger(ctx).WithField("room_id", targetEvent.RoomID()).Info("Backfilled to the beginning of the room")
|
util.GetLogger(ctx).WithField("room_id", targetEvent.RoomID().String()).Info("Backfilled to the beginning of the room")
|
||||||
b.eventIDToBeforeStateIDs[targetEvent.EventID()] = []string{}
|
b.eventIDToBeforeStateIDs[targetEvent.EventID()] = []string{}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -494,11 +494,7 @@ FindSuccessor:
|
||||||
// Store the server names in a temporary map to avoid duplicates.
|
// Store the server names in a temporary map to avoid duplicates.
|
||||||
serverSet := make(map[spec.ServerName]bool)
|
serverSet := make(map[spec.ServerName]bool)
|
||||||
for _, event := range memberEvents {
|
for _, event := range memberEvents {
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
if sender, err := b.querier.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID()); err == nil {
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if sender, err := b.querier.QueryUserIDForSender(ctx, *validRoomID, event.SenderID()); err == nil {
|
|
||||||
serverSet[sender.Domain()] = true
|
serverSet[sender.Domain()] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,16 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
||||||
} else {
|
} else {
|
||||||
senderID = spec.SenderID(userID.String())
|
senderID = spec.SenderID(userID.String())
|
||||||
}
|
}
|
||||||
createContent["creator"] = senderID
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
createContent["room_version"] = createRequest.RoomVersion
|
createContent["room_version"] = createRequest.RoomVersion
|
||||||
powerLevelContent := eventutil.InitialPowerLevelsContent(string(senderID))
|
powerLevelContent := eventutil.InitialPowerLevelsContent(string(senderID))
|
||||||
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
||||||
|
|
|
@ -100,16 +100,12 @@ func (r *Inviter) ProcessInviteMembership(
|
||||||
var outputUpdates []api.OutputEvent
|
var outputUpdates []api.OutputEvent
|
||||||
var updater *shared.MembershipUpdater
|
var updater *shared.MembershipUpdater
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(inviteEvent.RoomID())
|
userID, err := r.RSAPI.QueryUserIDForSender(ctx, inviteEvent.RoomID(), spec.SenderID(*inviteEvent.StateKey()))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
userID, err := r.RSAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*inviteEvent.StateKey()))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, api.ErrInvalidID{Err: fmt.Errorf("the user ID %s is invalid", *inviteEvent.StateKey())}
|
return nil, api.ErrInvalidID{Err: fmt.Errorf("the user ID %s is invalid", *inviteEvent.StateKey())}
|
||||||
}
|
}
|
||||||
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(userID.Domain())
|
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(userID.Domain())
|
||||||
if updater, err = r.DB.MembershipUpdater(ctx, inviteEvent.RoomID(), *inviteEvent.StateKey(), isTargetLocal, inviteEvent.Version()); err != nil {
|
if updater, err = r.DB.MembershipUpdater(ctx, inviteEvent.RoomID().String(), *inviteEvent.StateKey(), isTargetLocal, inviteEvent.Version()); err != nil {
|
||||||
return nil, fmt.Errorf("r.DB.MembershipUpdater: %w", err)
|
return nil, fmt.Errorf("r.DB.MembershipUpdater: %w", err)
|
||||||
}
|
}
|
||||||
outputUpdates, err = helpers.UpdateToInviteMembership(updater, &types.Event{
|
outputUpdates, err = helpers.UpdateToInviteMembership(updater, &types.Event{
|
||||||
|
|
|
@ -93,11 +93,21 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
isInvitePending, senderUser, eventID, _, err := helpers.IsInvitePending(ctx, r.DB, req.RoomID, *leaver)
|
isInvitePending, senderUser, eventID, _, err := helpers.IsInvitePending(ctx, r.DB, req.RoomID, *leaver)
|
||||||
if err == nil && isInvitePending {
|
if err == nil && isInvitePending {
|
||||||
sender, serr := r.RSAPI.QueryUserIDForSender(ctx, *roomID, senderUser)
|
sender, serr := r.RSAPI.QueryUserIDForSender(ctx, *roomID, senderUser)
|
||||||
if serr != nil || sender == nil {
|
if serr != nil {
|
||||||
return nil, fmt.Errorf("sender %q has no matching userID", senderUser)
|
return nil, fmt.Errorf("failed looking up userID for sender %q: %w", senderUser, serr)
|
||||||
}
|
}
|
||||||
if !r.Cfg.Matrix.IsLocalServerName(sender.Domain()) {
|
|
||||||
return r.performFederatedRejectInvite(ctx, req, res, *sender, eventID, *leaver)
|
var domain spec.ServerName
|
||||||
|
if sender == nil {
|
||||||
|
// TODO: Currently a federated invite has no way of knowing the mxid_mapping of the inviter.
|
||||||
|
// Should we add the inviter's m.room.member event (with mxid_mapping) to invite_room_state to allow
|
||||||
|
// the invited user to leave via the inviter's server?
|
||||||
|
domain = roomID.Domain()
|
||||||
|
} else {
|
||||||
|
domain = sender.Domain()
|
||||||
|
}
|
||||||
|
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||||
|
return r.performFederatedRejectInvite(ctx, req, res, domain, eventID, *leaver)
|
||||||
}
|
}
|
||||||
// check that this is not a "server notice room"
|
// check that this is not a "server notice room"
|
||||||
accData := &userapi.QueryAccountDataResponse{}
|
accData := &userapi.QueryAccountDataResponse{}
|
||||||
|
@ -219,14 +229,14 @@ func (r *Leaver) performFederatedRejectInvite(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformLeaveRequest,
|
req *api.PerformLeaveRequest,
|
||||||
res *api.PerformLeaveResponse, // nolint:unparam
|
res *api.PerformLeaveResponse, // nolint:unparam
|
||||||
inviteSender spec.UserID, eventID string,
|
inviteDomain spec.ServerName, eventID string,
|
||||||
leaver spec.SenderID,
|
leaver spec.SenderID,
|
||||||
) ([]api.OutputEvent, error) {
|
) ([]api.OutputEvent, error) {
|
||||||
// Ask the federation sender to perform a federated leave for us.
|
// Ask the federation sender to perform a federated leave for us.
|
||||||
leaveReq := fsAPI.PerformLeaveRequest{
|
leaveReq := fsAPI.PerformLeaveRequest{
|
||||||
RoomID: req.RoomID,
|
RoomID: req.RoomID,
|
||||||
UserID: req.Leaver.String(),
|
UserID: req.Leaver.String(),
|
||||||
ServerNames: []spec.ServerName{inviteSender.Domain()},
|
ServerNames: []spec.ServerName{inviteDomain},
|
||||||
}
|
}
|
||||||
leaveRes := fsAPI.PerformLeaveResponse{}
|
leaveRes := fsAPI.PerformLeaveResponse{}
|
||||||
if err := r.FSAPI.PerformLeave(ctx, &leaveReq, &leaveRes); err != nil {
|
if err := r.FSAPI.PerformLeave(ctx, &leaveReq, &leaveRes); err != nil {
|
||||||
|
|
|
@ -368,7 +368,16 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
|
||||||
// in the create event (such as for the room types MSC).
|
// in the create event (such as for the room types MSC).
|
||||||
newCreateContent := map[string]interface{}{}
|
newCreateContent := map[string]interface{}{}
|
||||||
_ = json.Unmarshal(oldCreateEvent.Content(), &newCreateContent)
|
_ = json.Unmarshal(oldCreateEvent.Content(), &newCreateContent)
|
||||||
newCreateContent["creator"] = string(senderID)
|
|
||||||
|
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["room_version"] = newVersion
|
||||||
newCreateContent["predecessor"] = gomatrixserverlib.PreviousRoom{
|
newCreateContent["predecessor"] = gomatrixserverlib.PreviousRoom{
|
||||||
EventID: tombstoneEvent.EventID(),
|
EventID: tombstoneEvent.EventID(),
|
||||||
|
|
|
@ -513,14 +513,14 @@ func restrictedJoinRuleAllowedRooms(ctx context.Context, joinRuleEv *types.Heade
|
||||||
}
|
}
|
||||||
var jrContent gomatrixserverlib.JoinRuleContent
|
var jrContent gomatrixserverlib.JoinRuleContent
|
||||||
if err := json.Unmarshal(joinRuleEv.Content(), &jrContent); err != nil {
|
if err := json.Unmarshal(joinRuleEv.Content(), &jrContent); err != nil {
|
||||||
util.GetLogger(ctx).Warnf("failed to check join_rule on room %s: %s", joinRuleEv.RoomID(), err)
|
util.GetLogger(ctx).Warnf("failed to check join_rule on room %s: %s", joinRuleEv.RoomID().String(), err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, allow := range jrContent.Allow {
|
for _, allow := range jrContent.Allow {
|
||||||
if allow.Type == spec.MRoomMembership {
|
if allow.Type == spec.MRoomMembership {
|
||||||
allowedRoomID, err := spec.NewRoomID(allow.RoomID)
|
allowedRoomID, err := spec.NewRoomID(allow.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).Warnf("invalid room ID '%s' found in join_rule on room %s: %s", allow.RoomID, joinRuleEv.RoomID(), err)
|
util.GetLogger(ctx).Warnf("invalid room ID '%s' found in join_rule on room %s: %s", allow.RoomID, joinRuleEv.RoomID().String(), err)
|
||||||
} else {
|
} else {
|
||||||
allows = append(allows, *allowedRoomID)
|
allows = append(allows, *allowedRoomID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ func (db *getEventDB) addFakeEvent(eventID string, authIDs []string) error {
|
||||||
}
|
}
|
||||||
builder := map[string]interface{}{
|
builder := map[string]interface{}{
|
||||||
"event_id": eventID,
|
"event_id": eventID,
|
||||||
|
"room_id": "!room:a",
|
||||||
"auth_events": authEvents,
|
"auth_events": authEvents,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -696,8 +696,8 @@ func (d *Database) GetOrCreateRoomInfo(ctx context.Context, event gomatrixserver
|
||||||
return nil, fmt.Errorf("extractRoomVersionFromCreateEvent: %w", err)
|
return nil, fmt.Errorf("extractRoomVersionFromCreateEvent: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
roomNID, nidOK := d.Cache.GetRoomServerRoomNID(event.RoomID())
|
roomNID, nidOK := d.Cache.GetRoomServerRoomNID(event.RoomID().String())
|
||||||
cachedRoomVersion, versionOK := d.Cache.GetRoomVersion(event.RoomID())
|
cachedRoomVersion, versionOK := d.Cache.GetRoomVersion(event.RoomID().String())
|
||||||
// if we found both, the roomNID and version in our cache, no need to query the database
|
// if we found both, the roomNID and version in our cache, no need to query the database
|
||||||
if nidOK && versionOK {
|
if nidOK && versionOK {
|
||||||
return &types.RoomInfo{
|
return &types.RoomInfo{
|
||||||
|
@ -707,14 +707,14 @@ func (d *Database) GetOrCreateRoomInfo(ctx context.Context, event gomatrixserver
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
||||||
roomNID, err = d.assignRoomNID(ctx, txn, event.RoomID(), roomVersion)
|
roomNID, err = d.assignRoomNID(ctx, txn, event.RoomID().String(), roomVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if roomVersion != "" {
|
if roomVersion != "" {
|
||||||
d.Cache.StoreRoomVersion(event.RoomID(), roomVersion)
|
d.Cache.StoreRoomVersion(event.RoomID().String(), roomVersion)
|
||||||
}
|
}
|
||||||
return &types.RoomInfo{
|
return &types.RoomInfo{
|
||||||
RoomVersion: roomVersion,
|
RoomVersion: roomVersion,
|
||||||
|
@ -1026,24 +1026,19 @@ func (d *EventDatabase) MaybeRedactEvent(
|
||||||
case validated || redactedEvent == nil || redactionEvent == nil:
|
case validated || redactedEvent == nil || redactionEvent == nil:
|
||||||
// we've seen this redaction before or there is nothing to redact
|
// we've seen this redaction before or there is nothing to redact
|
||||||
return nil
|
return nil
|
||||||
case redactedEvent.RoomID() != redactionEvent.RoomID():
|
case redactedEvent.RoomID().String() != redactionEvent.RoomID().String():
|
||||||
// redactions across rooms aren't allowed
|
// redactions across rooms aren't allowed
|
||||||
ignoreRedaction = true
|
ignoreRedaction = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var validRoomID *spec.RoomID
|
|
||||||
validRoomID, err = spec.NewRoomID(redactedEvent.RoomID())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sender1Domain := ""
|
sender1Domain := ""
|
||||||
sender1, err1 := querier.QueryUserIDForSender(ctx, *validRoomID, redactedEvent.SenderID())
|
sender1, err1 := querier.QueryUserIDForSender(ctx, redactedEvent.RoomID(), redactedEvent.SenderID())
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
sender1Domain = string(sender1.Domain())
|
sender1Domain = string(sender1.Domain())
|
||||||
}
|
}
|
||||||
sender2Domain := ""
|
sender2Domain := ""
|
||||||
sender2, err2 := querier.QueryUserIDForSender(ctx, *validRoomID, redactionEvent.SenderID())
|
sender2, err2 := querier.QueryUserIDForSender(ctx, redactedEvent.RoomID(), redactionEvent.SenderID())
|
||||||
if err2 == nil {
|
if err2 == nil {
|
||||||
sender2Domain = string(sender2.Domain())
|
sender2Domain = string(sender2.Domain())
|
||||||
}
|
}
|
||||||
|
@ -1522,7 +1517,7 @@ func (d *Database) GetBulkStateContent(ctx context.Context, roomIDs []string, tu
|
||||||
}
|
}
|
||||||
result[i] = tables.StrippedEvent{
|
result[i] = tables.StrippedEvent{
|
||||||
EventType: ev.Type(),
|
EventType: ev.Type(),
|
||||||
RoomID: ev.RoomID(),
|
RoomID: ev.RoomID().String(),
|
||||||
StateKey: *ev.StateKey(),
|
StateKey: *ev.StateKey(),
|
||||||
ContentValue: tables.ExtractContentValue(&types.HeaderedEvent{PDU: ev}),
|
ContentValue: tables.ExtractContentValue(&types.HeaderedEvent{PDU: ev}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@ func (rc *reqCtx) process() (*MSC2836EventRelationshipsResponse, *util.JSONRespo
|
||||||
event = rc.fetchUnknownEvent(rc.req.EventID, rc.req.RoomID)
|
event = rc.fetchUnknownEvent(rc.req.EventID, rc.req.RoomID)
|
||||||
}
|
}
|
||||||
if rc.req.RoomID == "" && event != nil {
|
if rc.req.RoomID == "" && event != nil {
|
||||||
rc.req.RoomID = event.RoomID()
|
rc.req.RoomID = event.RoomID().String()
|
||||||
}
|
}
|
||||||
if event == nil || !rc.authorisedToSeeEvent(event) {
|
if event == nil || !rc.authorisedToSeeEvent(event) {
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
|
@ -526,7 +526,7 @@ func (rc *reqCtx) authorisedToSeeEvent(event *types.HeaderedEvent) bool {
|
||||||
// make sure the server is in this room
|
// make sure the server is in this room
|
||||||
var res fs.QueryJoinedHostServerNamesInRoomResponse
|
var res fs.QueryJoinedHostServerNamesInRoomResponse
|
||||||
err := rc.fsAPI.QueryJoinedHostServerNamesInRoom(rc.ctx, &fs.QueryJoinedHostServerNamesInRoomRequest{
|
err := rc.fsAPI.QueryJoinedHostServerNamesInRoom(rc.ctx, &fs.QueryJoinedHostServerNamesInRoomRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
}, &res)
|
}, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(rc.ctx).WithError(err).Error("authorisedToSeeEvent: failed to QueryJoinedHostServerNamesInRoom")
|
util.GetLogger(rc.ctx).WithError(err).Error("authorisedToSeeEvent: failed to QueryJoinedHostServerNamesInRoom")
|
||||||
|
@ -545,7 +545,7 @@ func (rc *reqCtx) authorisedToSeeEvent(event *types.HeaderedEvent) bool {
|
||||||
// TODO: This does not honour m.room.create content
|
// TODO: This does not honour m.room.create content
|
||||||
var queryMembershipRes roomserver.QueryMembershipForUserResponse
|
var queryMembershipRes roomserver.QueryMembershipForUserResponse
|
||||||
err := rc.rsAPI.QueryMembershipForUser(rc.ctx, &roomserver.QueryMembershipForUserRequest{
|
err := rc.rsAPI.QueryMembershipForUser(rc.ctx, &roomserver.QueryMembershipForUserRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
UserID: rc.userID,
|
UserID: rc.userID,
|
||||||
}, &queryMembershipRes)
|
}, &queryMembershipRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -612,7 +612,7 @@ func (rc *reqCtx) lookForEvent(eventID string) *types.HeaderedEvent {
|
||||||
// inject all the events into the roomserver then return the event in question
|
// inject all the events into the roomserver then return the event in question
|
||||||
rc.injectResponseToRoomserver(queryRes)
|
rc.injectResponseToRoomserver(queryRes)
|
||||||
for _, ev := range queryRes.ParsedEvents {
|
for _, ev := range queryRes.ParsedEvents {
|
||||||
if ev.EventID() == eventID && rc.req.RoomID == ev.RoomID() {
|
if ev.EventID() == eventID && rc.req.RoomID == ev.RoomID().String() {
|
||||||
return &types.HeaderedEvent{PDU: ev}
|
return &types.HeaderedEvent{PDU: ev}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,7 +629,7 @@ func (rc *reqCtx) lookForEvent(eventID string) *types.HeaderedEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rc.req.RoomID == event.RoomID() {
|
if rc.req.RoomID == event.RoomID().String() {
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -239,7 +239,7 @@ func (p *DB) StoreRelation(ctx context.Context, ev *types.HeaderedEvent) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
util.GetLogger(ctx).Infof("StoreRelation child=%s parent=%s rel_type=%s", child, parent, relType)
|
util.GetLogger(ctx).Infof("StoreRelation child=%s parent=%s rel_type=%s", child, parent, relType)
|
||||||
_, err = txn.Stmt(p.insertNodeStmt).ExecContext(ctx, ev.EventID(), ev.OriginServerTS(), ev.RoomID(), count, base64.RawStdEncoding.EncodeToString(hash), 0)
|
_, err = txn.Stmt(p.insertNodeStmt).ExecContext(ctx, ev.EventID(), ev.OriginServerTS(), ev.RoomID().String(), count, base64.RawStdEncoding.EncodeToString(hash), 0)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ func (s *OutputClientDataConsumer) Start() error {
|
||||||
id = streamPos
|
id = streamPos
|
||||||
e := fulltext.IndexElement{
|
e := fulltext.IndexElement{
|
||||||
EventID: ev.EventID(),
|
EventID: ev.EventID(),
|
||||||
RoomID: ev.RoomID(),
|
RoomID: ev.RoomID().String(),
|
||||||
StreamPosition: streamPos,
|
StreamPosition: streamPos,
|
||||||
}
|
}
|
||||||
e.SetContentType(ev.Type())
|
e.SetContentType(ev.Type())
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/syncapi/notifier"
|
"github.com/matrix-org/dendrite/syncapi/notifier"
|
||||||
"github.com/matrix-org/dendrite/syncapi/storage"
|
"github.com/matrix-org/dendrite/syncapi/storage"
|
||||||
"github.com/matrix-org/dendrite/syncapi/streams"
|
"github.com/matrix-org/dendrite/syncapi/streams"
|
||||||
|
"github.com/matrix-org/dendrite/syncapi/synctypes"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
@ -165,9 +166,9 @@ func (s *OutputRoomEventConsumer) onRedactEvent(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = s.db.RedactRelations(ctx, msg.RedactedBecause.RoomID(), msg.RedactedEventID); err != nil {
|
if err = s.db.RedactRelations(ctx, msg.RedactedBecause.RoomID().String(), msg.RedactedEventID); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"room_id": msg.RedactedBecause.RoomID(),
|
"room_id": msg.RedactedBecause.RoomID().String(),
|
||||||
"event_id": msg.RedactedBecause.EventID(),
|
"event_id": msg.RedactedBecause.EventID(),
|
||||||
"redacted_event_id": msg.RedactedEventID,
|
"redacted_event_id": msg.RedactedEventID,
|
||||||
}).WithError(err).Warn("Failed to redact relations")
|
}).WithError(err).Warn("Failed to redact relations")
|
||||||
|
@ -221,7 +222,7 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent(
|
||||||
// Finally, work out if there are any more events missing.
|
// Finally, work out if there are any more events missing.
|
||||||
if len(missingEventIDs) > 0 {
|
if len(missingEventIDs) > 0 {
|
||||||
eventsReq := &api.QueryEventsByIDRequest{
|
eventsReq := &api.QueryEventsByIDRequest{
|
||||||
RoomID: ev.RoomID(),
|
RoomID: ev.RoomID().String(),
|
||||||
EventIDs: missingEventIDs,
|
EventIDs: missingEventIDs,
|
||||||
}
|
}
|
||||||
eventsRes := &api.QueryEventsByIDResponse{}
|
eventsRes := &api.QueryEventsByIDResponse{}
|
||||||
|
@ -256,17 +257,12 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.RewritesState {
|
if msg.RewritesState {
|
||||||
if err = s.db.PurgeRoomState(ctx, ev.RoomID()); err != nil {
|
if err = s.db.PurgeRoomState(ctx, ev.RoomID().String()); err != nil {
|
||||||
return fmt.Errorf("s.db.PurgeRoom: %w", err)
|
return fmt.Errorf("s.db.PurgeRoom: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
userID, err := s.rsAPI.QueryUserIDForSender(ctx, ev.RoomID(), ev.SenderID())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -306,7 +302,7 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
s.pduStream.Advance(pduPos)
|
s.pduStream.Advance(pduPos)
|
||||||
s.notifier.OnNewEvent(ev, ev.RoomID(), nil, types.StreamingToken{PDUPosition: pduPos})
|
s.notifier.OnNewEvent(ev, ev.RoomID().String(), nil, types.StreamingToken{PDUPosition: pduPos})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -323,12 +319,7 @@ func (s *OutputRoomEventConsumer) onOldRoomEvent(
|
||||||
// old events in the sync API, this should at least prevent us
|
// old events in the sync API, this should at least prevent us
|
||||||
// from confusing clients into thinking they've joined/left rooms.
|
// from confusing clients into thinking they've joined/left rooms.
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
userID, err := s.rsAPI.QueryUserIDForSender(ctx, ev.RoomID(), ev.SenderID())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -354,7 +345,7 @@ func (s *OutputRoomEventConsumer) onOldRoomEvent(
|
||||||
|
|
||||||
if err = s.db.UpdateRelations(ctx, ev); err != nil {
|
if err = s.db.UpdateRelations(ctx, ev); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"room_id": ev.RoomID(),
|
"room_id": ev.RoomID().String(),
|
||||||
"event_id": ev.EventID(),
|
"event_id": ev.EventID(),
|
||||||
"type": ev.Type(),
|
"type": ev.Type(),
|
||||||
}).WithError(err).Warn("Failed to update relations")
|
}).WithError(err).Warn("Failed to update relations")
|
||||||
|
@ -367,7 +358,7 @@ func (s *OutputRoomEventConsumer) onOldRoomEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
s.pduStream.Advance(pduPos)
|
s.pduStream.Advance(pduPos)
|
||||||
s.notifier.OnNewEvent(ev, ev.RoomID(), nil, types.StreamingToken{PDUPosition: pduPos})
|
s.notifier.OnNewEvent(ev, ev.RoomID().String(), nil, types.StreamingToken{PDUPosition: pduPos})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -387,11 +378,7 @@ func (s *OutputRoomEventConsumer) notifyJoinedPeeks(ctx context.Context, ev *rst
|
||||||
return sp, fmt.Errorf("unexpected nil state_key")
|
return sp, fmt.Errorf("unexpected nil state_key")
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
userID, err := s.rsAPI.QueryUserIDForSender(ctx, ev.RoomID(), spec.SenderID(*ev.StateKey()))
|
||||||
if err != nil {
|
|
||||||
return sp, err
|
|
||||||
}
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*ev.StateKey()))
|
|
||||||
if err != nil || userID == nil {
|
if err != nil || userID == nil {
|
||||||
return sp, fmt.Errorf("failed getting userID for sender: %w", err)
|
return sp, fmt.Errorf("failed getting userID for sender: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -400,7 +387,7 @@ func (s *OutputRoomEventConsumer) notifyJoinedPeeks(ctx context.Context, ev *rst
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel any peeks for it
|
// cancel any peeks for it
|
||||||
peekSP, peekErr := s.db.DeletePeeks(ctx, ev.RoomID(), *ev.StateKey())
|
peekSP, peekErr := s.db.DeletePeeks(ctx, ev.RoomID().String(), *ev.StateKey())
|
||||||
if peekErr != nil {
|
if peekErr != nil {
|
||||||
return sp, fmt.Errorf("s.db.DeletePeeks: %w", peekErr)
|
return sp, fmt.Errorf("s.db.DeletePeeks: %w", peekErr)
|
||||||
}
|
}
|
||||||
|
@ -418,11 +405,7 @@ func (s *OutputRoomEventConsumer) onNewInviteEvent(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(msg.Event.RoomID())
|
userID, err := s.rsAPI.QueryUserIDForSender(ctx, msg.Event.RoomID(), spec.SenderID(*msg.Event.StateKey()))
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*msg.Event.StateKey()))
|
|
||||||
if err != nil || userID == nil {
|
if err != nil || userID == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -559,15 +542,10 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent)
|
||||||
var succeeded bool
|
var succeeded bool
|
||||||
defer sqlutil.EndTransactionWithCheck(snapshot, &succeeded, &err)
|
defer sqlutil.EndTransactionWithCheck(snapshot, &succeeded, &err)
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
|
||||||
if err != nil {
|
|
||||||
return event, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sKeyUser := ""
|
sKeyUser := ""
|
||||||
if stateKey != "" {
|
if stateKey != "" {
|
||||||
var sku *spec.UserID
|
var sku *spec.UserID
|
||||||
sku, err = s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, spec.SenderID(stateKey))
|
sku, err = s.rsAPI.QueryUserIDForSender(s.ctx, event.RoomID(), spec.SenderID(stateKey))
|
||||||
if err == nil && sku != nil {
|
if err == nil && sku != nil {
|
||||||
sKeyUser = sku.String()
|
sKeyUser = sku.String()
|
||||||
event.StateKeyResolved = &sKeyUser
|
event.StateKeyResolved = &sKeyUser
|
||||||
|
@ -575,13 +553,13 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
prevEvent, err := snapshot.GetStateEvent(
|
prevEvent, err := snapshot.GetStateEvent(
|
||||||
s.ctx, event.RoomID(), event.Type(), sKeyUser,
|
s.ctx, event.RoomID().String(), event.Type(), sKeyUser,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return event, err
|
return event, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, event.SenderID())
|
userID, err := s.rsAPI.QueryUserIDForSender(s.ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return event, err
|
return event, err
|
||||||
}
|
}
|
||||||
|
@ -592,16 +570,10 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent)
|
||||||
return event, nil
|
return event, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
prevEventSender := string(prevEvent.SenderID())
|
prev := synctypes.PrevEventRef{
|
||||||
prevUser, err := s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, prevEvent.SenderID())
|
|
||||||
if err == nil && prevUser != nil {
|
|
||||||
prevEventSender = prevUser.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
prev := types.PrevEventRef{
|
|
||||||
PrevContent: prevEvent.Content(),
|
PrevContent: prevEvent.Content(),
|
||||||
ReplacesState: prevEvent.EventID(),
|
ReplacesState: prevEvent.EventID(),
|
||||||
PrevSenderID: prevEventSender,
|
PrevSenderID: string(prevEvent.SenderID()),
|
||||||
}
|
}
|
||||||
|
|
||||||
event.PDU, err = event.SetUnsigned(prev)
|
event.PDU, err = event.SetUnsigned(prev)
|
||||||
|
@ -615,7 +587,7 @@ func (s *OutputRoomEventConsumer) writeFTS(ev *rstypes.HeaderedEvent, pduPositio
|
||||||
}
|
}
|
||||||
e := fulltext.IndexElement{
|
e := fulltext.IndexElement{
|
||||||
EventID: ev.EventID(),
|
EventID: ev.EventID(),
|
||||||
RoomID: ev.RoomID(),
|
RoomID: ev.RoomID().String(),
|
||||||
StreamPosition: int64(pduPosition),
|
StreamPosition: int64(pduPosition),
|
||||||
}
|
}
|
||||||
e.SetContentType(ev.Type())
|
e.SetContentType(ev.Type())
|
||||||
|
|
|
@ -118,26 +118,23 @@ func ApplyHistoryVisibilityFilter(
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
// try to get the current membership of the user
|
// try to get the current membership of the user
|
||||||
membershipCurrent, _, err := syncDB.SelectMembershipForUser(ctx, events[0].RoomID(), userID.String(), math.MaxInt64)
|
membershipCurrent, _, err := syncDB.SelectMembershipForUser(ctx, events[0].RoomID().String(), userID.String(), math.MaxInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the mapping from eventID -> eventVisibility
|
// Get the mapping from eventID -> eventVisibility
|
||||||
eventsFiltered := make([]*types.HeaderedEvent, 0, len(events))
|
eventsFiltered := make([]*types.HeaderedEvent, 0, len(events))
|
||||||
firstEvRoomID, err := spec.NewRoomID(events[0].RoomID())
|
firstEvRoomID := events[0].RoomID()
|
||||||
|
senderID, err := rsAPI.QuerySenderIDForUser(ctx, firstEvRoomID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
senderID, err := rsAPI.QuerySenderIDForUser(ctx, *firstEvRoomID, userID)
|
visibilities := visibilityForEvents(ctx, rsAPI, events, senderID, firstEvRoomID)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
visibilities := visibilityForEvents(ctx, rsAPI, events, senderID, *firstEvRoomID)
|
|
||||||
|
|
||||||
for _, ev := range events {
|
for _, ev := range events {
|
||||||
// Validate same room assumption
|
// Validate same room assumption
|
||||||
if ev.RoomID() != firstEvRoomID.String() {
|
if ev.RoomID().String() != firstEvRoomID.String() {
|
||||||
return nil, fmt.Errorf("events from different rooms supplied to ApplyHistoryVisibilityFilter")
|
return nil, fmt.Errorf("events from different rooms supplied to ApplyHistoryVisibilityFilter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,20 +101,13 @@ func (n *Notifier) OnNewEvent(
|
||||||
n._removeEmptyUserStreams()
|
n._removeEmptyUserStreams()
|
||||||
|
|
||||||
if ev != nil {
|
if ev != nil {
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).WithField("event_id", ev.EventID()).Errorf(
|
|
||||||
"Notifier.OnNewEvent: RoomID is invalid",
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Map this event's room_id to a list of joined users, and wake them up.
|
// Map this event's room_id to a list of joined users, and wake them up.
|
||||||
usersToNotify := n._joinedUsers(ev.RoomID())
|
usersToNotify := n._joinedUsers(ev.RoomID().String())
|
||||||
// Map this event's room_id to a list of peeking devices, and wake them up.
|
// Map this event's room_id to a list of peeking devices, and wake them up.
|
||||||
peekingDevicesToNotify := n._peekingDevices(ev.RoomID())
|
peekingDevicesToNotify := n._peekingDevices(ev.RoomID().String())
|
||||||
// If this is an invite, also add in the invitee to this list.
|
// If this is an invite, also add in the invitee to this list.
|
||||||
if ev.Type() == "m.room.member" && ev.StateKey() != nil {
|
if ev.Type() == "m.room.member" && ev.StateKey() != nil {
|
||||||
targetUserID, err := n.rsAPI.QueryUserIDForSender(context.Background(), *validRoomID, spec.SenderID(*ev.StateKey()))
|
targetUserID, err := n.rsAPI.QueryUserIDForSender(context.Background(), ev.RoomID(), spec.SenderID(*ev.StateKey()))
|
||||||
if err != nil || targetUserID == nil {
|
if err != nil || targetUserID == nil {
|
||||||
log.WithError(err).WithField("event_id", ev.EventID()).Errorf(
|
log.WithError(err).WithField("event_id", ev.EventID()).Errorf(
|
||||||
"Notifier.OnNewEvent: Failed to find the userID for this event",
|
"Notifier.OnNewEvent: Failed to find the userID for this event",
|
||||||
|
@ -134,11 +127,11 @@ func (n *Notifier) OnNewEvent(
|
||||||
// Manually append the new user's ID so they get notified
|
// Manually append the new user's ID so they get notified
|
||||||
// along all members in the room
|
// along all members in the room
|
||||||
usersToNotify = append(usersToNotify, targetUserID.String())
|
usersToNotify = append(usersToNotify, targetUserID.String())
|
||||||
n._addJoinedUser(ev.RoomID(), targetUserID.String())
|
n._addJoinedUser(ev.RoomID().String(), targetUserID.String())
|
||||||
case spec.Leave:
|
case spec.Leave:
|
||||||
fallthrough
|
fallthrough
|
||||||
case spec.Ban:
|
case spec.Ban:
|
||||||
n._removeJoinedUser(ev.RoomID(), targetUserID.String())
|
n._removeJoinedUser(ev.RoomID().String(), targetUserID.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,32 +118,19 @@ func GetEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
senderUserID, err := rsAPI.QueryUserIDForSender(req.Context(), *roomID, events[0].SenderID())
|
clientEvent, err := synctypes.ToClientEvent(events[0], synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
if err != nil || senderUserID == nil {
|
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
util.GetLogger(req.Context()).WithError(err).WithField("senderID", events[0].SenderID()).WithField("roomID", *roomID).Error("QueryUserIDForSender errored or returned nil-user ID when user should be part of a room")
|
})
|
||||||
|
if err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).WithField("senderID", events[0].SenderID()).WithField("roomID", *roomID).Error("Failed converting to ClientEvent")
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
JSON: spec.Unknown("internal server error"),
|
JSON: spec.Unknown("internal server error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sk := events[0].StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
evRoomID, err := spec.NewRoomID(events[0].RoomID())
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.BadJSON("roomID is invalid"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
skUserID, err := rsAPI.QueryUserIDForSender(ctx, *evRoomID, spec.SenderID(*events[0].StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: synctypes.ToClientEvent(events[0], synctypes.FormatAll, *senderUserID, sk),
|
JSON: *clientEvent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,15 +152,7 @@ func GetMemberships(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(ev.RoomID())
|
userID, err := rsAPI.QueryUserIDForSender(req.Context(), ev.RoomID(), ev.SenderID())
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("roomID is invalid")
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
JSON: spec.InternalServerError{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userID, err := rsAPI.QueryUserIDForSender(req.Context(), *validRoomID, ev.SenderID())
|
|
||||||
if err != nil || userID == nil {
|
if err != nil || userID == nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryUserIDForSender failed")
|
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryUserIDForSender failed")
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
|
|
@ -130,23 +130,16 @@ func Relations(
|
||||||
// type if it was specified.
|
// type if it was specified.
|
||||||
res.Chunk = make([]synctypes.ClientEvent, 0, len(filteredEvents))
|
res.Chunk = make([]synctypes.ClientEvent, 0, len(filteredEvents))
|
||||||
for _, event := range filteredEvents {
|
for _, event := range filteredEvents {
|
||||||
sender := spec.UserID{}
|
clientEvent, err := synctypes.ToClientEvent(event.PDU, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
userID, err := rsAPI.QueryUserIDForSender(req.Context(), *roomID, event.SenderID())
|
return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID)
|
||||||
if err == nil && userID != nil {
|
})
|
||||||
sender = *userID
|
if err != nil {
|
||||||
}
|
util.GetLogger(req.Context()).WithError(err).WithField("senderID", events[0].SenderID()).WithField("roomID", *roomID).Error("Failed converting to ClientEvent")
|
||||||
|
continue
|
||||||
sk := event.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := rsAPI.QueryUserIDForSender(req.Context(), *roomID, spec.SenderID(*event.StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res.Chunk = append(
|
res.Chunk = append(
|
||||||
res.Chunk,
|
res.Chunk,
|
||||||
synctypes.ToClientEvent(event.PDU, synctypes.FormatAll, sender, sk),
|
*clientEvent,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,12 +205,7 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts
|
||||||
|
|
||||||
profileInfos := make(map[string]ProfileInfoResponse)
|
profileInfos := make(map[string]ProfileInfoResponse)
|
||||||
for _, ev := range append(eventsBefore, eventsAfter...) {
|
for _, ev := range append(eventsBefore, eventsAfter...) {
|
||||||
validRoomID, roomErr := spec.NewRoomID(ev.RoomID())
|
userID, queryErr := rsAPI.QueryUserIDForSender(req.Context(), ev.RoomID(), ev.SenderID())
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(roomErr).WithField("room_id", ev.RoomID()).Warn("failed to query userprofile")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
userID, queryErr := rsAPI.QueryUserIDForSender(req.Context(), *validRoomID, ev.SenderID())
|
|
||||||
if queryErr != nil {
|
if queryErr != nil {
|
||||||
logrus.WithError(queryErr).WithField("sender_id", ev.SenderID()).Warn("failed to query userprofile")
|
logrus.WithError(queryErr).WithField("sender_id", ev.SenderID()).Warn("failed to query userprofile")
|
||||||
continue
|
continue
|
||||||
|
@ -218,7 +213,7 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts
|
||||||
|
|
||||||
profile, ok := knownUsersProfiles[userID.String()]
|
profile, ok := knownUsersProfiles[userID.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
stateEvent, stateErr := snapshot.GetStateEvent(ctx, ev.RoomID(), spec.MRoomMember, string(ev.SenderID()))
|
stateEvent, stateErr := snapshot.GetStateEvent(ctx, ev.RoomID().String(), spec.MRoomMember, string(ev.SenderID()))
|
||||||
if stateErr != nil {
|
if stateErr != nil {
|
||||||
logrus.WithError(stateErr).WithField("sender_id", event.SenderID()).Warn("failed to query userprofile")
|
logrus.WithError(stateErr).WithField("sender_id", event.SenderID()).Warn("failed to query userprofile")
|
||||||
continue
|
continue
|
||||||
|
@ -235,25 +230,14 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts
|
||||||
profileInfos[userID.String()] = profile
|
profileInfos[userID.String()] = profile
|
||||||
}
|
}
|
||||||
|
|
||||||
sender := spec.UserID{}
|
clientEvent, err := synctypes.ToClientEvent(event, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
validRoomID, roomErr := spec.NewRoomID(event.RoomID())
|
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(roomErr).WithField("room_id", event.RoomID()).Warn("failed to query userprofile")
|
util.GetLogger(req.Context()).WithError(err).WithField("senderID", event.SenderID()).Error("Failed converting to ClientEvent")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
userID, err := rsAPI.QueryUserIDForSender(req.Context(), *validRoomID, event.SenderID())
|
|
||||||
if err == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := event.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := rsAPI.QueryUserIDForSender(req.Context(), *validRoomID, spec.SenderID(*event.StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results = append(results, Result{
|
results = append(results, Result{
|
||||||
Context: SearchContextResponse{
|
Context: SearchContextResponse{
|
||||||
Start: startToken.String(),
|
Start: startToken.String(),
|
||||||
|
@ -267,14 +251,14 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts
|
||||||
ProfileInfo: profileInfos,
|
ProfileInfo: profileInfos,
|
||||||
},
|
},
|
||||||
Rank: eventScore[event.EventID()].Score,
|
Rank: eventScore[event.EventID()].Score,
|
||||||
Result: synctypes.ToClientEvent(event, synctypes.FormatAll, sender, sk),
|
Result: *clientEvent,
|
||||||
})
|
})
|
||||||
roomGroup := groups[event.RoomID()]
|
roomGroup := groups[event.RoomID().String()]
|
||||||
roomGroup.Results = append(roomGroup.Results, event.EventID())
|
roomGroup.Results = append(roomGroup.Results, event.EventID())
|
||||||
groups[event.RoomID()] = roomGroup
|
groups[event.RoomID().String()] = roomGroup
|
||||||
if _, ok := stateForRooms[event.RoomID()]; searchReq.SearchCategories.RoomEvents.IncludeState && !ok {
|
if _, ok := stateForRooms[event.RoomID().String()]; searchReq.SearchCategories.RoomEvents.IncludeState && !ok {
|
||||||
stateFilter := synctypes.DefaultStateFilter()
|
stateFilter := synctypes.DefaultStateFilter()
|
||||||
state, err := snapshot.CurrentState(ctx, event.RoomID(), &stateFilter, nil)
|
state, err := snapshot.CurrentState(ctx, event.RoomID().String(), &stateFilter, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("unable to get current state")
|
logrus.WithError(err).Error("unable to get current state")
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
@ -282,7 +266,7 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stateForRooms[event.RoomID()] = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(state), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
stateForRooms[event.RoomID().String()] = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(state), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID)
|
return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -328,19 +312,19 @@ func contextEvents(
|
||||||
roomFilter *synctypes.RoomEventFilter,
|
roomFilter *synctypes.RoomEventFilter,
|
||||||
searchReq SearchRequest,
|
searchReq SearchRequest,
|
||||||
) ([]*types.HeaderedEvent, []*types.HeaderedEvent, error) {
|
) ([]*types.HeaderedEvent, []*types.HeaderedEvent, error) {
|
||||||
id, _, err := snapshot.SelectContextEvent(ctx, event.RoomID(), event.EventID())
|
id, _, err := snapshot.SelectContextEvent(ctx, event.RoomID().String(), event.EventID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("failed to query context event")
|
logrus.WithError(err).Error("failed to query context event")
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
roomFilter.Limit = searchReq.SearchCategories.RoomEvents.EventContext.BeforeLimit
|
roomFilter.Limit = searchReq.SearchCategories.RoomEvents.EventContext.BeforeLimit
|
||||||
eventsBefore, err := snapshot.SelectContextBeforeEvent(ctx, id, event.RoomID(), roomFilter)
|
eventsBefore, err := snapshot.SelectContextBeforeEvent(ctx, id, event.RoomID().String(), roomFilter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("failed to query before context event")
|
logrus.WithError(err).Error("failed to query before context event")
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
roomFilter.Limit = searchReq.SearchCategories.RoomEvents.EventContext.AfterLimit
|
roomFilter.Limit = searchReq.SearchCategories.RoomEvents.EventContext.AfterLimit
|
||||||
_, eventsAfter, err := snapshot.SelectContextAfterEvent(ctx, id, event.RoomID(), roomFilter)
|
_, eventsAfter, err := snapshot.SelectContextAfterEvent(ctx, id, event.RoomID().String(), roomFilter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("failed to query after context event")
|
logrus.WithError(err).Error("failed to query after context event")
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
|
@ -238,7 +238,7 @@ func TestSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
elements = append(elements, fulltext.IndexElement{
|
elements = append(elements, fulltext.IndexElement{
|
||||||
EventID: x.EventID(),
|
EventID: x.EventID(),
|
||||||
RoomID: x.RoomID(),
|
RoomID: x.RoomID().String(),
|
||||||
Content: string(x.Content()),
|
Content: string(x.Content()),
|
||||||
ContentType: x.Type(),
|
ContentType: x.Type(),
|
||||||
StreamPosition: int64(sp),
|
StreamPosition: int64(sp),
|
||||||
|
|
|
@ -340,7 +340,7 @@ func (s *currentRoomStateStatements) UpsertRoomState(
|
||||||
stmt := sqlutil.TxStmt(txn, s.upsertRoomStateStmt)
|
stmt := sqlutil.TxStmt(txn, s.upsertRoomStateStmt)
|
||||||
_, err = stmt.ExecContext(
|
_, err = stmt.ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
event.Type(),
|
event.Type(),
|
||||||
event.UserID.String(),
|
event.UserID.String(),
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (s *inviteEventsStatements) InsertInviteEvent(
|
||||||
|
|
||||||
err = sqlutil.TxStmt(txn, s.insertInviteEventStmt).QueryRowContext(
|
err = sqlutil.TxStmt(txn, s.insertInviteEventStmt).QueryRowContext(
|
||||||
ctx,
|
ctx,
|
||||||
inviteEvent.RoomID(),
|
inviteEvent.RoomID().String(),
|
||||||
inviteEvent.EventID(),
|
inviteEvent.EventID(),
|
||||||
inviteEvent.UserID.String(),
|
inviteEvent.UserID.String(),
|
||||||
headeredJSON,
|
headeredJSON,
|
||||||
|
|
|
@ -108,7 +108,7 @@ func (s *membershipsStatements) UpsertMembership(
|
||||||
}
|
}
|
||||||
_, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext(
|
_, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.StateKeyResolved,
|
event.StateKeyResolved,
|
||||||
membership,
|
membership,
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
|
|
|
@ -334,7 +334,7 @@ func (s *outputRoomEventsStatements) SelectStateInRange(
|
||||||
if err := json.Unmarshal(eventBytes, &ev); err != nil {
|
if err := json.Unmarshal(eventBytes, &ev); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
needSet := stateNeeded[ev.RoomID()]
|
needSet := stateNeeded[ev.RoomID().String()]
|
||||||
if needSet == nil { // make set if required
|
if needSet == nil { // make set if required
|
||||||
needSet = make(map[string]bool)
|
needSet = make(map[string]bool)
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ func (s *outputRoomEventsStatements) SelectStateInRange(
|
||||||
for _, id := range addIDs {
|
for _, id := range addIDs {
|
||||||
needSet[id] = true
|
needSet[id] = true
|
||||||
}
|
}
|
||||||
stateNeeded[ev.RoomID()] = needSet
|
stateNeeded[ev.RoomID().String()] = needSet
|
||||||
ev.Visibility = historyVisibility
|
ev.Visibility = historyVisibility
|
||||||
|
|
||||||
eventIDToEvent[eventID] = types.StreamEvent{
|
eventIDToEvent[eventID] = types.StreamEvent{
|
||||||
|
@ -403,7 +403,7 @@ func (s *outputRoomEventsStatements) InsertEvent(
|
||||||
stmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
stmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
||||||
err = stmt.QueryRowContext(
|
err = stmt.QueryRowContext(
|
||||||
ctx,
|
ctx,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
headeredJSON,
|
headeredJSON,
|
||||||
event.Type(),
|
event.Type(),
|
||||||
|
|
|
@ -107,7 +107,7 @@ func (s *outputRoomEventsTopologyStatements) InsertEventInTopology(
|
||||||
ctx context.Context, txn *sql.Tx, event *rstypes.HeaderedEvent, pos types.StreamPosition,
|
ctx context.Context, txn *sql.Tx, event *rstypes.HeaderedEvent, pos types.StreamPosition,
|
||||||
) (topoPos types.StreamPosition, err error) {
|
) (topoPos types.StreamPosition, err error) {
|
||||||
err = sqlutil.TxStmt(txn, s.insertEventInTopologyStmt).QueryRowContext(
|
err = sqlutil.TxStmt(txn, s.insertEventInTopologyStmt).QueryRowContext(
|
||||||
ctx, event.EventID(), event.Depth(), event.RoomID(), pos,
|
ctx, event.EventID(), event.Depth(), event.RoomID().String(), pos,
|
||||||
).Scan(&topoPos)
|
).Scan(&topoPos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,14 +114,7 @@ func (d *Database) StreamEventsToEvents(ctx context.Context, device *userapi.Dev
|
||||||
}).WithError(err).Warnf("Failed to add transaction ID to event")
|
}).WithError(err).Warnf("Failed to add transaction ID to event")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
roomID, err := spec.NewRoomID(in[i].RoomID())
|
deviceSenderID, err := rsAPI.QuerySenderIDForUser(ctx, in[i].RoomID(), *userID)
|
||||||
if err != nil {
|
|
||||||
logrus.WithFields(logrus.Fields{
|
|
||||||
"event_id": out[i].EventID(),
|
|
||||||
}).WithError(err).Warnf("Room ID is invalid")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
deviceSenderID, err := rsAPI.QuerySenderIDForUser(ctx, *roomID, *userID)
|
|
||||||
if err != nil || deviceSenderID == nil {
|
if err != nil || deviceSenderID == nil {
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"event_id": out[i].EventID(),
|
"event_id": out[i].EventID(),
|
||||||
|
@ -236,7 +229,7 @@ func (d *Database) UpsertAccountData(
|
||||||
// to account for the fact that the given event is no longer a backwards extremity, but may be marked as such.
|
// to account for the fact that the given event is no longer a backwards extremity, but may be marked as such.
|
||||||
// This function should always be called within a sqlutil.Writer for safety in SQLite.
|
// This function should always be called within a sqlutil.Writer for safety in SQLite.
|
||||||
func (d *Database) handleBackwardExtremities(ctx context.Context, txn *sql.Tx, ev *rstypes.HeaderedEvent) error {
|
func (d *Database) handleBackwardExtremities(ctx context.Context, txn *sql.Tx, ev *rstypes.HeaderedEvent) error {
|
||||||
if err := d.BackwardExtremities.DeleteBackwardExtremity(ctx, txn, ev.RoomID(), ev.EventID()); err != nil {
|
if err := d.BackwardExtremities.DeleteBackwardExtremity(ctx, txn, ev.RoomID().String(), ev.EventID()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +250,7 @@ func (d *Database) handleBackwardExtremities(ctx context.Context, txn *sql.Tx, e
|
||||||
|
|
||||||
// If the event is missing, consider it a backward extremity.
|
// If the event is missing, consider it a backward extremity.
|
||||||
if !found {
|
if !found {
|
||||||
if err = d.BackwardExtremities.InsertsBackwardExtremity(ctx, txn, ev.RoomID(), ev.EventID(), eID); err != nil {
|
if err = d.BackwardExtremities.InsertsBackwardExtremity(ctx, txn, ev.RoomID().String(), ev.EventID(), eID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +419,7 @@ func (d *Database) fetchStateEvents(
|
||||||
}
|
}
|
||||||
// we know we got them all otherwise an error would've been returned, so just loop the events
|
// we know we got them all otherwise an error would've been returned, so just loop the events
|
||||||
for _, ev := range evs {
|
for _, ev := range evs {
|
||||||
roomID := ev.RoomID()
|
roomID := ev.RoomID().String()
|
||||||
stateBetween[roomID] = append(stateBetween[roomID], ev)
|
stateBetween[roomID] = append(stateBetween[roomID], ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,11 +515,7 @@ func getMembershipFromEvent(ctx context.Context, ev gomatrixserverlib.PDU, userI
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
roomID, err := spec.NewRoomID(ev.RoomID())
|
senderID, err := rsAPI.QuerySenderIDForUser(ctx, ev.RoomID(), *fullUser)
|
||||||
if err != nil {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
senderID, err := rsAPI.QuerySenderIDForUser(ctx, *roomID, *fullUser)
|
|
||||||
if err != nil || senderID == nil {
|
if err != nil || senderID == nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
@ -626,7 +615,7 @@ func (d *Database) UpdateRelations(ctx context.Context, event *rstypes.HeaderedE
|
||||||
default:
|
default:
|
||||||
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
||||||
return d.Relations.InsertRelation(
|
return d.Relations.InsertRelation(
|
||||||
ctx, txn, event.RoomID(), content.Relations.EventID,
|
ctx, txn, event.RoomID().String(), content.Relations.EventID,
|
||||||
event.EventID(), event.Type(), content.Relations.RelationType,
|
event.EventID(), event.Type(), content.Relations.RelationType,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -339,7 +339,7 @@ func (s *currentRoomStateStatements) UpsertRoomState(
|
||||||
stmt := sqlutil.TxStmt(txn, s.upsertRoomStateStmt)
|
stmt := sqlutil.TxStmt(txn, s.upsertRoomStateStmt)
|
||||||
_, err = stmt.ExecContext(
|
_, err = stmt.ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
event.Type(),
|
event.Type(),
|
||||||
event.UserID.String(),
|
event.UserID.String(),
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (s *inviteEventsStatements) InsertInviteEvent(
|
||||||
_, err = stmt.ExecContext(
|
_, err = stmt.ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
streamPos,
|
streamPos,
|
||||||
inviteEvent.RoomID(),
|
inviteEvent.RoomID().String(),
|
||||||
inviteEvent.EventID(),
|
inviteEvent.EventID(),
|
||||||
inviteEvent.UserID.String(),
|
inviteEvent.UserID.String(),
|
||||||
headeredJSON,
|
headeredJSON,
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (s *membershipsStatements) UpsertMembership(
|
||||||
}
|
}
|
||||||
_, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext(
|
_, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.StateKeyResolved,
|
event.StateKeyResolved,
|
||||||
membership,
|
membership,
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
|
|
|
@ -254,7 +254,7 @@ func (s *outputRoomEventsStatements) SelectStateInRange(
|
||||||
if err := json.Unmarshal(eventBytes, &ev); err != nil {
|
if err := json.Unmarshal(eventBytes, &ev); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
needSet := stateNeeded[ev.RoomID()]
|
needSet := stateNeeded[ev.RoomID().String()]
|
||||||
if needSet == nil { // make set if required
|
if needSet == nil { // make set if required
|
||||||
needSet = make(map[string]bool)
|
needSet = make(map[string]bool)
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ func (s *outputRoomEventsStatements) SelectStateInRange(
|
||||||
for _, id := range addIDs {
|
for _, id := range addIDs {
|
||||||
needSet[id] = true
|
needSet[id] = true
|
||||||
}
|
}
|
||||||
stateNeeded[ev.RoomID()] = needSet
|
stateNeeded[ev.RoomID().String()] = needSet
|
||||||
ev.Visibility = historyVisibility
|
ev.Visibility = historyVisibility
|
||||||
|
|
||||||
eventIDToEvent[eventID] = types.StreamEvent{
|
eventIDToEvent[eventID] = types.StreamEvent{
|
||||||
|
@ -344,7 +344,7 @@ func (s *outputRoomEventsStatements) InsertEvent(
|
||||||
_, err = insertStmt.ExecContext(
|
_, err = insertStmt.ExecContext(
|
||||||
ctx,
|
ctx,
|
||||||
streamPos,
|
streamPos,
|
||||||
event.RoomID(),
|
event.RoomID().String(),
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
headeredJSON,
|
headeredJSON,
|
||||||
event.Type(),
|
event.Type(),
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (s *outputRoomEventsTopologyStatements) InsertEventInTopology(
|
||||||
ctx context.Context, txn *sql.Tx, event *rstypes.HeaderedEvent, pos types.StreamPosition,
|
ctx context.Context, txn *sql.Tx, event *rstypes.HeaderedEvent, pos types.StreamPosition,
|
||||||
) (types.StreamPosition, error) {
|
) (types.StreamPosition, error) {
|
||||||
_, err := sqlutil.TxStmt(txn, s.insertEventInTopologyStmt).ExecContext(
|
_, err := sqlutil.TxStmt(txn, s.insertEventInTopologyStmt).ExecContext(
|
||||||
ctx, event.EventID(), event.Depth(), event.RoomID(), pos,
|
ctx, event.EventID(), event.Depth(), event.RoomID().String(), pos,
|
||||||
)
|
)
|
||||||
return types.StreamPosition(event.Depth()), err
|
return types.StreamPosition(event.Depth()), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,31 +63,27 @@ func (p *InviteStreamProvider) IncrementalSync(
|
||||||
return from
|
return from
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventFormat := synctypes.FormatSync
|
||||||
|
if req.Filter.EventFormat == synctypes.EventFormatFederation {
|
||||||
|
eventFormat = synctypes.FormatSyncFederation
|
||||||
|
}
|
||||||
|
|
||||||
for roomID, inviteEvent := range invites {
|
for roomID, inviteEvent := range invites {
|
||||||
user := spec.UserID{}
|
user := spec.UserID{}
|
||||||
validRoomID, err := spec.NewRoomID(inviteEvent.RoomID())
|
sender, err := p.rsAPI.QueryUserIDForSender(ctx, inviteEvent.RoomID(), inviteEvent.SenderID())
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sender, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, inviteEvent.SenderID())
|
|
||||||
if err == nil && sender != nil {
|
if err == nil && sender != nil {
|
||||||
user = *sender
|
user = *sender
|
||||||
}
|
}
|
||||||
|
|
||||||
sk := inviteEvent.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*inviteEvent.StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip ignored user events
|
// skip ignored user events
|
||||||
if _, ok := req.IgnoredUsers.List[user.String()]; ok {
|
if _, ok := req.IgnoredUsers.List[user.String()]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ir := types.NewInviteResponse(inviteEvent, user, sk)
|
ir, err := types.NewInviteResponse(ctx, p.rsAPI, inviteEvent, eventFormat)
|
||||||
|
if err != nil {
|
||||||
|
req.Log.WithError(err).Error("failed creating invite response")
|
||||||
|
continue
|
||||||
|
}
|
||||||
req.Response.Rooms.Invite[roomID] = ir
|
req.Response.Rooms.Invite[roomID] = ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package streams
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,8 +15,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"github.com/tidwall/sjson"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/syncapi/notifier"
|
"github.com/matrix-org/dendrite/syncapi/notifier"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
@ -88,6 +85,11 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
req.Log.WithError(err).Error("unable to update event filter with ignored users")
|
req.Log.WithError(err).Error("unable to update event filter with ignored users")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventFormat := synctypes.FormatSync
|
||||||
|
if req.Filter.EventFormat == synctypes.EventFormatFederation {
|
||||||
|
eventFormat = synctypes.FormatSyncFederation
|
||||||
|
}
|
||||||
|
|
||||||
recentEvents, err := snapshot.RecentEvents(ctx, joinedRoomIDs, r, &eventFilter, true, true)
|
recentEvents, err := snapshot.RecentEvents(ctx, joinedRoomIDs, r, &eventFilter, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return from
|
return from
|
||||||
|
@ -105,7 +107,7 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
// get the join response for each room
|
// get the join response for each room
|
||||||
jr, jerr := p.getJoinResponseForCompleteSync(
|
jr, jerr := p.getJoinResponseForCompleteSync(
|
||||||
ctx, snapshot, roomID, &stateFilter, req.WantFullState, req.Device, false,
|
ctx, snapshot, roomID, &stateFilter, req.WantFullState, req.Device, false,
|
||||||
events.Events, events.Limited,
|
events.Events, events.Limited, eventFormat,
|
||||||
)
|
)
|
||||||
if jerr != nil {
|
if jerr != nil {
|
||||||
req.Log.WithError(jerr).Error("p.getJoinResponseForCompleteSync failed")
|
req.Log.WithError(jerr).Error("p.getJoinResponseForCompleteSync failed")
|
||||||
|
@ -142,7 +144,7 @@ func (p *PDUStreamProvider) CompleteSync(
|
||||||
events := recentEvents[roomID]
|
events := recentEvents[roomID]
|
||||||
jr, err = p.getJoinResponseForCompleteSync(
|
jr, err = p.getJoinResponseForCompleteSync(
|
||||||
ctx, snapshot, roomID, &stateFilter, req.WantFullState, req.Device, true,
|
ctx, snapshot, roomID, &stateFilter, req.WantFullState, req.Device, true,
|
||||||
events.Events, events.Limited,
|
events.Events, events.Limited, eventFormat,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.Log.WithError(err).Error("p.getJoinResponseForCompleteSync failed")
|
req.Log.WithError(err).Error("p.getJoinResponseForCompleteSync failed")
|
||||||
|
@ -346,26 +348,14 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
return r.From, fmt.Errorf("p.DB.GetBackwardTopologyPos: %w", err)
|
return r.From, fmt.Errorf("p.DB.GetBackwardTopologyPos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventFormat := synctypes.FormatSync
|
||||||
|
if req.Filter.EventFormat == synctypes.EventFormatFederation {
|
||||||
|
eventFormat = synctypes.FormatSyncFederation
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we've filtered the timeline, work out which state events are still
|
// Now that we've filtered the timeline, work out which state events are still
|
||||||
// left. Anything that appears in the filtered timeline will be removed from the
|
// left. Anything that appears in the filtered timeline will be removed from the
|
||||||
// "state" section and kept in "timeline".
|
// "state" section and kept in "timeline".
|
||||||
|
|
||||||
// update the powerlevel event for timeline events
|
|
||||||
for i, ev := range events {
|
|
||||||
if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var newEvent gomatrixserverlib.PDU
|
|
||||||
newEvent, err = p.updatePowerLevelEvent(ctx, ev)
|
|
||||||
if err != nil {
|
|
||||||
return r.From, err
|
|
||||||
}
|
|
||||||
events[i] = &rstypes.HeaderedEvent{PDU: newEvent}
|
|
||||||
}
|
|
||||||
|
|
||||||
sEvents := gomatrixserverlib.HeaderedReverseTopologicalOrdering(
|
sEvents := gomatrixserverlib.HeaderedReverseTopologicalOrdering(
|
||||||
gomatrixserverlib.ToPDUs(removeDuplicates(delta.StateEvents, events)),
|
gomatrixserverlib.ToPDUs(removeDuplicates(delta.StateEvents, events)),
|
||||||
gomatrixserverlib.TopologicalOrderByAuthEvents,
|
gomatrixserverlib.TopologicalOrderByAuthEvents,
|
||||||
|
@ -380,15 +370,6 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delta.StateEvents[i-skipped] = he
|
delta.StateEvents[i-skipped] = he
|
||||||
// update the powerlevel event for state events
|
|
||||||
if ev.Version() == gomatrixserverlib.RoomVersionPseudoIDs && ev.Type() == spec.MRoomPowerLevels && ev.StateKeyEquals("") {
|
|
||||||
var newEvent gomatrixserverlib.PDU
|
|
||||||
newEvent, err = p.updatePowerLevelEvent(ctx, he)
|
|
||||||
if err != nil {
|
|
||||||
return r.From, err
|
|
||||||
}
|
|
||||||
delta.StateEvents[i-skipped] = &rstypes.HeaderedEvent{PDU: newEvent}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delta.StateEvents = delta.StateEvents[:len(sEvents)-skipped]
|
delta.StateEvents = delta.StateEvents[:len(sEvents)-skipped]
|
||||||
|
|
||||||
|
@ -413,13 +394,13 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jr.Timeline.PrevBatch = &prevBatch
|
jr.Timeline.PrevBatch = &prevBatch
|
||||||
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
// If we are limited by the filter AND the history visibility filter
|
// If we are limited by the filter AND the history visibility filter
|
||||||
// didn't "remove" events, return that the response is limited.
|
// didn't "remove" events, return that the response is limited.
|
||||||
jr.Timeline.Limited = (limited && len(events) == len(recentEvents)) || delta.NewlyJoined
|
jr.Timeline.Limited = (limited && len(events) == len(recentEvents)) || delta.NewlyJoined
|
||||||
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
req.Response.Rooms.Join[delta.RoomID] = jr
|
req.Response.Rooms.Join[delta.RoomID] = jr
|
||||||
|
@ -428,11 +409,11 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
jr := types.NewJoinResponse()
|
jr := types.NewJoinResponse()
|
||||||
jr.Timeline.PrevBatch = &prevBatch
|
jr.Timeline.PrevBatch = &prevBatch
|
||||||
// TODO: Apply history visibility on peeked rooms
|
// TODO: Apply history visibility on peeked rooms
|
||||||
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(recentEvents), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(recentEvents), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
jr.Timeline.Limited = limited
|
jr.Timeline.Limited = limited
|
||||||
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
req.Response.Rooms.Peek[delta.RoomID] = jr
|
req.Response.Rooms.Peek[delta.RoomID] = jr
|
||||||
|
@ -443,13 +424,13 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
case spec.Ban:
|
case spec.Ban:
|
||||||
lr := types.NewLeaveResponse()
|
lr := types.NewLeaveResponse()
|
||||||
lr.Timeline.PrevBatch = &prevBatch
|
lr.Timeline.PrevBatch = &prevBatch
|
||||||
lr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
lr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
// If we are limited by the filter AND the history visibility filter
|
// If we are limited by the filter AND the history visibility filter
|
||||||
// didn't "remove" events, return that the response is limited.
|
// didn't "remove" events, return that the response is limited.
|
||||||
lr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
lr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
||||||
lr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
lr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
req.Response.Rooms.Leave[delta.RoomID] = lr
|
req.Response.Rooms.Leave[delta.RoomID] = lr
|
||||||
|
@ -458,75 +439,6 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse(
|
||||||
return latestPosition, nil
|
return latestPosition, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PDUStreamProvider) updatePowerLevelEvent(ctx context.Context, ev *rstypes.HeaderedEvent) (gomatrixserverlib.PDU, error) {
|
|
||||||
pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newPls := make(map[string]int64)
|
|
||||||
var userID *spec.UserID
|
|
||||||
for user, level := range pls.Users {
|
|
||||||
validRoomID, _ := spec.NewRoomID(ev.RoomID())
|
|
||||||
userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newPls[userID.String()] = level
|
|
||||||
}
|
|
||||||
var newPlBytes, newEv []byte
|
|
||||||
newPlBytes, err = json.Marshal(newPls)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newEv, err = sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the same for prev content
|
|
||||||
prevContent := gjson.GetBytes(ev.JSON(), "unsigned.prev_content")
|
|
||||||
if !prevContent.Exists() {
|
|
||||||
var evNew gomatrixserverlib.PDU
|
|
||||||
evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return evNew, err
|
|
||||||
}
|
|
||||||
pls = gomatrixserverlib.PowerLevelContent{}
|
|
||||||
err = json.Unmarshal([]byte(prevContent.Raw), &pls)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
newPls = make(map[string]int64)
|
|
||||||
for user, level := range pls.Users {
|
|
||||||
validRoomID, _ := spec.NewRoomID(ev.RoomID())
|
|
||||||
userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newPls[userID.String()] = level
|
|
||||||
}
|
|
||||||
newPlBytes, err = json.Marshal(newPls)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
newEv, err = sjson.SetRawBytes(newEv, "unsigned.prev_content.users", newPlBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var evNew gomatrixserverlib.PDU
|
|
||||||
evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSONWithEventID(ev.EventID(), newEv, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return evNew, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyHistoryVisibilityFilter gets the current room state and supplies it to ApplyHistoryVisibilityFilter, to make
|
// applyHistoryVisibilityFilter gets the current room state and supplies it to ApplyHistoryVisibilityFilter, to make
|
||||||
// sure we always return the required events in the timeline.
|
// sure we always return the required events in the timeline.
|
||||||
func applyHistoryVisibilityFilter(
|
func applyHistoryVisibilityFilter(
|
||||||
|
@ -592,6 +504,7 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync(
|
||||||
isPeek bool,
|
isPeek bool,
|
||||||
recentStreamEvents []types.StreamEvent,
|
recentStreamEvents []types.StreamEvent,
|
||||||
limited bool,
|
limited bool,
|
||||||
|
eventFormat synctypes.ClientEventFormat,
|
||||||
) (jr *types.JoinResponse, err error) {
|
) (jr *types.JoinResponse, err error) {
|
||||||
jr = types.NewJoinResponse()
|
jr = types.NewJoinResponse()
|
||||||
// TODO: When filters are added, we may need to call this multiple times to get enough events.
|
// TODO: When filters are added, we may need to call this multiple times to get enough events.
|
||||||
|
@ -675,43 +588,14 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync(
|
||||||
prevBatch.Decrement()
|
prevBatch.Decrement()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update powerlevel events for timeline events
|
|
||||||
for i, ev := range events {
|
|
||||||
if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newEvent, err := p.updatePowerLevelEvent(ctx, ev)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
events[i] = &rstypes.HeaderedEvent{PDU: newEvent}
|
|
||||||
}
|
|
||||||
// Update powerlevel events for state events
|
|
||||||
for i, ev := range stateEvents {
|
|
||||||
if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newEvent, err := p.updatePowerLevelEvent(ctx, ev)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
stateEvents[i] = &rstypes.HeaderedEvent{PDU: newEvent}
|
|
||||||
}
|
|
||||||
|
|
||||||
jr.Timeline.PrevBatch = prevBatch
|
jr.Timeline.PrevBatch = prevBatch
|
||||||
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
// If we are limited by the filter AND the history visibility filter
|
// If we are limited by the filter AND the history visibility filter
|
||||||
// didn't "remove" events, return that the response is limited.
|
// didn't "remove" events, return that the response is limited.
|
||||||
jr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
jr.Timeline.Limited = limited && len(events) == len(recentEvents)
|
||||||
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(stateEvents), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(stateEvents), eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
})
|
})
|
||||||
return jr, nil
|
return jr, nil
|
||||||
|
|
|
@ -209,6 +209,156 @@ func testSyncAccessTokens(t *testing.T, dbType test.DBType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSyncAPIEventFormatPowerLevels(t *testing.T) {
|
||||||
|
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
||||||
|
testSyncEventFormatPowerLevels(t, dbType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSyncEventFormatPowerLevels(t *testing.T, dbType test.DBType) {
|
||||||
|
user := test.NewUser(t)
|
||||||
|
setRoomVersion := func(t *testing.T, r *test.Room) { r.Version = gomatrixserverlib.RoomVersionPseudoIDs }
|
||||||
|
room := test.NewRoom(t, user, setRoomVersion)
|
||||||
|
alice := userapi.Device{
|
||||||
|
ID: "ALICEID",
|
||||||
|
UserID: user.ID,
|
||||||
|
AccessToken: "ALICE_BEARER_TOKEN",
|
||||||
|
DisplayName: "Alice",
|
||||||
|
AccountType: userapi.AccountTypeUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
room.CreateAndInsert(t, user, spec.MRoomPowerLevels, gomatrixserverlib.PowerLevelContent{
|
||||||
|
Users: map[string]int64{
|
||||||
|
user.ID: 100,
|
||||||
|
},
|
||||||
|
}, test.WithStateKey(""))
|
||||||
|
|
||||||
|
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
|
||||||
|
routers := httputil.NewRouters()
|
||||||
|
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
|
||||||
|
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
|
||||||
|
natsInstance := jetstream.NATSInstance{}
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
|
||||||
|
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
|
||||||
|
msgs := toNATSMsgs(t, cfg, room.Events()...)
|
||||||
|
AddPublicRoutes(processCtx, routers, cfg, cm, &natsInstance, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{rooms: []*test.Room{room}}, caches, caching.DisableMetrics)
|
||||||
|
testrig.MustPublishMsgs(t, jsctx, msgs...)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
wantCode int
|
||||||
|
wantJoinedRooms []string
|
||||||
|
eventFormat synctypes.ClientEventFormat
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Client format",
|
||||||
|
wantCode: 200,
|
||||||
|
wantJoinedRooms: []string{room.ID},
|
||||||
|
eventFormat: synctypes.FormatSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Federation format",
|
||||||
|
wantCode: 200,
|
||||||
|
wantJoinedRooms: []string{room.ID},
|
||||||
|
eventFormat: synctypes.FormatSyncFederation,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
syncUntil(t, routers, alice.AccessToken, false, func(syncBody string) bool {
|
||||||
|
// wait for the last sent eventID to come down sync
|
||||||
|
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(event_id=="%s")`, room.ID, room.Events()[len(room.Events())-1].EventID())
|
||||||
|
return gjson.Get(syncBody, path).Exists()
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
format := ""
|
||||||
|
if tc.eventFormat == synctypes.FormatSyncFederation {
|
||||||
|
format = "federation"
|
||||||
|
}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
|
||||||
|
"access_token": alice.AccessToken,
|
||||||
|
"timeout": "0",
|
||||||
|
"filter": fmt.Sprintf(`{"event_format":"%s"}`, format),
|
||||||
|
})))
|
||||||
|
if w.Code != tc.wantCode {
|
||||||
|
t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode)
|
||||||
|
}
|
||||||
|
if tc.wantJoinedRooms != nil {
|
||||||
|
var res types.Response
|
||||||
|
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||||
|
t.Fatalf("%s: failed to decode response body: %s", tc.name, err)
|
||||||
|
}
|
||||||
|
if len(res.Rooms.Join) != len(tc.wantJoinedRooms) {
|
||||||
|
t.Errorf("%s: got %v joined rooms, want %v.\nResponse: %+v", tc.name, len(res.Rooms.Join), len(tc.wantJoinedRooms), res)
|
||||||
|
}
|
||||||
|
t.Logf("res: %+v", res.Rooms.Join[room.ID])
|
||||||
|
|
||||||
|
gotEventIDs := make([]string, len(res.Rooms.Join[room.ID].Timeline.Events))
|
||||||
|
for i, ev := range res.Rooms.Join[room.ID].Timeline.Events {
|
||||||
|
gotEventIDs[i] = ev.EventID
|
||||||
|
}
|
||||||
|
test.AssertEventIDsEqual(t, gotEventIDs, room.Events())
|
||||||
|
|
||||||
|
event := room.CreateAndInsert(t, user, spec.MRoomPowerLevels, gomatrixserverlib.PowerLevelContent{
|
||||||
|
Users: map[string]int64{
|
||||||
|
user.ID: 100,
|
||||||
|
"@otheruser:localhost": 50,
|
||||||
|
},
|
||||||
|
}, test.WithStateKey(""))
|
||||||
|
|
||||||
|
msgs := toNATSMsgs(t, cfg, event)
|
||||||
|
testrig.MustPublishMsgs(t, jsctx, msgs...)
|
||||||
|
|
||||||
|
syncUntil(t, routers, alice.AccessToken, false, func(syncBody string) bool {
|
||||||
|
// wait for the last sent eventID to come down sync
|
||||||
|
path := fmt.Sprintf(`rooms.join.%s.timeline.events.#(event_id=="%s")`, room.ID, room.Events()[len(room.Events())-1].EventID())
|
||||||
|
return gjson.Get(syncBody, path).Exists()
|
||||||
|
})
|
||||||
|
|
||||||
|
since := res.NextBatch.String()
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
|
||||||
|
"access_token": alice.AccessToken,
|
||||||
|
"timeout": "0",
|
||||||
|
"filter": fmt.Sprintf(`{"event_format":"%s"}`, format),
|
||||||
|
"since": since,
|
||||||
|
})))
|
||||||
|
if w.Code != 200 {
|
||||||
|
t.Errorf("since=%s got HTTP %d want 200", since, w.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
res = *types.NewResponse()
|
||||||
|
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
||||||
|
t.Errorf("failed to decode response body: %s", err)
|
||||||
|
}
|
||||||
|
if len(res.Rooms.Join) != 1 {
|
||||||
|
t.Fatalf("since=%s got %d joined rooms, want 1", since, len(res.Rooms.Join))
|
||||||
|
}
|
||||||
|
gotEventIDs = make([]string, len(res.Rooms.Join[room.ID].Timeline.Events))
|
||||||
|
for j, ev := range res.Rooms.Join[room.ID].Timeline.Events {
|
||||||
|
gotEventIDs[j] = ev.EventID
|
||||||
|
if ev.Type == spec.MRoomPowerLevels {
|
||||||
|
content := gomatrixserverlib.PowerLevelContent{}
|
||||||
|
err := json.Unmarshal(ev.Content, &content)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to unmarshal power level content: %s", err)
|
||||||
|
}
|
||||||
|
otherUserLevel := content.UserLevel("@otheruser:localhost")
|
||||||
|
if otherUserLevel != 50 {
|
||||||
|
t.Errorf("Expected user PL of %d but got %d", 50, otherUserLevel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
events := []*rstypes.HeaderedEvent{room.Events()[len(room.Events())-1]}
|
||||||
|
test.AssertEventIDsEqual(t, gotEventIDs, events)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests what happens when we create a room and then /sync before all events from /createRoom have
|
// Tests what happens when we create a room and then /sync before all events from /createRoom have
|
||||||
// been sent to the syncapi
|
// been sent to the syncapi
|
||||||
func TestSyncAPICreateRoomSyncEarly(t *testing.T) {
|
func TestSyncAPICreateRoomSyncEarly(t *testing.T) {
|
||||||
|
@ -1251,7 +1401,7 @@ func toNATSMsgs(t *testing.T, cfg *config.Dendrite, input ...*rstypes.HeaderedEv
|
||||||
if ev.StateKey() != nil {
|
if ev.StateKey() != nil {
|
||||||
addsStateIDs = append(addsStateIDs, ev.EventID())
|
addsStateIDs = append(addsStateIDs, ev.EventID())
|
||||||
}
|
}
|
||||||
result[i] = testrig.NewOutputEventMsg(t, cfg, ev.RoomID(), api.OutputEvent{
|
result[i] = testrig.NewOutputEventMsg(t, cfg, ev.RoomID().String(), api.OutputEvent{
|
||||||
Type: rsapi.OutputTypeNewRoomEvent,
|
Type: rsapi.OutputTypeNewRoomEvent,
|
||||||
NewRoomEvent: &rsapi.OutputNewRoomEvent{
|
NewRoomEvent: &rsapi.OutputNewRoomEvent{
|
||||||
Event: ev,
|
Event: ev,
|
||||||
|
|
|
@ -16,12 +16,23 @@
|
||||||
package synctypes
|
package synctypes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PrevEventRef represents a reference to a previous event in a state event upgrade
|
||||||
|
type PrevEventRef struct {
|
||||||
|
PrevContent json.RawMessage `json:"prev_content"`
|
||||||
|
ReplacesState string `json:"replaces_state"`
|
||||||
|
PrevSenderID string `json:"prev_sender"`
|
||||||
|
}
|
||||||
|
|
||||||
type ClientEventFormat int
|
type ClientEventFormat int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -30,8 +41,21 @@ const (
|
||||||
// FormatSync will include only the event keys required by the /sync API. Notably, this
|
// FormatSync will include only the event keys required by the /sync API. Notably, this
|
||||||
// means the 'room_id' will be missing from the events.
|
// means the 'room_id' will be missing from the events.
|
||||||
FormatSync
|
FormatSync
|
||||||
|
// FormatSyncFederation will include all event keys normally included in federated events.
|
||||||
|
// This allows clients to request federated formatted events via the /sync API.
|
||||||
|
FormatSyncFederation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ClientFederationFields extends a ClientEvent to contain the additional fields present in a
|
||||||
|
// federation event. Used when the client requests `event_format` of type `federation`.
|
||||||
|
type ClientFederationFields struct {
|
||||||
|
Depth int64 `json:"depth,omitempty"`
|
||||||
|
PrevEvents []string `json:"prev_events,omitempty"`
|
||||||
|
AuthEvents []string `json:"auth_events,omitempty"`
|
||||||
|
Signatures spec.RawJSON `json:"signatures,omitempty"`
|
||||||
|
Hashes spec.RawJSON `json:"hashes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ClientEvent is an event which is fit for consumption by clients, in accordance with the specification.
|
// ClientEvent is an event which is fit for consumption by clients, in accordance with the specification.
|
||||||
type ClientEvent struct {
|
type ClientEvent struct {
|
||||||
Content spec.RawJSON `json:"content"`
|
Content spec.RawJSON `json:"content"`
|
||||||
|
@ -44,6 +68,9 @@ type ClientEvent struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Unsigned spec.RawJSON `json:"unsigned,omitempty"`
|
Unsigned spec.RawJSON `json:"unsigned,omitempty"`
|
||||||
Redacts string `json:"redacts,omitempty"`
|
Redacts string `json:"redacts,omitempty"`
|
||||||
|
|
||||||
|
// Only sent to clients when `event_format` == `federation`.
|
||||||
|
ClientFederationFields
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToClientEvents converts server events to client events.
|
// ToClientEvents converts server events to client events.
|
||||||
|
@ -53,72 +80,24 @@ func ToClientEvents(serverEvs []gomatrixserverlib.PDU, format ClientEventFormat,
|
||||||
if se == nil {
|
if se == nil {
|
||||||
continue // TODO: shouldn't happen?
|
continue // TODO: shouldn't happen?
|
||||||
}
|
}
|
||||||
sender := spec.UserID{}
|
ev, err := ToClientEvent(se, format, userIDForSender)
|
||||||
validRoomID, err := spec.NewRoomID(se.RoomID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logrus.WithError(err).Warn("Failed converting event to ClientEvent")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
userID, err := userIDForSender(*validRoomID, se.SenderID())
|
evs = append(evs, *ev)
|
||||||
if err == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := se.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := userIDForSender(*validRoomID, spec.SenderID(*sk))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
evs = append(evs, ToClientEvent(se, format, sender, sk))
|
|
||||||
}
|
}
|
||||||
return evs
|
return evs
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToClientEvent converts a single server event to a client event.
|
// ToClientEventDefault converts a single server event to a client event.
|
||||||
func ToClientEvent(se gomatrixserverlib.PDU, format ClientEventFormat, sender spec.UserID, stateKey *string) ClientEvent {
|
|
||||||
ce := ClientEvent{
|
|
||||||
Content: spec.RawJSON(se.Content()),
|
|
||||||
Sender: sender.String(),
|
|
||||||
Type: se.Type(),
|
|
||||||
StateKey: stateKey,
|
|
||||||
Unsigned: spec.RawJSON(se.Unsigned()),
|
|
||||||
OriginServerTS: se.OriginServerTS(),
|
|
||||||
EventID: se.EventID(),
|
|
||||||
Redacts: se.Redacts(),
|
|
||||||
}
|
|
||||||
if format == FormatAll {
|
|
||||||
ce.RoomID = se.RoomID()
|
|
||||||
}
|
|
||||||
if se.Version() == gomatrixserverlib.RoomVersionPseudoIDs {
|
|
||||||
ce.SenderKey = se.SenderID()
|
|
||||||
}
|
|
||||||
return ce
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToClientEvent converts a single server event to a client event.
|
|
||||||
// It provides default logic for event.SenderID & event.StateKey -> userID conversions.
|
// It provides default logic for event.SenderID & event.StateKey -> userID conversions.
|
||||||
func ToClientEventDefault(userIDQuery spec.UserIDForSender, event gomatrixserverlib.PDU) ClientEvent {
|
func ToClientEventDefault(userIDQuery spec.UserIDForSender, event gomatrixserverlib.PDU) ClientEvent {
|
||||||
sender := spec.UserID{}
|
ev, err := ToClientEvent(event, FormatAll, userIDQuery)
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ClientEvent{}
|
return ClientEvent{}
|
||||||
}
|
}
|
||||||
userID, err := userIDQuery(*validRoomID, event.SenderID())
|
return *ev
|
||||||
if err == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := event.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, err := userIDQuery(*validRoomID, spec.SenderID(*event.StateKey()))
|
|
||||||
if err == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ToClientEvent(event, FormatAll, sender, sk)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If provided state key is a user ID (state keys beginning with @ are reserved for this purpose)
|
// If provided state key is a user ID (state keys beginning with @ are reserved for this purpose)
|
||||||
|
@ -132,11 +111,11 @@ func FromClientStateKey(roomID spec.RoomID, stateKey string, senderIDQuery spec.
|
||||||
parsedStateKey, err := spec.NewUserID(stateKey, true)
|
parsedStateKey, err := spec.NewUserID(stateKey, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If invalid user ID, then there is no associated state event.
|
// If invalid user ID, then there is no associated state event.
|
||||||
return nil, fmt.Errorf("Provided state key begins with @ but is not a valid user ID: %s", err.Error())
|
return nil, fmt.Errorf("Provided state key begins with @ but is not a valid user ID: %w", err)
|
||||||
}
|
}
|
||||||
senderID, err := senderIDQuery(roomID, *parsedStateKey)
|
senderID, err := senderIDQuery(roomID, *parsedStateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to query sender ID: %s", err.Error())
|
return nil, fmt.Errorf("Failed to query sender ID: %w", err)
|
||||||
}
|
}
|
||||||
if senderID == nil {
|
if senderID == nil {
|
||||||
// If no sender ID, then there is no associated state event.
|
// If no sender ID, then there is no associated state event.
|
||||||
|
@ -148,3 +127,304 @@ func FromClientStateKey(roomID spec.RoomID, stateKey string, senderIDQuery spec.
|
||||||
return &stateKey, nil
|
return &stateKey, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToClientEvent converts a single server event to a client event.
|
||||||
|
func ToClientEvent(se gomatrixserverlib.PDU, format ClientEventFormat, userIDForSender spec.UserIDForSender) (*ClientEvent, error) {
|
||||||
|
ce := ClientEvent{
|
||||||
|
Content: se.Content(),
|
||||||
|
Sender: string(se.SenderID()),
|
||||||
|
Type: se.Type(),
|
||||||
|
StateKey: se.StateKey(),
|
||||||
|
Unsigned: se.Unsigned(),
|
||||||
|
OriginServerTS: se.OriginServerTS(),
|
||||||
|
EventID: se.EventID(),
|
||||||
|
Redacts: se.Redacts(),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch format {
|
||||||
|
case FormatAll:
|
||||||
|
ce.RoomID = se.RoomID().String()
|
||||||
|
case FormatSync:
|
||||||
|
case FormatSyncFederation:
|
||||||
|
ce.RoomID = se.RoomID().String()
|
||||||
|
ce.AuthEvents = se.AuthEventIDs()
|
||||||
|
ce.PrevEvents = se.PrevEventIDs()
|
||||||
|
ce.Depth = se.Depth()
|
||||||
|
// TODO: Set Signatures & Hashes fields
|
||||||
|
}
|
||||||
|
|
||||||
|
if format != FormatSyncFederation && se.Version() == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||||
|
err := updatePseudoIDs(&ce, se, userIDForSender, format)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ce, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePseudoIDs(ce *ClientEvent, se gomatrixserverlib.PDU, userIDForSender spec.UserIDForSender, format ClientEventFormat) error {
|
||||||
|
ce.SenderKey = se.SenderID()
|
||||||
|
|
||||||
|
userID, err := userIDForSender(se.RoomID(), se.SenderID())
|
||||||
|
if err == nil && userID != nil {
|
||||||
|
ce.Sender = userID.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
sk := se.StateKey()
|
||||||
|
if sk != nil && *sk != "" {
|
||||||
|
skUserID, err := userIDForSender(se.RoomID(), spec.SenderID(*sk))
|
||||||
|
if err == nil && skUserID != nil {
|
||||||
|
skString := skUserID.String()
|
||||||
|
ce.StateKey = &skString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var prev PrevEventRef
|
||||||
|
if err := json.Unmarshal(se.Unsigned(), &prev); err == nil && prev.PrevSenderID != "" {
|
||||||
|
prevUserID, err := userIDForSender(se.RoomID(), spec.SenderID(prev.PrevSenderID))
|
||||||
|
if err == nil && userID != nil {
|
||||||
|
prev.PrevSenderID = prevUserID.String()
|
||||||
|
} else {
|
||||||
|
errString := "userID unknown"
|
||||||
|
if err != nil {
|
||||||
|
errString = err.Error()
|
||||||
|
}
|
||||||
|
logrus.Warnf("Failed to find userID for prev_sender in ClientEvent: %s", errString)
|
||||||
|
// NOTE: Not much can be done here, so leave the previous value in place.
|
||||||
|
}
|
||||||
|
ce.Unsigned, err = json.Marshal(prev)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to marshal unsigned content for ClientEvent: %w", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch se.Type() {
|
||||||
|
case spec.MRoomCreate:
|
||||||
|
updatedContent, err := updateCreateEvent(se.Content(), userIDForSender, se.RoomID())
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to update m.room.create event for ClientEvent: %w", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ce.Content = updatedContent
|
||||||
|
case spec.MRoomMember:
|
||||||
|
updatedEvent, err := updateInviteEvent(userIDForSender, se, format)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to update m.room.member event for ClientEvent: %w", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if updatedEvent != nil {
|
||||||
|
ce.Unsigned = updatedEvent.Unsigned()
|
||||||
|
}
|
||||||
|
case spec.MRoomPowerLevels:
|
||||||
|
updatedEvent, err := updatePowerLevelEvent(userIDForSender, se, format)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed update m.room.power_levels event for ClientEvent: %w", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if updatedEvent != nil {
|
||||||
|
ce.Content = updatedEvent.Content()
|
||||||
|
ce.Unsigned = updatedEvent.Unsigned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCreateEvent(content spec.RawJSON, userIDForSender spec.UserIDForSender, roomID spec.RoomID) (spec.RawJSON, error) {
|
||||||
|
if creator := gjson.GetBytes(content, "creator"); creator.Exists() {
|
||||||
|
oldCreator := creator.Str
|
||||||
|
userID, err := userIDForSender(roomID, spec.SenderID(oldCreator))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to find userID for creator in ClientEvent: %w", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if userID != nil {
|
||||||
|
var newCreatorBytes, newContent []byte
|
||||||
|
newCreatorBytes, err = json.Marshal(userID.String())
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to marshal new creator for ClientEvent: %w", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newContent, err = sjson.SetRawBytes([]byte(content), "creator", newCreatorBytes)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to set new creator for ClientEvent: %w", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newContent, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateInviteEvent(userIDForSender spec.UserIDForSender, ev gomatrixserverlib.PDU, eventFormat ClientEventFormat) (gomatrixserverlib.PDU, error) {
|
||||||
|
if inviteRoomState := gjson.GetBytes(ev.Unsigned(), "invite_room_state"); inviteRoomState.Exists() {
|
||||||
|
userID, err := userIDForSender(ev.RoomID(), ev.SenderID())
|
||||||
|
if err != nil || userID == nil {
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("invalid userID found when updating invite_room_state: %w", err)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newState, err := GetUpdatedInviteRoomState(userIDForSender, inviteRoomState, ev, ev.RoomID(), eventFormat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var newEv []byte
|
||||||
|
newEv, err = sjson.SetRawBytes(ev.JSON(), "unsigned.invite_room_state", newState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gomatrixserverlib.MustGetRoomVersion(ev.Version()).NewEventFromTrustedJSON(newEv, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type InviteRoomStateEvent struct {
|
||||||
|
Content spec.RawJSON `json:"content"`
|
||||||
|
SenderID string `json:"sender"`
|
||||||
|
StateKey *string `json:"state_key"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUpdatedInviteRoomState(userIDForSender spec.UserIDForSender, inviteRoomState gjson.Result, event gomatrixserverlib.PDU, roomID spec.RoomID, eventFormat ClientEventFormat) (spec.RawJSON, error) {
|
||||||
|
var res spec.RawJSON
|
||||||
|
inviteStateEvents := []InviteRoomStateEvent{}
|
||||||
|
err := json.Unmarshal([]byte(inviteRoomState.Raw), &inviteStateEvents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Version() == gomatrixserverlib.RoomVersionPseudoIDs && eventFormat != FormatSyncFederation {
|
||||||
|
for i, ev := range inviteStateEvents {
|
||||||
|
userID, userIDErr := userIDForSender(roomID, spec.SenderID(ev.SenderID))
|
||||||
|
if userIDErr != nil {
|
||||||
|
return nil, userIDErr
|
||||||
|
}
|
||||||
|
if userID != nil {
|
||||||
|
inviteStateEvents[i].SenderID = userID.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ev.StateKey != nil && *ev.StateKey != "" {
|
||||||
|
userID, senderErr := userIDForSender(roomID, spec.SenderID(*ev.StateKey))
|
||||||
|
if senderErr != nil {
|
||||||
|
return nil, senderErr
|
||||||
|
}
|
||||||
|
if userID != nil {
|
||||||
|
user := userID.String()
|
||||||
|
inviteStateEvents[i].StateKey = &user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedContent, updateErr := updateCreateEvent(ev.Content, userIDForSender, roomID)
|
||||||
|
if updateErr != nil {
|
||||||
|
updateErr = fmt.Errorf("Failed to update m.room.create event for ClientEvent: %w", userIDErr)
|
||||||
|
return nil, updateErr
|
||||||
|
}
|
||||||
|
inviteStateEvents[i].Content = updatedContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = json.Marshal(inviteStateEvents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePowerLevelEvent(userIDForSender spec.UserIDForSender, se gomatrixserverlib.PDU, eventFormat ClientEventFormat) (gomatrixserverlib.PDU, error) {
|
||||||
|
if !se.StateKeyEquals("") {
|
||||||
|
return se, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
newEv := se.JSON()
|
||||||
|
|
||||||
|
usersField := gjson.GetBytes(se.JSON(), "content.users")
|
||||||
|
if usersField.Exists() {
|
||||||
|
pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(se)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newPls := make(map[string]int64)
|
||||||
|
var userID *spec.UserID
|
||||||
|
for user, level := range pls.Users {
|
||||||
|
if eventFormat != FormatSyncFederation {
|
||||||
|
userID, err = userIDForSender(se.RoomID(), spec.SenderID(user))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user = userID.String()
|
||||||
|
}
|
||||||
|
newPls[user] = level
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPlBytes []byte
|
||||||
|
newPlBytes, err = json.Marshal(newPls)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newEv, err = sjson.SetRawBytes(se.JSON(), "content.users", newPlBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the same for prev content
|
||||||
|
prevUsersField := gjson.GetBytes(se.JSON(), "unsigned.prev_content.users")
|
||||||
|
if prevUsersField.Exists() {
|
||||||
|
prevContent := gjson.GetBytes(se.JSON(), "unsigned.prev_content")
|
||||||
|
if !prevContent.Exists() {
|
||||||
|
evNew, err := gomatrixserverlib.MustGetRoomVersion(se.Version()).NewEventFromTrustedJSON(newEv, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return evNew, err
|
||||||
|
}
|
||||||
|
pls := gomatrixserverlib.PowerLevelContent{}
|
||||||
|
err := json.Unmarshal([]byte(prevContent.Raw), &pls)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newPls := make(map[string]int64)
|
||||||
|
for user, level := range pls.Users {
|
||||||
|
if eventFormat != FormatSyncFederation {
|
||||||
|
userID, userErr := userIDForSender(se.RoomID(), spec.SenderID(user))
|
||||||
|
if userErr != nil {
|
||||||
|
return nil, userErr
|
||||||
|
}
|
||||||
|
user = userID.String()
|
||||||
|
}
|
||||||
|
newPls[user] = level
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPlBytes []byte
|
||||||
|
newPlBytes, err = json.Marshal(newPls)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newEv, err = sjson.SetRawBytes(newEv, "unsigned.prev_content.users", newPlBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evNew, err := gomatrixserverlib.MustGetRoomVersion(se.Version()).NewEventFromTrustedJSONWithEventID(se.EventID(), newEv, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return evNew, err
|
||||||
|
}
|
||||||
|
|
|
@ -18,12 +18,77 @@ package synctypes
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func queryUserIDForSender(senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
if senderID == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.NewUserID(string(senderID), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const testSenderID = "testSenderID"
|
||||||
|
const testUserID = "@test:localhost"
|
||||||
|
|
||||||
|
type EventFieldsToVerify struct {
|
||||||
|
EventID string
|
||||||
|
Type string
|
||||||
|
OriginServerTS spec.Timestamp
|
||||||
|
StateKey *string
|
||||||
|
Content spec.RawJSON
|
||||||
|
Unsigned spec.RawJSON
|
||||||
|
Sender string
|
||||||
|
Depth int64
|
||||||
|
PrevEvents []string
|
||||||
|
AuthEvents []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyEventFields(t *testing.T, got EventFieldsToVerify, want EventFieldsToVerify) {
|
||||||
|
if got.EventID != want.EventID {
|
||||||
|
t.Errorf("ClientEvent.EventID: wanted %s, got %s", want.EventID, got.EventID)
|
||||||
|
}
|
||||||
|
if got.OriginServerTS != want.OriginServerTS {
|
||||||
|
t.Errorf("ClientEvent.OriginServerTS: wanted %d, got %d", want.OriginServerTS, got.OriginServerTS)
|
||||||
|
}
|
||||||
|
if got.StateKey == nil && want.StateKey != nil {
|
||||||
|
t.Errorf("ClientEvent.StateKey: no state key present when one was wanted: %s", *want.StateKey)
|
||||||
|
}
|
||||||
|
if got.StateKey != nil && want.StateKey == nil {
|
||||||
|
t.Errorf("ClientEvent.StateKey: state key present when one was not wanted: %s", *got.StateKey)
|
||||||
|
}
|
||||||
|
if got.StateKey != nil && want.StateKey != nil && *got.StateKey != *want.StateKey {
|
||||||
|
t.Errorf("ClientEvent.StateKey: wanted %s, got %s", *want.StateKey, *got.StateKey)
|
||||||
|
}
|
||||||
|
if got.Type != want.Type {
|
||||||
|
t.Errorf("ClientEvent.Type: wanted %s, got %s", want.Type, got.Type)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(got.Content, want.Content) {
|
||||||
|
t.Errorf("ClientEvent.Content: wanted %s, got %s", string(want.Content), string(got.Content))
|
||||||
|
}
|
||||||
|
if !bytes.Equal(got.Unsigned, want.Unsigned) {
|
||||||
|
t.Errorf("ClientEvent.Unsigned: wanted %s, got %s", string(want.Unsigned), string(got.Unsigned))
|
||||||
|
}
|
||||||
|
if got.Sender != want.Sender {
|
||||||
|
t.Errorf("ClientEvent.Sender: wanted %s, got %s", want.Sender, got.Sender)
|
||||||
|
}
|
||||||
|
if got.Depth != want.Depth {
|
||||||
|
t.Errorf("ClientEvent.Depth: wanted %d, got %d", want.Depth, got.Depth)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got.PrevEvents, want.PrevEvents) {
|
||||||
|
t.Errorf("ClientEvent.PrevEvents: wanted %v, got %v", want.PrevEvents, got.PrevEvents)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got.AuthEvents, want.AuthEvents) {
|
||||||
|
t.Errorf("ClientEvent.AuthEvents: wanted %v, got %v", want.AuthEvents, got.AuthEvents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestToClientEvent(t *testing.T) { // nolint: gocyclo
|
func TestToClientEvent(t *testing.T) { // nolint: gocyclo
|
||||||
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV1).NewEventFromTrustedJSON([]byte(`{
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV1).NewEventFromTrustedJSON([]byte(`{
|
||||||
"type": "m.room.name",
|
"type": "m.room.name",
|
||||||
|
@ -49,28 +114,33 @@ func TestToClientEvent(t *testing.T) { // nolint: gocyclo
|
||||||
t.Fatalf("failed to create userID: %s", err)
|
t.Fatalf("failed to create userID: %s", err)
|
||||||
}
|
}
|
||||||
sk := ""
|
sk := ""
|
||||||
ce := ToClientEvent(ev, FormatAll, *userID, &sk)
|
ce, err := ToClientEvent(ev, FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
if ce.EventID != ev.EventID() {
|
return queryUserIDForSender(senderID)
|
||||||
t.Errorf("ClientEvent.EventID: wanted %s, got %s", ev.EventID(), ce.EventID)
|
})
|
||||||
}
|
if err != nil {
|
||||||
if ce.OriginServerTS != ev.OriginServerTS() {
|
t.Fatalf("failed to create ClientEvent: %s", err)
|
||||||
t.Errorf("ClientEvent.OriginServerTS: wanted %d, got %d", ev.OriginServerTS(), ce.OriginServerTS)
|
|
||||||
}
|
|
||||||
if ce.StateKey == nil || *ce.StateKey != "" {
|
|
||||||
t.Errorf("ClientEvent.StateKey: wanted '', got %v", ce.StateKey)
|
|
||||||
}
|
|
||||||
if ce.Type != ev.Type() {
|
|
||||||
t.Errorf("ClientEvent.Type: wanted %s, got %s", ev.Type(), ce.Type)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(ce.Content, ev.Content()) {
|
|
||||||
t.Errorf("ClientEvent.Content: wanted %s, got %s", string(ev.Content()), string(ce.Content))
|
|
||||||
}
|
|
||||||
if !bytes.Equal(ce.Unsigned, ev.Unsigned()) {
|
|
||||||
t.Errorf("ClientEvent.Unsigned: wanted %s, got %s", string(ev.Unsigned()), string(ce.Unsigned))
|
|
||||||
}
|
|
||||||
if ce.Sender != userID.String() {
|
|
||||||
t.Errorf("ClientEvent.Sender: wanted %s, got %s", userID.String(), ce.Sender)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce.EventID,
|
||||||
|
Type: ce.Type,
|
||||||
|
OriginServerTS: ce.OriginServerTS,
|
||||||
|
StateKey: ce.StateKey,
|
||||||
|
Content: ce.Content,
|
||||||
|
Unsigned: ce.Unsigned,
|
||||||
|
Sender: ce.Sender,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev.EventID(),
|
||||||
|
Type: ev.Type(),
|
||||||
|
OriginServerTS: ev.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev.Content(),
|
||||||
|
Unsigned: ev.Unsigned(),
|
||||||
|
Sender: userID.String(),
|
||||||
|
})
|
||||||
|
|
||||||
j, err := json.Marshal(ce)
|
j, err := json.Marshal(ce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to Marshal ClientEvent: %s", err)
|
t.Fatalf("failed to Marshal ClientEvent: %s", err)
|
||||||
|
@ -104,13 +174,388 @@ func TestToClientFormatSync(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create Event: %s", err)
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
}
|
}
|
||||||
|
ce, err := ToClientEvent(ev, FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return queryUserIDForSender(senderID)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create ClientEvent: %s", err)
|
||||||
|
}
|
||||||
|
if ce.RoomID != "" {
|
||||||
|
t.Errorf("ClientEvent.RoomID: wanted '', got %s", ce.RoomID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToClientEventFormatSyncFederation(t *testing.T) { // nolint: gocyclo
|
||||||
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV10).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "",
|
||||||
|
"event_id": "$test:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "@test:localhost",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 123456,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depth": 8,
|
||||||
|
"prev_events": [
|
||||||
|
"$f597Tp0Mm1PPxEgiprzJc2cZAjVhxCxACOGuwJb33Oo"
|
||||||
|
],
|
||||||
|
"auth_events": [
|
||||||
|
"$Bj0ZGgX6VTqAQdqKH4ZG3l6rlbxY3rZlC5D3MeuK1OQ",
|
||||||
|
"$QsMs6A1PUVUhgSvmHBfpqEYJPgv4DXt96r8P2AK7iXQ",
|
||||||
|
"$tBteKtlnFiwlmPJsv0wkKTMEuUVWpQH89H7Xskxve1Q"
|
||||||
|
]
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
userID, err := spec.NewUserID("@test:localhost", true)
|
userID, err := spec.NewUserID("@test:localhost", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create userID: %s", err)
|
t.Fatalf("failed to create userID: %s", err)
|
||||||
}
|
}
|
||||||
sk := ""
|
sk := ""
|
||||||
ce := ToClientEvent(ev, FormatSync, *userID, &sk)
|
ce, err := ToClientEvent(ev, FormatSyncFederation, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
if ce.RoomID != "" {
|
return queryUserIDForSender(senderID)
|
||||||
t.Errorf("ClientEvent.RoomID: wanted '', got %s", ce.RoomID)
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create ClientEvent: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce.EventID,
|
||||||
|
Type: ce.Type,
|
||||||
|
OriginServerTS: ce.OriginServerTS,
|
||||||
|
StateKey: ce.StateKey,
|
||||||
|
Content: ce.Content,
|
||||||
|
Unsigned: ce.Unsigned,
|
||||||
|
Sender: ce.Sender,
|
||||||
|
Depth: ce.Depth,
|
||||||
|
PrevEvents: ce.PrevEvents,
|
||||||
|
AuthEvents: ce.AuthEvents,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev.EventID(),
|
||||||
|
Type: ev.Type(),
|
||||||
|
OriginServerTS: ev.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev.Content(),
|
||||||
|
Unsigned: ev.Unsigned(),
|
||||||
|
Sender: userID.String(),
|
||||||
|
Depth: ev.Depth(),
|
||||||
|
PrevEvents: ev.PrevEventIDs(),
|
||||||
|
AuthEvents: ev.AuthEventIDs(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func userIDForSender(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
if senderID == "unknownSenderID" {
|
||||||
|
return nil, fmt.Errorf("Cannot find userID")
|
||||||
|
}
|
||||||
|
return spec.NewUserID(testUserID, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToClientEventsFormatSyncFederation(t *testing.T) { // nolint: gocyclo
|
||||||
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 123456,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depth": 8,
|
||||||
|
"prev_events": [
|
||||||
|
"$f597Tp0Mm1PPxEgiprzJc2cZAjVhxCxACOGuwJb33Oo"
|
||||||
|
],
|
||||||
|
"auth_events": [
|
||||||
|
"$Bj0ZGgX6VTqAQdqKH4ZG3l6rlbxY3rZlC5D3MeuK1OQ",
|
||||||
|
"$QsMs6A1PUVUhgSvmHBfpqEYJPgv4DXt96r8P2AK7iXQ",
|
||||||
|
"$tBteKtlnFiwlmPJsv0wkKTMEuUVWpQH89H7Xskxve1Q"
|
||||||
|
]
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
ev2, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test2:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World 2"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 1234567,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World 2"
|
||||||
|
},
|
||||||
|
"prev_sender": "testSenderID"
|
||||||
|
},
|
||||||
|
"depth": 9,
|
||||||
|
"prev_events": [
|
||||||
|
"$f597Tp0Mm1PPxEgiprzJc2cZAjVhxCxACOGuwJb33Oo"
|
||||||
|
],
|
||||||
|
"auth_events": [
|
||||||
|
"$Bj0ZGgX6VTqAQdqKH4ZG3l6rlbxY3rZlC5D3MeuK1OQ",
|
||||||
|
"$QsMs6A1PUVUhgSvmHBfpqEYJPgv4DXt96r8P2AK7iXQ",
|
||||||
|
"$tBteKtlnFiwlmPJsv0wkKTMEuUVWpQH89H7Xskxve1Q"
|
||||||
|
]
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientEvents := ToClientEvents([]gomatrixserverlib.PDU{ev, ev2}, FormatSyncFederation, userIDForSender)
|
||||||
|
ce := clientEvents[0]
|
||||||
|
sk := testSenderID
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce.EventID,
|
||||||
|
Type: ce.Type,
|
||||||
|
OriginServerTS: ce.OriginServerTS,
|
||||||
|
StateKey: ce.StateKey,
|
||||||
|
Content: ce.Content,
|
||||||
|
Unsigned: ce.Unsigned,
|
||||||
|
Sender: ce.Sender,
|
||||||
|
Depth: ce.Depth,
|
||||||
|
PrevEvents: ce.PrevEvents,
|
||||||
|
AuthEvents: ce.AuthEvents,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev.EventID(),
|
||||||
|
Type: ev.Type(),
|
||||||
|
OriginServerTS: ev.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev.Content(),
|
||||||
|
Unsigned: ev.Unsigned(),
|
||||||
|
Sender: testSenderID,
|
||||||
|
Depth: ev.Depth(),
|
||||||
|
PrevEvents: ev.PrevEventIDs(),
|
||||||
|
AuthEvents: ev.AuthEventIDs(),
|
||||||
|
})
|
||||||
|
|
||||||
|
ce2 := clientEvents[1]
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce2.EventID,
|
||||||
|
Type: ce2.Type,
|
||||||
|
OriginServerTS: ce2.OriginServerTS,
|
||||||
|
StateKey: ce2.StateKey,
|
||||||
|
Content: ce2.Content,
|
||||||
|
Unsigned: ce2.Unsigned,
|
||||||
|
Sender: ce2.Sender,
|
||||||
|
Depth: ce2.Depth,
|
||||||
|
PrevEvents: ce2.PrevEvents,
|
||||||
|
AuthEvents: ce2.AuthEvents,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev2.EventID(),
|
||||||
|
Type: ev2.Type(),
|
||||||
|
OriginServerTS: ev2.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev2.Content(),
|
||||||
|
Unsigned: ev2.Unsigned(),
|
||||||
|
Sender: testSenderID,
|
||||||
|
Depth: ev2.Depth(),
|
||||||
|
PrevEvents: ev2.PrevEventIDs(),
|
||||||
|
AuthEvents: ev2.AuthEventIDs(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToClientEventsFormatSync(t *testing.T) { // nolint: gocyclo
|
||||||
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 123456,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
ev2, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test2:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World 2"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 1234567,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World 2"
|
||||||
|
},
|
||||||
|
"prev_sender": "testSenderID"
|
||||||
|
},
|
||||||
|
"depth": 9
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientEvents := ToClientEvents([]gomatrixserverlib.PDU{ev, ev2}, FormatSync, userIDForSender)
|
||||||
|
ce := clientEvents[0]
|
||||||
|
sk := testUserID
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce.EventID,
|
||||||
|
Type: ce.Type,
|
||||||
|
OriginServerTS: ce.OriginServerTS,
|
||||||
|
StateKey: ce.StateKey,
|
||||||
|
Content: ce.Content,
|
||||||
|
Unsigned: ce.Unsigned,
|
||||||
|
Sender: ce.Sender,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev.EventID(),
|
||||||
|
Type: ev.Type(),
|
||||||
|
OriginServerTS: ev.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev.Content(),
|
||||||
|
Unsigned: ev.Unsigned(),
|
||||||
|
Sender: testUserID,
|
||||||
|
})
|
||||||
|
|
||||||
|
var prev PrevEventRef
|
||||||
|
prev.PrevContent = []byte(`{"name": "Goodbye World 2"}`)
|
||||||
|
prev.PrevSenderID = testUserID
|
||||||
|
expectedUnsigned, _ := json.Marshal(prev)
|
||||||
|
|
||||||
|
ce2 := clientEvents[1]
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce2.EventID,
|
||||||
|
Type: ce2.Type,
|
||||||
|
OriginServerTS: ce2.OriginServerTS,
|
||||||
|
StateKey: ce2.StateKey,
|
||||||
|
Content: ce2.Content,
|
||||||
|
Unsigned: ce2.Unsigned,
|
||||||
|
Sender: ce2.Sender,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev2.EventID(),
|
||||||
|
Type: ev2.Type(),
|
||||||
|
OriginServerTS: ev2.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev2.Content(),
|
||||||
|
Unsigned: expectedUnsigned,
|
||||||
|
Sender: testUserID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToClientEventsFormatSyncUnknownPrevSender(t *testing.T) { // nolint: gocyclo
|
||||||
|
ev, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 123456,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
ev2, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON([]byte(`{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "testSenderID",
|
||||||
|
"event_id": "$test2:localhost",
|
||||||
|
"room_id": "!test:localhost",
|
||||||
|
"sender": "testSenderID",
|
||||||
|
"content": {
|
||||||
|
"name": "Hello World 2"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 1234567,
|
||||||
|
"unsigned": {
|
||||||
|
"prev_content": {
|
||||||
|
"name": "Goodbye World 2"
|
||||||
|
},
|
||||||
|
"prev_sender": "unknownSenderID"
|
||||||
|
},
|
||||||
|
"depth": 9
|
||||||
|
}`), false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create Event: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientEvents := ToClientEvents([]gomatrixserverlib.PDU{ev, ev2}, FormatSync, userIDForSender)
|
||||||
|
ce := clientEvents[0]
|
||||||
|
sk := testUserID
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce.EventID,
|
||||||
|
Type: ce.Type,
|
||||||
|
OriginServerTS: ce.OriginServerTS,
|
||||||
|
StateKey: ce.StateKey,
|
||||||
|
Content: ce.Content,
|
||||||
|
Unsigned: ce.Unsigned,
|
||||||
|
Sender: ce.Sender,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev.EventID(),
|
||||||
|
Type: ev.Type(),
|
||||||
|
OriginServerTS: ev.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev.Content(),
|
||||||
|
Unsigned: ev.Unsigned(),
|
||||||
|
Sender: testUserID,
|
||||||
|
})
|
||||||
|
|
||||||
|
var prev PrevEventRef
|
||||||
|
prev.PrevContent = []byte(`{"name": "Goodbye World 2"}`)
|
||||||
|
prev.PrevSenderID = "unknownSenderID"
|
||||||
|
expectedUnsigned, _ := json.Marshal(prev)
|
||||||
|
|
||||||
|
ce2 := clientEvents[1]
|
||||||
|
verifyEventFields(t,
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ce2.EventID,
|
||||||
|
Type: ce2.Type,
|
||||||
|
OriginServerTS: ce2.OriginServerTS,
|
||||||
|
StateKey: ce2.StateKey,
|
||||||
|
Content: ce2.Content,
|
||||||
|
Unsigned: ce2.Unsigned,
|
||||||
|
Sender: ce2.Sender,
|
||||||
|
},
|
||||||
|
EventFieldsToVerify{
|
||||||
|
EventID: ev2.EventID(),
|
||||||
|
Type: ev2.Type(),
|
||||||
|
OriginServerTS: ev2.OriginServerTS(),
|
||||||
|
StateKey: &sk,
|
||||||
|
Content: ev2.Content(),
|
||||||
|
Unsigned: expectedUnsigned,
|
||||||
|
Sender: testUserID,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,9 +78,14 @@ type RoomEventFilter struct {
|
||||||
ContainsURL *bool `json:"contains_url,omitempty"`
|
ContainsURL *bool `json:"contains_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
EventFormatClient = "client"
|
||||||
|
EventFormatFederation = "federation"
|
||||||
|
)
|
||||||
|
|
||||||
// Validate checks if the filter contains valid property values
|
// Validate checks if the filter contains valid property values
|
||||||
func (filter *Filter) Validate() error {
|
func (filter *Filter) Validate() error {
|
||||||
if filter.EventFormat != "" && filter.EventFormat != "client" && filter.EventFormat != "federation" {
|
if filter.EventFormat != "" && filter.EventFormat != EventFormatClient && filter.EventFormat != EventFormatFederation {
|
||||||
return errors.New("Bad event_format value. Must be one of [\"client\", \"federation\"]")
|
return errors.New("Bad event_format value. Must be one of [\"client\", \"federation\"]")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -339,13 +340,6 @@ func NewStreamTokenFromString(tok string) (token StreamingToken, err error) {
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevEventRef represents a reference to a previous event in a state event upgrade
|
|
||||||
type PrevEventRef struct {
|
|
||||||
PrevContent json.RawMessage `json:"prev_content"`
|
|
||||||
ReplacesState string `json:"replaces_state"`
|
|
||||||
PrevSenderID string `json:"prev_sender"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeviceLists struct {
|
type DeviceLists struct {
|
||||||
Changed []string `json:"changed,omitempty"`
|
Changed []string `json:"changed,omitempty"`
|
||||||
Left []string `json:"left,omitempty"`
|
Left []string `json:"left,omitempty"`
|
||||||
|
@ -539,7 +533,7 @@ type InviteResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInviteResponse creates an empty response with initialised arrays.
|
// NewInviteResponse creates an empty response with initialised arrays.
|
||||||
func NewInviteResponse(event *types.HeaderedEvent, userID spec.UserID, stateKey *string) *InviteResponse {
|
func NewInviteResponse(ctx context.Context, rsAPI api.QuerySenderIDAPI, event *types.HeaderedEvent, eventFormat synctypes.ClientEventFormat) (*InviteResponse, error) {
|
||||||
res := InviteResponse{}
|
res := InviteResponse{}
|
||||||
res.InviteState.Events = []json.RawMessage{}
|
res.InviteState.Events = []json.RawMessage{}
|
||||||
|
|
||||||
|
@ -547,18 +541,42 @@ func NewInviteResponse(event *types.HeaderedEvent, userID spec.UserID, stateKey
|
||||||
// If there is then unmarshal it into the response. This will contain the
|
// If there is then unmarshal it into the response. This will contain the
|
||||||
// partial room state such as join rules, room name etc.
|
// partial room state such as join rules, room name etc.
|
||||||
if inviteRoomState := gjson.GetBytes(event.Unsigned(), "invite_room_state"); inviteRoomState.Exists() {
|
if inviteRoomState := gjson.GetBytes(event.Unsigned(), "invite_room_state"); inviteRoomState.Exists() {
|
||||||
_ = json.Unmarshal([]byte(inviteRoomState.Raw), &res.InviteState.Events)
|
if event.Version() == gomatrixserverlib.RoomVersionPseudoIDs && eventFormat != synctypes.FormatSyncFederation {
|
||||||
|
updatedInvite, err := synctypes.GetUpdatedInviteRoomState(func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
|
}, inviteRoomState, event.PDU, event.RoomID(), eventFormat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_ = json.Unmarshal(updatedInvite, &res.InviteState.Events)
|
||||||
|
} else {
|
||||||
|
_ = json.Unmarshal([]byte(inviteRoomState.Raw), &res.InviteState.Events)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear unsigned so it doesn't have pseudoIDs converted during ToClientEvent
|
||||||
|
eventNoUnsigned, err := event.SetUnsigned(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we'll see if we can create a partial of the invite event itself.
|
// Then we'll see if we can create a partial of the invite event itself.
|
||||||
// This is needed for clients to work out *who* sent the invite.
|
// This is needed for clients to work out *who* sent the invite.
|
||||||
inviteEvent := synctypes.ToClientEvent(event.PDU, synctypes.FormatSync, userID, stateKey)
|
inviteEvent, err := synctypes.ToClientEvent(eventNoUnsigned, eventFormat, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure unsigned field is empty so it isn't marshalled into the final JSON
|
||||||
inviteEvent.Unsigned = nil
|
inviteEvent.Unsigned = nil
|
||||||
if ev, err := json.Marshal(inviteEvent); err == nil {
|
|
||||||
|
if ev, err := json.Marshal(*inviteEvent); err == nil {
|
||||||
res.InviteState.Events = append(res.InviteState.Events, ev)
|
res.InviteState.Events = append(res.InviteState.Events, ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeaveResponse represents a /sync response for a room which is under the 'leave' key.
|
// LeaveResponse represents a /sync response for a room which is under the 'leave' key.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -11,8 +12,19 @@ import (
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UserIDForSender(roomID string, senderID string) (*spec.UserID, error) {
|
type FakeRoomserverAPI struct{}
|
||||||
return spec.NewUserID(senderID, true)
|
|
||||||
|
func (f *FakeRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
if senderID == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.NewUserID(string(senderID), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) {
|
||||||
|
sender := spec.SenderID(userID.String())
|
||||||
|
return &sender, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncTokens(t *testing.T) {
|
func TestSyncTokens(t *testing.T) {
|
||||||
|
@ -61,25 +73,18 @@ func TestNewInviteResponse(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sender, err := spec.NewUserID("@neilalexander:matrix.org", true)
|
rsAPI := FakeRoomserverAPI{}
|
||||||
|
res, err := NewInviteResponse(context.Background(), &rsAPI, &types.HeaderedEvent{PDU: ev}, synctypes.FormatSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
skUserID, err := spec.NewUserID("@neilalexander:dendrite.neilalexander.dev", true)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk := &skString
|
|
||||||
|
|
||||||
res := NewInviteResponse(&types.HeaderedEvent{PDU: ev}, *sender, sk)
|
|
||||||
j, err := json.Marshal(res)
|
j, err := json.Marshal(res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(j) != expected {
|
if string(j) != expected {
|
||||||
t.Fatalf("Invite response didn't contain correct info")
|
t.Fatalf("Invite response didn't contain correct info, \nexpected: %s \ngot: %s", expected, string(j))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -783,4 +783,16 @@ Invited user can reject invite for empty room
|
||||||
Invited user can reject local invite after originator leaves
|
Invited user can reject local invite after originator leaves
|
||||||
Guest users can join guest_access rooms
|
Guest users can join guest_access rooms
|
||||||
Forgotten room messages cannot be paginated
|
Forgotten room messages cannot be paginated
|
||||||
Local device key changes get to remote servers with correct prev_id
|
Local device key changes get to remote servers with correct prev_id
|
||||||
|
HS provides query metadata
|
||||||
|
HS can provide query metadata on a single protocol
|
||||||
|
Invites over federation are correctly pushed
|
||||||
|
Invites over federation are correctly pushed with name
|
||||||
|
User can create and send/receive messages in a room with version 11
|
||||||
|
local user can join room with version 11
|
||||||
|
User can invite local user to room with version 11
|
||||||
|
remote user can join room with version 11
|
||||||
|
User can invite remote user to room with version 11
|
||||||
|
Remote user can backfill in a room with version 11
|
||||||
|
Can reject invites over federation for rooms with version 11
|
||||||
|
Can receive redactions from regular users over federation in room version 11
|
|
@ -92,30 +92,43 @@ func (s *OutputRoomEventConsumer) Start() error {
|
||||||
func (s *OutputRoomEventConsumer) onMessage(ctx context.Context, msgs []*nats.Msg) bool {
|
func (s *OutputRoomEventConsumer) onMessage(ctx context.Context, msgs []*nats.Msg) bool {
|
||||||
msg := msgs[0] // Guaranteed to exist if onMessage is called
|
msg := msgs[0] // Guaranteed to exist if onMessage is called
|
||||||
// Only handle events we care about
|
// Only handle events we care about
|
||||||
if rsapi.OutputType(msg.Header.Get(jetstream.RoomEventType)) != rsapi.OutputTypeNewRoomEvent {
|
|
||||||
return true
|
var event *rstypes.HeaderedEvent
|
||||||
}
|
var isNewRoomEvent bool
|
||||||
var output rsapi.OutputEvent
|
switch rsapi.OutputType(msg.Header.Get(jetstream.RoomEventType)) {
|
||||||
if err := json.Unmarshal(msg.Data, &output); err != nil {
|
case rsapi.OutputTypeNewRoomEvent:
|
||||||
// If the message was invalid, log it and move on to the next message in the stream
|
isNewRoomEvent = true
|
||||||
log.WithError(err).Errorf("roomserver output log: message parse failure")
|
fallthrough
|
||||||
return true
|
case rsapi.OutputTypeNewInviteEvent:
|
||||||
}
|
var output rsapi.OutputEvent
|
||||||
event := output.NewRoomEvent.Event
|
if err := json.Unmarshal(msg.Data, &output); err != nil {
|
||||||
if event == nil {
|
// If the message was invalid, log it and move on to the next message in the stream
|
||||||
log.Errorf("userapi consumer: expected event")
|
log.WithError(err).Errorf("roomserver output log: message parse failure")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if isNewRoomEvent {
|
||||||
|
event = output.NewRoomEvent.Event
|
||||||
|
} else {
|
||||||
|
event = output.NewInviteEvent.Event
|
||||||
|
}
|
||||||
|
|
||||||
|
if event == nil {
|
||||||
|
log.Errorf("userapi consumer: expected event")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"event_id": event.EventID(),
|
||||||
|
"event_type": event.Type(),
|
||||||
|
}).Tracef("Received message from roomserver: %#v", output)
|
||||||
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.cfg.Matrix.ReportStats.Enabled {
|
if s.cfg.Matrix.ReportStats.Enabled {
|
||||||
go s.storeMessageStats(ctx, event.Type(), string(event.SenderID()), event.RoomID())
|
go s.storeMessageStats(ctx, event.Type(), string(event.SenderID()), event.RoomID().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"event_id": event.EventID(),
|
|
||||||
"event_type": event.Type(),
|
|
||||||
}).Tracef("Received message from roomserver: %#v", output)
|
|
||||||
|
|
||||||
metadata, err := msg.Metadata()
|
metadata, err := msg.Metadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true
|
||||||
|
@ -253,8 +266,8 @@ func (s *OutputRoomEventConsumer) updateMDirect(ctx context.Context, oldRoomID,
|
||||||
directChats := gjson.ParseBytes(directChatsRaw)
|
directChats := gjson.ParseBytes(directChatsRaw)
|
||||||
newDirectChats := make(map[string][]string)
|
newDirectChats := make(map[string][]string)
|
||||||
// iterate over all userID -> roomIDs
|
// iterate over all userID -> roomIDs
|
||||||
|
var found bool
|
||||||
directChats.ForEach(func(userID, roomIDs gjson.Result) bool {
|
directChats.ForEach(func(userID, roomIDs gjson.Result) bool {
|
||||||
var found bool
|
|
||||||
for _, roomID := range roomIDs.Array() {
|
for _, roomID := range roomIDs.Array() {
|
||||||
newDirectChats[userID.Str] = append(newDirectChats[userID.Str], roomID.Str)
|
newDirectChats[userID.Str] = append(newDirectChats[userID.Str], roomID.Str)
|
||||||
// add the new roomID to m.direct
|
// add the new roomID to m.direct
|
||||||
|
@ -263,22 +276,21 @@ func (s *OutputRoomEventConsumer) updateMDirect(ctx context.Context, oldRoomID,
|
||||||
newDirectChats[userID.Str] = append(newDirectChats[userID.Str], newRoomID)
|
newDirectChats[userID.Str] = append(newDirectChats[userID.Str], newRoomID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only hit the database if we found the old room as a DM for this user
|
|
||||||
if found {
|
|
||||||
var data []byte
|
|
||||||
data, err = json.Marshal(newDirectChats)
|
|
||||||
if err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if err = s.db.SaveAccountData(ctx, localpart, serverName, "", "m.direct", data); err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to update m.direct state")
|
// Only hit the database if we found the old room as a DM for this user
|
||||||
|
if found {
|
||||||
|
var data []byte
|
||||||
|
data, err = json.Marshal(newDirectChats)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = s.db.SaveAccountData(ctx, localpart, serverName, "", "m.direct", data); err != nil {
|
||||||
|
return fmt.Errorf("failed to update m.direct state: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,36 +306,21 @@ func (s *OutputRoomEventConsumer) copyTags(ctx context.Context, oldRoomID, newRo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OutputRoomEventConsumer) processMessage(ctx context.Context, event *rstypes.HeaderedEvent, streamPos uint64) error {
|
func (s *OutputRoomEventConsumer) processMessage(ctx context.Context, event *rstypes.HeaderedEvent, streamPos uint64) error {
|
||||||
members, roomSize, err := s.localRoomMembers(ctx, event.RoomID())
|
members, roomSize, err := s.localRoomMembers(ctx, event.RoomID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("s.localRoomMembers: %w", err)
|
return fmt.Errorf("s.localRoomMembers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case event.Type() == spec.MRoomMember:
|
case event.Type() == spec.MRoomMember:
|
||||||
sender := spec.UserID{}
|
cevent, clientEvErr := synctypes.ToClientEvent(event, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
validRoomID, roomErr := spec.NewRoomID(event.RoomID())
|
return s.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
if roomErr != nil {
|
})
|
||||||
return roomErr
|
if clientEvErr != nil {
|
||||||
|
return clientEvErr
|
||||||
}
|
}
|
||||||
userID, queryErr := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if queryErr == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := event.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, queryErr := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*sk))
|
|
||||||
if queryErr == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("queryUserIDForSender: userID unknown for %s", *sk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cevent := synctypes.ToClientEvent(event, synctypes.FormatAll, sender, sk)
|
|
||||||
var member *localMembership
|
var member *localMembership
|
||||||
member, err = newLocalMembership(&cevent)
|
member, err = newLocalMembership(cevent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("newLocalMembership: %w", err)
|
return fmt.Errorf("newLocalMembership: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -334,7 +331,7 @@ func (s *OutputRoomEventConsumer) processMessage(ctx context.Context, event *rst
|
||||||
}
|
}
|
||||||
case event.Type() == "m.room.tombstone" && event.StateKeyEquals(""):
|
case event.Type() == "m.room.tombstone" && event.StateKeyEquals(""):
|
||||||
// Handle room upgrades
|
// Handle room upgrades
|
||||||
oldRoomID := event.RoomID()
|
oldRoomID := event.RoomID().String()
|
||||||
newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str
|
newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str
|
||||||
if err = s.handleRoomUpgrade(ctx, oldRoomID, newRoomID, members, roomSize); err != nil {
|
if err = s.handleRoomUpgrade(ctx, oldRoomID, newRoomID, members, roomSize); err != nil {
|
||||||
// while inconvenient, this shouldn't stop us from sending push notifications
|
// while inconvenient, this shouldn't stop us from sending push notifications
|
||||||
|
@ -351,7 +348,7 @@ func (s *OutputRoomEventConsumer) processMessage(ctx context.Context, event *rst
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"num_members": len(members),
|
"num_members": len(members),
|
||||||
"room_size": roomSize,
|
"room_size": roomSize,
|
||||||
}).Tracef("Notifying members")
|
}).Tracef("Notifying members")
|
||||||
|
@ -463,8 +460,21 @@ func (s *OutputRoomEventConsumer) roomName(ctx context.Context, event *rstypes.H
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case for invites, as we don't store any "current state" for these events,
|
||||||
|
// we need to make sure that, if present, the m.room.name is sent as well.
|
||||||
|
if event.Type() == spec.MRoomMember &&
|
||||||
|
gjson.GetBytes(event.Content(), "membership").Str == "invite" {
|
||||||
|
invState := gjson.GetBytes(event.JSON(), "unsigned.invite_room_state")
|
||||||
|
for _, ev := range invState.Array() {
|
||||||
|
if ev.Get("type").Str == spec.MRoomName {
|
||||||
|
name := ev.Get("content.name").Str
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req := &rsapi.QueryCurrentStateRequest{
|
req := &rsapi.QueryCurrentStateRequest{
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
StateTuples: []gomatrixserverlib.StateKeyTuple{roomNameTuple, canonicalAliasTuple},
|
StateTuples: []gomatrixserverlib.StateKeyTuple{roomNameTuple, canonicalAliasTuple},
|
||||||
}
|
}
|
||||||
var res rsapi.QueryCurrentStateResponse
|
var res rsapi.QueryCurrentStateResponse
|
||||||
|
@ -532,7 +542,7 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
||||||
if a != pushrules.NotifyAction && a != pushrules.CoalesceAction {
|
if a != pushrules.NotifyAction && a != pushrules.CoalesceAction {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"localpart": mem.Localpart,
|
"localpart": mem.Localpart,
|
||||||
}).Tracef("Push rule evaluation rejected the event")
|
}).Tracef("Push rule evaluation rejected the event")
|
||||||
return nil
|
return nil
|
||||||
|
@ -542,44 +552,32 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("s.localPushDevices: %w", err)
|
return fmt.Errorf("s.localPushDevices: %w", err)
|
||||||
}
|
}
|
||||||
|
clientEvent, err := synctypes.ToClientEvent(event, synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
sender := spec.UserID{}
|
return s.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err == nil && userID != nil {
|
|
||||||
sender = *userID
|
|
||||||
}
|
|
||||||
|
|
||||||
sk := event.StateKey()
|
|
||||||
if sk != nil && *sk != "" {
|
|
||||||
skUserID, queryErr := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*event.StateKey()))
|
|
||||||
if queryErr == nil && skUserID != nil {
|
|
||||||
skString := skUserID.String()
|
|
||||||
sk = &skString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n := &api.Notification{
|
n := &api.Notification{
|
||||||
Actions: actions,
|
Actions: actions,
|
||||||
// UNSPEC: the spec doesn't say this is a ClientEvent, but the
|
// UNSPEC: the spec doesn't say this is a ClientEvent, but the
|
||||||
// fields seem to match. room_id should be missing, which
|
// fields seem to match. room_id should be missing, which
|
||||||
// matches the behaviour of FormatSync.
|
// matches the behaviour of FormatSync.
|
||||||
Event: synctypes.ToClientEvent(event, synctypes.FormatSync, sender, sk),
|
Event: *clientEvent,
|
||||||
// TODO: this is per-device, but it's not part of the primary
|
// TODO: this is per-device, but it's not part of the primary
|
||||||
// key. So inserting one notification per profile tag doesn't
|
// key. So inserting one notification per profile tag doesn't
|
||||||
// make sense. What is this supposed to be? Sytests require it
|
// make sense. What is this supposed to be? Sytests require it
|
||||||
// to "work", but they only use a single device.
|
// to "work", but they only use a single device.
|
||||||
ProfileTag: profileTag,
|
ProfileTag: profileTag,
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
TS: spec.AsTimestamp(time.Now()),
|
TS: spec.AsTimestamp(time.Now()),
|
||||||
}
|
}
|
||||||
if err = s.db.InsertNotification(ctx, mem.Localpart, mem.Domain, event.EventID(), streamPos, tweaks, n); err != nil {
|
if err = s.db.InsertNotification(ctx, mem.Localpart, mem.Domain, event.EventID(), streamPos, tweaks, n); err != nil {
|
||||||
return fmt.Errorf("s.db.InsertNotification: %w", err)
|
return fmt.Errorf("s.db.InsertNotification: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = s.syncProducer.GetAndSendNotificationData(ctx, mem.UserID, event.RoomID()); err != nil {
|
if err = s.syncProducer.GetAndSendNotificationData(ctx, mem.UserID, event.RoomID().String()); err != nil {
|
||||||
return fmt.Errorf("s.syncProducer.GetAndSendNotificationData: %w", err)
|
return fmt.Errorf("s.syncProducer.GetAndSendNotificationData: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +589,7 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"localpart": mem.Localpart,
|
"localpart": mem.Localpart,
|
||||||
"num_urls": len(devicesByURLAndFormat),
|
"num_urls": len(devicesByURLAndFormat),
|
||||||
"num_unread": userNumUnreadNotifs,
|
"num_unread": userNumUnreadNotifs,
|
||||||
|
@ -648,11 +646,7 @@ func (s *OutputRoomEventConsumer) notifyLocal(ctx context.Context, event *rstype
|
||||||
// user. Returns actions (including dont_notify).
|
// user. Returns actions (including dont_notify).
|
||||||
func (s *OutputRoomEventConsumer) evaluatePushRules(ctx context.Context, event *rstypes.HeaderedEvent, mem *localMembership, roomSize int) ([]*pushrules.Action, error) {
|
func (s *OutputRoomEventConsumer) evaluatePushRules(ctx context.Context, event *rstypes.HeaderedEvent, mem *localMembership, roomSize int) ([]*pushrules.Action, error) {
|
||||||
user := ""
|
user := ""
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
sender, err := s.rsAPI.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sender, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
user = sender.String()
|
user = sender.String()
|
||||||
}
|
}
|
||||||
|
@ -686,7 +680,7 @@ func (s *OutputRoomEventConsumer) evaluatePushRules(ctx context.Context, event *
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
rsAPI: s.rsAPI,
|
rsAPI: s.rsAPI,
|
||||||
mem: mem,
|
mem: mem,
|
||||||
roomID: event.RoomID(),
|
roomID: event.RoomID().String(),
|
||||||
roomSize: roomSize,
|
roomSize: roomSize,
|
||||||
}
|
}
|
||||||
eval := pushrules.NewRuleSetEvaluator(ec, &ruleSets.Global)
|
eval := pushrules.NewRuleSetEvaluator(ec, &ruleSets.Global)
|
||||||
|
@ -704,7 +698,7 @@ func (s *OutputRoomEventConsumer) evaluatePushRules(ctx context.Context, event *
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"event_id": event.EventID(),
|
"event_id": event.EventID(),
|
||||||
"room_id": event.RoomID(),
|
"room_id": event.RoomID().String(),
|
||||||
"localpart": mem.Localpart,
|
"localpart": mem.Localpart,
|
||||||
"rule_id": rule.RuleID,
|
"rule_id": rule.RuleID,
|
||||||
}).Trace("Matched a push rule")
|
}).Trace("Matched a push rule")
|
||||||
|
@ -793,16 +787,12 @@ func (s *OutputRoomEventConsumer) notifyHTTP(ctx context.Context, event *rstypes
|
||||||
},
|
},
|
||||||
Devices: devices,
|
Devices: devices,
|
||||||
EventID: event.EventID(),
|
EventID: event.EventID(),
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
sender, err := s.rsAPI.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sender, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Errorf("Failed to get userID for sender %s", event.SenderID())
|
logger.WithError(err).Errorf("Failed to get userID for sender %s", event.SenderID())
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -816,7 +806,7 @@ func (s *OutputRoomEventConsumer) notifyHTTP(ctx context.Context, event *rstypes
|
||||||
Devices: devices,
|
Devices: devices,
|
||||||
EventID: event.EventID(),
|
EventID: event.EventID(),
|
||||||
ID: event.EventID(),
|
ID: event.EventID(),
|
||||||
RoomID: event.RoomID(),
|
RoomID: event.RoomID().String(),
|
||||||
RoomName: roomName,
|
RoomName: roomName,
|
||||||
Sender: sender.String(),
|
Sender: sender.String(),
|
||||||
Type: event.Type(),
|
Type: event.Type(),
|
||||||
|
@ -830,19 +820,13 @@ func (s *OutputRoomEventConsumer) notifyHTTP(ctx context.Context, event *rstypes
|
||||||
logger.WithError(err).Errorf("Failed to convert local user to userID %s", localpart)
|
logger.WithError(err).Errorf("Failed to convert local user to userID %s", localpart)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
roomID, err := spec.NewRoomID(event.RoomID())
|
localSender, err := s.rsAPI.QuerySenderIDForUser(ctx, event.RoomID(), *userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Errorf("event roomID is invalid %s", event.RoomID())
|
logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID().String())
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
localSender, err := s.rsAPI.QuerySenderIDForUser(ctx, *roomID, *userID)
|
|
||||||
if err != nil {
|
|
||||||
logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID())
|
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if localSender == nil {
|
} else if localSender == nil {
|
||||||
logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID())
|
logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID().String())
|
||||||
return nil, fmt.Errorf("no sender ID for user %s in %s", userID.String(), roomID.String())
|
return nil, fmt.Errorf("no sender ID for user %s in %s", userID.String(), event.RoomID().String())
|
||||||
}
|
}
|
||||||
if event.StateKey() != nil && *event.StateKey() == string(*localSender) {
|
if event.StateKey() != nil && *event.StateKey() == string(*localSender) {
|
||||||
req.Notification.UserIsTarget = true
|
req.Notification.UserIsTarget = true
|
||||||
|
|
|
@ -563,12 +563,15 @@ func (a *UserInternalAPI) QueryAccountData(ctx context.Context, req *api.QueryAc
|
||||||
func (a *UserInternalAPI) QueryAccessToken(ctx context.Context, req *api.QueryAccessTokenRequest, res *api.QueryAccessTokenResponse) error {
|
func (a *UserInternalAPI) QueryAccessToken(ctx context.Context, req *api.QueryAccessTokenRequest, res *api.QueryAccessTokenResponse) error {
|
||||||
if req.AppServiceUserID != "" {
|
if req.AppServiceUserID != "" {
|
||||||
appServiceDevice, err := a.queryAppServiceToken(ctx, req.AccessToken, req.AppServiceUserID)
|
appServiceDevice, err := a.queryAppServiceToken(ctx, req.AccessToken, req.AppServiceUserID)
|
||||||
if err != nil {
|
if err != nil || appServiceDevice != nil {
|
||||||
res.Err = err.Error()
|
if err != nil {
|
||||||
}
|
res.Err = err.Error()
|
||||||
res.Device = appServiceDevice
|
}
|
||||||
|
res.Device = appServiceDevice
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
// If the provided token wasn't an as_token (both err and appServiceDevice are nil), continue with normal auth.
|
||||||
}
|
}
|
||||||
device, err := a.DB.GetDeviceByAccessToken(ctx, req.AccessToken)
|
device, err := a.DB.GetDeviceByAccessToken(ctx, req.AccessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -23,6 +23,14 @@ import (
|
||||||
userUtil "github.com/matrix-org/dendrite/userapi/util"
|
userUtil "github.com/matrix-org/dendrite/userapi/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func queryUserIDForSender(senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
if senderID == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.NewUserID(string(senderID), true)
|
||||||
|
}
|
||||||
|
|
||||||
func TestNotifyUserCountsAsync(t *testing.T) {
|
func TestNotifyUserCountsAsync(t *testing.T) {
|
||||||
alice := test.NewUser(t)
|
alice := test.NewUser(t)
|
||||||
aliceLocalpart, serverName, err := gomatrixserverlib.SplitID('@', alice.ID)
|
aliceLocalpart, serverName, err := gomatrixserverlib.SplitID('@', alice.ID)
|
||||||
|
@ -100,13 +108,14 @@ func TestNotifyUserCountsAsync(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a dummy event
|
// Insert a dummy event
|
||||||
sender, err := spec.NewUserID(alice.ID, true)
|
ev, err := synctypes.ToClientEvent(dummyEvent, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return queryUserIDForSender(senderID)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
sk := ""
|
|
||||||
if err := db.InsertNotification(ctx, aliceLocalpart, serverName, dummyEvent.EventID(), 0, nil, &api.Notification{
|
if err := db.InsertNotification(ctx, aliceLocalpart, serverName, dummyEvent.EventID(), 0, nil, &api.Notification{
|
||||||
Event: synctypes.ToClientEvent(dummyEvent, synctypes.FormatAll, *sender, &sk),
|
Event: *ev,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue