Fix unfederated invite dialog (#9618)

* clarify error message for unfederated room invites

* hide external user suggesetions

* rename some descriptors

* fix i18n

* add warning for unfederated spaces

* i18n

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Ole Wieners 2023-10-25 12:08:10 +02:00 committed by GitHub
parent a306a08780
commit 4ff35f0471
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 13 deletions

View file

@ -16,7 +16,7 @@ limitations under the License.
import React, { createRef, ReactNode, SyntheticEvent } from "react";
import classNames from "classnames";
import { RoomMember, Room, MatrixError } from "matrix-js-sdk/src/matrix";
import { RoomMember, Room, MatrixError, EventType } from "matrix-js-sdk/src/matrix";
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { logger } from "matrix-js-sdk/src/logger";
import { uniqBy } from "lodash";
@ -368,26 +368,32 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.profilesStore = SdkContextClass.instance.userProfilesStore;
const alreadyInvited = new Set([MatrixClientPeg.safeGet().getUserId()!]);
const excludedIds = new Set([MatrixClientPeg.safeGet().getUserId()!]);
const welcomeUserId = SdkConfig.get("welcome_user_id");
if (welcomeUserId) alreadyInvited.add(welcomeUserId);
if (welcomeUserId) excludedIds.add(welcomeUserId);
if (isRoomInvite(props)) {
const room = MatrixClientPeg.safeGet().getRoom(props.roomId);
const isFederated = room?.currentState.getStateEvents(EventType.RoomCreate, "")?.getContent()["m.federate"];
if (!room) throw new Error("Room ID given to InviteDialog does not look like a room");
room.getMembersWithMembership("invite").forEach((m) => alreadyInvited.add(m.userId));
room.getMembersWithMembership("join").forEach((m) => alreadyInvited.add(m.userId));
room.getMembersWithMembership("invite").forEach((m) => excludedIds.add(m.userId));
room.getMembersWithMembership("join").forEach((m) => excludedIds.add(m.userId));
// add banned users, so we don't try to invite them
room.getMembersWithMembership("ban").forEach((m) => alreadyInvited.add(m.userId));
room.getMembersWithMembership("ban").forEach((m) => excludedIds.add(m.userId));
if (isFederated === false) {
// exclude users from external servers
const homeserver = props.roomId.split(":")[1];
this.excludeExternals(homeserver, excludedIds);
}
}
this.state = {
targets: [], // array of Member objects (see interface above)
filterText: this.props.initialText || "",
// Mutates alreadyInvited set so that buildSuggestions doesn't duplicate any users
recents: InviteDialog.buildRecents(alreadyInvited),
recents: InviteDialog.buildRecents(excludedIds),
numRecentsShown: INITIAL_ROOMS_SHOWN,
suggestions: this.buildSuggestions(alreadyInvited),
suggestions: this.buildSuggestions(excludedIds),
numSuggestionsShown: INITIAL_ROOMS_SHOWN,
serverResultsMixin: [],
threepidResultsMixin: [],
@ -418,6 +424,18 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.setState({ consultFirst: ev.target.checked });
};
private excludeExternals(homeserver: string, excludedTargetIds: Set<string>): void {
const client = MatrixClientPeg.safeGet();
// users with room membership
const members = Object.values(buildMemberScores(client)).map(({ member }) => member.userId);
// users with dm membership
const roomMembers = Object.keys(DMRoomMap.shared().getUniqueRoomsWithIndividuals());
roomMembers.forEach((id) => members.push(id));
// filter duplicates and user IDs from external servers
const externals = new Set(members.filter((id) => !id.includes(homeserver)));
externals.forEach((id) => excludedTargetIds.add(id));
}
public static buildRecents(excludedTargetIds: Set<string>): Result[] {
const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room