mirror of
https://github.com/matrix-org/sliding-sync.git
synced 2025-03-10 13:37:11 +00:00
parent
c806b264bf
commit
b2c26b7e93
2
go.mod
2
go.mod
@ -9,7 +9,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/jmoiron/sqlx v1.3.3
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230105074811-965b10ae73ab
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
|
||||
github.com/pressly/goose/v3 v3.14.0
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
|
2
go.sum
2
go.sum
@ -187,6 +187,8 @@ github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5d
|
||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230105074811-965b10ae73ab h1:ChaQdT2mpxMm3GRXNOZzLDQ/wOnlKZ8o60LmZGOjdj8=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230105074811-965b10ae73ab/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993 h1:88wDfSsqSFyeCnTha8vfK9XJUbNjNXdEZAieOjbBzos=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk=
|
||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/matrix-org/sliding-sync/internal"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
@ -398,11 +399,13 @@ func (a *Accumulator) Accumulate(txn *sqlx.Tx, userID, roomID string, prevBatch
|
||||
|
||||
var latestNID int64
|
||||
newEvents := make([]Event, 0, len(eventIDToNID))
|
||||
var redactTheseEventIDs []string
|
||||
for _, ev := range dedupedEvents {
|
||||
nid, ok := eventIDToNID[ev.ID]
|
||||
if ok {
|
||||
ev.NID = int64(nid)
|
||||
if gjson.GetBytes(ev.JSON, "state_key").Exists() {
|
||||
parsedEv := gjson.ParseBytes(ev.JSON)
|
||||
if parsedEv.Get("state_key").Exists() {
|
||||
// XXX: reusing this to mean "it's a state event" as well as "it's part of the state v2 response"
|
||||
// its important that we don't insert 'ev' at this point as this should be False in the DB.
|
||||
ev.IsState = true
|
||||
@ -412,11 +415,40 @@ func (a *Accumulator) Accumulate(txn *sqlx.Tx, userID, roomID string, prevBatch
|
||||
if ev.NID > latestNID {
|
||||
latestNID = ev.NID
|
||||
}
|
||||
// if this is a redaction, try to redact the referenced event (best effort)
|
||||
if !ev.IsState && ev.Type == "m.room.redaction" {
|
||||
// look for top-level redacts then content.redacts (room version 11+)
|
||||
redactsEventID := parsedEv.Get("redacts").Str
|
||||
if redactsEventID == "" {
|
||||
redactsEventID = parsedEv.Get("content.redacts").Str
|
||||
}
|
||||
if redactsEventID != "" {
|
||||
redactTheseEventIDs = append(redactTheseEventIDs, redactsEventID)
|
||||
}
|
||||
}
|
||||
newEvents = append(newEvents, ev)
|
||||
timelineNIDs = append(timelineNIDs, ev.NID)
|
||||
}
|
||||
}
|
||||
|
||||
// if we are going to redact things, we need the room version to know the redaction algorithm
|
||||
// so pull it out once now.
|
||||
var roomVersion string
|
||||
if len(redactTheseEventIDs) > 0 {
|
||||
createEventJSON, err := a.eventsTable.SelectCreateEvent(txn, roomID)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("SelectCreateEvent: %s", err)
|
||||
}
|
||||
roomVersion = gjson.GetBytes(createEventJSON, "content.room_version").Str
|
||||
if roomVersion == "" {
|
||||
// Defaults to "1" if the key does not exist.
|
||||
roomVersion = "1"
|
||||
}
|
||||
if err = a.eventsTable.Redact(txn, roomVersion, redactTheseEventIDs); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, ev := range newEvents {
|
||||
var replacesNID int64
|
||||
// the snapshot ID we assign to this event is unaffected by whether /this/ event is state or not,
|
||||
|
@ -2,6 +2,7 @@ package state
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
@ -10,6 +11,7 @@ import (
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/sliding-sync/internal"
|
||||
"github.com/matrix-org/sliding-sync/sqlutil"
|
||||
)
|
||||
@ -336,6 +338,30 @@ func (t *EventTable) LatestEventNIDInRooms(txn *sqlx.Tx, roomIDs []string, highe
|
||||
return
|
||||
}
|
||||
|
||||
func (t *EventTable) Redact(txn *sqlx.Tx, roomVer string, eventIDs []string) error {
|
||||
// verifyAll=false so if we are asked to redact an event we don't have we don't fall over.
|
||||
eventsToRedact, err := t.SelectByIDs(txn, false, eventIDs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("EventTable.Redact[%v]: %s", eventIDs, err)
|
||||
}
|
||||
rv, err := gomatrixserverlib.GetRoomVersion(gomatrixserverlib.RoomVersion(roomVer))
|
||||
if err != nil {
|
||||
// unknown room version... let's just default to "1"
|
||||
rv = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV1)
|
||||
}
|
||||
for i := range eventsToRedact {
|
||||
eventsToRedact[i].JSON, err = rv.RedactEventJSON(eventsToRedact[i].JSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("RedactEventJSON[%s]: %s", eventsToRedact[i].ID, err)
|
||||
}
|
||||
_, err = txn.Exec(`UPDATE syncv3_events SET event=$1 WHERE event_id=$2`, eventsToRedact[i].JSON, eventsToRedact[i].ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update event %s: %v", eventsToRedact[i].ID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EventTable) SelectLatestEventsBetween(txn *sqlx.Tx, roomID string, lowerExclusive, upperInclusive int64, limit int) ([]Event, error) {
|
||||
var events []Event
|
||||
// do not pull in events which were in the v2 state block
|
||||
@ -440,6 +466,13 @@ func (t *EventTable) SelectClosestPrevBatch(txn *sqlx.Tx, roomID string, eventNI
|
||||
return
|
||||
}
|
||||
|
||||
func (t *EventTable) SelectCreateEvent(txn *sqlx.Tx, roomID string) (json.RawMessage, error) {
|
||||
var evJSON []byte
|
||||
// there is only 1 create event
|
||||
err := txn.QueryRow(`SELECT event FROM syncv3_events WHERE room_id=$1 AND event_type='m.room.create' AND state_key=''`, roomID).Scan(&evJSON)
|
||||
return evJSON, err
|
||||
}
|
||||
|
||||
type EventChunker []Event
|
||||
|
||||
func (c EventChunker) Len() int {
|
||||
|
@ -3,6 +3,7 @@ package state
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
@ -924,3 +925,168 @@ func TestEventTableSelectUnknownEventIDs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventTableRedact(t *testing.T) {
|
||||
db, close := connectToDB(t)
|
||||
defer close()
|
||||
table := NewEventTable(db)
|
||||
txn, err := db.Beginx()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start txn: %s", err)
|
||||
}
|
||||
defer txn.Rollback()
|
||||
|
||||
testCases := []struct {
|
||||
original map[string]interface{}
|
||||
roomVer string
|
||||
wantContent map[string]interface{}
|
||||
}{
|
||||
// sanity check
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.message",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"msgtype": "m.text",
|
||||
"body": "Something not very nice",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{},
|
||||
roomVer: "10",
|
||||
},
|
||||
// keep membership
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.member",
|
||||
"state_key": "@nasty-mc-nastyface:localhost",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"membership": "join",
|
||||
"displayname": "Something not very nice",
|
||||
"avatar_url": "mxc://something/not/very/nice",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{
|
||||
"membership": "join",
|
||||
},
|
||||
roomVer: "10",
|
||||
},
|
||||
// keep join rule
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.join_rules",
|
||||
"state_key": "",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"join_rule": "invite",
|
||||
"extra_data": "not very nice",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{
|
||||
"join_rule": "invite",
|
||||
},
|
||||
roomVer: "10",
|
||||
},
|
||||
// keep his vis
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.history_visibility",
|
||||
"state_key": "",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"history_visibility": "shared",
|
||||
"extra_data": "not very nice",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{
|
||||
"history_visibility": "shared",
|
||||
},
|
||||
roomVer: "10",
|
||||
},
|
||||
// keep version specific fields
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.member",
|
||||
"state_key": "@nasty-mc-nastyface:localhost",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"membership": "join",
|
||||
"displayname": "Something not very nice",
|
||||
"avatar_url": "mxc://something/not/very/nice",
|
||||
"join_authorised_via_users_server": "@bob:localhost",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{
|
||||
"membership": "join",
|
||||
"join_authorised_via_users_server": "@bob:localhost",
|
||||
},
|
||||
roomVer: "10",
|
||||
},
|
||||
// remove same field on lower room version
|
||||
{
|
||||
original: map[string]interface{}{
|
||||
"type": "m.room.member",
|
||||
"state_key": "@nasty-mc-nastyface:localhost",
|
||||
"sender": "@nasty-mc-nastyface:localhost",
|
||||
"content": map[string]interface{}{
|
||||
"membership": "join",
|
||||
"displayname": "Something not very nice",
|
||||
"avatar_url": "mxc://something/not/very/nice",
|
||||
"join_authorised_via_users_server": "@bob:localhost",
|
||||
},
|
||||
},
|
||||
wantContent: map[string]interface{}{
|
||||
"membership": "join",
|
||||
},
|
||||
roomVer: "2",
|
||||
},
|
||||
}
|
||||
|
||||
roomID := "!TestEventTableRedact"
|
||||
for i, tc := range testCases {
|
||||
eventID := fmt.Sprintf("$TestEventTableRedact_%d", i)
|
||||
tc.original["event_id"] = eventID
|
||||
tc.original["room_id"] = roomID
|
||||
stateKey := ""
|
||||
if tc.original["state_key"] != nil {
|
||||
stateKey = tc.original["state_key"].(string)
|
||||
}
|
||||
j, err := json.Marshal(tc.original)
|
||||
assertNoError(t, err)
|
||||
table.Insert(txn, []Event{
|
||||
{
|
||||
ID: eventID,
|
||||
Type: tc.original["type"].(string),
|
||||
RoomID: roomID,
|
||||
StateKey: stateKey,
|
||||
BeforeStateSnapshotID: 22,
|
||||
JSON: j,
|
||||
},
|
||||
}, false)
|
||||
assertNoError(t, table.Redact(txn, tc.roomVer, []string{eventID}))
|
||||
gots, err := table.SelectByIDs(txn, true, []string{eventID})
|
||||
assertNoError(t, err)
|
||||
if len(gots) != 1 {
|
||||
t.Errorf("SelectByIDs: got %v results, want 1", len(gots))
|
||||
continue
|
||||
}
|
||||
got := gots[0]
|
||||
assertVal(t, "event id mismatch", got.ID, eventID)
|
||||
assertVal(t, "room id mismatch", got.RoomID, roomID)
|
||||
var gotJSON map[string]interface{}
|
||||
assertNoError(t, json.Unmarshal(got.JSON, &gotJSON))
|
||||
assertVal(t, "content mismatch", gotJSON["content"], tc.wantContent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventTableRedactMissingOK(t *testing.T) {
|
||||
db, close := connectToDB(t)
|
||||
defer close()
|
||||
table := NewEventTable(db)
|
||||
txn, err := db.Beginx()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start txn: %s", err)
|
||||
}
|
||||
defer txn.Rollback()
|
||||
assertNoError(t, table.Redact(txn, "2", []string{"$unknown", "$event", "$ids"}))
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/sliding-sync/internal"
|
||||
"github.com/matrix-org/sliding-sync/sqlutil"
|
||||
"github.com/matrix-org/sliding-sync/testutils"
|
||||
@ -308,7 +308,7 @@ func TestVisibleEventNIDsBetween(t *testing.T) {
|
||||
t.Fatalf("LatestEventNID: %s", err)
|
||||
}
|
||||
|
||||
baseTimestamp := gomatrixserverlib.Timestamp(1632131678061).Time()
|
||||
baseTimestamp := spec.Timestamp(1632131678061).Time()
|
||||
// Test the examples
|
||||
// Stream Positions
|
||||
// 1 2 3 4 5 6 7 8 9 10
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
@ -135,7 +134,7 @@ type SyncResponse struct {
|
||||
NextBatch string `json:"next_batch"`
|
||||
AccountData EventsResponse `json:"account_data"`
|
||||
Presence struct {
|
||||
Events []gomatrixserverlib.ClientEvent `json:"events,omitempty"`
|
||||
Events []json.RawMessage `json:"events,omitempty"`
|
||||
} `json:"presence"`
|
||||
Rooms SyncRoomsResponse `json:"rooms"`
|
||||
ToDevice EventsResponse `json:"to_device"`
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/sliding-sync/internal"
|
||||
"github.com/matrix-org/sliding-sync/sync3"
|
||||
"github.com/matrix-org/sliding-sync/sync3/caches"
|
||||
@ -37,7 +37,7 @@ func (t *NopTransactionFetcher) TransactionIDForEvents(userID, deviceID string,
|
||||
return
|
||||
}
|
||||
|
||||
func newRoomMetadata(roomID string, lastMsgTimestamp gomatrixserverlib.Timestamp) internal.RoomMetadata {
|
||||
func newRoomMetadata(roomID string, lastMsgTimestamp spec.Timestamp) internal.RoomMetadata {
|
||||
m := internal.NewRoomMetadata(roomID)
|
||||
m.NameEvent = "Room " + roomID
|
||||
m.LastMessageTimestamp = uint64(lastMsgTimestamp)
|
||||
@ -62,11 +62,11 @@ func TestConnStateInitial(t *testing.T) {
|
||||
}
|
||||
userID := "@TestConnStateInitial_alice:localhost"
|
||||
deviceID := "yep"
|
||||
timestampNow := gomatrixserverlib.Timestamp(1632131678061).Time()
|
||||
timestampNow := spec.Timestamp(1632131678061).Time()
|
||||
// initial sort order B, C, A
|
||||
roomA := newRoomMetadata("!a:localhost", gomatrixserverlib.AsTimestamp(timestampNow.Add(-8*time.Second)))
|
||||
roomB := newRoomMetadata("!b:localhost", gomatrixserverlib.AsTimestamp(timestampNow))
|
||||
roomC := newRoomMetadata("!c:localhost", gomatrixserverlib.AsTimestamp(timestampNow.Add(-4*time.Second)))
|
||||
roomA := newRoomMetadata("!a:localhost", spec.AsTimestamp(timestampNow.Add(-8*time.Second)))
|
||||
roomB := newRoomMetadata("!b:localhost", spec.AsTimestamp(timestampNow))
|
||||
roomC := newRoomMetadata("!c:localhost", spec.AsTimestamp(timestampNow.Add(-4*time.Second)))
|
||||
timeline := map[string]json.RawMessage{
|
||||
roomA.RoomID: testutils.NewEvent(t, "m.room.message", userID, map[string]interface{}{"body": "a"}),
|
||||
roomB.RoomID: testutils.NewEvent(t, "m.room.message", userID, map[string]interface{}{"body": "b"}),
|
||||
@ -232,7 +232,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
}
|
||||
userID := "@TestConnStateMultipleRanges_alice:localhost"
|
||||
deviceID := "yep"
|
||||
timestampNow := gomatrixserverlib.Timestamp(1632131678061)
|
||||
timestampNow := spec.Timestamp(1632131678061)
|
||||
var rooms []*internal.RoomMetadata
|
||||
var roomIDs []string
|
||||
globalCache := caches.NewGlobalCache(nil)
|
||||
@ -373,7 +373,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
// ` ` ` `
|
||||
// 8,0,1,9,2,3,4,5,6,7 room
|
||||
middleTimestamp := int64((roomIDToRoom[roomIDs[1]].LastMessageTimestamp + roomIDToRoom[roomIDs[2]].LastMessageTimestamp) / 2)
|
||||
newEvent = testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(gomatrixserverlib.Timestamp(middleTimestamp).Time()))
|
||||
newEvent = testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(spec.Timestamp(middleTimestamp).Time()))
|
||||
dispatcher.OnNewEvent(context.Background(), roomIDs[9], newEvent, 1)
|
||||
t.Logf("new event %s : %s", roomIDs[9], string(newEvent))
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
@ -414,7 +414,7 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
}
|
||||
userID := "@TestBumpToOutsideRange_alice:localhost"
|
||||
deviceID := "yep"
|
||||
timestampNow := gomatrixserverlib.Timestamp(1632131678061)
|
||||
timestampNow := spec.Timestamp(1632131678061)
|
||||
roomA := newRoomMetadata("!a:localhost", timestampNow)
|
||||
roomB := newRoomMetadata("!b:localhost", timestampNow-1000)
|
||||
roomC := newRoomMetadata("!c:localhost", timestampNow-2000)
|
||||
@ -482,7 +482,7 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
})
|
||||
|
||||
// D gets bumped to C's position but it's still outside the range so nothing should happen
|
||||
newEvent := testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(gomatrixserverlib.Timestamp(roomC.LastMessageTimestamp+2).Time()))
|
||||
newEvent := testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(spec.Timestamp(roomC.LastMessageTimestamp+2).Time()))
|
||||
dispatcher.OnNewEvent(context.Background(), roomD.RoomID, newEvent, 1)
|
||||
|
||||
// expire the context after 10ms so we don't wait forevar
|
||||
@ -511,11 +511,11 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
}
|
||||
userID := "@TestConnStateRoomSubscriptions_alice:localhost"
|
||||
deviceID := "yep"
|
||||
timestampNow := gomatrixserverlib.Timestamp(1632131678061)
|
||||
timestampNow := spec.Timestamp(1632131678061)
|
||||
roomA := newRoomMetadata("!a:localhost", timestampNow)
|
||||
roomB := newRoomMetadata("!b:localhost", gomatrixserverlib.Timestamp(timestampNow-1000))
|
||||
roomC := newRoomMetadata("!c:localhost", gomatrixserverlib.Timestamp(timestampNow-2000))
|
||||
roomD := newRoomMetadata("!d:localhost", gomatrixserverlib.Timestamp(timestampNow-3000))
|
||||
roomB := newRoomMetadata("!b:localhost", spec.Timestamp(timestampNow-1000))
|
||||
roomC := newRoomMetadata("!c:localhost", spec.Timestamp(timestampNow-2000))
|
||||
roomD := newRoomMetadata("!d:localhost", spec.Timestamp(timestampNow-3000))
|
||||
roomIDs := []string{roomA.RoomID, roomB.RoomID, roomC.RoomID, roomD.RoomID}
|
||||
globalCache := caches.NewGlobalCache(nil)
|
||||
globalCache.Startup(map[string]internal.RoomMetadata{
|
||||
@ -620,7 +620,7 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
},
|
||||
})
|
||||
// room D gets a new event but it's so old it doesn't bump to the top of the list
|
||||
newEvent := testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(gomatrixserverlib.Timestamp(timestampNow-20000).Time()))
|
||||
newEvent := testutils.NewEvent(t, "unimportant", "me", struct{}{}, testutils.WithTimestamp(spec.Timestamp(timestampNow-20000).Time()))
|
||||
dispatcher.OnNewEvent(context.Background(), roomD.RoomID, newEvent, 1)
|
||||
// we should get this message even though it's not in the range because we are subscribed to this room.
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
|
@ -275,6 +275,15 @@ func (c *CSAPI) SendEventSynced(t *testing.T, roomID string, e Event) string {
|
||||
return eventID
|
||||
}
|
||||
|
||||
func (c *CSAPI) RedactEvent(t *testing.T, roomID, eventID string) string {
|
||||
c.txnID++
|
||||
res := c.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "redact", eventID, strconv.Itoa(c.txnID)}, WithJSONBody(t, map[string]interface{}{
|
||||
"reason": "who knows",
|
||||
}))
|
||||
body := ParseJSON(t, res)
|
||||
return GetJSONFieldStr(t, body, "event_id")
|
||||
}
|
||||
|
||||
func (c *CSAPI) SendReceipt(t *testing.T, roomID, eventID, receiptType string) *http.Response {
|
||||
return c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, WithJSONBody(t, map[string]interface{}{
|
||||
receiptType: eventID,
|
||||
|
63
tests-e2e/redaction_test.go
Normal file
63
tests-e2e/redaction_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package syncv3_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/sliding-sync/sync3"
|
||||
"github.com/matrix-org/sliding-sync/testutils/m"
|
||||
)
|
||||
|
||||
func TestRedactionsAreRedactedWherePossible(t *testing.T) {
|
||||
alice := registerNamedUser(t, "alice")
|
||||
room := alice.CreateRoom(t, map[string]any{"preset": "public_chat"})
|
||||
|
||||
eventID := alice.SendEventSynced(t, room, Event{
|
||||
Type: "m.room.message",
|
||||
Content: map[string]interface{}{
|
||||
"msgtype": "m.text",
|
||||
"body": "I will be redacted",
|
||||
},
|
||||
})
|
||||
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
room: {MatchRoomTimelineMostRecent(1, []Event{{ID: eventID, Content: map[string]interface{}{
|
||||
"msgtype": "m.text",
|
||||
"body": "I will be redacted",
|
||||
}}})},
|
||||
}))
|
||||
|
||||
// redact the event
|
||||
redactionEventID := alice.RedactEvent(t, room, eventID)
|
||||
|
||||
// see the redaction
|
||||
alice.SlidingSyncUntilEventID(t, res.Pos, room, redactionEventID)
|
||||
|
||||
// now resync from scratch, the event should be redacted this time around.
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
room: {MatchRoomTimelineMostRecent(2, []Event{
|
||||
{ID: eventID, Content: map[string]interface{}{}},
|
||||
{ID: redactionEventID},
|
||||
})},
|
||||
}))
|
||||
|
||||
}
|
@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// Common functions between testing.T and testing.B
|
||||
@ -47,7 +47,7 @@ type eventMockModifier func(e *eventMock)
|
||||
|
||||
func WithTimestamp(ts time.Time) eventMockModifier {
|
||||
return func(e *eventMock) {
|
||||
e.OriginServerTS = int64(gomatrixserverlib.AsTimestamp(ts))
|
||||
e.OriginServerTS = int64(spec.AsTimestamp(ts))
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ func NewStateEvent(t TestBenchInterface, evType, stateKey, sender string, conten
|
||||
Sender: sender,
|
||||
Content: content,
|
||||
EventID: generateEventID(t),
|
||||
OriginServerTS: int64(gomatrixserverlib.AsTimestamp(time.Now())),
|
||||
OriginServerTS: int64(spec.AsTimestamp(time.Now())),
|
||||
}
|
||||
for _, m := range modifiers {
|
||||
m(e)
|
||||
@ -98,7 +98,7 @@ func NewEvent(t TestBenchInterface, evType, sender string, content interface{},
|
||||
Sender: sender,
|
||||
Content: content,
|
||||
EventID: generateEventID(t),
|
||||
OriginServerTS: int64(gomatrixserverlib.AsTimestamp(time.Now())),
|
||||
OriginServerTS: int64(spec.AsTimestamp(time.Now())),
|
||||
}
|
||||
for _, m := range modifiers {
|
||||
m(e)
|
||||
@ -132,7 +132,7 @@ func SetTimestamp(t *testing.T, event json.RawMessage, ts time.Time) json.RawMes
|
||||
t.Errorf("Failed to parse eventMock: %s", err)
|
||||
return nil
|
||||
}
|
||||
parsed.OriginServerTS = int64(gomatrixserverlib.AsTimestamp(ts))
|
||||
parsed.OriginServerTS = int64(spec.AsTimestamp(ts))
|
||||
edited, err := json.Marshal(parsed)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to serialise eventMock: %s", err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user