diff --git a/clientapi/routing/directory.go b/clientapi/routing/directory.go index 473b6071a..76d848a39 100644 --- a/clientapi/routing/directory.go +++ b/clientapi/routing/directory.go @@ -15,14 +15,12 @@ package routing import ( - "encoding/json" "fmt" "net/http" "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/jsonerror" federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api" - "github.com/matrix-org/dendrite/internal/eventutil" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/userapi/api" @@ -223,132 +221,12 @@ func RemoveLocalAlias( } } - updatedCanonicalAlias := eventutil.CanonicalAlias{ - Alias: "", - AltAliases: []string{""}, - } - updated, resErr := getUpdatedCanonicalAliasState(req, queryRes.RoomID, alias, rsAPI, &updatedCanonicalAlias) - if resErr != nil { - return *resErr - } - // If the alias removed is one of the alt_aliases or the canonical one, - // we need to also remove it from the canonical_alias event - if updated { - resErr := updateCanonicalAlias(req, device, queryRes.RoomID, cfg, rsAPI, &updatedCanonicalAlias) - if resErr != nil { - return *resErr - } - } - return util.JSONResponse{ Code: http.StatusOK, JSON: struct{}{}, } } -func getUpdatedCanonicalAliasState( - req *http.Request, - roomID string, - alias string, - rsAPI roomserverAPI.RoomserverInternalAPI, - updatedCanonicalAlias *eventutil.CanonicalAlias, -) (bool, *util.JSONResponse) { - updated := false - stateTuple := gomatrixserverlib.StateKeyTuple{ - EventType: gomatrixserverlib.MRoomCanonicalAlias, - StateKey: "", - } - stateReq := roomserverAPI.QueryCurrentStateRequest{ - RoomID: roomID, - StateTuples: []gomatrixserverlib.StateKeyTuple{stateTuple}, - } - stateRes := &roomserverAPI.QueryCurrentStateResponse{} - err := rsAPI.QueryCurrentState(req.Context(), &stateReq, stateRes) - if err != nil { - util.GetLogger(req.Context()).WithError(err).Error("Query state failed") - resErr := jsonerror.InternalServerError() - return false, &resErr - } - - // We try to get the current canonical_alias state, and if found compare its content - // to the removed alias - if canonicalAliasEvent, ok := stateRes.StateEvents[stateTuple]; ok { - canonicalAliasContent := eventutil.CanonicalAlias{ - Alias: "", - AltAliases: []string{""}, - } - // TODO handle differently malformed event? - err := json.Unmarshal(canonicalAliasEvent.Content(), &canonicalAliasContent) - if err != nil { - util.GetLogger(req.Context()).WithError(err).Error("Get canonical_alias event content failed") - resErr := jsonerror.InternalServerError() - return false, &resErr - } - if alias == canonicalAliasContent.Alias { - updated = true - } else { - updatedCanonicalAlias.Alias = canonicalAliasContent.Alias - } - for _, s := range canonicalAliasContent.AltAliases { - if alias == s { - updated = true - } else { - updatedCanonicalAlias.AltAliases = append(updatedCanonicalAlias.AltAliases, s) - } - } - } - return updated, nil -} - -func updateCanonicalAlias( - req *http.Request, - device *api.Device, - roomID string, - cfg *config.ClientAPI, - rsAPI roomserverAPI.RoomserverInternalAPI, - updatedCanonicalAlias *eventutil.CanonicalAlias, -) *util.JSONResponse { - var stateKey = "" - // We create a new canonical_alias event with the new alias and alt_aliase - // May cause some auth problems - builder := gomatrixserverlib.EventBuilder{ - Sender: device.UserID, - RoomID: roomID, - Type: gomatrixserverlib.MRoomCanonicalAlias, - StateKey: &stateKey, - } - err := builder.SetContent(updatedCanonicalAlias) - if err != nil { - util.GetLogger(req.Context()).WithError(err).Error("builder.SetContent failed") - resErr := jsonerror.InternalServerError() - return &resErr - } - - evTime, err := httputil.ParseTSParam(req) - if err != nil { - return &util.JSONResponse{ - Code: http.StatusBadRequest, - JSON: jsonerror.InvalidArgumentValue(err.Error()), - } - } - - // Build the event - e, err := eventutil.QueryAndBuildEvent(req.Context(), &builder, cfg.Matrix, evTime, rsAPI, nil) - if err != nil { - util.GetLogger(req.Context()).WithError(err).Errorf("failed to QueryAndBuildEvent") - resErr := jsonerror.InternalServerError() - return &resErr - } - // Send the event to the room server - err = roomserverAPI.SendEvents(req.Context(), rsAPI, roomserverAPI.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, cfg.Matrix.ServerName, nil) - if err != nil { - util.GetLogger(req.Context()).WithError(err).Errorf("failed to SendEvents") - resErr := jsonerror.InternalServerError() - return &resErr - } - return nil -} - type roomVisibility struct { Visibility string `json:"visibility"` } diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go index 55d1042c3..8abcc30ed 100644 --- a/roomserver/internal/alias.go +++ b/roomserver/internal/alias.go @@ -16,12 +16,16 @@ package internal import ( "context" + "encoding/json" "fmt" + "time" + "github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/gomatrixserverlib" asAPI "github.com/matrix-org/dendrite/appservice/api" + "github.com/matrix-org/util" ) // RoomserverInternalAPIDatabase has the storage APIs needed to implement the alias API. @@ -190,5 +194,101 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( } response.Removed = true + + // If the alias removed is one of the alt_aliases or the canonical one, + // we need to also remove it from the canonical_alias event + _ = updateCanonicalAlias(context.TODO(), r, request.UserID, roomID, request.Alias) return nil } + +type roomAliasesContent struct { + Alias string `json:"alias,omitempty"` + Aliases []string `json:"alt_aliases,omitempty"` +} + +// Build the updated m.room.aliases event to send to the room after addition or +// removal of an alias +func updateCanonicalAlias( + ctx context.Context, + rsAPI *RoomserverInternalAPI, + userID string, + roomID string, + alias string, +) error { + updated := false + stateTuple := gomatrixserverlib.StateKeyTuple{ + EventType: gomatrixserverlib.MRoomCanonicalAlias, + StateKey: "", + } + stateReq := api.QueryCurrentStateRequest{ + RoomID: roomID, + StateTuples: []gomatrixserverlib.StateKeyTuple{stateTuple}, + } + stateRes := &api.QueryCurrentStateResponse{} + err := rsAPI.QueryCurrentState(ctx, &stateReq, stateRes) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("Query state failed") + return err + } + + updatedCanonicalAlias := roomAliasesContent{ + Alias: "", + Aliases: []string{""}, + } + + // We try to get the current canonical_alias state, and if found compare its content + // to the removed alias + if canonicalAliasEvent, ok := stateRes.StateEvents[stateTuple]; ok { + canonicalAliasContent := roomAliasesContent{ + Alias: "", + Aliases: []string{""}, + } + // TODO skip malformed event? + err = json.Unmarshal(canonicalAliasEvent.Content(), &canonicalAliasContent) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("Get canonical_alias event content failed") + return err + } + if alias == canonicalAliasContent.Alias { + updated = true + } else { + updatedCanonicalAlias.Alias = canonicalAliasContent.Alias + } + for _, s := range canonicalAliasContent.Aliases { + if alias == s { + updated = true + } else { + updatedCanonicalAlias.Aliases = append(updatedCanonicalAlias.Aliases, s) + } + } + } + + if !updated { + return nil + } + + stateKey := "" + + builder := gomatrixserverlib.EventBuilder{ + Sender: userID, + RoomID: roomID, + Type: gomatrixserverlib.MRoomCanonicalAlias, + StateKey: &stateKey, + } + + rawContent, err := json.Marshal(updatedCanonicalAlias) + if err != nil { + return err + } + err = builder.SetContent(json.RawMessage(rawContent)) + if err != nil { + return err + } + now := time.Now() + e, err := eventutil.QueryAndBuildEvent(ctx, &builder, rsAPI.Cfg.Matrix, now, rsAPI, nil) + if err != nil { + return err + } + err = api.SendEvents(ctx, rsAPI, api.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, rsAPI.Cfg.Matrix.ServerName, nil) + return err +}