aboutsummaryrefslogtreecommitdiff
path: root/roomserver
diff options
context:
space:
mode:
authorTill <2353100+S7evinK@users.noreply.github.com>2023-06-28 20:29:49 +0200
committerGitHub <noreply@github.com>2023-06-28 20:29:49 +0200
commit23cd7877a14bca5315467591cd47a7d51aec22ce (patch)
tree8176360a4366e7b4670839b6581b7ff728599a02 /roomserver
parent4722f12fab65f3247cd253825d86206bfbfc6f95 (diff)
Add `MXIDMapping` for pseudoID rooms (#3112)
Add `MXIDMapping` on membership events when creating/joining rooms.
Diffstat (limited to 'roomserver')
-rw-r--r--roomserver/api/api.go7
-rw-r--r--roomserver/api/query.go2
-rw-r--r--roomserver/internal/alias.go11
-rw-r--r--roomserver/internal/api.go50
-rw-r--r--roomserver/internal/input/input.go2
-rw-r--r--roomserver/internal/input/input_events.go19
-rw-r--r--roomserver/internal/perform/perform_backfill.go2
-rw-r--r--roomserver/internal/perform/perform_create_room.go89
-rw-r--r--roomserver/internal/perform/perform_invite.go17
-rw-r--r--roomserver/internal/perform/perform_join.go39
-rw-r--r--roomserver/internal/perform/perform_leave.go9
-rw-r--r--roomserver/internal/query/query.go3
-rw-r--r--roomserver/roomserver_test.go10
-rw-r--r--roomserver/storage/interface.go5
-rw-r--r--roomserver/storage/shared/storage.go102
-rw-r--r--roomserver/storage/sqlite3/user_room_keys_table.go5
-rw-r--r--roomserver/types/headered_event.go5
17 files changed, 278 insertions, 99 deletions
diff --git a/roomserver/api/api.go b/roomserver/api/api.go
index e2dd5dd7..ab56529c 100644
--- a/roomserver/api/api.go
+++ b/roomserver/api/api.go
@@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
@@ -73,6 +74,7 @@ type RoomserverInternalAPI interface {
type UserRoomPrivateKeyCreator interface {
// GetOrCreateUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created.
GetOrCreateUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error)
+ StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error
}
type InputRoomEventsAPI interface {
@@ -184,6 +186,7 @@ type ClientRoomserverAPI interface {
QueryBulkStateContentAPI
QueryEventsAPI
QuerySenderIDAPI
+ UserRoomPrivateKeyCreator
QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error
QueryMembershipsForRoom(ctx context.Context, req *QueryMembershipsForRoomRequest, res *QueryMembershipsForRoomResponse) error
QueryRoomsForUser(ctx context.Context, req *QueryRoomsForUserRequest, res *QueryRoomsForUserResponse) error
@@ -213,6 +216,7 @@ type ClientRoomserverAPI interface {
PerformForget(ctx context.Context, req *PerformForgetRequest, resp *PerformForgetResponse) error
SetRoomAlias(ctx context.Context, req *SetRoomAliasRequest, res *SetRoomAliasResponse) error
RemoveRoomAlias(ctx context.Context, req *RemoveRoomAliasRequest, res *RemoveRoomAliasResponse) error
+ SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
}
type UserRoomserverAPI interface {
@@ -232,7 +236,8 @@ type FederationRoomserverAPI interface {
QueryBulkStateContentAPI
QuerySenderIDAPI
UserRoomPrivateKeyCreator
-
+ AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error)
+ SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
// QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs.
QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error
QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error
diff --git a/roomserver/api/query.go b/roomserver/api/query.go
index 684a5b0e..b6140afd 100644
--- a/roomserver/api/query.go
+++ b/roomserver/api/query.go
@@ -174,6 +174,8 @@ type QueryServerJoinedToRoomResponse struct {
RoomExists bool `json:"room_exists"`
// True if we still believe that the server is participating in the room
IsInRoom bool `json:"is_in_room"`
+ // The roomversion if joined to room
+ RoomVersion gomatrixserverlib.RoomVersion
}
// QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent
diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go
index e6fb7338..b04a56fe 100644
--- a/roomserver/internal/alias.go
+++ b/roomserver/internal/alias.go
@@ -115,6 +115,7 @@ func (r *RoomserverInternalAPI) GetAliasesForRoomID(
// nolint:gocyclo
// RemoveRoomAlias implements alias.RoomserverInternalAPI
+// nolint: gocyclo
func (r *RoomserverInternalAPI) RemoveRoomAlias(
ctx context.Context,
request *api.RemoveRoomAliasRequest,
@@ -188,9 +189,11 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err
}
- senderDomain := sender.Domain()
-
- identity, err := r.Cfg.Global.SigningIdentityFor(senderDomain)
+ validRoomID, err := spec.NewRoomID(roomID)
+ if err != nil {
+ return err
+ }
+ identity, err := r.SigningIdentityFor(ctx, *validRoomID, *sender)
if err != nil {
return err
}
@@ -216,7 +219,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err
}
- newEvent, err := eventutil.BuildEvent(ctx, proto, 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 7943ae5c..2e12671f 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/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"github.com/nats-io/nats.go"
@@ -110,11 +111,6 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio
r.fsAPI = fsAPI
r.KeyRing = keyRing
- identity, err := r.Cfg.Global.SigningIdentityFor(r.ServerName)
- if err != nil {
- logrus.Panic(err)
- }
-
r.Inputer = &input.Inputer{
Cfg: &r.Cfg.RoomServer,
ProcessContext: r.ProcessContext,
@@ -125,7 +121,7 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio
NATSClient: r.NATSClient,
Durable: nats.Durable(r.Durable),
ServerName: r.ServerName,
- SigningIdentity: identity,
+ SigningIdentity: r.SigningIdentityFor,
FSAPI: fsAPI,
KeyRing: keyRing,
ACLs: r.ServerACLs,
@@ -292,3 +288,45 @@ func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Contex
}
return key, nil
}
+
+func (r *RoomserverInternalAPI) StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error {
+ pubKeyBytes, err := senderID.RawBytes()
+ if err != nil {
+ return err
+ }
+ _, err = r.DB.InsertUserRoomPublicKey(ctx, userID, roomID, ed25519.PublicKey(pubKeyBytes))
+ return err
+}
+
+func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) {
+ roomVersion, ok := r.Cache.GetRoomVersion(roomID.String())
+ if !ok {
+ roomInfo, err := r.DB.RoomInfo(ctx, roomID.String())
+ if err != nil {
+ return fclient.SigningIdentity{}, err
+ }
+ if roomInfo != nil {
+ roomVersion = roomInfo.RoomVersion
+ }
+ }
+ if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
+ privKey, err := r.GetOrCreateUserRoomPrivateKey(ctx, senderID, roomID)
+ if err != nil {
+ return fclient.SigningIdentity{}, err
+ }
+ return fclient.SigningIdentity{
+ PrivateKey: privKey,
+ KeyID: "ed25519:1",
+ ServerName: "self",
+ }, nil
+ }
+ identity, err := r.Cfg.Global.SigningIdentityFor(senderID.Domain())
+ if err != nil {
+ return fclient.SigningIdentity{}, err
+ }
+ return *identity, err
+}
+
+func (r *RoomserverInternalAPI) AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) {
+ return r.DB.AssignRoomNID(ctx, roomID, roomVersion)
+}
diff --git a/roomserver/internal/input/input.go b/roomserver/internal/input/input.go
index 3db2d0a6..dea8f8c8 100644
--- a/roomserver/internal/input/input.go
+++ b/roomserver/internal/input/input.go
@@ -81,7 +81,7 @@ type Inputer struct {
JetStream nats.JetStreamContext
Durable nats.SubOpt
ServerName spec.ServerName
- SigningIdentity *fclient.SigningIdentity
+ SigningIdentity func(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
FSAPI fedapi.RoomserverFederationAPI
KeyRing gomatrixserverlib.JSONVerifier
ACLs *acls.ServerACLs
diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go
index aa05d959..db3c9550 100644
--- a/roomserver/internal/input/input_events.go
+++ b/roomserver/internal/input/input_events.go
@@ -406,7 +406,7 @@ func (r *Inputer) processRoomEvent(
)
if !isRejected && !isCreateEvent {
resolver := state.NewStateResolution(r.DB, roomInfo, r.Queryer)
- redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, &resolver)
+ redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, &resolver, r.Queryer)
if err != nil {
return err
}
@@ -895,7 +895,22 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
return err
}
- event, err := eventutil.BuildEvent(ctx, fledglingEvent, r.SigningIdentity, time.Now(), &eventsNeeded, latestRes)
+ validRoomID, err := spec.NewRoomID(event.RoomID())
+ if err != nil {
+ return err
+ }
+
+ userID, err := spec.NewUserID(stateKey, true)
+ if err != nil {
+ return err
+ }
+
+ signingIdentity, err := r.SigningIdentity(ctx, *validRoomID, *userID)
+ if err != nil {
+ return err
+ }
+
+ event, err := eventutil.BuildEvent(ctx, fledglingEvent, &signingIdentity, time.Now(), &eventsNeeded, latestRes)
if err != nil {
return err
}
diff --git a/roomserver/internal/perform/perform_backfill.go b/roomserver/internal/perform/perform_backfill.go
index 3fdc8e4d..33200e81 100644
--- a/roomserver/internal/perform/perform_backfill.go
+++ b/roomserver/internal/perform/perform_backfill.go
@@ -647,7 +647,7 @@ func persistEvents(ctx context.Context, db storage.Database, querier api.QuerySe
resolver := state.NewStateResolution(db, roomInfo, querier)
- _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev, &resolver)
+ _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev, &resolver, querier)
if err != nil {
logrus.WithError(err).WithField("event_id", ev.EventID()).Error("Failed to redact event")
continue
diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go
index dcaf8dca..8c965645 100644
--- a/roomserver/internal/perform/perform_create_room.go
+++ b/roomserver/internal/perform/perform_create_room.go
@@ -31,6 +31,7 @@ import (
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
+ "github.com/sirupsen/logrus"
)
const (
@@ -64,6 +65,16 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
}
}
}
+
+ _, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
var senderID spec.SenderID
if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
// create user room key if needed
@@ -75,7 +86,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
JSON: spec.InternalServerError{},
}
}
- senderID = spec.SenderID(spec.Base64Bytes(key.Public().(ed25519.PublicKey)).Encode())
+ senderID = spec.SenderIDFromPseudoIDKey(key)
} else {
senderID = spec.SenderID(userID.String())
}
@@ -138,13 +149,59 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
membershipEvent := gomatrixserverlib.FledglingEvent{
Type: spec.MRoomMember,
StateKey: string(senderID),
- Content: gomatrixserverlib.MemberContent{
- Membership: spec.Join,
- DisplayName: createRequest.UserDisplayName,
- AvatarURL: createRequest.UserAvatarURL,
- },
}
+ memberContent := gomatrixserverlib.MemberContent{
+ Membership: spec.Join,
+ DisplayName: createRequest.UserDisplayName,
+ AvatarURL: createRequest.UserAvatarURL,
+ }
+
+ // get the signing identity
+ identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping
+ if err != nil {
+ logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ // If we are creating a room with pseudo IDs, create and sign the MXIDMapping
+ if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
+ var pseudoIDKey ed25519.PrivateKey
+ pseudoIDKey, err = c.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed")
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+
+ mapping := &gomatrixserverlib.MXIDMapping{
+ UserRoomKey: spec.SenderIDFromPseudoIDKey(pseudoIDKey),
+ UserID: userID.String(),
+ }
+
+ // Sign the mapping with the server identity
+ if err = mapping.Sign(identity.ServerName, identity.KeyID, identity.PrivateKey); err != nil {
+ return "", &util.JSONResponse{
+ Code: http.StatusInternalServerError,
+ JSON: spec.InternalServerError{},
+ }
+ }
+ memberContent.MXIDMapping = mapping
+
+ // sign all events with the pseudo ID key
+ identity = &fclient.SigningIdentity{
+ ServerName: "self",
+ KeyID: "ed25519:1",
+ PrivateKey: pseudoIDKey,
+ }
+ }
+ membershipEvent.Content = memberContent
+
var nameEvent *gomatrixserverlib.FledglingEvent
var topicEvent *gomatrixserverlib.FledglingEvent
var guestAccessEvent *gomatrixserverlib.FledglingEvent
@@ -322,7 +379,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
JSON: spec.InternalServerError{},
}
}
- ev, err = builder.Build(createRequest.EventTime, userID.Domain(), createRequest.KeyID, createRequest.PrivateKey)
+ ev, err = builder.Build(createRequest.EventTime, identity.ServerName, identity.KeyID, identity.PrivateKey)
if err != nil {
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
return "", &util.JSONResponse{
@@ -363,17 +420,8 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
})
}
- // first send the `m.room.create` event, so we have a roomNID
- if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[:1], false); err != nil {
- util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
- return "", &util.JSONResponse{
- Code: http.StatusInternalServerError,
- JSON: spec.InternalServerError{},
- }
- }
-
- // send the remaining events
- if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[1:], false); err != nil {
+ // send the events to the roomserver
+ 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,
@@ -483,11 +531,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
}
// 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 {
diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go
index babd5f81..f19a508a 100644
--- a/roomserver/internal/perform/perform_invite.go
+++ b/roomserver/internal/perform/perform_invite.go
@@ -153,6 +153,23 @@ func (r *Inviter) PerformInvite(
}
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(invitedUser.Domain())
+ // If we're inviting a local user, we can generate the needed pseudoID key here. (if needed)
+ if isTargetLocal {
+ var roomVersion gomatrixserverlib.RoomVersion
+ roomVersion, err = r.DB.GetRoomVersion(ctx, event.RoomID())
+ if err != nil {
+ return err
+ }
+
+ switch roomVersion {
+ case gomatrixserverlib.RoomVersionPseudoIDs:
+ _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *invitedUser, *validRoomID)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
invitedSenderID, err := r.RSAPI.QuerySenderIDForUser(ctx, *validRoomID, *invitedUser)
if err != nil {
return fmt.Errorf("failed looking up senderID for invited user")
diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go
index 5867ee6e..c1455464 100644
--- a/roomserver/internal/perform/perform_join.go
+++ b/roomserver/internal/perform/perform_join.go
@@ -16,6 +16,7 @@ package perform
import (
"context"
+ "crypto/ed25519"
"database/sql"
"errors"
"fmt"
@@ -24,6 +25,7 @@ import (
"github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"github.com/sirupsen/logrus"
@@ -202,14 +204,15 @@ func (r *Joiner) performJoinRoomByID(
senderID, err = r.Queryer.QuerySenderIDForUser(ctx, *roomID, *userID)
if err == nil {
checkInvitePending = true
- } else {
+ }
+ if senderID == "" {
// create user room key if needed
key, keyErr := r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID)
if keyErr != nil {
util.GetLogger(ctx).WithError(keyErr).Error("GetOrCreateUserRoomPrivateKey failed")
return "", "", fmt.Errorf("GetOrCreateUserRoomPrivateKey failed: %w", keyErr)
}
- senderID = spec.SenderID(spec.Base64Bytes(key).Encode())
+ senderID = spec.SenderIDFromPseudoIDKey(key)
}
default:
checkInvitePending = true
@@ -283,11 +286,39 @@ func (r *Joiner) performJoinRoomByID(
// but everyone has since left. I suspect it does the wrong thing.
var buildRes rsAPI.QueryLatestEventsAndStateResponse
- identity, err := r.Cfg.Matrix.SigningIdentityFor(userDomain)
+ identity, err := r.RSAPI.SigningIdentityFor(ctx, *roomID, *userID)
if err != nil {
return "", "", fmt.Errorf("error joining local room: %q", err)
}
+ // at this point we know we have an existing room
+ if inRoomRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
+ var pseudoIDKey ed25519.PrivateKey
+ pseudoIDKey, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed")
+ return "", "", err
+ }
+
+ mapping := &gomatrixserverlib.MXIDMapping{
+ UserRoomKey: spec.SenderIDFromPseudoIDKey(pseudoIDKey),
+ UserID: userID.String(),
+ }
+
+ // Sign the mapping with the server identity
+ if err = mapping.Sign(identity.ServerName, identity.KeyID, identity.PrivateKey); err != nil {
+ return "", "", err
+ }
+ req.Content["mxid_mapping"] = mapping
+
+ // sign the event with the pseudo ID key
+ identity = fclient.SigningIdentity{
+ ServerName: "self",
+ KeyID: "ed25519:1",
+ PrivateKey: pseudoIDKey,
+ }
+ }
+
senderIDString := string(senderID)
// Prepare the template for the join event.
@@ -317,7 +348,7 @@ func (r *Joiner) performJoinRoomByID(
if err = proto.SetContent(req.Content); err != nil {
return "", "", fmt.Errorf("eb.SetContent: %w", err)
}
- event, err := eventutil.QueryAndBuildEvent(ctx, &proto, 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 e1ddb9b5..a20896cf 100644
--- a/roomserver/internal/perform/perform_leave.go
+++ b/roomserver/internal/perform/perform_leave.go
@@ -177,12 +177,17 @@ func (r *Leaver) performLeaveRoomByID(
// TODO: Check what happens if the room exists on the server
// but everyone has since left. I suspect it does the wrong thing.
+ validRoomID, err := spec.NewRoomID(req.RoomID)
+ if err != nil {
+ return nil, err
+ }
+
var buildRes rsAPI.QueryLatestEventsAndStateResponse
- identity, err := r.Cfg.Matrix.SigningIdentityFor(req.Leaver.Domain())
+ identity, err := r.RSAPI.SigningIdentityFor(ctx, *validRoomID, req.Leaver)
if err != nil {
return nil, fmt.Errorf("SigningIdentityFor: %w", err)
}
- event, err := eventutil.QueryAndBuildEvent(ctx, &proto, 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/query/query.go b/roomserver/internal/query/query.go
index 19fd456b..918619e5 100644
--- a/roomserver/internal/query/query.go
+++ b/roomserver/internal/query/query.go
@@ -478,6 +478,9 @@ func (r *Queryer) QueryServerJoinedToRoom(
if err != nil {
return fmt.Errorf("r.DB.RoomInfo: %w", err)
}
+ if info != nil {
+ response.RoomVersion = info.RoomVersion
+ }
if info == nil || info.IsStub() {
return nil
}
diff --git a/roomserver/roomserver_test.go b/roomserver/roomserver_test.go
index 077957fa..76b21ad2 100644
--- a/roomserver/roomserver_test.go
+++ b/roomserver/roomserver_test.go
@@ -35,6 +35,14 @@ import (
"github.com/matrix-org/dendrite/test/testrig"
)
+type FakeQuerier struct {
+ api.QuerySenderIDAPI
+}
+
+func (f *FakeQuerier) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
+ return spec.NewUserID(string(senderID), true)
+}
+
func TestUsers(t *testing.T) {
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
@@ -566,7 +574,7 @@ func TestRedaction(t *testing.T) {
err = updater.Commit()
assert.NoError(t, err)
- _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.PDU, &plResolver)
+ _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.PDU, &plResolver, &FakeQuerier{})
assert.NoError(t, err)
if redactedEvent != nil {
assert.Equal(t, ev.Redacts(), redactedEvent.EventID())
diff --git a/roomserver/storage/interface.go b/roomserver/storage/interface.go
index 7156c11c..e9b4609e 100644
--- a/roomserver/storage/interface.go
+++ b/roomserver/storage/interface.go
@@ -18,6 +18,7 @@ import (
"context"
"crypto/ed25519"
+ "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
@@ -190,7 +191,7 @@ type Database interface {
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
MaybeRedactEvent(
- ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver,
+ ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, querier api.QuerySenderIDAPI,
) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error)
}
@@ -251,7 +252,7 @@ type EventDatabase interface {
// MaybeRedactEvent returns the redaction event and the redacted event if this call resulted in a redaction, else an error
// (nil if there was nothing to do)
MaybeRedactEvent(
- ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver,
+ ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, querier api.QuerySenderIDAPI,
) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error)
StoreEvent(ctx context.Context, event gomatrixserverlib.PDU, roomInfo *types.RoomInfo, eventTypeNID types.EventTypeNID, eventStateKeyNID types.EventStateKeyNID, authEventNIDs []types.EventNID, isRejected bool) (types.EventNID, types.StateAtEvent, error)
}
diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go
index 61a3520a..fc3ace6a 100644
--- a/roomserver/storage/shared/storage.go
+++ b/roomserver/storage/shared/storage.go
@@ -10,6 +10,7 @@ import (
"sort"
"github.com/matrix-org/dendrite/internal/eventutil"
+ "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
@@ -991,6 +992,7 @@ func extractRoomVersionFromCreateEvent(event gomatrixserverlib.PDU) (
// Returns the redaction event and the redacted event if this call resulted in a redaction.
func (d *EventDatabase) MaybeRedactEvent(
ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver,
+ querier api.QuerySenderIDAPI,
) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error) {
var (
redactionEvent, redactedEvent *types.Event
@@ -1030,15 +1032,18 @@ func (d *EventDatabase) MaybeRedactEvent(
return nil
}
- // TODO: Don't hack senderID into userID here (pseudoIDs)
+ var validRoomID *spec.RoomID
+ validRoomID, err = spec.NewRoomID(redactedEvent.RoomID())
+ if err != nil {
+ return err
+ }
sender1Domain := ""
- sender1, err1 := spec.NewUserID(string(redactedEvent.SenderID()), true)
+ sender1, err1 := querier.QueryUserIDForSender(ctx, *validRoomID, redactedEvent.SenderID())
if err1 == nil {
sender1Domain = string(sender1.Domain())
}
- // TODO: Don't hack senderID into userID here (pseudoIDs)
sender2Domain := ""
- sender2, err2 := spec.NewUserID(string(redactionEvent.SenderID()), true)
+ sender2, err2 := querier.QueryUserIDForSender(ctx, *validRoomID, redactionEvent.SenderID())
if err2 == nil {
sender2Domain = string(sender2.Domain())
}
@@ -1698,6 +1703,7 @@ func (d *Database) InsertUserRoomPublicKey(ctx context.Context, userID spec.User
// SelectUserRoomPrivateKey queries the users room private key.
// If no key exists, returns no key and no error. Otherwise returns
// the key and a database error, if any.
+// TODO: Cache this?
func (d *Database) SelectUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (key ed25519.PrivateKey, err error) {
uID := userID.String()
stateKeyNIDMap, sErr := d.eventStateKeyNIDs(ctx, nil, []string{uID})
@@ -1756,58 +1762,54 @@ func (d *Database) SelectUserRoomPublicKey(ctx context.Context, userID spec.User
// SelectUserIDsForPublicKeys returns a map from roomID -> map from senderKey -> userID
func (d *Database) SelectUserIDsForPublicKeys(ctx context.Context, publicKeys map[spec.RoomID][]ed25519.PublicKey) (result map[spec.RoomID]map[string]string, err error) {
result = make(map[spec.RoomID]map[string]string, len(publicKeys))
- err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
- // map all roomIDs to roomNIDs
- query := make(map[types.RoomNID][]ed25519.PublicKey)
- rooms := make(map[types.RoomNID]spec.RoomID)
- for roomID, keys := range publicKeys {
- roomNID, ok := d.Cache.GetRoomServerRoomNID(roomID.String())
- if !ok {
- roomInfo, rErr := d.roomInfo(ctx, txn, roomID.String())
- if rErr != nil {
- return rErr
- }
- if roomInfo == nil {
- logrus.Warnf("missing room info for %s, there will be missing users in the response", roomID.String())
- continue
- }
- roomNID = roomInfo.RoomNID
+ // map all roomIDs to roomNIDs
+ query := make(map[types.RoomNID][]ed25519.PublicKey)
+ rooms := make(map[types.RoomNID]spec.RoomID)
+ for roomID, keys := range publicKeys {
+ roomNID, ok := d.Cache.GetRoomServerRoomNID(roomID.String())
+ if !ok {
+ roomInfo, rErr := d.roomInfo(ctx, nil, roomID.String())
+ if rErr != nil {
+ return nil, rErr
}
-
- query[roomNID] = keys
- rooms[roomNID] = roomID
+ if roomInfo == nil {
+ logrus.Warnf("missing room info for %s, there will be missing users in the response", roomID.String())
+ continue
+ }
+ roomNID = roomInfo.RoomNID
}
- // get the user room key pars
- userRoomKeyPairMap, sErr := d.UserRoomKeyTable.BulkSelectUserNIDs(ctx, txn, query)
- if sErr != nil {
- return sErr
- }
- nids := make([]types.EventStateKeyNID, 0, len(userRoomKeyPairMap))
- for _, nid := range userRoomKeyPairMap {
- nids = append(nids, nid.EventStateKeyNID)
- }
- // get the userIDs
- nidMap, seErr := d.EventStateKeys(ctx, nids)
- if seErr != nil {
- return seErr
- }
+ query[roomNID] = keys
+ rooms[roomNID] = roomID
+ }
- // build the result map (roomID -> map publicKey -> userID)
- for publicKey, userRoomKeyPair := range userRoomKeyPairMap {
- userID := nidMap[userRoomKeyPair.EventStateKeyNID]
- roomID := rooms[userRoomKeyPair.RoomNID]
- resMap, exists := result[roomID]
- if !exists {
- resMap = map[string]string{}
- }
- resMap[publicKey] = userID
- result[roomID] = resMap
- }
+ // get the user room key pars
+ userRoomKeyPairMap, sErr := d.UserRoomKeyTable.BulkSelectUserNIDs(ctx, nil, query)
+ if sErr != nil {
+ return nil, sErr
+ }
+ nids := make([]types.EventStateKeyNID, 0, len(userRoomKeyPairMap))
+ for _, nid := range userRoomKeyPairMap {
+ nids = append(nids, nid.EventStateKeyNID)
+ }
+ // get the userIDs
+ nidMap, seErr := d.EventStateKeys(ctx, nids)
+ if seErr != nil {
+ return nil, seErr
+ }
- return nil
- })
+ // build the result map (roomID -> map publicKey -> userID)
+ for publicKey, userRoomKeyPair := range userRoomKeyPairMap {
+ userID := nidMap[userRoomKeyPair.EventStateKeyNID]
+ roomID := rooms[userRoomKeyPair.RoomNID]
+ resMap, exists := result[roomID]
+ if !exists {
+ resMap = map[string]string{}
+ }
+ resMap[publicKey] = userID
+ result[roomID] = resMap
+ }
return result, err
}
diff --git a/roomserver/storage/sqlite3/user_room_keys_table.go b/roomserver/storage/sqlite3/user_room_keys_table.go
index d58b8ac3..5d6ddc9a 100644
--- a/roomserver/storage/sqlite3/user_room_keys_table.go
+++ b/roomserver/storage/sqlite3/user_room_keys_table.go
@@ -57,6 +57,7 @@ const selectUserRoomPublicKeySQL = `SELECT pseudo_id_pub_key FROM roomserver_use
const selectUserNIDsSQL = `SELECT user_nid, room_nid, pseudo_id_pub_key FROM roomserver_user_room_keys WHERE room_nid IN ($1) AND pseudo_id_pub_key IN ($2)`
type userRoomKeysStatements struct {
+ db *sql.DB
insertUserRoomPrivateKeyStmt *sql.Stmt
insertUserRoomPublicKeyStmt *sql.Stmt
selectUserRoomKeyStmt *sql.Stmt
@@ -70,7 +71,7 @@ func CreateUserRoomKeysTable(db *sql.DB) error {
}
func PrepareUserRoomKeysTable(db *sql.DB) (tables.UserRoomKeys, error) {
- s := &userRoomKeysStatements{}
+ s := &userRoomKeysStatements{db: db}
return s, sqlutil.StatementList{
{&s.insertUserRoomPrivateKeyStmt, insertUserRoomKeySQL},
{&s.insertUserRoomPublicKeyStmt, insertUserRoomPublicKeySQL},
@@ -137,7 +138,7 @@ func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sq
selectSQL := strings.Replace(selectUserNIDsSQL, "($2)", sqlutil.QueryVariadicOffset(len(senders), len(senderKeys)), 1)
selectSQL = strings.Replace(selectSQL, "($1)", sqlutil.QueryVariadic(len(senderKeys)), 1) // replace $1 with the roomNIDs
- selectStmt, err := txn.Prepare(selectSQL)
+ selectStmt, err := s.db.Prepare(selectSQL)
if err != nil {
return nil, err
}
diff --git a/roomserver/types/headered_event.go b/roomserver/types/headered_event.go
index 52d006bd..78399982 100644
--- a/roomserver/types/headered_event.go
+++ b/roomserver/types/headered_event.go
@@ -18,6 +18,7 @@ import (
"unsafe"
"github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/gomatrixserverlib/spec"
)
// HeaderedEvent is an Event which serialises to the headered form, which includes
@@ -25,6 +26,10 @@ import (
type HeaderedEvent struct {
gomatrixserverlib.PDU
Visibility gomatrixserverlib.HistoryVisibility
+ // TODO: Remove this. This is a temporary workaround to store the userID in the syncAPI.
+ // It really should be the userKey instead.
+ UserID spec.UserID
+ StateKeyResolved *string
}
func (h *HeaderedEvent) CacheCost() int {