Only send two power levels if we needed to override the levels, preserve miscellaneous fields in the create event

This commit is contained in:
Neil Alexander 2022-04-04 10:29:32 +01:00
parent df99cf6eaa
commit 292b3707e4
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944

View file

@ -363,19 +363,22 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, userID, roomID, ne
oldPowerLevelsEvent := state[gomatrixserverlib.StateKeyTuple{EventType: gomatrixserverlib.MRoomPowerLevels, StateKey: ""}] oldPowerLevelsEvent := state[gomatrixserverlib.StateKeyTuple{EventType: gomatrixserverlib.MRoomPowerLevels, StateKey: ""}]
oldJoinRulesEvent := state[gomatrixserverlib.StateKeyTuple{EventType: gomatrixserverlib.MRoomJoinRules, StateKey: ""}] oldJoinRulesEvent := state[gomatrixserverlib.StateKeyTuple{EventType: gomatrixserverlib.MRoomJoinRules, StateKey: ""}]
newCreateContent := map[string]interface{}{ // Create the new room create event. Using a map here instead of CreateContent
"creator": userID, // means that we preserve any other interesting fields that might be present
"room_version": newVersion, // TODO: change struct to single var? // in the create event (such as for the room types MSC).
"predecessor": gomatrixserverlib.PreviousRoom{ newCreateContent := map[string]interface{}{}
EventID: tombstoneEvent.EventID(), if err := json.Unmarshal(oldCreateEvent.Content(), &newCreateContent); err != nil {
RoomID: roomID, util.GetLogger(ctx).WithError(err).Error()
}, return nil, &api.PerformError{
Msg: "Create event content was invalid",
}
} }
oldCreateContent := unmarshal(oldCreateEvent.Content()) newCreateContent["creator"] = userID
if federate, ok := oldCreateContent["m.federate"].(bool); ok { newCreateContent["room_version"] = newVersion
newCreateContent["m.federate"] = federate newCreateContent["predecessor"] = gomatrixserverlib.PreviousRoom{
EventID: tombstoneEvent.EventID(),
RoomID: roomID,
} }
newCreateEvent := fledglingEvent{ newCreateEvent := fledglingEvent{
Type: gomatrixserverlib.MRoomCreate, Type: gomatrixserverlib.MRoomCreate,
Content: newCreateContent, Content: newCreateContent,
@ -401,22 +404,21 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, userID, roomID, ne
if err != nil { if err != nil {
util.GetLogger(ctx).WithError(err).Error() util.GetLogger(ctx).WithError(err).Error()
return nil, &api.PerformError{ return nil, &api.PerformError{
Msg: "powerLevel event was not actually a power level event", Msg: "Power level event content was invalid",
} }
} }
newPowerLevelsEvent := fledglingEvent{ // We might need to temporarily give ourselves a higher power level
Type: gomatrixserverlib.MRoomPowerLevels, // than we had in the old room in order to be able to send all of
Content: powerLevelContent, // the relevant state events. This function will return whether we
} // had to override the power level events or not — if we did, we
// need to send the original power levels again later on.
//create temporary power level event that elevates upgrading user's prvileges to create every copied state event tempPowerLevelsEvent, powerLevelsOverridden := createTemporaryPowerLevels(powerLevelContent, userID)
tempPowerLevelsEvent := createTemporaryPowerLevels(powerLevelContent, userID)
joinRulesContent, err := oldJoinRulesEvent.JoinRule() joinRulesContent, err := oldJoinRulesEvent.JoinRule()
if err != nil { if err != nil {
return nil, &api.PerformError{ return nil, &api.PerformError{
Msg: "Join rules event had bad content", Msg: "Join rules event content was invalid",
} }
} }
newJoinRulesEvent := fledglingEvent{ newJoinRulesEvent := fledglingEvent{
@ -462,7 +464,15 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, userID, roomID, ne
} }
eventsToMake = append(eventsToMake, newEvent) eventsToMake = append(eventsToMake, newEvent)
} }
eventsToMake = append(eventsToMake, newPowerLevelsEvent)
// If we sent a temporary power level event into the room before,
// override that now by restoring the original power levels.
if powerLevelsOverridden {
eventsToMake = append(eventsToMake, fledglingEvent{
Type: gomatrixserverlib.MRoomPowerLevels,
Content: powerLevelContent,
})
}
return eventsToMake, nil return eventsToMake, nil
} }
@ -600,7 +610,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user
return headeredEvent, nil return headeredEvent, nil
} }
func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, userID string) fledglingEvent { func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, userID string) (fledglingEvent, bool) {
// Work out what power level we need in order to be able to send events // Work out what power level we need in order to be able to send events
// of all types into the room. // of all types into the room.
neededPowerLevel := powerLevelContent.StateDefault neededPowerLevel := powerLevelContent.StateDefault
@ -612,6 +622,7 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC
// Make a copy of the existing power level content. // Make a copy of the existing power level content.
tempPowerLevelContent := *powerLevelContent tempPowerLevelContent := *powerLevelContent
powerLevelsOverridden := false
// At this point, the "Users", "Events" and "Notifications" keys are all // At this point, the "Users", "Events" and "Notifications" keys are all
// pointing to the map of the original PL content, so we will specifically // pointing to the map of the original PL content, so we will specifically
@ -624,15 +635,16 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC
// If the user who is upgrading the room doesn't already have sufficient // If the user who is upgrading the room doesn't already have sufficient
// power, then elevate their power levels. // power, then elevate their power levels.
if val := tempPowerLevelContent.Users[userID]; val < neededPowerLevel { if tempPowerLevelContent.UserLevel(userID) < neededPowerLevel {
tempPowerLevelContent.Users[userID] = neededPowerLevel tempPowerLevelContent.Users[userID] = neededPowerLevel
powerLevelsOverridden = true
} }
// Then return the temporary power levels event. // Then return the temporary power levels event.
return fledglingEvent{ return fledglingEvent{
Type: gomatrixserverlib.MRoomPowerLevels, Type: gomatrixserverlib.MRoomPowerLevels,
Content: tempPowerLevelContent, Content: tempPowerLevelContent,
} }, powerLevelsOverridden
} }
func (r *Upgrader) sendHeaderedEvent( func (r *Upgrader) sendHeaderedEvent(
@ -679,12 +691,3 @@ func (r *Upgrader) buildEvent(
} }
return event, nil return event, nil
} }
func unmarshal(in []byte) map[string]interface{} {
ret := make(map[string]interface{})
err := json.Unmarshal(in, &ret)
if err != nil {
logrus.Fatalf("One of our own state events is not valid JSON: %v", err)
}
return ret
}