mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-28 17:23:09 -06:00
[WIP] User directory respects room privacy
This commit is contained in:
parent
125ea75b24
commit
66cb93c010
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue