From a2ca37e4c0000878069a90f067c46d86f3eaebc8 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 7 Oct 2024 16:18:06 +0200 Subject: [PATCH 1/4] Remove usage of `CryptoEvent.DeviceVerificationChanged` --- src/DeviceListener.ts | 8 -------- src/components/structures/RoomView.tsx | 10 ---------- src/components/views/right_panel/UserInfo.tsx | 6 ------ src/components/views/rooms/EventTile.tsx | 8 -------- src/components/views/rooms/MemberTile.tsx | 8 -------- 5 files changed, 40 deletions(-) diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 813a734260..15b66788ec 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -87,7 +87,6 @@ export default class DeviceListener { this.client = matrixClient; this.client.on(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices); this.client.on(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); - this.client.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); this.client.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); this.client.on(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); this.client.on(ClientEvent.AccountData, this.onAccountData); @@ -111,7 +110,6 @@ export default class DeviceListener { if (this.client) { this.client.removeListener(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices); this.client.removeListener(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); - this.client.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); this.client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); this.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); this.client.removeListener(ClientEvent.AccountData, this.onAccountData); @@ -190,12 +188,6 @@ export default class DeviceListener { this.recheck(); }; - private onDeviceVerificationChanged = (userId: string): void => { - if (!this.client) return; - if (userId !== this.client.getUserId()) return; - this.recheck(); - }; - private onUserTrustStatusChanged = (userId: string): void => { if (!this.client) return; if (userId !== this.client.getUserId()) return; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 958c93bebc..1b191f5d8e 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -428,7 +428,6 @@ export class RoomView extends React.Component { context.client.on(RoomStateEvent.Update, this.onRoomStateUpdate); context.client.on(RoomEvent.MyMembership, this.onMyMembership); context.client.on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus); - context.client.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); context.client.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); context.client.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged); context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted); @@ -974,7 +973,6 @@ export class RoomView extends React.Component { this.context.client.removeListener(RoomEvent.MyMembership, this.onMyMembership); this.context.client.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate); this.context.client.removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus); - this.context.client.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); this.context.client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); this.context.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged); this.context.client.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted); @@ -1438,14 +1436,6 @@ export class RoomView extends React.Component { ); }; - private onDeviceVerificationChanged = (userId: string): void => { - const room = this.state.room; - if (!room?.currentState.getMember(userId)) { - return; - } - this.updateE2EStatus(room); - }; - private onUserVerificationChanged = (userId: string): void => { const room = this.state.room; if (!room || !room.currentState.getMember(userId)) { diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index dd4752b783..38c234318b 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -1381,22 +1381,16 @@ export const useDevices = (userId: string): IDevice[] | undefined | null => { if (!users.includes(userId)) return; updateDevices(); }; - const onDeviceVerificationChanged = (_userId: string, deviceId: string): void => { - if (_userId !== userId) return; - updateDevices(); - }; const onUserTrustStatusChanged = (_userId: string, trustLevel: UserVerificationStatus): void => { if (_userId !== userId) return; updateDevices(); }; cli.on(CryptoEvent.DevicesUpdated, onDevicesUpdated); - cli.on(CryptoEvent.DeviceVerificationChanged, onDeviceVerificationChanged); cli.on(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged); // Handle being unmounted return () => { cancel = true; cli.removeListener(CryptoEvent.DevicesUpdated, onDevicesUpdated); - cli.removeListener(CryptoEvent.DeviceVerificationChanged, onDeviceVerificationChanged); cli.removeListener(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged); }; }, [cli, userId]); diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index a41dbc218f..81791bdcce 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -385,7 +385,6 @@ export class UnwrappedEventTile extends React.Component this.suppressReadReceiptAnimation = false; const client = MatrixClientPeg.safeGet(); if (!this.props.forExport) { - client.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); client.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); this.props.mxEvent.on(MatrixEventEvent.Decrypted, this.onDecrypted); this.props.mxEvent.on(MatrixEventEvent.Replaced, this.onReplaced); @@ -425,7 +424,6 @@ export class UnwrappedEventTile extends React.Component public componentWillUnmount(): void { const client = MatrixClientPeg.get(); if (client) { - client.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); client.removeListener(RoomEvent.Receipt, this.onRoomReceipt); const room = client.getRoom(this.props.mxEvent.getRoomId()); @@ -564,12 +562,6 @@ export class UnwrappedEventTile extends React.Component this.forceUpdate(this.props.onHeightChanged); }; - private onDeviceVerificationChanged = (userId: string, device: string): void => { - if (userId === this.props.mxEvent.getSender()) { - this.verifyEvent(); - } - }; - private onUserVerificationChanged = (userId: string, _trustStatus: UserVerificationStatus): void => { if (userId === this.props.mxEvent.getSender()) { this.verifyEvent(); diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index d81a54494e..61b6c750fe 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { RoomMember, RoomStateEvent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; -import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; @@ -62,7 +61,6 @@ export default class MemberTile extends React.Component { }); if (isRoomEncrypted) { cli.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); - cli.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); this.updateE2EStatus(); } else { // Listen for room to become encrypted @@ -77,7 +75,6 @@ export default class MemberTile extends React.Component { if (cli) { cli.removeListener(RoomStateEvent.Events, this.onRoomStateEvents); cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); - cli.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged); } } @@ -100,11 +97,6 @@ export default class MemberTile extends React.Component { this.updateE2EStatus(); }; - private onDeviceVerificationChanged = (userId: string, deviceId: string, deviceInfo: DeviceInfo): void => { - if (userId !== this.props.member.userId) return; - this.updateE2EStatus(); - }; - private async updateE2EStatus(): Promise { const cli = MatrixClientPeg.safeGet(); const { userId } = this.props.member; From 82a98cab7cc4588cf69bb6ee348cf6e7e4540080 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 7 Oct 2024 16:26:07 +0200 Subject: [PATCH 2/4] Remove usage of `CryptoEvent.KeySignatureUploadFailure` --- src/components/structures/MatrixChat.tsx | 5 - .../KeySignatureUploadFailedDialog.tsx | 117 ------------------ src/i18n/strings/en_EN.json | 10 -- 3 files changed, 132 deletions(-) delete mode 100644 src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index f3b75dfce8..31c3957213 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -82,7 +82,6 @@ import Spinner from "../views/elements/Spinner"; import QuestionDialog from "../views/dialogs/QuestionDialog"; import UserSettingsDialog from "../views/dialogs/UserSettingsDialog"; import CreateRoomDialog from "../views/dialogs/CreateRoomDialog"; -import KeySignatureUploadFailedDialog from "../views/dialogs/KeySignatureUploadFailedDialog"; import IncomingSasDialog from "../views/dialogs/IncomingSasDialog"; import CompleteSecurity from "./auth/CompleteSecurity"; import Welcome from "../views/auth/Welcome"; @@ -1674,10 +1673,6 @@ export default class MatrixChat extends React.PureComponent { } }); - cli.on(CryptoEvent.KeySignatureUploadFailure, (failures, source, continuation) => { - Modal.createDialog(KeySignatureUploadFailedDialog, { failures, source, continuation }); - }); - cli.on(CryptoEvent.VerificationRequestReceived, (request) => { if (request.verifier) { Modal.createDialog( diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx b/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx deleted file mode 100644 index 9684f25134..0000000000 --- a/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2020 The Matrix.org Foundation C.I.C. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only -Please see LICENSE files in the repository root for full details. -*/ - -import React, { useState, useCallback, useRef } from "react"; - -import { _t } from "../../../languageHandler"; -import SdkConfig from "../../../SdkConfig"; -import BaseDialog from "./BaseDialog"; -import DialogButtons from "../elements/DialogButtons"; -import Spinner from "../elements/Spinner"; - -interface IProps { - failures: Record< - string, - Record< - string, - { - errcode: string; - error: string; - } - > - >; - source: string; - continuation: (opts: { shouldEmit: boolean }) => Promise; - onFinished(): void; -} - -const KeySignatureUploadFailedDialog: React.FC = ({ failures, source, continuation, onFinished }) => { - const RETRIES = 2; - const [retry, setRetry] = useState(RETRIES); - const [cancelled, setCancelled] = useState(false); - const [retrying, setRetrying] = useState(false); - const [success, setSuccess] = useState(false); - const onCancel = useRef(onFinished); - - const causes = new Map([ - ["_afterCrossSigningLocalKeyChange", _t("encryption|key_signature_upload_failed_master_key_signature")], - ["checkOwnCrossSigningTrust", _t("encryption|key_signature_upload_failed_cross_signing_key_signature")], - ["setDeviceVerification", _t("encryption|key_signature_upload_failed_device_cross_signing_key_signature")], - ]); - const defaultCause = _t("encryption|key_signature_upload_failed_key_signature"); - - const onRetry = useCallback(async (): Promise => { - try { - setRetrying(true); - const cancel = new Promise((resolve, reject) => { - onCancel.current = reject; - }).finally(() => { - setCancelled(true); - }); - await Promise.race([continuation({ shouldEmit: false }), cancel]); - setSuccess(true); - } catch (e) { - setRetry((r) => r - 1); - } finally { - onCancel.current = onFinished; - setRetrying(false); - } - }, [continuation, onFinished]); - - let body; - if (!success && !cancelled && retry > 0) { - const reason = causes.get(source) || defaultCause; - const brand = SdkConfig.get().brand; - - body = ( -
-

{_t("encryption|key_signature_upload_failed_body", { brand })}

-

{reason}

- {retrying && } -
{JSON.stringify(failures, null, 2)}
- -
- ); - } else { - let text = _t("encryption|key_signature_upload_completed"); - if (!success) { - text = cancelled - ? _t("encryption|key_signature_upload_cancelled") - : _t("encryption|key_signature_upload_failed"); - } - - body = ( -
- {text} - -
- ); - } - - return ( - {}} - > - {body} - - ); -}; - -export default KeySignatureUploadFailedDialog; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 21619b99d7..6632533c67 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -904,16 +904,6 @@ "incompatible_database_disable": "Continue With Encryption Disabled", "incompatible_database_sign_out_description": "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this", "incompatible_database_title": "Incompatible Database", - "key_signature_upload_cancelled": "Cancelled signature upload", - "key_signature_upload_completed": "Upload completed", - "key_signature_upload_failed": "Unable to upload", - "key_signature_upload_failed_body": "%(brand)s encountered an error during upload of:", - "key_signature_upload_failed_cross_signing_key_signature": "a new cross-signing key signature", - "key_signature_upload_failed_device_cross_signing_key_signature": "a device cross-signing signature", - "key_signature_upload_failed_key_signature": "a key signature", - "key_signature_upload_failed_master_key_signature": "a new master key signature", - "key_signature_upload_failed_title": "Signature upload failed", - "key_signature_upload_success_title": "Signature upload success", "messages_not_secure": { "cause_1": "Your homeserver", "cause_2": "The homeserver the user you're verifying is connected to", From 6aa0e1320a4da8611efcd36017bd8a25d6bdc164 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 7 Oct 2024 16:52:17 +0200 Subject: [PATCH 3/4] Remove usage of `CryptoEvent.Warning` --- src/components/structures/MatrixChat.tsx | 12 ------------ src/i18n/strings/en_EN.json | 2 -- 2 files changed, 14 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 31c3957213..7689017856 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1628,18 +1628,6 @@ export default class MatrixChat extends React.PureComponent { room.setBlacklistUnverifiedDevices(blacklistEnabled); } }); - cli.on(CryptoEvent.Warning, (type) => { - switch (type) { - case "CRYPTO_WARNING_OLD_VERSION_DETECTED": - Modal.createDialog(ErrorDialog, { - title: _t("encryption|old_version_detected_title"), - description: _t("encryption|old_version_detected_description", { - brand: SdkConfig.get().brand, - }), - }); - break; - } - }); cli.on(CryptoEvent.KeyBackupFailed, async (errcode): Promise => { let haveNewVersion: boolean | undefined; let newVersionInfo: KeyBackupInfo | null = null; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6632533c67..8b43b71ac1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -919,8 +919,6 @@ "warning": "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings." }, "not_supported": "", - "old_version_detected_description": "Data from an older version of %(brand)s has been detected. This will have caused end-to-end cryptography to malfunction in the older version. End-to-end encrypted messages exchanged recently whilst using the older version may not be decryptable in this version. This may also cause messages exchanged with this version to fail. If you experience problems, log out and back in again. To retain message history, export and re-import your keys.", - "old_version_detected_title": "Old cryptography data detected", "recovery_method_removed": { "description_1": "This session has detected that your Security Phrase and key for Secure Messages have been removed.", "description_2": "If you did this accidentally, you can setup Secure Messages on this session which will re-encrypt this session's message history with a new recovery method.", From d4f63e6b55097ef1c27c6ec4750033f0c30c3826 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 7 Oct 2024 17:02:38 +0200 Subject: [PATCH 4/4] Merge `CryptoEvent.DevicesUpdated` and `CryptoEvent.WillUpdateDevices` behaviour --- src/DeviceListener.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 15b66788ec..949bf3d9f4 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -85,7 +85,6 @@ export default class DeviceListener { public start(matrixClient: MatrixClient): void { this.running = true; this.client = matrixClient; - this.client.on(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices); this.client.on(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); this.client.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); this.client.on(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); @@ -108,7 +107,6 @@ export default class DeviceListener { public stop(): void { this.running = false; if (this.client) { - this.client.removeListener(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices); this.client.removeListener(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); this.client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); this.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); @@ -168,7 +166,7 @@ export default class DeviceListener { return await getUserDeviceIds(cli, cli.getSafeUserId()); } - private onWillUpdateDevices = async (users: string[], initialFetch?: boolean): Promise => { + private onDevicesUpdated = async (users: string[], initialFetch?: boolean): Promise => { if (!this.client) return; // If we didn't know about *any* devices before (ie. it's fresh login), // then they are all pre-existing devices, so ignore this and set the @@ -178,13 +176,6 @@ export default class DeviceListener { const myUserId = this.client.getSafeUserId(); if (users.includes(myUserId)) await this.ensureDeviceIdsAtStartPopulated(); - // No need to do a recheck here: we just need to get a snapshot of our devices - // before we download any new ones. - }; - - private onDevicesUpdated = (users: string[]): void => { - if (!this.client) return; - if (!users.includes(this.client.getSafeUserId())) return; this.recheck(); };