diff --git a/clientapi/routing/userdirectory.go b/clientapi/routing/userdirectory.go index 2659bc9cc..9f8f0184a 100644 --- a/clientapi/routing/userdirectory.go +++ b/clientapi/routing/userdirectory.go @@ -19,7 +19,7 @@ import ( "fmt" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" - "github.com/matrix-org/dendrite/roomserver/api" + rsapi "github.com/matrix-org/dendrite/roomserver/api" userapi "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" @@ -34,7 +34,7 @@ func SearchUserDirectory( ctx context.Context, device *userapi.Device, userAPI userapi.UserInternalAPI, - rsAPI api.RoomserverInternalAPI, + rsAPI rsapi.RoomserverInternalAPI, serverName gomatrixserverlib.ServerName, searchString string, limit int, @@ -49,58 +49,25 @@ func SearchUserDirectory( Limited: false, } - // First start searching local users. - - userReq := &userapi.QuerySearchProfilesRequest{ + stateReq := &rsapi.QueryKnownUsersRequest{ + UserID: device.UserID, SearchString: searchString, Limit: limit, } - userRes := &userapi.QuerySearchProfilesResponse{} - if err := userAPI.QuerySearchProfiles(ctx, userReq, userRes); err != nil { - errRes := util.ErrorResponse(fmt.Errorf("userAPI.QuerySearchProfiles: %w", err)) + stateRes := &rsapi.QueryKnownUsersResponse{} + if err := rsAPI.QueryKnownUsers(ctx, stateReq, stateRes); err != nil { + errRes := util.ErrorResponse(fmt.Errorf("rsAPI.QueryKnownUsers: %w", err)) return &errRes } - for _, user := range userRes.Profiles { + for _, user := range stateRes.Users { if len(results) == limit { response.Limited = true break } - userID := fmt.Sprintf("@%s:%s", user.Localpart, serverName) - if _, ok := results[userID]; !ok { - results[userID] = authtypes.FullyQualifiedProfile{ - UserID: userID, - DisplayName: user.DisplayName, - AvatarURL: user.AvatarURL, - } - } - } - - // Then, if we have enough room left in the response, - // start searching for known users from joined rooms. - - if len(results) <= limit { - stateReq := &api.QueryKnownUsersRequest{ - UserID: device.UserID, - SearchString: searchString, - Limit: limit - len(results), - } - stateRes := &api.QueryKnownUsersResponse{} - if err := rsAPI.QueryKnownUsers(ctx, stateReq, stateRes); err != nil { - errRes := util.ErrorResponse(fmt.Errorf("rsAPI.QueryKnownUsers: %w", err)) - return &errRes - } - - for _, user := range stateRes.Users { - if len(results) == limit { - response.Limited = true - break - } - - if _, ok := results[user.UserID]; !ok { - results[user.UserID] = user - } + if _, ok := results[user.UserID]; !ok { + results[user.UserID] = user } } diff --git a/roomserver/internal/input/input_membership.go b/roomserver/internal/input/input_membership.go index 2511097d0..30bba6fa2 100644 --- a/roomserver/internal/input/input_membership.go +++ b/roomserver/internal/input/input_membership.go @@ -157,11 +157,22 @@ func (r *Inputer) isLocalTarget(event *gomatrixserverlib.Event) bool { func updateToJoinMembership( mu *shared.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent, ) ([]api.OutputEvent, error) { + // Extract the displayname, if there is one, from the membership event + // so that we can add it as a queryable field to the membership table + memberEvent, err := gomatrixserverlib.NewMemberContentFromEvent(add) + if err != nil { + return nil, err + } + var displayname string + if memberEvent.DisplayName != "" { + displayname = memberEvent.DisplayName + } + // If the user is already marked as being joined, we call SetToJoin to update // the event ID then we can return immediately. Retired is ignored as there // is no invite event to retire. if mu.IsJoin() { - _, err := mu.SetToJoin(add.Sender(), add.EventID(), true) + _, err := mu.SetToJoin(add.Sender(), add.EventID(), displayname, true) if err != nil { return nil, err } @@ -171,7 +182,7 @@ func updateToJoinMembership( // are active for that user. We notify the consumers that the invites have // been retired using a special event, even though they could infer this // by studying the state changes in the room event stream. - retired, err := mu.SetToJoin(add.Sender(), add.EventID(), false) + retired, err := mu.SetToJoin(add.Sender(), add.EventID(), displayname, false) if err != nil { return nil, err } diff --git a/roomserver/storage/postgres/deltas/2021062221090000_add_displayname_column.go b/roomserver/storage/postgres/deltas/2021062221090000_add_displayname_column.go new file mode 100644 index 000000000..be9c61e5d --- /dev/null +++ b/roomserver/storage/postgres/deltas/2021062221090000_add_displayname_column.go @@ -0,0 +1,52 @@ +// Copyright 2020 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 deltas + +import ( + "database/sql" + "fmt" + + "github.com/matrix-org/dendrite/internal/sqlutil" +) + +func LoadAddDisplaynameColumn(m *sqlutil.Migrations) { + m.AddMigration(UpAddDisplaynameColumn, DownAddDisplaynameColumn) +} + +func UpAddDisplaynameColumn(tx *sql.Tx) error { + _, err := tx.Exec(`ALTER TABLE roomserver_membership ADD COLUMN IF NOT EXISTS displayname TEXT NOT NULL DEFAULT '';`) + if err != nil { + return fmt.Errorf("failed to execute upgrade: %w", err) + } + + _, err = tx.Exec(`UPDATE roomserver_membership SET displayname = event_json::json->'content'->'displayname' +FROM roomserver_event_json WHERE + roomserver_membership.event_nid = roomserver_event_json.event_nid + AND event_json::json->'content'->'displayname' IS NOT NULL; +`) + if err != nil { + return fmt.Errorf("failed to move displayname from JSON to column: %w", err) + } + + return nil +} + +func DownAddDisplaynameColumn(tx *sql.Tx) error { + _, err := tx.Exec(`ALTER TABLE roomserver_membership DROP COLUMN IF EXISTS displayname;`) + if err != nil { + return fmt.Errorf("failed to execute downgrade: %w", err) + } + return nil +} diff --git a/roomserver/storage/postgres/membership_table.go b/roomserver/storage/postgres/membership_table.go index b0d906c80..a41844ad7 100644 --- a/roomserver/storage/postgres/membership_table.go +++ b/roomserver/storage/postgres/membership_table.go @@ -61,6 +61,7 @@ CREATE TABLE IF NOT EXISTS roomserver_membership ( -- room joins. target_local BOOLEAN NOT NULL DEFAULT false, forgotten BOOLEAN NOT NULL DEFAULT FALSE, + displayname TEXT NOT NULL DEFAULT '', UNIQUE (room_nid, target_nid) ); ` @@ -104,7 +105,7 @@ const selectMembershipForUpdateSQL = "" + " WHERE room_nid = $1 AND target_nid = $2 FOR UPDATE" const updateMembershipSQL = "" + - "UPDATE roomserver_membership SET sender_nid = $3, membership_nid = $4, event_nid = $5, forgotten = $6" + + "UPDATE roomserver_membership SET sender_nid = $3, membership_nid = $4, event_nid = $5, forgotten = $6, displayname = $7" + " WHERE room_nid = $1 AND target_nid = $2" const updateMembershipForgetRoom = "" + @@ -118,11 +119,16 @@ const selectRoomsWithMembershipSQL = "" + // joined to. Since this information is used to populate the user directory, we will // only return users that the user would ordinarily be able to see anyway. var selectKnownUsersSQL = "" + - "SELECT DISTINCT event_state_key FROM roomserver_membership INNER JOIN roomserver_event_state_keys ON " + - "roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid" + - " WHERE room_nid = ANY(" + - " SELECT DISTINCT room_nid FROM roomserver_membership WHERE target_nid=$1 AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + - ") AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + " AND event_state_key LIKE $2 LIMIT $3" + "SELECT DISTINCT event_state_key, displayname FROM roomserver_membership INNER JOIN roomserver_event_state_keys ON " + + "roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid " + + "WHERE room_nid IN (" + + " SELECT DISTINCT room_nid FROM roomserver_membership WHERE target_nid = $1 AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + + " UNION " + + " SELECT DISTINCT room_nid from roomserver_rooms INNER JOIN roomserver_published ON " + + " roomserver_rooms.room_id = roomserver_published.room_id WHERE published = true " + + ") AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + " AND ( " + + " event_state_key LIKE $2 OR displayname LIKE $2" + + ") LIMIT $3" // selectLocalServerInRoomSQL is an optimised case for checking if we, the local server, // are in the room by using the target_local column of the membership table. Normally when @@ -270,10 +276,10 @@ func (s *membershipStatements) SelectMembershipsFromRoomAndMembership( func (s *membershipStatements) UpdateMembership( ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, senderUserNID types.EventStateKeyNID, membership tables.MembershipState, - eventNID types.EventNID, forgotten bool, + eventNID types.EventNID, forgotten bool, displayname string, ) error { _, err := sqlutil.TxStmt(txn, s.updateMembershipStmt).ExecContext( - ctx, roomNID, targetUserNID, senderUserNID, membership, eventNID, forgotten, + ctx, roomNID, targetUserNID, senderUserNID, membership, eventNID, forgotten, displayname, ) return err } @@ -328,7 +334,8 @@ func (s *membershipStatements) SelectKnownUsers(ctx context.Context, userID type defer internal.CloseAndLogIfError(ctx, rows, "SelectKnownUsers: rows.close() failed") for rows.Next() { var userID string - if err := rows.Scan(&userID); err != nil { + var displayname string + if err := rows.Scan(&userID, &displayname); err != nil { return nil, err } result = append(result, userID) diff --git a/roomserver/storage/postgres/storage.go b/roomserver/storage/postgres/storage.go index 863a15939..4de926a14 100644 --- a/roomserver/storage/postgres/storage.go +++ b/roomserver/storage/postgres/storage.go @@ -53,6 +53,7 @@ func Open(dbProperties *config.DatabaseOptions, cache caching.RoomServerCaches) m := sqlutil.NewMigrations() deltas.LoadAddForgottenColumn(m) deltas.LoadStateBlocksRefactor(m) + deltas.LoadAddDisplaynameColumn(m) if err := m.RunDeltas(db, dbProperties); err != nil { return nil, err } diff --git a/roomserver/storage/shared/membership_updater.go b/roomserver/storage/shared/membership_updater.go index f1f589a31..fe6844afa 100644 --- a/roomserver/storage/shared/membership_updater.go +++ b/roomserver/storage/shared/membership_updater.go @@ -106,7 +106,7 @@ func (u *MembershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, er return fmt.Errorf("u.d.InvitesTable.InsertInviteEvent: %w", err) } if u.membership != tables.MembershipStateInvite { - if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateInvite, 0, false); err != nil { + if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateInvite, 0, false, ""); err != nil { return fmt.Errorf("u.d.MembershipTable.UpdateMembership: %w", err) } } @@ -116,7 +116,7 @@ func (u *MembershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, er } // SetToJoin implements types.MembershipUpdater -func (u *MembershipUpdater) SetToJoin(senderUserID string, eventID string, isUpdate bool) ([]string, error) { +func (u *MembershipUpdater) SetToJoin(senderUserID string, eventID string, displayname string, isUpdate bool) ([]string, error) { var inviteEventIDs []string err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { @@ -142,7 +142,7 @@ func (u *MembershipUpdater) SetToJoin(senderUserID string, eventID string, isUpd } if u.membership != tables.MembershipStateJoin || isUpdate { - if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateJoin, nIDs[eventID], false); err != nil { + if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateJoin, nIDs[eventID], false, displayname); err != nil { return fmt.Errorf("u.d.MembershipTable.UpdateMembership: %w", err) } } @@ -176,7 +176,7 @@ func (u *MembershipUpdater) SetToLeave(senderUserID string, eventID string) ([]s } if u.membership != tables.MembershipStateLeaveOrBan { - if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateLeaveOrBan, nIDs[eventID], false); err != nil { + if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateLeaveOrBan, nIDs[eventID], false, ""); err != nil { return fmt.Errorf("u.d.MembershipTable.UpdateMembership: %w", err) } } diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index e18516791..693ca6392 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -1080,7 +1080,13 @@ func (d *Database) GetServerInRoom(ctx context.Context, roomNID types.RoomNID, s func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) { stateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, userID) if err != nil { - return nil, err + if err == sql.ErrNoRows { + // Happens if a search is performed before user joins any rooms + // NID is never -1, so SelectKnownUsers will only pull users in public rooms + stateKeyNID = -1 + } else { + return nil, err + } } return d.MembershipTable.SelectKnownUsers(ctx, stateKeyNID, searchString, limit) } diff --git a/roomserver/storage/sqlite3/deltas/2021062221090000_add_displayname_column.go b/roomserver/storage/sqlite3/deltas/2021062221090000_add_displayname_column.go new file mode 100644 index 000000000..7f430a287 --- /dev/null +++ b/roomserver/storage/sqlite3/deltas/2021062221090000_add_displayname_column.go @@ -0,0 +1,126 @@ +// Copyright 2020 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 deltas + +import ( + "database/sql" + "encoding/json" + "fmt" + + "github.com/matrix-org/dendrite/internal/sqlutil" + "github.com/matrix-org/dendrite/roomserver/types" +) + +func LoadAddDisplaynameColumn(m *sqlutil.Migrations) { + m.AddMigration(UpAddDisplaynameColumn, DownAddDisplaynameColumn) +} + +func UpAddDisplaynameColumn(tx *sql.Tx) error { + _, err := tx.Exec(` ALTER TABLE roomserver_membership RENAME TO roomserver_membership_tmp; +CREATE TABLE IF NOT EXISTS roomserver_membership ( + room_nid INTEGER NOT NULL, + target_nid INTEGER NOT NULL, + sender_nid INTEGER NOT NULL DEFAULT 0, + membership_nid INTEGER NOT NULL DEFAULT 1, + event_nid INTEGER NOT NULL DEFAULT 0, + target_local BOOLEAN NOT NULL DEFAULT false, + forgotten BOOLEAN NOT NULL DEFAULT false, + displayname TEXT NOT NULL DEFAULT '', + UNIQUE (room_nid, target_nid) +); +INSERT + INTO roomserver_membership ( + room_nid, target_nid, sender_nid, membership_nid, event_nid, target_local, forgotten + ) SELECT + room_nid, target_nid, sender_nid, membership_nid, event_nid, target_local, forgotten + FROM roomserver_membership_tmp +; +DROP TABLE roomserver_membership_tmp;`) + if err != nil { + return fmt.Errorf("failed to execute upgrade: %w", err) + } + + rows, err := tx.Query(`SELECT room_nid, target_nid, event_json FROM roomserver_membership +INNER JOIN roomserver_event_json ON + roomserver_membership.event_nid = roomserver_event_json.event_nid +WHERE displayname = ''; +`) + if err != nil { + return fmt.Errorf("failed to execute upgrade: %w", err) + } + + for rows.Next() { + var roomNID types.RoomNID + var targetUserNID types.EventStateKeyNID + var eventJSONRaw []byte + + if err = rows.Scan(&roomNID, &targetUserNID, &eventJSONRaw); err != nil { + return fmt.Errorf("error scanning row: %v", err) + } + + eventJSON := make(map[string]interface{}) + err = json.Unmarshal(eventJSONRaw, &eventJSON) + if err != nil { + return fmt.Errorf("could not unmarshal event JSON: %v", err) + } + + eventDisplayname := "" + if content, ok := eventJSON["content"]; ok { + if displayname, ok := content.(map[string]interface{})["displayname"]; ok { + if displaynameString, ok := displayname.(string); ok { + eventDisplayname = displaynameString + } + } + } + if eventDisplayname != "" { + _, err = tx.Exec(`UPDATE roomserver_membership +SET displayname = $1 +WHERE room_nid = $2 AND target_nid = $3;`, + eventDisplayname, roomNID, targetUserNID) + if err != nil { + return fmt.Errorf("could not update displayname field: %v", err) + } + } + + } + + return nil +} + +func DownAddDisplaynameColumn(tx *sql.Tx) error { + _, err := tx.Exec(` ALTER TABLE roomserver_membership RENAME TO roomserver_membership_tmp; +CREATE TABLE IF NOT EXISTS roomserver_membership ( + room_nid INTEGER NOT NULL, + target_nid INTEGER NOT NULL, + sender_nid INTEGER NOT NULL DEFAULT 0, + membership_nid INTEGER NOT NULL DEFAULT 1, + event_nid INTEGER NOT NULL DEFAULT 0, + target_local BOOLEAN NOT NULL DEFAULT false, + forgotten BOOLEAN NOT NULL DEFAULT false, + UNIQUE (room_nid, target_nid) +); +INSERT + INTO roomserver_membership ( + room_nid, target_nid, sender_nid, membership_nid, event_nid, target_local, forgotten + ) SELECT + room_nid, target_nid, sender_nid, membership_nid, event_nid, target_local, forgotten + FROM roomserver_membership_tmp +; +DROP TABLE roomserver_membership_tmp;`) + if err != nil { + return fmt.Errorf("failed to execute downgrade: %w", err) + } + return nil +} diff --git a/roomserver/storage/sqlite3/membership_table.go b/roomserver/storage/sqlite3/membership_table.go index 2e58431d3..4d2735660 100644 --- a/roomserver/storage/sqlite3/membership_table.go +++ b/roomserver/storage/sqlite3/membership_table.go @@ -37,6 +37,7 @@ const membershipSchema = ` event_nid INTEGER NOT NULL DEFAULT 0, target_local BOOLEAN NOT NULL DEFAULT false, forgotten BOOLEAN NOT NULL DEFAULT false, + displayname TEXT NOT NULL DEFAULT '', UNIQUE (room_nid, target_nid) ); ` @@ -80,8 +81,8 @@ const selectMembershipForUpdateSQL = "" + " WHERE room_nid = $1 AND target_nid = $2" const updateMembershipSQL = "" + - "UPDATE roomserver_membership SET sender_nid = $1, membership_nid = $2, event_nid = $3, forgotten = $4" + - " WHERE room_nid = $5 AND target_nid = $6" + "UPDATE roomserver_membership SET sender_nid = $1, membership_nid = $2, event_nid = $3, forgotten = $4, displayname = $5" + + " WHERE room_nid = $6 AND target_nid = $7" const updateMembershipForgetRoom = "" + "UPDATE roomserver_membership SET forgotten = $1" + @@ -94,11 +95,16 @@ const selectRoomsWithMembershipSQL = "" + // joined to. Since this information is used to populate the user directory, we will // only return users that the user would ordinarily be able to see anyway. var selectKnownUsersSQL = "" + - "SELECT DISTINCT event_state_key FROM roomserver_membership INNER JOIN roomserver_event_state_keys ON " + - "roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid" + - " WHERE room_nid IN (" + - " SELECT DISTINCT room_nid FROM roomserver_membership WHERE target_nid=$1 AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + - ") AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + " AND event_state_key LIKE $2 LIMIT $3" + "SELECT DISTINCT event_state_key, displayname FROM roomserver_membership INNER JOIN roomserver_event_state_keys ON " + + "roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid " + + "WHERE room_nid IN (" + + " SELECT DISTINCT room_nid FROM roomserver_membership WHERE target_nid = $1 AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + + " UNION " + + " SELECT DISTINCT room_nid from roomserver_rooms INNER JOIN roomserver_published ON " + + " roomserver_rooms.room_id = roomserver_published.room_id WHERE published = true " + + ") AND membership_nid = " + fmt.Sprintf("%d", tables.MembershipStateJoin) + " AND ( " + + " event_state_key LIKE $2 OR displayname LIKE $2" + + ") LIMIT $3" // selectLocalServerInRoomSQL is an optimised case for checking if we, the local server, // are in the room by using the target_local column of the membership table. Normally when @@ -248,11 +254,11 @@ func (s *membershipStatements) SelectMembershipsFromRoomAndMembership( func (s *membershipStatements) UpdateMembership( ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, senderUserNID types.EventStateKeyNID, membership tables.MembershipState, - eventNID types.EventNID, forgotten bool, + eventNID types.EventNID, forgotten bool, displayname string, ) error { stmt := sqlutil.TxStmt(txn, s.updateMembershipStmt) _, err := stmt.ExecContext( - ctx, senderUserNID, membership, eventNID, forgotten, roomNID, targetUserNID, + ctx, senderUserNID, membership, eventNID, forgotten, displayname, roomNID, targetUserNID, ) return err } @@ -308,7 +314,8 @@ func (s *membershipStatements) SelectKnownUsers(ctx context.Context, userID type defer internal.CloseAndLogIfError(ctx, rows, "SelectKnownUsers: rows.close() failed") for rows.Next() { var userID string - if err := rows.Scan(&userID); err != nil { + var displayname string + if err := rows.Scan(&userID, &displayname); err != nil { return nil, err } result = append(result, userID) diff --git a/roomserver/storage/sqlite3/storage.go b/roomserver/storage/sqlite3/storage.go index e081acdbd..452f054fa 100644 --- a/roomserver/storage/sqlite3/storage.go +++ b/roomserver/storage/sqlite3/storage.go @@ -61,6 +61,7 @@ func Open(dbProperties *config.DatabaseOptions, cache caching.RoomServerCaches) m := sqlutil.NewMigrations() deltas.LoadAddForgottenColumn(m) deltas.LoadStateBlocksRefactor(m) + deltas.LoadAddDisplaynameColumn(m) if err := m.RunDeltas(db, dbProperties); err != nil { return nil, err } diff --git a/roomserver/storage/tables/interface.go b/roomserver/storage/tables/interface.go index 8720d4007..4cd34bec9 100644 --- a/roomserver/storage/tables/interface.go +++ b/roomserver/storage/tables/interface.go @@ -129,7 +129,7 @@ type Membership interface { SelectMembershipFromRoomAndTarget(ctx context.Context, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID) (types.EventNID, MembershipState, bool, error) SelectMembershipsFromRoom(ctx context.Context, roomNID types.RoomNID, localOnly bool) (eventNIDs []types.EventNID, err error) SelectMembershipsFromRoomAndMembership(ctx context.Context, roomNID types.RoomNID, membership MembershipState, localOnly bool) (eventNIDs []types.EventNID, err error) - UpdateMembership(ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, senderUserNID types.EventStateKeyNID, membership MembershipState, eventNID types.EventNID, forgotten bool) error + UpdateMembership(ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, senderUserNID types.EventStateKeyNID, membership MembershipState, eventNID types.EventNID, forgotten bool, displayname string) error SelectRoomsWithMembership(ctx context.Context, userID types.EventStateKeyNID, membershipState MembershipState) ([]types.RoomNID, error) // SelectJoinedUsersSetForRooms returns the set of all users in the rooms who are joined to any of these rooms, along with the // counts of how many rooms they are joined. diff --git a/sytest-whitelist b/sytest-whitelist index d2f2a1c7d..45e07cdf0 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -554,3 +554,7 @@ Can upload self-signing keys Fails to upload self-signing keys with no auth Fails to upload self-signing key without master key can fetch self-signing keys over federation +User in private room doesn't appear in user directory +User joining then leaving public room appears and dissappears from directory +User in remote room doesn't appear in user directory after server left room +User in shared private room does appear in user directory until leave