diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 43a16945..f789ae10 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -213,6 +213,25 @@ func createRoom( return jsonerror.InternalServerError() } + var roomAlias string + if r.RoomAliasName != "" { + roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName) + // check it's free TODO: This races but is better than nothing + hasAliasReq := roomserverAPI.GetRoomIDForAliasRequest{ + Alias: roomAlias, + } + + var aliasResp roomserverAPI.GetRoomIDForAliasResponse + err = rsAPI.GetRoomIDForAlias(req.Context(), &hasAliasReq, &aliasResp) + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed") + return jsonerror.InternalServerError() + } + if aliasResp.RoomID != "" { + return util.MessageResponse(400, "Alias already exists") + } + } + membershipContent := gomatrixserverlib.MemberContent{ Membership: gomatrixserverlib.Join, DisplayName: profile.DisplayName, @@ -244,9 +263,9 @@ func createRoom( // 1- m.room.create // 2- room creator join member // 3- m.room.power_levels - // 4- m.room.canonical_alias (opt) TODO - // 5- m.room.join_rules - // 6- m.room.history_visibility + // 4- m.room.join_rules + // 5- m.room.history_visibility + // 6- m.room.canonical_alias (opt) // 7- m.room.guest_access (opt) // 8- other initial state items // 9- m.room.name (opt) @@ -262,10 +281,15 @@ func createRoom( {"m.room.create", "", r.CreationContent}, {"m.room.member", userID, membershipContent}, {"m.room.power_levels", "", common.InitialPowerLevelsContent(userID)}, - // TODO: m.room.canonical_alias {"m.room.join_rules", "", gomatrixserverlib.JoinRuleContent{JoinRule: joinRules}}, {"m.room.history_visibility", "", common.HistoryVisibilityContent{HistoryVisibility: historyVisibility}}, } + if roomAlias != "" { + // TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room. + // This means we might fail creating the alias but say the canonical alias is something that doesn't exist. + // m.room.aliases is handled when we call roomserver.SetRoomAlias + eventsToMake = append(eventsToMake, fledglingEvent{"m.room.canonical_alias", "", common.CanonicalAlias{Alias: roomAlias}}) + } if r.GuestCanJoin { eventsToMake = append(eventsToMake, fledglingEvent{"m.room.guest_access", "", common.GuestAccessContent{GuestAccess: "can_join"}}) } @@ -278,7 +302,6 @@ func createRoom( } // TODO: invite events // TODO: 3pid invite events - // TODO: m.room.aliases authEvents := gomatrixserverlib.NewAuthEvents(nil) for i, e := range eventsToMake { @@ -330,10 +353,7 @@ func createRoom( // TODO(#269): Reserve room alias while we create the room. This stops us // from creating the room but still failing due to the alias having already // been taken. - var roomAlias string - if r.RoomAliasName != "" { - roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName) - + if roomAlias != "" { aliasReq := roomserverAPI.SetRoomAliasRequest{ Alias: roomAlias, RoomID: roomID, diff --git a/common/eventcontent.go b/common/eventcontent.go index f3817ba6..e7e1a2c8 100644 --- a/common/eventcontent.go +++ b/common/eventcontent.go @@ -36,6 +36,11 @@ type HistoryVisibilityContent struct { HistoryVisibility string `json:"history_visibility"` } +// CanonicalAlias is the event content for https://matrix.org/docs/spec/client_server/r0.6.0#m-room-canonical-alias +type CanonicalAlias struct { + Alias string `json:"alias"` +} + // InitialPowerLevelsContent returns the initial values for m.room.power_levels on room creation // if they have not been specified. // http://matrix.org/docs/spec/client_server/r0.2.0.html#m-room-power-levels