Initial room creation refactor

This commit is contained in:
Devon Hudson 2023-05-25 18:06:40 -06:00
parent 11b557097c
commit 1c36c6a8d4
No known key found for this signature in database
GPG key ID: CD06B18E77F6A628
15 changed files with 75 additions and 51 deletions

View file

@ -165,6 +165,7 @@ func CreateRoom(
// nolint: gocyclo // nolint: gocyclo
func createRoom( func createRoom(
ctx context.Context, ctx context.Context,
// TODO: remove dependency on createRoomRequest
r createRoomRequest, device *api.Device, r createRoomRequest, device *api.Device,
cfg *config.ClientAPI, cfg *config.ClientAPI,
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI, profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
@ -186,13 +187,13 @@ func createRoom(
} }
} }
logger := util.GetLogger(ctx)
userID := device.UserID
// TODO (#267): Check room ID doesn't clash with an existing one, and we // TODO (#267): Check room ID doesn't clash with an existing one, and we
// probably shouldn't be using pseudo-random strings, maybe GUIDs? // probably shouldn't be using pseudo-random strings, maybe GUIDs?
roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), userDomain) roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), userDomain)
logger := util.GetLogger(ctx)
userID := device.UserID
// Clobber keys: creator, room_version // Clobber keys: creator, room_version
roomVersion := roomserverVersion.DefaultRoomVersion() roomVersion := roomserverVersion.DefaultRoomVersion()
@ -208,10 +209,6 @@ func createRoom(
roomVersion = candidateVersion 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{ logger.WithFields(log.Fields{
"userID": userID, "userID": userID,
"roomID": roomID, "roomID": roomID,
@ -227,6 +224,19 @@ func createRoom(
} }
} }
userDisplayName := profile.DisplayName
userAvatarURL := profile.AvatarURL
keyID := cfg.Matrix.KeyID
privateKey := cfg.Matrix.PrivateKey
// TODO: Move this whole function to roomserver to start
// HACK: asdklfjsdklfj
// TODO: visibility/presets/raw initial state
// TODO: Create room alias association
// Make sure this doesn't fall into an application service's namespace though!
createContent := map[string]interface{}{} createContent := map[string]interface{}{}
if len(r.CreationContent) > 0 { if len(r.CreationContent) > 0 {
if err = json.Unmarshal(r.CreationContent, &createContent); err != nil { if err = json.Unmarshal(r.CreationContent, &createContent); err != nil {
@ -298,8 +308,8 @@ func createRoom(
StateKey: userID, StateKey: userID,
Content: gomatrixserverlib.MemberContent{ Content: gomatrixserverlib.MemberContent{
Membership: spec.Join, Membership: spec.Join,
DisplayName: profile.DisplayName, DisplayName: userDisplayName,
AvatarURL: profile.AvatarURL, AvatarURL: userAvatarURL,
}, },
} }
@ -480,7 +490,7 @@ func createRoom(
JSON: spec.InternalServerError{}, JSON: spec.InternalServerError{},
} }
} }
ev, err = builder.Build(evTime, userDomain, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) ev, err = builder.Build(evTime, userDomain, keyID, privateKey)
if err != nil { if err != nil {
util.GetLogger(ctx).WithError(err).Error("buildEvent failed") util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
return util.JSONResponse{ return util.JSONResponse{
@ -518,7 +528,7 @@ func createRoom(
SendAsServer: roomserverAPI.DoNotSendToOtherServers, SendAsServer: roomserverAPI.DoNotSendToOtherServers,
}) })
} }
if err = roomserverAPI.SendInputRoomEvents(ctx, rsAPI, device.UserDomain(), inputs, false); err != nil { if err = roomserverAPI.SendInputRoomEvents(ctx, rsAPI, userDomain, inputs, false); err != nil {
util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed") util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
@ -589,9 +599,9 @@ func createRoom(
var inviteEvent *types.HeaderedEvent var inviteEvent *types.HeaderedEvent
for _, invitee := range r.Invite { for _, invitee := range r.Invite {
// Build the invite event. // Build the invite event.
inviteEvent, err = buildMembershipEvent( inviteEvent, err = buildMembershipEventDirect(
ctx, invitee, "", profileAPI, device, spec.Invite, ctx, invitee, "", userDisplayName, userAvatarURL, userID, userDomain, spec.Invite,
roomID, r.IsDirect, cfg, evTime, rsAPI, asAPI, roomID, r.IsDirect, keyID, privateKey, evTime, rsAPI,
) )
if err != nil { if err != nil {
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed") util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")

View file

@ -16,12 +16,14 @@ package routing
import ( import (
"context" "context"
"crypto/ed25519"
"fmt" "fmt"
"net/http" "net/http"
"time" "time"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib/spec"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api" appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
@ -308,6 +310,37 @@ func sendInvite(
}, nil }, nil
} }
func buildMembershipEventDirect(
ctx context.Context,
targetUserID, reason string, userDisplayName, userAvatarURL string,
sender string, senderDomain spec.ServerName,
membership, roomID string, isDirect bool,
keyID gomatrixserverlib.KeyID, privateKey ed25519.PrivateKey, evTime time.Time,
rsAPI roomserverAPI.ClientRoomserverAPI,
) (*types.HeaderedEvent, error) {
proto := gomatrixserverlib.ProtoEvent{
Sender: sender,
RoomID: roomID,
Type: "m.room.member",
StateKey: &targetUserID,
}
content := gomatrixserverlib.MemberContent{
Membership: membership,
DisplayName: userDisplayName,
AvatarURL: userAvatarURL,
Reason: reason,
IsDirect: isDirect,
}
if err := proto.SetContent(content); err != nil {
return nil, err
}
identity := &fclient.SigningIdentity{senderDomain, keyID, privateKey}
return eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil)
}
func buildMembershipEvent( func buildMembershipEvent(
ctx context.Context, ctx context.Context,
targetUserID, reason string, profileAPI userapi.ClientUserAPI, targetUserID, reason string, profileAPI userapi.ClientUserAPI,
@ -321,31 +354,13 @@ func buildMembershipEvent(
return nil, err return nil, err
} }
proto := gomatrixserverlib.ProtoEvent{
Sender: device.UserID,
RoomID: roomID,
Type: "m.room.member",
StateKey: &targetUserID,
}
content := gomatrixserverlib.MemberContent{
Membership: membership,
DisplayName: profile.DisplayName,
AvatarURL: profile.AvatarURL,
Reason: reason,
IsDirect: isDirect,
}
if err = proto.SetContent(content); err != nil {
return nil, err
}
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain()) identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
if err != nil { if err != nil {
return nil, err 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 // loadProfile lookups the profile of a given user from the database and returns

View file

@ -387,7 +387,7 @@ func buildMembershipEvents(
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }

View file

@ -137,7 +137,7 @@ func SendRedaction(
} }
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse 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{}) { if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View file

@ -293,7 +293,7 @@ func generateSendEvent(
} }
var queryRes api.QueryLatestEventsAndStateResponse 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) { switch specificErr := err.(type) {
case nil: case nil:
case eventutil.ErrRoomNoExists: case eventutil.ErrRoomNoExists:

View file

@ -380,7 +380,7 @@ func emit3PIDInviteEvent(
} }
queryRes := api.QueryLatestEventsAndStateResponse{} 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 { if err != nil {
return err return err
} }

View file

@ -121,7 +121,7 @@ func MakeJoin(
queryRes := api.QueryLatestEventsAndStateResponse{ queryRes := api.QueryLatestEventsAndStateResponse{
RoomVersion: roomVersion, 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) { switch e := err.(type) {
case nil: case nil:
case eventutil.ErrRoomNoExists: case eventutil.ErrRoomNoExists:

View file

@ -66,7 +66,7 @@ func MakeLeave(
} }
queryRes := api.QueryLatestEventsAndStateResponse{} 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) { switch e := err.(type) {
case nil: case nil:
case eventutil.ErrRoomNoExists: case eventutil.ErrRoomNoExists:

View file

@ -22,7 +22,6 @@ import (
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types" "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/fclient"
"github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib/spec"
@ -51,7 +50,7 @@ func (e ErrRoomNoExists) Unwrap() error {
// Returns an error if something else went wrong // Returns an error if something else went wrong
func QueryAndBuildEvent( func QueryAndBuildEvent(
ctx context.Context, ctx context.Context,
proto *gomatrixserverlib.ProtoEvent, cfg *config.Global, proto *gomatrixserverlib.ProtoEvent,
identity *fclient.SigningIdentity, evTime time.Time, identity *fclient.SigningIdentity, evTime time.Time,
rsAPI api.QueryLatestEventsAndStateAPI, queryRes *api.QueryLatestEventsAndStateResponse, rsAPI api.QueryLatestEventsAndStateAPI, queryRes *api.QueryLatestEventsAndStateResponse,
) (*types.HeaderedEvent, error) { ) (*types.HeaderedEvent, error) {
@ -64,14 +63,14 @@ func QueryAndBuildEvent(
// This can pass through a ErrRoomNoExists to the caller // This can pass through a ErrRoomNoExists to the caller
return nil, err 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 // BuildEvent builds a Matrix event from the builder and QueryLatestEventsAndStateResponse
// provided. // provided.
func BuildEvent( func BuildEvent(
ctx context.Context, ctx context.Context,
proto *gomatrixserverlib.ProtoEvent, cfg *config.Global, proto *gomatrixserverlib.ProtoEvent,
identity *fclient.SigningIdentity, evTime time.Time, identity *fclient.SigningIdentity, evTime time.Time,
eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse, eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse,
) (*types.HeaderedEvent, error) { ) (*types.HeaderedEvent, error) {

View file

@ -208,7 +208,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err 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 { if err != nil {
return err return err
} }

View file

@ -872,7 +872,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
return err 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 { if err != nil {
return err return err
} }

View file

@ -119,7 +119,7 @@ func (r *Admin) PerformAdminEvacuateRoom(
continue 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 { if err != nil {
return nil, err return nil, err
} }
@ -306,7 +306,7 @@ func (r *Admin) PerformAdminDownloadState(
return err 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 { if err != nil {
return fmt.Errorf("eventutil.BuildEvent: %w", err) return fmt.Errorf("eventutil.BuildEvent: %w", err)
} }

View file

@ -284,7 +284,7 @@ func (r *Joiner) performJoinRoomByID(
if err != nil { if err != nil {
return "", "", fmt.Errorf("error joining local room: %q", err) 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) { switch err.(type) {
case nil: case nil:

View file

@ -183,7 +183,7 @@ func (r *Leaver) performLeaveRoomByID(
if err != nil { if err != nil {
return nil, fmt.Errorf("SigningIdentityFor: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err) return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err)
} }

View file

@ -555,7 +555,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) return nil, fmt.Errorf("failed to get signing identity for %q: %w", senderDomain, err)
} }
var queryRes api.QueryLatestEventsAndStateResponse 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) { switch e := err.(type) {
case nil: case nil:
case eventutil.ErrRoomNoExists: case eventutil.ErrRoomNoExists: