mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-07-31 13:22:46 +00:00
Merge SenderID & Per Room User Key work (#3109)
This commit is contained in:
parent
7a2e325d10
commit
e4665979bf
75 changed files with 801 additions and 379 deletions
|
@ -169,10 +169,6 @@ type Database interface {
|
|||
GetServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName spec.ServerName) (bool, error)
|
||||
// GetKnownUsers searches all users that userID knows about.
|
||||
GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error)
|
||||
// GetKnownUsers tries to obtain the current mxid for a given user.
|
||||
GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error)
|
||||
// GetKnownUsers tries to obtain the current senderID for a given user.
|
||||
GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error)
|
||||
// GetKnownRooms returns a list of all rooms we know about.
|
||||
GetKnownRooms(ctx context.Context) ([]string, error)
|
||||
// ForgetRoom sets a flag in the membership table, that the user wishes to forget a specific room
|
||||
|
@ -190,6 +186,7 @@ type Database interface {
|
|||
ctx context.Context, userNID types.EventStateKeyNID, info *types.RoomInfo, eventIDs ...string,
|
||||
) (map[string]*types.HeaderedEvent, error)
|
||||
GetOrCreateRoomInfo(ctx context.Context, event gomatrixserverlib.PDU) (*types.RoomInfo, error)
|
||||
GetRoomVersion(ctx context.Context, roomID string) (gomatrixserverlib.RoomVersion, error)
|
||||
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
||||
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
||||
MaybeRedactEvent(
|
||||
|
@ -205,8 +202,12 @@ type UserRoomKeys interface {
|
|||
InsertUserRoomPublicKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID, key ed25519.PublicKey) (result ed25519.PublicKey, err error)
|
||||
// SelectUserRoomPrivateKey selects the private key for the given user and room combination
|
||||
SelectUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (key ed25519.PrivateKey, err error)
|
||||
// SelectUserRoomPublicKey selects the public key for the given user and room combination
|
||||
SelectUserRoomPublicKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (key ed25519.PublicKey, err error)
|
||||
// SelectUserIDsForPublicKeys selects all userIDs for the requested senderKeys. Returns a map from roomID -> map from publicKey to userID.
|
||||
// If a senderKey can't be found, it is omitted in the result.
|
||||
// TODO: Why is the result map indexed by string not public key?
|
||||
// TODO: Shouldn't the input & result map be changed to be indexed by string instead of the RoomID struct?
|
||||
SelectUserIDsForPublicKeys(ctx context.Context, publicKeys map[spec.RoomID][]ed25519.PublicKey) (map[spec.RoomID]map[string]string, error)
|
||||
}
|
||||
|
||||
|
@ -233,7 +234,6 @@ type RoomDatabase interface {
|
|||
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
||||
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
||||
GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*types.HeaderedEvent, error)
|
||||
GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error)
|
||||
}
|
||||
|
||||
type EventDatabase interface {
|
||||
|
|
|
@ -51,12 +51,15 @@ const insertUserRoomPublicKeySQL = `
|
|||
|
||||
const selectUserRoomKeySQL = `SELECT pseudo_id_key FROM roomserver_user_room_keys WHERE user_nid = $1 AND room_nid = $2`
|
||||
|
||||
const selectUserRoomPublicKeySQL = `SELECT pseudo_id_pub_key FROM roomserver_user_room_keys WHERE user_nid = $1 AND room_nid = $2`
|
||||
|
||||
const selectUserNIDsSQL = `SELECT user_nid, room_nid, pseudo_id_pub_key FROM roomserver_user_room_keys WHERE room_nid = ANY($1) AND pseudo_id_pub_key = ANY($2)`
|
||||
|
||||
type userRoomKeysStatements struct {
|
||||
insertUserRoomPrivateKeyStmt *sql.Stmt
|
||||
insertUserRoomPublicKeyStmt *sql.Stmt
|
||||
selectUserRoomKeyStmt *sql.Stmt
|
||||
selectUserRoomPublicKeyStmt *sql.Stmt
|
||||
selectUserNIDsStmt *sql.Stmt
|
||||
}
|
||||
|
||||
|
@ -71,6 +74,7 @@ func PrepareUserRoomKeysTable(db *sql.DB) (tables.UserRoomKeys, error) {
|
|||
{&s.insertUserRoomPrivateKeyStmt, insertUserRoomPrivateKeySQL},
|
||||
{&s.insertUserRoomPublicKeyStmt, insertUserRoomPublicKeySQL},
|
||||
{&s.selectUserRoomKeyStmt, selectUserRoomKeySQL},
|
||||
{&s.selectUserRoomPublicKeyStmt, selectUserRoomPublicKeySQL},
|
||||
{&s.selectUserNIDsStmt, selectUserNIDsSQL},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
@ -102,6 +106,21 @@ func (s *userRoomKeysStatements) SelectUserRoomPrivateKey(
|
|||
return result, err
|
||||
}
|
||||
|
||||
func (s *userRoomKeysStatements) SelectUserRoomPublicKey(
|
||||
ctx context.Context,
|
||||
txn *sql.Tx,
|
||||
userNID types.EventStateKeyNID,
|
||||
roomNID types.RoomNID,
|
||||
) (ed25519.PublicKey, error) {
|
||||
stmt := sqlutil.TxStmtContext(ctx, txn, s.selectUserRoomPublicKeyStmt)
|
||||
var result ed25519.PublicKey
|
||||
err := stmt.QueryRowContext(ctx, userNID, roomNID).Scan(&result)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sql.Tx, senderKeys map[types.RoomNID][]ed25519.PublicKey) (map[string]types.UserRoomKeyPair, error) {
|
||||
stmt := sqlutil.TxStmtContext(ctx, txn, s.selectUserNIDsStmt)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
)
|
||||
|
@ -251,7 +250,3 @@ func (u *RoomUpdater) MarkEventAsSent(eventNID types.EventNID) error {
|
|||
func (u *RoomUpdater) MembershipUpdater(targetUserNID types.EventStateKeyNID, targetLocal bool) (*MembershipUpdater, error) {
|
||||
return u.d.membershipUpdaterTxn(u.ctx, u.txn, u.roomInfo.RoomNID, targetUserNID, targetLocal)
|
||||
}
|
||||
|
||||
func (u *RoomUpdater) GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return u.d.GetUserIDForSender(ctx, roomID, senderID)
|
||||
}
|
||||
|
|
|
@ -721,6 +721,22 @@ func (d *Database) GetOrCreateRoomInfo(ctx context.Context, event gomatrixserver
|
|||
}, err
|
||||
}
|
||||
|
||||
func (d *Database) GetRoomVersion(ctx context.Context, roomID string) (gomatrixserverlib.RoomVersion, error) {
|
||||
cachedRoomVersion, versionOK := d.Cache.GetRoomVersion(roomID)
|
||||
if versionOK {
|
||||
return cachedRoomVersion, nil
|
||||
}
|
||||
|
||||
roomInfo, err := d.RoomInfo(ctx, roomID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if roomInfo == nil {
|
||||
return "", nil
|
||||
}
|
||||
return roomInfo.RoomVersion, nil
|
||||
}
|
||||
|
||||
func (d *Database) GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error) {
|
||||
err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
||||
if eventTypeNID, err = d.assignEventTypeNID(ctx, txn, eventType); err != nil {
|
||||
|
@ -1550,16 +1566,6 @@ func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString strin
|
|||
return d.MembershipTable.SelectKnownUsers(ctx, nil, stateKeyNID, searchString, limit)
|
||||
}
|
||||
|
||||
func (d *Database) GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
// TODO: Use real logic once DB for pseudoIDs is in place
|
||||
return spec.NewUserID(string(senderID), true)
|
||||
}
|
||||
|
||||
func (d *Database) GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) {
|
||||
// TODO: Use real logic once DB for pseudoIDs is in place
|
||||
return spec.SenderID(userID.String()), nil
|
||||
}
|
||||
|
||||
// GetKnownRooms returns a list of all rooms we know about.
|
||||
func (d *Database) GetKnownRooms(ctx context.Context) ([]string, error) {
|
||||
return d.RoomsTable.SelectRoomIDsWithEvents(ctx, nil)
|
||||
|
@ -1718,6 +1724,35 @@ func (d *Database) SelectUserRoomPrivateKey(ctx context.Context, userID spec.Use
|
|||
return
|
||||
}
|
||||
|
||||
// SelectUserRoomPublicKey queries the users room public key.
|
||||
// If no key exists, returns no key and no error. Otherwise returns
|
||||
// the key and a database error, if any.
|
||||
func (d *Database) SelectUserRoomPublicKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (key ed25519.PublicKey, err error) {
|
||||
uID := userID.String()
|
||||
stateKeyNIDMap, sErr := d.eventStateKeyNIDs(ctx, nil, []string{uID})
|
||||
if sErr != nil {
|
||||
return nil, sErr
|
||||
}
|
||||
stateKeyNID := stateKeyNIDMap[uID]
|
||||
|
||||
err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
|
||||
roomInfo, rErr := d.roomInfo(ctx, txn, roomID.String())
|
||||
if rErr != nil {
|
||||
return rErr
|
||||
}
|
||||
if roomInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
key, sErr = d.UserRoomKeyTable.SelectUserRoomPublicKey(ctx, txn, stateKeyNID, roomInfo.RoomNID)
|
||||
if !errors.Is(sErr, sql.ErrNoRows) {
|
||||
return sErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 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))
|
||||
|
|
|
@ -163,12 +163,17 @@ func TestUserRoomKeys(t *testing.T) {
|
|||
gotKey, err = db.SelectUserRoomPrivateKey(context.Background(), *userID, *roomID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, key, gotKey)
|
||||
pubKey, err := db.SelectUserRoomPublicKey(context.Background(), *userID, *roomID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, key.Public(), pubKey)
|
||||
|
||||
// Key doesn't exist, we shouldn't get anything back
|
||||
assert.NoError(t, err)
|
||||
gotKey, err = db.SelectUserRoomPrivateKey(context.Background(), *userID, *doesNotExist)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, gotKey)
|
||||
pubKey, err = db.SelectUserRoomPublicKey(context.Background(), *userID, *doesNotExist)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, pubKey)
|
||||
|
||||
queryUserIDs := map[spec.RoomID][]ed25519.PublicKey{
|
||||
*roomID: {key.Public().(ed25519.PublicKey)},
|
||||
|
|
|
@ -51,12 +51,15 @@ const insertUserRoomPublicKeySQL = `
|
|||
|
||||
const selectUserRoomKeySQL = `SELECT pseudo_id_key FROM roomserver_user_room_keys WHERE user_nid = $1 AND room_nid = $2`
|
||||
|
||||
const selectUserRoomPublicKeySQL = `SELECT pseudo_id_pub_key FROM roomserver_user_room_keys WHERE user_nid = $1 AND room_nid = $2`
|
||||
|
||||
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 {
|
||||
insertUserRoomPrivateKeyStmt *sql.Stmt
|
||||
insertUserRoomPublicKeyStmt *sql.Stmt
|
||||
selectUserRoomKeyStmt *sql.Stmt
|
||||
selectUserRoomPublicKeyStmt *sql.Stmt
|
||||
//selectUserNIDsStmt *sql.Stmt //prepared at runtime
|
||||
}
|
||||
|
||||
|
@ -71,6 +74,7 @@ func PrepareUserRoomKeysTable(db *sql.DB) (tables.UserRoomKeys, error) {
|
|||
{&s.insertUserRoomPrivateKeyStmt, insertUserRoomKeySQL},
|
||||
{&s.insertUserRoomPublicKeyStmt, insertUserRoomPublicKeySQL},
|
||||
{&s.selectUserRoomKeyStmt, selectUserRoomKeySQL},
|
||||
{&s.selectUserRoomPublicKeyStmt, selectUserRoomPublicKeySQL},
|
||||
//{&s.selectUserNIDsStmt, selectUserNIDsSQL}, //prepared at runtime
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
@ -102,6 +106,21 @@ func (s *userRoomKeysStatements) SelectUserRoomPrivateKey(
|
|||
return result, err
|
||||
}
|
||||
|
||||
func (s *userRoomKeysStatements) SelectUserRoomPublicKey(
|
||||
ctx context.Context,
|
||||
txn *sql.Tx,
|
||||
userNID types.EventStateKeyNID,
|
||||
roomNID types.RoomNID,
|
||||
) (ed25519.PublicKey, error) {
|
||||
stmt := sqlutil.TxStmtContext(ctx, txn, s.selectUserRoomPublicKeyStmt)
|
||||
var result ed25519.PublicKey
|
||||
err := stmt.QueryRowContext(ctx, userNID, roomNID).Scan(&result)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sql.Tx, senderKeys map[types.RoomNID][]ed25519.PublicKey) (map[string]types.UserRoomKeyPair, error) {
|
||||
|
||||
roomNIDs := make([]any, 0, len(senderKeys))
|
||||
|
|
|
@ -193,6 +193,8 @@ type UserRoomKeys interface {
|
|||
InsertUserRoomPublicKey(ctx context.Context, txn *sql.Tx, userNID types.EventStateKeyNID, roomNID types.RoomNID, key ed25519.PublicKey) (ed25519.PublicKey, error)
|
||||
// SelectUserRoomPrivateKey selects the private key for the given user and room combination
|
||||
SelectUserRoomPrivateKey(ctx context.Context, txn *sql.Tx, userNID types.EventStateKeyNID, roomNID types.RoomNID) (ed25519.PrivateKey, error)
|
||||
// SelectUserRoomPublicKey selects the public key for the given user and room combination
|
||||
SelectUserRoomPublicKey(ctx context.Context, txn *sql.Tx, userNID types.EventStateKeyNID, roomNID types.RoomNID) (ed25519.PublicKey, error)
|
||||
// BulkSelectUserNIDs selects all userIDs for the requested senderKeys. Returns a map from publicKey -> types.UserRoomKeyPair.
|
||||
// If a senderKey can't be found, it is omitted in the result.
|
||||
BulkSelectUserNIDs(ctx context.Context, txn *sql.Tx, senderKeys map[types.RoomNID][]ed25519.PublicKey) (map[string]types.UserRoomKeyPair, error)
|
||||
|
|
|
@ -50,6 +50,7 @@ func TestUserRoomKeysTable(t *testing.T) {
|
|||
|
||||
err = sqlutil.WithTransaction(db, func(txn *sql.Tx) error {
|
||||
var gotKey, key2, key3 ed25519.PrivateKey
|
||||
var pubKey ed25519.PublicKey
|
||||
gotKey, err = tab.InsertUserRoomPrivatePublicKey(context.Background(), txn, userNID, roomNID, key)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gotKey, key)
|
||||
|
@ -71,6 +72,9 @@ func TestUserRoomKeysTable(t *testing.T) {
|
|||
gotKey, err = tab.SelectUserRoomPrivateKey(context.Background(), txn, userNID, roomNID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, key, gotKey)
|
||||
pubKey, err = tab.SelectUserRoomPublicKey(context.Background(), txn, userNID, roomNID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, key.Public(), pubKey)
|
||||
|
||||
// try to update an existing key, this should only be done for users NOT on this homeserver
|
||||
var gotPubKey ed25519.PublicKey
|
||||
|
@ -82,6 +86,9 @@ func TestUserRoomKeysTable(t *testing.T) {
|
|||
gotKey, err = tab.SelectUserRoomPrivateKey(context.Background(), txn, userNID, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, gotKey)
|
||||
pubKey, err = tab.SelectUserRoomPublicKey(context.Background(), txn, userNID, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, pubKey)
|
||||
|
||||
// query user NIDs for senderKeys
|
||||
var gotKeys map[string]types.UserRoomKeyPair
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue