aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordevonh <devon.dmytro@gmail.com>2023-05-31 15:27:08 +0000
committerGitHub <noreply@github.com>2023-05-31 15:27:08 +0000
commitcbdc601f1b6d1c2a648b69ff44b3a49916f4d31a (patch)
tree6d14c55508579211e3833cab60cfdfea3fab04a6
parent61341aca500ec4d87e5b6d4c3f965c3836d6e6d6 (diff)
Move CreateRoom logic to Roomserver (#3093)
Move create room logic over to roomserver.
-rw-r--r--clientapi/routing/createroom.go544
-rw-r--r--clientapi/routing/joinroom_test.go5
-rw-r--r--clientapi/routing/membership.go49
-rw-r--r--clientapi/routing/profile.go2
-rw-r--r--clientapi/routing/redaction.go2
-rw-r--r--clientapi/routing/sendevent.go2
-rw-r--r--clientapi/routing/server_notices.go2
-rw-r--r--clientapi/threepid/invites.go2
-rw-r--r--cmd/dendrite-upgrade-tests/tests.go5
-rw-r--r--federationapi/routing/join.go2
-rw-r--r--federationapi/routing/leave.go2
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--internal/eventutil/events.go7
-rw-r--r--roomserver/api/api.go2
-rw-r--r--roomserver/api/perform.go24
-rw-r--r--roomserver/internal/alias.go2
-rw-r--r--roomserver/internal/api.go13
-rw-r--r--roomserver/internal/input/input_events.go2
-rw-r--r--roomserver/internal/perform/perform_admin.go4
-rw-r--r--roomserver/internal/perform/perform_create_room.go498
-rw-r--r--roomserver/internal/perform/perform_join.go2
-rw-r--r--roomserver/internal/perform/perform_leave.go2
-rw-r--r--roomserver/internal/perform/perform_upgrade.go39
24 files changed, 676 insertions, 542 deletions
diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go
index 7a7a85e8..aaa305f0 100644
--- a/clientapi/routing/createroom.go
+++ b/clientapi/routing/createroom.go
@@ -22,17 +22,13 @@ import (
"strings"
"time"
- "github.com/getsentry/sentry-go"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
- "github.com/matrix-org/dendrite/roomserver/types"
roomserverVersion "github.com/matrix-org/dendrite/roomserver/version"
"github.com/matrix-org/dendrite/userapi/api"
- "github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/dendrite/clientapi/httputil"
- "github.com/matrix-org/dendrite/internal/eventutil"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@@ -41,32 +37,19 @@ import (
// https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom
type createRoomRequest struct {
- Invite []string `json:"invite"`
- Name string `json:"name"`
- Visibility string `json:"visibility"`
- Topic string `json:"topic"`
- Preset string `json:"preset"`
- CreationContent json.RawMessage `json:"creation_content"`
- InitialState []fledglingEvent `json:"initial_state"`
- RoomAliasName string `json:"room_alias_name"`
- RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
- PowerLevelContentOverride json.RawMessage `json:"power_level_content_override"`
- IsDirect bool `json:"is_direct"`
+ Invite []string `json:"invite"`
+ Name string `json:"name"`
+ Visibility string `json:"visibility"`
+ Topic string `json:"topic"`
+ Preset string `json:"preset"`
+ CreationContent json.RawMessage `json:"creation_content"`
+ InitialState []gomatrixserverlib.FledglingEvent `json:"initial_state"`
+ RoomAliasName string `json:"room_alias_name"`
+ RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
+ PowerLevelContentOverride json.RawMessage `json:"power_level_content_override"`
+ IsDirect bool `json:"is_direct"`
}
-const (
- presetPrivateChat = "private_chat"
- presetTrustedPrivateChat = "trusted_private_chat"
- presetPublicChat = "public_chat"
-)
-
-const (
- historyVisibilityShared = "shared"
- // TODO: These should be implemented once history visibility is implemented
- // historyVisibilityWorldReadable = "world_readable"
- // historyVisibilityInvited = "invited"
-)
-
func (r createRoomRequest) Validate() *util.JSONResponse {
whitespace := "\t\n\x0b\x0c\r " // https://docs.python.org/2/library/string.html#string.whitespace
// https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/handlers/room.py#L81
@@ -78,12 +61,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
}
}
for _, userID := range r.Invite {
- // TODO: We should put user ID parsing code into gomatrixserverlib and use that instead
- // (see https://github.com/matrix-org/gomatrixserverlib/blob/3394e7c7003312043208aa73727d2256eea3d1f6/eventcontent.go#L347 )
- // It should be a struct (with pointers into a single string to avoid copying) and
- // we should update all refs to use UserID types rather than strings.
- // https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/types.py#L92
- if _, _, err := gomatrixserverlib.SplitID('@', userID); err != nil {
+ if _, err := spec.NewUserID(userID, true); err != nil {
return &util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.BadJSON("user id must be in the form @localpart:domain"),
@@ -91,7 +69,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
}
}
switch r.Preset {
- case presetPrivateChat, presetTrustedPrivateChat, presetPublicChat, "":
+ case spec.PresetPrivateChat, spec.PresetTrustedPrivateChat, spec.PresetPublicChat, "":
default:
return &util.JSONResponse{
Code: http.StatusBadRequest,
@@ -129,13 +107,6 @@ type createRoomResponse struct {
RoomAlias string `json:"room_alias,omitempty"` // in synapse not spec
}
-// fledglingEvent is a helper representation of an event used when creating many events in succession.
-type fledglingEvent struct {
- Type string `json:"type"`
- StateKey string `json:"state_key"`
- Content interface{} `json:"content"`
-}
-
// CreateRoom implements /createRoom
func CreateRoom(
req *http.Request, device *api.Device,
@@ -143,12 +114,12 @@ func CreateRoom(
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
asAPI appserviceAPI.AppServiceInternalAPI,
) util.JSONResponse {
- var r createRoomRequest
- resErr := httputil.UnmarshalJSONRequest(req, &r)
+ var createRequest createRoomRequest
+ resErr := httputil.UnmarshalJSONRequest(req, &createRequest)
if resErr != nil {
return *resErr
}
- if resErr = r.Validate(); resErr != nil {
+ if resErr = createRequest.Validate(); resErr != nil {
return *resErr
}
evTime, err := httputil.ParseTSParam(req)
@@ -158,46 +129,52 @@ func CreateRoom(
JSON: spec.InvalidParam(err.Error()),
}
}
- return createRoom(req.Context(), r, device, cfg, profileAPI, rsAPI, asAPI, evTime)
+ return createRoom(req.Context(), createRequest, device, cfg, profileAPI, rsAPI, asAPI, evTime)
}
// createRoom implements /createRoom
-// nolint: gocyclo
func createRoom(
ctx context.Context,
- r createRoomRequest, device *api.Device,
+ // TODO: remove dependency on createRoomRequest
+ createRequest createRoomRequest, device *api.Device,
cfg *config.ClientAPI,
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
asAPI appserviceAPI.AppServiceInternalAPI,
evTime time.Time,
) util.JSONResponse {
- _, userDomain, err := gomatrixserverlib.SplitID('@', device.UserID)
+ userID, err := spec.NewUserID(device.UserID, true)
if err != nil {
- util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
+ util.GetLogger(ctx).WithError(err).Error("invalid userID")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
- if !cfg.Matrix.IsLocalServerName(userDomain) {
+ if !cfg.Matrix.IsLocalServerName(userID.Domain()) {
return util.JSONResponse{
Code: http.StatusForbidden,
- JSON: spec.Forbidden(fmt.Sprintf("User domain %q not configured locally", userDomain)),
+ JSON: spec.Forbidden(fmt.Sprintf("User domain %q not configured locally", userID.Domain())),
}
}
- // TODO (#267): Check room ID doesn't clash with an existing one, and we
- // probably shouldn't be using pseudo-random strings, maybe GUIDs?
- roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), userDomain)
-
logger := util.GetLogger(ctx)
- userID := device.UserID
+
+ // TODO: Check room ID doesn't clash with an existing one, and we
+ // probably shouldn't be using pseudo-random strings, maybe GUIDs?
+ roomID, err := spec.NewRoomID(fmt.Sprintf("!%s:%s", util.RandomString(16), userID.Domain()))
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("invalid roomID")
+ return util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
// Clobber keys: creator, room_version
roomVersion := roomserverVersion.DefaultRoomVersion()
- if r.RoomVersion != "" {
- candidateVersion := gomatrixserverlib.RoomVersion(r.RoomVersion)
+ if createRequest.RoomVersion != "" {
+ candidateVersion := gomatrixserverlib.RoomVersion(createRequest.RoomVersion)
_, roomVersionError := roomserverVersion.SupportedRoomVersion(candidateVersion)
if roomVersionError != nil {
return util.JSONResponse{
@@ -208,17 +185,13 @@ func createRoom(
roomVersion = candidateVersion
}
- // TODO: visibility/presets/raw initial state
- // TODO: Create room alias association
- // Make sure this doesn't fall into an application service's namespace though!
-
logger.WithFields(log.Fields{
- "userID": userID,
- "roomID": roomID,
+ "userID": userID.String(),
+ "roomID": roomID.String(),
"roomVersion": roomVersion,
}).Info("Creating new room")
- profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID, asAPI, profileAPI)
+ profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID.String(), asAPI, profileAPI)
if err != nil {
util.GetLogger(ctx).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
return util.JSONResponse{
@@ -227,427 +200,38 @@ func createRoom(
}
}
- createContent := map[string]interface{}{}
- if len(r.CreationContent) > 0 {
- if err = json.Unmarshal(r.CreationContent, &createContent); err != nil {
- util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for creation_content failed")
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.BadJSON("invalid create content"),
- }
- }
- }
- createContent["creator"] = userID
- createContent["room_version"] = roomVersion
- powerLevelContent := eventutil.InitialPowerLevelsContent(userID)
- joinRuleContent := gomatrixserverlib.JoinRuleContent{
- JoinRule: spec.Invite,
- }
- historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{
- HistoryVisibility: historyVisibilityShared,
- }
-
- if r.PowerLevelContentOverride != nil {
- // Merge powerLevelContentOverride fields by unmarshalling it atop the defaults
- err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for power_level_content_override failed")
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.BadJSON("malformed power_level_content_override"),
- }
- }
- }
-
- var guestsCanJoin bool
- switch r.Preset {
- case presetPrivateChat:
- joinRuleContent.JoinRule = spec.Invite
- historyVisibilityContent.HistoryVisibility = historyVisibilityShared
- guestsCanJoin = true
- case presetTrustedPrivateChat:
- joinRuleContent.JoinRule = spec.Invite
- historyVisibilityContent.HistoryVisibility = historyVisibilityShared
- for _, invitee := range r.Invite {
- powerLevelContent.Users[invitee] = 100
- }
- guestsCanJoin = true
- case presetPublicChat:
- joinRuleContent.JoinRule = spec.Public
- historyVisibilityContent.HistoryVisibility = historyVisibilityShared
- }
-
- createEvent := fledglingEvent{
- Type: spec.MRoomCreate,
- Content: createContent,
- }
- powerLevelEvent := fledglingEvent{
- Type: spec.MRoomPowerLevels,
- Content: powerLevelContent,
- }
- joinRuleEvent := fledglingEvent{
- Type: spec.MRoomJoinRules,
- Content: joinRuleContent,
- }
- historyVisibilityEvent := fledglingEvent{
- Type: spec.MRoomHistoryVisibility,
- Content: historyVisibilityContent,
- }
- membershipEvent := fledglingEvent{
- Type: spec.MRoomMember,
- StateKey: userID,
- Content: gomatrixserverlib.MemberContent{
- Membership: spec.Join,
- DisplayName: profile.DisplayName,
- AvatarURL: profile.AvatarURL,
- },
- }
-
- var nameEvent *fledglingEvent
- var topicEvent *fledglingEvent
- var guestAccessEvent *fledglingEvent
- var aliasEvent *fledglingEvent
-
- if r.Name != "" {
- nameEvent = &fledglingEvent{
- Type: spec.MRoomName,
- Content: eventutil.NameContent{
- Name: r.Name,
- },
- }
- }
-
- if r.Topic != "" {
- topicEvent = &fledglingEvent{
- Type: spec.MRoomTopic,
- Content: eventutil.TopicContent{
- Topic: r.Topic,
- },
- }
- }
-
- if guestsCanJoin {
- guestAccessEvent = &fledglingEvent{
- Type: spec.MRoomGuestAccess,
- Content: eventutil.GuestAccessContent{
- GuestAccess: "can_join",
- },
- }
- }
-
- var roomAlias string
- if r.RoomAliasName != "" {
- roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, userDomain)
- // check it's free TODO: This races but is better than nothing
- hasAliasReq := roomserverAPI.GetRoomIDForAliasRequest{
- Alias: roomAlias,
- IncludeAppservices: false,
- }
-
- var aliasResp roomserverAPI.GetRoomIDForAliasResponse
- err = rsAPI.GetRoomIDForAlias(ctx, &hasAliasReq, &aliasResp)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
- if aliasResp.RoomID != "" {
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.RoomInUse("Room ID already exists."),
- }
- }
-
- aliasEvent = &fledglingEvent{
- Type: spec.MRoomCanonicalAlias,
- Content: eventutil.CanonicalAlias{
- Alias: roomAlias,
- },
- }
- }
-
- var initialStateEvents []fledglingEvent
- for i := range r.InitialState {
- if r.InitialState[i].StateKey != "" {
- initialStateEvents = append(initialStateEvents, r.InitialState[i])
- continue
- }
-
- switch r.InitialState[i].Type {
- case spec.MRoomCreate:
- continue
-
- case spec.MRoomPowerLevels:
- powerLevelEvent = r.InitialState[i]
-
- case spec.MRoomJoinRules:
- joinRuleEvent = r.InitialState[i]
-
- case spec.MRoomHistoryVisibility:
- historyVisibilityEvent = r.InitialState[i]
-
- case spec.MRoomGuestAccess:
- guestAccessEvent = &r.InitialState[i]
-
- case spec.MRoomName:
- nameEvent = &r.InitialState[i]
-
- case spec.MRoomTopic:
- topicEvent = &r.InitialState[i]
-
- default:
- initialStateEvents = append(initialStateEvents, r.InitialState[i])
- }
- }
-
- // send events into the room in order of:
- // 1- m.room.create
- // 2- room creator join member
- // 3- m.room.power_levels
- // 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)
- // 10- m.room.topic (opt)
- // 11- invite events (opt) - with is_direct flag if applicable TODO
- // 12- 3pid invite events (opt) TODO
- // This differs from Synapse slightly. Synapse would vary the ordering of 3-7
- // depending on if those events were in "initial_state" or not. This made it
- // harder to reason about, hence sticking to a strict static ordering.
- // TODO: Synapse has txn/token ID on each event. Do we need to do this here?
- eventsToMake := []fledglingEvent{
- createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
- }
- if guestAccessEvent != nil {
- eventsToMake = append(eventsToMake, *guestAccessEvent)
- }
- eventsToMake = append(eventsToMake, initialStateEvents...)
- if nameEvent != nil {
- eventsToMake = append(eventsToMake, *nameEvent)
- }
- if topicEvent != nil {
- eventsToMake = append(eventsToMake, *topicEvent)
- }
- if aliasEvent != nil {
- // 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.
- eventsToMake = append(eventsToMake, *aliasEvent)
- }
-
- // TODO: invite events
- // TODO: 3pid invite events
-
- verImpl, err := gomatrixserverlib.GetRoomVersion(roomVersion)
- if err != nil {
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.BadJSON("unknown room version"),
- }
- }
-
- var builtEvents []*types.HeaderedEvent
- authEvents := gomatrixserverlib.NewAuthEvents(nil)
- for i, e := range eventsToMake {
- depth := i + 1 // depth starts at 1
-
- builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
- Sender: userID,
- RoomID: roomID,
- Type: e.Type,
- StateKey: &e.StateKey,
- Depth: int64(depth),
- })
- err = builder.SetContent(e.Content)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
- if i > 0 {
- builder.PrevEvents = []string{builtEvents[i-1].EventID()}
- }
- var ev gomatrixserverlib.PDU
- if err = builder.AddAuthEvents(&authEvents); err != nil {
- util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
- ev, err = builder.Build(evTime, userDomain, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
-
- if err = gomatrixserverlib.Allowed(ev, &authEvents); err != nil {
- util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
-
- // Add the event to the list of auth events
- builtEvents = append(builtEvents, &types.HeaderedEvent{PDU: ev})
- err = authEvents.AddEvent(ev)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("authEvents.AddEvent failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
- }
-
- inputs := make([]roomserverAPI.InputRoomEvent, 0, len(builtEvents))
- for _, event := range builtEvents {
- inputs = append(inputs, roomserverAPI.InputRoomEvent{
- Kind: roomserverAPI.KindNew,
- Event: event,
- Origin: userDomain,
- SendAsServer: roomserverAPI.DoNotSendToOtherServers,
- })
- }
- if err = roomserverAPI.SendInputRoomEvents(ctx, rsAPI, device.UserDomain(), inputs, false); err != nil {
- util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
-
- // 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.
- if roomAlias != "" {
- aliasReq := roomserverAPI.SetRoomAliasRequest{
- Alias: roomAlias,
- RoomID: roomID,
- UserID: userID,
- }
+ userDisplayName := profile.DisplayName
+ userAvatarURL := profile.AvatarURL
- var aliasResp roomserverAPI.SetRoomAliasResponse
- err = rsAPI.SetRoomAlias(ctx, &aliasReq, &aliasResp)
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("aliasAPI.SetRoomAlias failed")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
-
- if aliasResp.AliasExists {
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.RoomInUse("Room alias already exists."),
- }
- }
- }
+ keyID := cfg.Matrix.KeyID
+ privateKey := cfg.Matrix.PrivateKey
- // If this is a direct message then we should invite the participants.
- if len(r.Invite) > 0 {
- // Build some stripped state for the invite.
- var globalStrippedState []fclient.InviteV2StrippedState
- for _, event := range builtEvents {
- // Chosen events from the spec:
- // https://spec.matrix.org/v1.3/client-server-api/#stripped-state
- switch event.Type() {
- case spec.MRoomCreate:
- fallthrough
- case spec.MRoomName:
- fallthrough
- case spec.MRoomAvatar:
- fallthrough
- case spec.MRoomTopic:
- fallthrough
- case spec.MRoomCanonicalAlias:
- fallthrough
- case spec.MRoomEncryption:
- fallthrough
- case spec.MRoomMember:
- fallthrough
- case spec.MRoomJoinRules:
- ev := event.PDU
- globalStrippedState = append(
- globalStrippedState,
- fclient.NewInviteV2StrippedState(ev),
- )
- }
- }
+ req := roomserverAPI.PerformCreateRoomRequest{
+ InvitedUsers: createRequest.Invite,
+ RoomName: createRequest.Name,
+ Visibility: createRequest.Visibility,
+ Topic: createRequest.Topic,
+ StatePreset: createRequest.Preset,
+ CreationContent: createRequest.CreationContent,
+ InitialState: createRequest.InitialState,
+ RoomAliasName: createRequest.RoomAliasName,
+ RoomVersion: roomVersion,
+ PowerLevelContentOverride: createRequest.PowerLevelContentOverride,
+ IsDirect: createRequest.IsDirect,
- // Process the invites.
- var inviteEvent *types.HeaderedEvent
- for _, invitee := range r.Invite {
- // Build the invite event.
- inviteEvent, err = buildMembershipEvent(
- ctx, invitee, "", profileAPI, device, spec.Invite,
- roomID, r.IsDirect, cfg, evTime, rsAPI, asAPI,
- )
- if err != nil {
- util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
- continue
- }
- inviteStrippedState := append(
- globalStrippedState,
- fclient.NewInviteV2StrippedState(inviteEvent.PDU),
- )
- // Send the invite event to the roomserver.
- event := inviteEvent
- err = rsAPI.PerformInvite(ctx, &roomserverAPI.PerformInviteRequest{
- Event: event,
- InviteRoomState: inviteStrippedState,
- RoomVersion: event.Version(),
- SendAsServer: string(userDomain),
- })
- switch e := err.(type) {
- case roomserverAPI.ErrInvalidID:
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: spec.Unknown(e.Error()),
- }
- case roomserverAPI.ErrNotAllowed:
- return util.JSONResponse{
- Code: http.StatusForbidden,
- JSON: spec.Forbidden(e.Error()),
- }
- case nil:
- default:
- util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
- sentry.CaptureException(err)
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
- }
+ UserDisplayName: userDisplayName,
+ UserAvatarURL: userAvatarURL,
+ KeyID: keyID,
+ PrivateKey: privateKey,
+ EventTime: evTime,
}
-
- if r.Visibility == spec.Public {
- // expose this room in the published room list
- if err = rsAPI.PerformPublish(ctx, &roomserverAPI.PerformPublishRequest{
- RoomID: roomID,
- Visibility: spec.Public,
- }); err != nil {
- util.GetLogger(ctx).WithError(err).Error("failed to publish room")
- return util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
+ roomAlias, createRes := rsAPI.PerformCreateRoom(ctx, *userID, *roomID, &req)
+ if createRes != nil {
+ return *createRes
}
response := createRoomResponse{
- RoomID: roomID,
+ RoomID: roomID.String(),
RoomAlias: roomAlias,
}
diff --git a/clientapi/routing/joinroom_test.go b/clientapi/routing/joinroom_test.go
index 4b67b09f..0ddff8a9 100644
--- a/clientapi/routing/joinroom_test.go
+++ b/clientapi/routing/joinroom_test.go
@@ -11,6 +11,7 @@ import (
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/roomserver"
@@ -63,7 +64,7 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
IsDirect: true,
Topic: "testing",
Visibility: "public",
- Preset: presetPublicChat,
+ Preset: spec.PresetPublicChat,
RoomAliasName: "alias",
Invite: []string{bob.ID},
}, aliceDev, &cfg.ClientAPI, userAPI, rsAPI, asAPI, time.Now())
@@ -78,7 +79,7 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
IsDirect: true,
Topic: "testing",
Visibility: "public",
- Preset: presetPublicChat,
+ Preset: spec.PresetPublicChat,
Invite: []string{charlie.ID},
}, aliceDev, &cfg.ClientAPI, userAPI, rsAPI, asAPI, time.Now())
crRespWithGuestAccess, ok := resp.JSON.(createRoomResponse)
diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go
index 4f2a0e39..0fe0a4ad 100644
--- a/clientapi/routing/membership.go
+++ b/clientapi/routing/membership.go
@@ -16,12 +16,14 @@ package routing
import (
"context"
+ "crypto/ed25519"
"fmt"
"net/http"
"time"
"github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
@@ -308,21 +310,16 @@ func sendInvite(
}, nil
}
-func buildMembershipEvent(
+func buildMembershipEventDirect(
ctx context.Context,
- targetUserID, reason string, profileAPI userapi.ClientUserAPI,
- device *userapi.Device,
+ targetUserID, reason string, userDisplayName, userAvatarURL string,
+ sender string, senderDomain spec.ServerName,
membership, roomID string, isDirect bool,
- cfg *config.ClientAPI, evTime time.Time,
- rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
+ keyID gomatrixserverlib.KeyID, privateKey ed25519.PrivateKey, evTime time.Time,
+ rsAPI roomserverAPI.ClientRoomserverAPI,
) (*types.HeaderedEvent, error) {
- profile, err := loadProfile(ctx, targetUserID, cfg, profileAPI, asAPI)
- if err != nil {
- return nil, err
- }
-
proto := gomatrixserverlib.ProtoEvent{
- Sender: device.UserID,
+ Sender: sender,
RoomID: roomID,
Type: "m.room.member",
StateKey: &targetUserID,
@@ -330,13 +327,34 @@ func buildMembershipEvent(
content := gomatrixserverlib.MemberContent{
Membership: membership,
- DisplayName: profile.DisplayName,
- AvatarURL: profile.AvatarURL,
+ DisplayName: userDisplayName,
+ AvatarURL: userAvatarURL,
Reason: reason,
IsDirect: isDirect,
}
- if err = proto.SetContent(content); err != nil {
+ if err := proto.SetContent(content); err != nil {
+ return nil, err
+ }
+
+ identity := &fclient.SigningIdentity{
+ ServerName: senderDomain,
+ KeyID: keyID,
+ PrivateKey: privateKey,
+ }
+ return eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil)
+}
+
+func buildMembershipEvent(
+ ctx context.Context,
+ targetUserID, reason string, profileAPI userapi.ClientUserAPI,
+ device *userapi.Device,
+ membership, roomID string, isDirect bool,
+ cfg *config.ClientAPI, evTime time.Time,
+ rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
+) (*types.HeaderedEvent, error) {
+ profile, err := loadProfile(ctx, targetUserID, cfg, profileAPI, asAPI)
+ if err != nil {
return nil, err
}
@@ -345,7 +363,8 @@ func buildMembershipEvent(
return nil, err
}
- return eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil)
+ return buildMembershipEventDirect(ctx, targetUserID, reason, profile.DisplayName, profile.AvatarURL,
+ device.UserID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI)
}
// loadProfile lookups the profile of a given user from the database and returns
diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go
index 76129f0a..2c9d0cbb 100644
--- a/clientapi/routing/profile.go
+++ b/clientapi/routing/profile.go
@@ -387,7 +387,7 @@ func buildMembershipEvents(
return nil, err
}
- event, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil)
+ event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil)
if err != nil {
return nil, err
}
diff --git a/clientapi/routing/redaction.go b/clientapi/routing/redaction.go
index ed70e5c5..88312642 100644
--- a/clientapi/routing/redaction.go
+++ b/clientapi/routing/redaction.go
@@ -137,7 +137,7 @@ func SendRedaction(
}
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
- e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
+ e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, identity, time.Now(), rsAPI, &queryRes)
if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{
Code: http.StatusNotFound,
diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go
index bc14642f..1a2e25c9 100644
--- a/clientapi/routing/sendevent.go
+++ b/clientapi/routing/sendevent.go
@@ -293,7 +293,7 @@ func generateSendEvent(
}
var queryRes api.QueryLatestEventsAndStateResponse
- e, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
+ e, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, &queryRes)
switch specificErr := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
diff --git a/clientapi/routing/server_notices.go b/clientapi/routing/server_notices.go
index ad50cc80..06714ed1 100644
--- a/clientapi/routing/server_notices.go
+++ b/clientapi/routing/server_notices.go
@@ -155,7 +155,7 @@ func SendServerNotice(
Invite: []string{r.UserID},
Name: cfgNotices.RoomName,
Visibility: "private",
- Preset: presetPrivateChat,
+ Preset: spec.PresetPrivateChat,
CreationContent: cc,
RoomVersion: roomVersion,
PowerLevelContentOverride: pl,
diff --git a/clientapi/threepid/invites.go b/clientapi/threepid/invites.go
index c296939d..9f4f62e4 100644
--- a/clientapi/threepid/invites.go
+++ b/clientapi/threepid/invites.go
@@ -380,7 +380,7 @@ func emit3PIDInviteEvent(
}
queryRes := api.QueryLatestEventsAndStateResponse{}
- event, err := eventutil.QueryAndBuildEvent(ctx, proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
+ event, err := eventutil.QueryAndBuildEvent(ctx, proto, identity, evTime, rsAPI, &queryRes)
if err != nil {
return err
}
diff --git a/cmd/dendrite-upgrade-tests/tests.go b/cmd/dendrite-upgrade-tests/tests.go
index 03438bd4..692ab34e 100644
--- a/cmd/dendrite-upgrade-tests/tests.go
+++ b/cmd/dendrite-upgrade-tests/tests.go
@@ -9,6 +9,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/spec"
)
const userPassword = "this_is_a_long_password"
@@ -56,7 +57,7 @@ func runTests(baseURL string, v *semver.Version) error {
// create DM room, join it and exchange messages
createRoomResp, err := users[0].client.CreateRoom(&gomatrix.ReqCreateRoom{
- Preset: "trusted_private_chat",
+ Preset: spec.PresetTrustedPrivateChat,
Invite: []string{users[1].userID},
IsDirect: true,
})
@@ -98,7 +99,7 @@ func runTests(baseURL string, v *semver.Version) error {
publicRoomID := ""
createRoomResp, err = users[0].client.CreateRoom(&gomatrix.ReqCreateRoom{
RoomAliasName: "global",
- Preset: "public_chat",
+ Preset: spec.PresetPublicChat,
})
if err != nil { // this is okay and expected if the room already exists and the aliases clash
// try to join it
diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go
index 4cbfc5e8..03d3309a 100644
--- a/federationapi/routing/join.go
+++ b/federationapi/routing/join.go
@@ -121,7 +121,7 @@ func MakeJoin(
queryRes := api.QueryLatestEventsAndStateResponse{
RoomVersion: roomVersion,
}
- event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
+ event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes)
switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go
index 3e576e09..a767168d 100644
--- a/federationapi/routing/leave.go
+++ b/federationapi/routing/leave.go
@@ -66,7 +66,7 @@ func MakeLeave(
}
queryRes := api.QueryLatestEventsAndStateResponse{}
- event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
+ event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes)
switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
diff --git a/go.mod b/go.mod
index 360ddf5b..0e979de6 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
- github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6
+ github.com/matrix-org/gomatrixserverlib v0.0.0-20230531143710-c681a0658246
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
github.com/mattn/go-sqlite3 v1.14.16
diff --git a/go.sum b/go.sum
index 4a6054af..8baa50e8 100644
--- a/go.sum
+++ b/go.sum
@@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
-github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6 h1:FQpdh/KGCCQJytz4GAdG6pbx3DJ1HNzdKFc/BCZ0hP0=
-github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
+github.com/matrix-org/gomatrixserverlib v0.0.0-20230531143710-c681a0658246 h1:1sYXx7p9BIf0R7OIV/TZg3SCvNehEQPCKNqwV1ONfwU=
+github.com/matrix-org/gomatrixserverlib v0.0.0-20230531143710-c681a0658246/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
diff --git a/internal/eventutil/events.go b/internal/eventutil/events.go
index ca052c31..0f73db2d 100644
--- a/internal/eventutil/events.go
+++ b/internal/eventutil/events.go
@@ -22,7 +22,6 @@ import (
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types"
- "github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
@@ -51,7 +50,7 @@ func (e ErrRoomNoExists) Unwrap() error {
// Returns an error if something else went wrong
func QueryAndBuildEvent(
ctx context.Context,
- proto *gomatrixserverlib.ProtoEvent, cfg *config.Global,
+ proto *gomatrixserverlib.ProtoEvent,
identity *fclient.SigningIdentity, evTime time.Time,
rsAPI api.QueryLatestEventsAndStateAPI, queryRes *api.QueryLatestEventsAndStateResponse,
) (*types.HeaderedEvent, error) {
@@ -64,14 +63,14 @@ func QueryAndBuildEvent(
// This can pass through a ErrRoomNoExists to the caller
return nil, err
}
- return BuildEvent(ctx, proto, cfg, identity, evTime, eventsNeeded, queryRes)
+ return BuildEvent(ctx, proto, identity, evTime, eventsNeeded, queryRes)
}
// BuildEvent builds a Matrix event from the builder and QueryLatestEventsAndStateResponse
// provided.
func BuildEvent(
ctx context.Context,
- proto *gomatrixserverlib.ProtoEvent, cfg *config.Global,
+ proto *gomatrixserverlib.ProtoEvent,
identity *fclient.SigningIdentity, evTime time.Time,
eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse,
) (*types.HeaderedEvent, error) {
diff --git a/roomserver/api/api.go b/roomserver/api/api.go
index 213e16e5..571aa40b 100644
--- a/roomserver/api/api.go
+++ b/roomserver/api/api.go
@@ -5,6 +5,7 @@ import (
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
+ "github.com/matrix-org/util"
asAPI "github.com/matrix-org/dendrite/appservice/api"
fsAPI "github.com/matrix-org/dendrite/federationapi/api"
@@ -169,6 +170,7 @@ type ClientRoomserverAPI interface {
GetRoomIDForAlias(ctx context.Context, req *GetRoomIDForAliasRequest, res *GetRoomIDForAliasResponse) error
GetAliasesForRoomID(ctx context.Context, req *GetAliasesForRoomIDRequest, res *GetAliasesForRoomIDResponse) error
+ PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *PerformCreateRoomRequest) (string, *util.JSONResponse)
// PerformRoomUpgrade upgrades a room to a newer version
PerformRoomUpgrade(ctx context.Context, roomID, userID string, roomVersion gomatrixserverlib.RoomVersion) (newRoomID string, err error)
PerformAdminEvacuateRoom(ctx context.Context, roomID string) (affected []string, err error)
diff --git a/roomserver/api/perform.go b/roomserver/api/perform.go
index c6e5f5a1..8d9742c6 100644
--- a/roomserver/api/perform.go
+++ b/roomserver/api/perform.go
@@ -1,6 +1,10 @@
package api
import (
+ "crypto/ed25519"
+ "encoding/json"
+ "time"
+
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
@@ -8,6 +12,26 @@ import (
"github.com/matrix-org/util"
)
+type PerformCreateRoomRequest struct {
+ InvitedUsers []string
+ RoomName string
+ Visibility string
+ Topic string
+ StatePreset string
+ CreationContent json.RawMessage
+ InitialState []gomatrixserverlib.FledglingEvent
+ RoomAliasName string
+ RoomVersion gomatrixserverlib.RoomVersion
+ PowerLevelContentOverride json.RawMessage
+ IsDirect bool
+
+ UserDisplayName string
+ UserAvatarURL string
+ KeyID gomatrixserverlib.KeyID
+ PrivateKey ed25519.PrivateKey
+ EventTime time.Time
+}
+
type PerformJoinRequest struct {
RoomIDOrAlias string `json:"room_id_or_alias"`
UserID string `json:"user_id"`
diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go
index 4d2de9a5..52b90cf4 100644
--- a/roomserver/internal/alias.go
+++ b/roomserver/internal/alias.go
@@ -208,7 +208,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err
}
- newEvent, err := eventutil.BuildEvent(ctx, proto, &r.Cfg.Global, identity, time.Now(), &eventsNeeded, stateRes)
+ newEvent, err := eventutil.BuildEvent(ctx, proto, identity, time.Now(), &eventsNeeded, stateRes)
if err != nil {
return err
}
diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go
index 81904c8b..f61f8918 100644
--- a/roomserver/internal/api.go
+++ b/roomserver/internal/api.go
@@ -6,6 +6,7 @@ import (
"github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
+ "github.com/matrix-org/util"
"github.com/nats-io/nats.go"
"github.com/sirupsen/logrus"
@@ -40,6 +41,7 @@ type RoomserverInternalAPI struct {
*perform.Forgetter
*perform.Upgrader
*perform.Admin
+ *perform.Creator
ProcessContext *process.ProcessContext
DB storage.Database
Cfg *config.Dendrite
@@ -191,6 +193,11 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio
Queryer: r.Queryer,
Leaver: r.Leaver,
}
+ r.Creator = &perform.Creator{
+ DB: r.DB,
+ Cfg: &r.Cfg.RoomServer,
+ RSAPI: r,
+ }
if err := r.Inputer.Start(); err != nil {
logrus.WithError(err).Panic("failed to start roomserver input API")
@@ -206,6 +213,12 @@ func (r *RoomserverInternalAPI) SetAppserviceAPI(asAPI asAPI.AppServiceInternalA
r.asAPI = asAPI
}
+func (r *RoomserverInternalAPI) PerformCreateRoom(
+ ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *api.PerformCreateRoomRequest,
+) (string, *util.JSONResponse) {
+ return r.Creator.PerformCreateRoom(ctx, userID, roomID, createRequest)
+}
+
func (r *RoomserverInternalAPI) PerformInvite(
ctx context.Context,
req *api.PerformInviteRequest,
diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go
index 02a1a280..386083f6 100644
--- a/roomserver/internal/input/input_events.go
+++ b/roomserver/internal/input/input_events.go
@@ -872,7 +872,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
return err
}
- event, err := eventutil.BuildEvent(ctx, fledglingEvent, r.Cfg.Matrix, r.SigningIdentity, time.Now(), &eventsNeeded, latestRes)
+ event, err := eventutil.BuildEvent(ctx, fledglingEvent, r.SigningIdentity, time.Now(), &eventsNeeded, latestRes)
if err != nil {
return err
}
diff --git a/roomserver/internal/perform/perform_admin.go b/roomserver/internal/perform/perform_admin.go
index 8d21b782..575525e2 100644
--- a/roomserver/internal/perform/perform_admin.go
+++ b/roomserver/internal/perform/perform_admin.go
@@ -119,7 +119,7 @@ func (r *Admin) PerformAdminEvacuateRoom(
continue
}
- event, err = eventutil.BuildEvent(ctx, fledglingEvent, r.Cfg.Matrix, identity, time.Now(), &eventsNeeded, latestRes)
+ event, err = eventutil.BuildEvent(ctx, fledglingEvent, identity, time.Now(), &eventsNeeded, latestRes)
if err != nil {
return nil, err
}
@@ -312,7 +312,7 @@ func (r *Admin) PerformAdminDownloadState(
return err
}
- ev, err := eventutil.BuildEvent(ctx, proto, r.Cfg.Matrix, identity, time.Now(), &eventsNeeded, queryRes)
+ ev, err := eventutil.BuildEvent(ctx, proto, identity, time.Now(), &eventsNeeded, queryRes)
if err != nil {
return fmt.Errorf("eventutil.BuildEvent: %w", err)
}
diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go
new file mode 100644
index 00000000..0f917008
--- /dev/null
+++ b/roomserver/internal/perform/perform_create_room.go
@@ -0,0 +1,498 @@
+// Copyright 2023 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package perform
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+
+ "github.com/getsentry/sentry-go"
+ "github.com/matrix-org/dendrite/internal/eventutil"
+ "github.com/matrix-org/dendrite/roomserver/api"
+ "github.com/matrix-org/dendrite/roomserver/storage"
+ "github.com/matrix-org/dendrite/roomserver/types"
+ "github.com/matrix-org/dendrite/setup/config"
+ "github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/fclient"
+ "github.com/matrix-org/gomatrixserverlib/spec"
+ "github.com/matrix-org/util"
+)
+
+const (
+ historyVisibilityShared = "shared"
+)
+
+type Creator struct {
+ DB storage.Database
+ Cfg *config.RoomServer
+ RSAPI api.RoomserverInternalAPI
+}
+
+// PerformCreateRoom handles all the steps necessary to create a new room.
+// nolint: gocyclo
+func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *api.PerformCreateRoomRequest) (string, *util.JSONResponse) {
+ verImpl, err := gomatrixserverlib.GetRoomVersion(createRequest.RoomVersion)
+ if err != nil {
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.BadJSON("unknown room version"),
+ }
+ }
+
+ createContent := map[string]interface{}{}
+ if len(createRequest.CreationContent) > 0 {
+ if err = json.Unmarshal(createRequest.CreationContent, &createContent); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for creation_content failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.BadJSON("invalid create content"),
+ }
+ }
+ }
+ createContent["creator"] = userID.String()
+ createContent["room_version"] = createRequest.RoomVersion
+ powerLevelContent := eventutil.InitialPowerLevelsContent(userID.String())
+ joinRuleContent := gomatrixserverlib.JoinRuleContent{
+ JoinRule: spec.Invite,
+ }
+ historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{
+ HistoryVisibility: historyVisibilityShared,
+ }
+
+ if createRequest.PowerLevelContentOverride != nil {
+ // Merge powerLevelContentOverride fields by unmarshalling it atop the defaults
+ err = json.Unmarshal(createRequest.PowerLevelContentOverride, &powerLevelContent)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for power_level_content_override failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.BadJSON("malformed power_level_content_override"),
+ }
+ }
+ }
+
+ var guestsCanJoin bool
+ switch createRequest.StatePreset {
+ case spec.PresetPrivateChat:
+ joinRuleContent.JoinRule = spec.Invite
+ historyVisibilityContent.HistoryVisibility = historyVisibilityShared
+ guestsCanJoin = true
+ case spec.PresetTrustedPrivateChat:
+ joinRuleContent.JoinRule = spec.Invite
+ historyVisibilityContent.HistoryVisibility = historyVisibilityShared
+ for _, invitee := range createRequest.InvitedUsers {
+ powerLevelContent.Users[invitee] = 100
+ }
+ guestsCanJoin = true
+ case spec.PresetPublicChat:
+ joinRuleContent.JoinRule = spec.Public
+ historyVisibilityContent.HistoryVisibility = historyVisibilityShared
+ }
+
+ createEvent := gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomCreate,
+ Content: createContent,
+ }
+ powerLevelEvent := gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomPowerLevels,
+ Content: powerLevelContent,
+ }
+ joinRuleEvent := gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomJoinRules,
+ Content: joinRuleContent,
+ }
+ historyVisibilityEvent := gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomHistoryVisibility,
+ Content: historyVisibilityContent,
+ }
+ membershipEvent := gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomMember,
+ StateKey: userID.String(),
+ Content: gomatrixserverlib.MemberContent{
+ Membership: spec.Join,
+ DisplayName: createRequest.UserDisplayName,
+ AvatarURL: createRequest.UserAvatarURL,
+ },
+ }
+
+ var nameEvent *gomatrixserverlib.FledglingEvent
+ var topicEvent *gomatrixserverlib.FledglingEvent
+ var guestAccessEvent *gomatrixserverlib.FledglingEvent
+ var aliasEvent *gomatrixserverlib.FledglingEvent
+
+ if createRequest.RoomName != "" {
+ nameEvent = &gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomName,
+ Content: eventutil.NameContent{
+ Name: createRequest.RoomName,
+ },
+ }
+ }
+
+ if createRequest.Topic != "" {
+ topicEvent = &gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomTopic,
+ Content: eventutil.TopicContent{
+ Topic: createRequest.Topic,
+ },
+ }
+ }
+
+ if guestsCanJoin {
+ guestAccessEvent = &gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomGuestAccess,
+ Content: eventutil.GuestAccessContent{
+ GuestAccess: "can_join",
+ },
+ }
+ }
+
+ var roomAlias string
+ if createRequest.RoomAliasName != "" {
+ roomAlias = fmt.Sprintf("#%s:%s", createRequest.RoomAliasName, userID.Domain())
+ // check it's free
+ // TODO: This races but is better than nothing
+ hasAliasReq := api.GetRoomIDForAliasRequest{
+ Alias: roomAlias,
+ IncludeAppservices: false,
+ }
+
+ var aliasResp api.GetRoomIDForAliasResponse
+ err = c.RSAPI.GetRoomIDForAlias(ctx, &hasAliasReq, &aliasResp)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ if aliasResp.RoomID != "" {
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.RoomInUse("Room ID already exists."),
+ }
+ }
+
+ aliasEvent = &gomatrixserverlib.FledglingEvent{
+ Type: spec.MRoomCanonicalAlias,
+ Content: eventutil.CanonicalAlias{
+ Alias: roomAlias,
+ },
+ }
+ }
+
+ var initialStateEvents []gomatrixserverlib.FledglingEvent
+ for i := range createRequest.InitialState {
+ if createRequest.InitialState[i].StateKey != "" {
+ initialStateEvents = append(initialStateEvents, createRequest.InitialState[i])
+ continue
+ }
+
+ switch createRequest.InitialState[i].Type {
+ case spec.MRoomCreate:
+ continue
+
+ case spec.MRoomPowerLevels:
+ powerLevelEvent = createRequest.InitialState[i]
+
+ case spec.MRoomJoinRules:
+ joinRuleEvent = createRequest.InitialState[i]
+
+ case spec.MRoomHistoryVisibility:
+ historyVisibilityEvent = createRequest.InitialState[i]
+
+ case spec.MRoomGuestAccess:
+ guestAccessEvent = &createRequest.InitialState[i]
+
+ case spec.MRoomName:
+ nameEvent = &createRequest.InitialState[i]
+
+ case spec.MRoomTopic:
+ topicEvent = &createRequest.InitialState[i]
+
+ default:
+ initialStateEvents = append(initialStateEvents, createRequest.InitialState[i])
+ }
+ }
+
+ // send events into the room in order of:
+ // 1- m.room.create
+ // 2- room creator join member
+ // 3- m.room.power_levels
+ // 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)
+ // 10- m.room.topic (opt)
+ // 11- invite events (opt) - with is_direct flag if applicable TODO
+ // 12- 3pid invite events (opt) TODO
+ // This differs from Synapse slightly. Synapse would vary the ordering of 3-7
+ // depending on if those events were in "initial_state" or not. This made it
+ // harder to reason about, hence sticking to a strict static ordering.
+ // TODO: Synapse has txn/token ID on each event. Do we need to do this here?
+ eventsToMake := []gomatrixserverlib.FledglingEvent{
+ createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
+ }
+ if guestAccessEvent != nil {
+ eventsToMake = append(eventsToMake, *guestAccessEvent)
+ }
+ eventsToMake = append(eventsToMake, initialStateEvents...)
+ if nameEvent != nil {
+ eventsToMake = append(eventsToMake, *nameEvent)
+ }
+ if topicEvent != nil {
+ eventsToMake = append(eventsToMake, *topicEvent)
+ }
+ if aliasEvent != nil {
+ // 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.
+ eventsToMake = append(eventsToMake, *aliasEvent)
+ }
+
+ // TODO: invite events
+ // TODO: 3pid invite events
+
+ var builtEvents []*types.HeaderedEvent
+ authEvents := gomatrixserverlib.NewAuthEvents(nil)
+ for i, e := range eventsToMake {
+ depth := i + 1 // depth starts at 1
+
+ builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
+ Sender: userID.String(),
+ RoomID: roomID.String(),
+ Type: e.Type,
+ StateKey: &e.StateKey,
+ Depth: int64(depth),
+ })
+ err = builder.SetContent(e.Content)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ if i > 0 {
+ builder.PrevEvents = []string{builtEvents[i-1].EventID()}
+ }
+ var ev gomatrixserverlib.PDU
+ if err = builder.AddAuthEvents(&authEvents); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ ev, err = builder.Build(createRequest.EventTime, userID.Domain(), createRequest.KeyID, createRequest.PrivateKey)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ if err = gomatrixserverlib.Allowed(ev, &authEvents); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ // Add the event to the list of auth events
+ builtEvents = append(builtEvents, &types.HeaderedEvent{PDU: ev})
+ err = authEvents.AddEvent(ev)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("authEvents.AddEvent failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ }
+
+ inputs := make([]api.InputRoomEvent, 0, len(builtEvents))
+ for _, event := range builtEvents {
+ inputs = append(inputs, api.InputRoomEvent{
+ Kind: api.KindNew,
+ Event: event,
+ Origin: userID.Domain(),
+ SendAsServer: api.DoNotSendToOtherServers,
+ })
+ }
+ if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs, false); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ // 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.
+ if roomAlias != "" {
+ aliasReq := api.SetRoomAliasRequest{
+ Alias: roomAlias,
+ RoomID: roomID.String(),
+ UserID: userID.String(),
+ }
+
+ var aliasResp api.SetRoomAliasResponse
+ err = c.RSAPI.SetRoomAlias(ctx, &aliasReq, &aliasResp)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("aliasAPI.SetRoomAlias failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ if aliasResp.AliasExists {
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.RoomInUse("Room alias already exists."),
+ }
+ }
+ }
+
+ // If this is a direct message then we should invite the participants.
+ if len(createRequest.InvitedUsers) > 0 {
+ // Build some stripped state for the invite.
+ var globalStrippedState []fclient.InviteV2StrippedState
+ for _, event := range builtEvents {
+ // Chosen events from the spec:
+ // https://spec.matrix.org/v1.3/client-server-api/#stripped-state
+ switch event.Type() {
+ case spec.MRoomCreate:
+ fallthrough
+ case spec.MRoomName:
+ fallthrough
+ case spec.MRoomAvatar:
+ fallthrough
+ case spec.MRoomTopic:
+ fallthrough
+ case spec.MRoomCanonicalAlias:
+ fallthrough
+ case spec.MRoomEncryption:
+ fallthrough
+ case spec.MRoomMember:
+ fallthrough
+ case spec.MRoomJoinRules:
+ ev := event.PDU
+ globalStrippedState = append(
+ globalStrippedState,
+ fclient.NewInviteV2StrippedState(ev),
+ )
+ }
+ }
+
+ // Process the invites.
+ var inviteEvent *types.HeaderedEvent
+ for _, invitee := range createRequest.InvitedUsers {
+ proto := gomatrixserverlib.ProtoEvent{
+ Sender: userID.String(),
+ RoomID: roomID.String(),
+ Type: "m.room.member",
+ StateKey: &invitee,
+ }
+
+ content := gomatrixserverlib.MemberContent{
+ Membership: spec.Invite,
+ DisplayName: createRequest.UserDisplayName,
+ AvatarURL: createRequest.UserAvatarURL,
+ Reason: "",
+ IsDirect: createRequest.IsDirect,
+ }
+
+ if err = proto.SetContent(content); err != nil {
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ // Build the invite event.
+ identity := &fclient.SigningIdentity{
+ ServerName: userID.Domain(),
+ KeyID: createRequest.KeyID,
+ PrivateKey: createRequest.PrivateKey,
+ }
+ inviteEvent, err = eventutil.QueryAndBuildEvent(ctx, &proto, identity, createRequest.EventTime, c.RSAPI, nil)
+
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
+ continue
+ }
+ inviteStrippedState := append(
+ globalStrippedState,
+ fclient.NewInviteV2StrippedState(inviteEvent.PDU),
+ )
+ // Send the invite event to the roomserver.
+ event := inviteEvent
+ err = c.RSAPI.PerformInvite(ctx, &api.PerformInviteRequest{
+ Event: event,
+ InviteRoomState: inviteStrippedState,
+ RoomVersion: event.Version(),
+ SendAsServer: string(userID.Domain()),
+ })
+ switch e := err.(type) {
+ case api.ErrInvalidID:
+ return "", &util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: spec.Unknown(e.Error()),
+ }
+ case api.ErrNotAllowed:
+ return "", &util.JSONResponse{
+ Code: http.StatusForbidden,
+ JSON: spec.Forbidden(e.Error()),
+ }
+ case nil:
+ default:
+ util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
+ sentry.CaptureException(err)
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ }
+ }
+
+ if createRequest.Visibility == spec.Public {
+ // expose this room in the published room list
+ if err = c.RSAPI.PerformPublish(ctx, &api.PerformPublishRequest{
+ RoomID: roomID.String(),
+ Visibility: spec.Public,
+ }); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("failed to publish room")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ }
+
+ // TODO: visibility/presets/raw initial state
+ // TODO: Create room alias association
+ // Make sure this doesn't fall into an application service's namespace though!
+
+ return roomAlias, nil
+}
diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go
index 5f4ad186..34bea5b6 100644
--- a/roomserver/internal/perform/perform_join.go
+++ b/roomserver/internal/perform/perform_join.go
@@ -284,7 +284,7 @@ func (r *Joiner) performJoinRoomByID(
if err != nil {
return "", "", fmt.Errorf("error joining local room: %q", err)
}
- event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes)
+ event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes)
switch err.(type) {
case nil:
diff --git a/roomserver/internal/perform/perform_leave.go b/roomserver/internal/perform/perform_leave.go
index e71b3e90..90102aee 100644
--- a/roomserver/internal/perform/perform_leave.go
+++ b/roomserver/internal/perform/perform_leave.go
@@ -183,7 +183,7 @@ func (r *Leaver) performLeaveRoomByID(
if err != nil {
return nil, fmt.Errorf("SigningIdentityFor: %w", err)
}
- event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes)
+ event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes)
if err != nil {
return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err)
}
diff --git a/roomserver/internal/perform/perform_upgrade.go b/roomserver/internal/perform/perform_upgrade.go
index 60085cb6..ff4a6a1d 100644
--- a/roomserver/internal/perform/perform_upgrade.go
+++ b/roomserver/internal/perform/perform_upgrade.go
@@ -35,13 +35,6 @@ type Upgrader struct {
URSAPI api.RoomserverInternalAPI
}
-// fledglingEvent is a helper representation of an event used when creating many events in succession.
-type fledglingEvent struct {
- Type string `json:"type"`
- StateKey string `json:"state_key"`
- Content interface{} `json:"content"`
-}
-
// PerformRoomUpgrade upgrades a room from one version to another
func (r *Upgrader) PerformRoomUpgrade(
ctx context.Context,
@@ -154,7 +147,7 @@ func (r *Upgrader) restrictOldRoomPowerLevels(ctx context.Context, evTime time.T
restrictedPowerLevelContent.EventsDefault = restrictedDefaultPowerLevel
restrictedPowerLevelContent.Invite = restrictedDefaultPowerLevel
- restrictedPowerLevelsHeadered, resErr := r.makeHeaderedEvent(ctx, evTime, userID, roomID, fledglingEvent{
+ restrictedPowerLevelsHeadered, resErr := r.makeHeaderedEvent(ctx, evTime, userID, roomID, gomatrixserverlib.FledglingEvent{
Type: spec.MRoomPowerLevels,
StateKey: "",
Content: restrictedPowerLevelContent,
@@ -216,7 +209,7 @@ func (r *Upgrader) clearOldCanonicalAliasEvent(ctx context.Context, oldRoom *api
}
}
- emptyCanonicalAliasEvent, resErr := r.makeHeaderedEvent(ctx, evTime, userID, roomID, fledglingEvent{
+ emptyCanonicalAliasEvent, resErr := r.makeHeaderedEvent(ctx, evTime, userID, roomID, gomatrixserverlib.FledglingEvent{
Type: spec.MRoomCanonicalAlias,
Content: map[string]interface{}{},
})
@@ -298,7 +291,7 @@ func (r *Upgrader) userIsAuthorized(ctx context.Context, userID, roomID string,
}
// nolint:gocyclo
-func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, userID, roomID string, newVersion gomatrixserverlib.RoomVersion, tombstoneEvent *types.HeaderedEvent) ([]fledglingEvent, error) {
+func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.QueryLatestEventsAndStateResponse, userID, roomID string, newVersion gomatrixserverlib.RoomVersion, tombstoneEvent *types.HeaderedEvent) ([]gomatrixserverlib.FledglingEvent, error) {
state := make(map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent, len(oldRoom.StateEvents))
for _, event := range oldRoom.StateEvents {
if event.StateKey() == nil {
@@ -361,7 +354,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
EventID: tombstoneEvent.EventID(),
RoomID: roomID,
}
- newCreateEvent := fledglingEvent{
+ newCreateEvent := gomatrixserverlib.FledglingEvent{
Type: spec.MRoomCreate,
StateKey: "",
Content: newCreateContent,
@@ -374,7 +367,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
newMembershipContent := map[string]interface{}{}
_ = json.Unmarshal(oldMembershipEvent.Content(), &newMembershipContent)
newMembershipContent["membership"] = spec.Join
- newMembershipEvent := fledglingEvent{
+ newMembershipEvent := gomatrixserverlib.FledglingEvent{
Type: spec.MRoomMember,
StateKey: userID,
Content: newMembershipContent,
@@ -400,13 +393,13 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
"join_rule": spec.Invite, // sane default
}
_ = json.Unmarshal(oldJoinRulesEvent.Content(), &newJoinRulesContent)
- newJoinRulesEvent := fledglingEvent{
+ newJoinRulesEvent := gomatrixserverlib.FledglingEvent{
Type: spec.MRoomJoinRules,
StateKey: "",
Content: newJoinRulesContent,
}
- eventsToMake := make([]fledglingEvent, 0, len(state))
+ eventsToMake := make([]gomatrixserverlib.FledglingEvent, 0, len(state))
eventsToMake = append(
eventsToMake, newCreateEvent, newMembershipEvent,
tempPowerLevelsEvent, newJoinRulesEvent,
@@ -415,7 +408,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
// For some reason Sytest expects there to be a guest access event.
// Create one if it doesn't exist.
if _, ok := state[gomatrixserverlib.StateKeyTuple{EventType: spec.MRoomGuestAccess, StateKey: ""}]; !ok {
- eventsToMake = append(eventsToMake, fledglingEvent{
+ eventsToMake = append(eventsToMake, gomatrixserverlib.FledglingEvent{
Type: spec.MRoomGuestAccess,
Content: map[string]string{
"guest_access": "forbidden",
@@ -430,7 +423,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
// are already in `eventsToMake`.
continue
}
- newEvent := fledglingEvent{
+ newEvent := gomatrixserverlib.FledglingEvent{
Type: tuple.EventType,
StateKey: tuple.StateKey,
}
@@ -444,7 +437,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
// 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{
+ eventsToMake = append(eventsToMake, gomatrixserverlib.FledglingEvent{
Type: spec.MRoomPowerLevels,
Content: powerLevelContent,
})
@@ -452,7 +445,7 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query
return eventsToMake, nil
}
-func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, userID string, userDomain spec.ServerName, newRoomID string, newVersion gomatrixserverlib.RoomVersion, eventsToMake []fledglingEvent) error {
+func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, userID string, userDomain spec.ServerName, newRoomID string, newVersion gomatrixserverlib.RoomVersion, eventsToMake []gomatrixserverlib.FledglingEvent) error {
var err error
var builtEvents []*types.HeaderedEvent
authEvents := gomatrixserverlib.NewAuthEvents(nil)
@@ -527,14 +520,14 @@ func (r *Upgrader) makeTombstoneEvent(
"body": "This room has been replaced",
"replacement_room": newRoomID,
}
- event := fledglingEvent{
+ event := gomatrixserverlib.FledglingEvent{
Type: "m.room.tombstone",
Content: content,
}
return r.makeHeaderedEvent(ctx, evTime, userID, roomID, event)
}
-func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, userID, roomID string, event fledglingEvent) (*types.HeaderedEvent, error) {
+func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, userID, roomID string, event gomatrixserverlib.FledglingEvent) (*types.HeaderedEvent, error) {
proto := gomatrixserverlib.ProtoEvent{
Sender: userID,
RoomID: roomID,
@@ -555,7 +548,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user
return nil, fmt.Errorf("failed to get signing identity for %q: %w", senderDomain, err)
}
var queryRes api.QueryLatestEventsAndStateResponse
- headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, evTime, r.URSAPI, &queryRes)
+ headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, r.URSAPI, &queryRes)
switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
@@ -581,7 +574,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user
return headeredEvent, nil
}
-func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, userID string) (fledglingEvent, bool) {
+func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, userID string) (gomatrixserverlib.FledglingEvent, bool) {
// Work out what power level we need in order to be able to send events
// of all types into the room.
neededPowerLevel := powerLevelContent.StateDefault
@@ -612,7 +605,7 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC
}
// Then return the temporary power levels event.
- return fledglingEvent{
+ return gomatrixserverlib.FledglingEvent{
Type: spec.MRoomPowerLevels,
Content: tempPowerLevelContent,
}, powerLevelsOverridden