Handle remote room upgrades
Makes the following tests pass
```
/upgrade moves remote aliases to the new room
Local and remote users' homeservers remove a room from their public directory on upgrade
```
MODIFY
roomserver/internal/input/input_events.go
roomserver/internal/input/input_events.go
@@ -23,6 +23,8 @@ import (
"fmt"
"time"
+ "github.com/tidwall/gjson"
+
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
"github.com/opentracing/opentracing-go"
@@ -409,6 +411,13 @@ func (r *Inputer) processRoomEvent(
}
}
+ // Handle remote room upgrades, e.g. remove published room
+ if event.Type() == "m.room.tombstone" && event.StateKeyEquals("") && !r.Cfg.Matrix.IsLocalServerName(senderDomain) {
+ if err = r.handleRemoteRoomUpgrade(ctx, event); err != nil {
+ return fmt.Errorf("failed to handle remote room upgrade: %w", err)
+ }
+ }
+
// processing this event resulted in an event (which may not be the one we're processing)
// being redacted. We are guaranteed to have both sides (the redaction/redacted event),
// so notify downstream components to redact this event - they should have it if they've
@@ -434,6 +443,13 @@ func (r *Inputer) processRoomEvent(
return nil
}
+// handleRemoteRoomUpgrade updates published rooms and room aliases
+func (r *Inputer) handleRemoteRoomUpgrade(ctx context.Context, event *gomatrixserverlib.Event) error {
+ oldRoomID := event.RoomID()
+ newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str
+ return r.DB.UpgradeRoom(ctx, oldRoomID, newRoomID, event.Sender())
+}
+
// processStateBefore works out what the state is before the event and
// then checks the event auths against the state at the time. It also
// tries to determine what the history visibility was of the event at

MODIFY
roomserver/storage/interface.go
roomserver/storage/interface.go
@@ -172,4 +172,5 @@ type Database interface {
ForgetRoom(ctx context.Context, userID, roomID string, forget bool) error
GetHistoryVisibilityState(ctx context.Context, roomInfo *types.RoomInfo, eventID string, domain string) ([]*gomatrixserverlib.Event, error)
+ UpgradeRoom(ctx context.Context, oldRoomID, newRoomID, eventSender string) error
}

MODIFY
roomserver/storage/shared/storage.go
roomserver/storage/shared/storage.go
@@ -1408,6 +1408,36 @@ func (d *Database) ForgetRoom(ctx context.Context, userID, roomID string, forget
})
}
+func (d *Database) UpgradeRoom(ctx context.Context, oldRoomID, newRoomID, eventSender string) error {
+
+ return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
+ // un-publish old room
+ if err := d.PublishedTable.UpsertRoomPublished(ctx, txn, oldRoomID, "", "", false); err != nil {
+ return fmt.Errorf("failed to unpublish room: %w", err)
+ }
+ // publish new room
+ if err := d.PublishedTable.UpsertRoomPublished(ctx, txn, newRoomID, "", "", true); err != nil {
+ return fmt.Errorf("failed to publish room: %w", err)
+ }
+
+ // Migrate any existing room aliases
+ aliases, err := d.RoomAliasesTable.SelectAliasesFromRoomID(ctx, txn, oldRoomID)
+ if err != nil {
+ return fmt.Errorf("failed to get room aliases: %w", err)
+ }
+
+ for _, alias := range aliases {
+ if err = d.RoomAliasesTable.DeleteRoomAlias(ctx, txn, alias); err != nil {
+ return fmt.Errorf("failed to remove room alias: %w", err)
+ }
+ if err = d.RoomAliasesTable.InsertRoomAlias(ctx, txn, alias, newRoomID, eventSender); err != nil {
+ return fmt.Errorf("failed to set room alias: %w", err)
+ }
+ }
+ return nil
+ })
+}
+
// FIXME TODO: Remove all this - horrible dupe with roomserver/state. Can't use the original impl because of circular loops
// it should live in this package!

MODIFY
sytest-whitelist
sytest-whitelist
@@ -762,3 +762,5 @@ AS and main public room lists are separate
/upgrade preserves direct room state
local user has tags copied to the new room
remote user has tags copied to the new room
+/upgrade moves remote aliases to the new room
+Local and remote users' homeservers remove a room from their public directory on upgrade
\ No newline at end of file

Handle remote room upgrades (#2866)

Makes the following tests pass
```
/upgrade moves remote aliases to the new room
Local and remote users' homeservers remove a room from their public directory on upgrade
```