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
```
This commit is contained in:
Till 2022-11-14 13:07:13 +01:00 committed by GitHub
parent 858a4af224
commit 2a77a910eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 1 deletions

View File

@ -23,6 +23,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/tidwall/gjson"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/opentracing/opentracing-go" "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) // 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), // 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 // 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 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 // processStateBefore works out what the state is before the event and
// then checks the event auths against the state at the time. It also // 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 // tries to determine what the history visibility was of the event at

View File

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

View File

@ -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 // 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! // it should live in this package!

View File

@ -761,4 +761,6 @@ AS can publish rooms in their own list
AS and main public room lists are separate AS and main public room lists are separate
/upgrade preserves direct room state /upgrade preserves direct room state
local user has tags copied to the new room local user has tags copied to the new room
remote 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