Remove usage of deprecated CryptoEvents (#126)

* Remove usage of `CryptoEvent.DeviceVerificationChanged`

* Remove usage of `CryptoEvent.KeySignatureUploadFailure`

* Remove usage of `CryptoEvent.Warning`

* Merge `CryptoEvent.DevicesUpdated` and `CryptoEvent.WillUpdateDevices` behaviour
This commit is contained in:
Florian Duros 2024-10-08 10:13:44 +02:00 committed by GitHub
parent a0cb9470cc
commit 31bd10e887
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 1 additions and 196 deletions

View file

@ -85,9 +85,7 @@ export default class DeviceListener {
public start(matrixClient: MatrixClient): void { public start(matrixClient: MatrixClient): void {
this.running = true; this.running = true;
this.client = matrixClient; this.client = matrixClient;
this.client.on(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices);
this.client.on(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); 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.UserTrustStatusChanged, this.onUserTrustStatusChanged);
this.client.on(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); this.client.on(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged);
this.client.on(ClientEvent.AccountData, this.onAccountData); this.client.on(ClientEvent.AccountData, this.onAccountData);
@ -109,9 +107,7 @@ export default class DeviceListener {
public stop(): void { public stop(): void {
this.running = false; this.running = false;
if (this.client) { if (this.client) {
this.client.removeListener(CryptoEvent.WillUpdateDevices, this.onWillUpdateDevices);
this.client.removeListener(CryptoEvent.DevicesUpdated, this.onDevicesUpdated); 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.UserTrustStatusChanged, this.onUserTrustStatusChanged);
this.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged); this.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSingingKeysChanged);
this.client.removeListener(ClientEvent.AccountData, this.onAccountData); this.client.removeListener(ClientEvent.AccountData, this.onAccountData);
@ -170,7 +166,7 @@ export default class DeviceListener {
return await getUserDeviceIds(cli, cli.getSafeUserId()); return await getUserDeviceIds(cli, cli.getSafeUserId());
} }
private onWillUpdateDevices = async (users: string[], initialFetch?: boolean): Promise<void> => { private onDevicesUpdated = async (users: string[], initialFetch?: boolean): Promise<void> => {
if (!this.client) return; if (!this.client) return;
// If we didn't know about *any* devices before (ie. it's fresh login), // 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 // then they are all pre-existing devices, so ignore this and set the
@ -180,19 +176,6 @@ export default class DeviceListener {
const myUserId = this.client.getSafeUserId(); const myUserId = this.client.getSafeUserId();
if (users.includes(myUserId)) await this.ensureDeviceIdsAtStartPopulated(); 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();
};
private onDeviceVerificationChanged = (userId: string): void => {
if (!this.client) return;
if (userId !== this.client.getUserId()) return;
this.recheck(); this.recheck();
}; };

View file

@ -82,7 +82,6 @@ import Spinner from "../views/elements/Spinner";
import QuestionDialog from "../views/dialogs/QuestionDialog"; import QuestionDialog from "../views/dialogs/QuestionDialog";
import UserSettingsDialog from "../views/dialogs/UserSettingsDialog"; import UserSettingsDialog from "../views/dialogs/UserSettingsDialog";
import CreateRoomDialog from "../views/dialogs/CreateRoomDialog"; import CreateRoomDialog from "../views/dialogs/CreateRoomDialog";
import KeySignatureUploadFailedDialog from "../views/dialogs/KeySignatureUploadFailedDialog";
import IncomingSasDialog from "../views/dialogs/IncomingSasDialog"; import IncomingSasDialog from "../views/dialogs/IncomingSasDialog";
import CompleteSecurity from "./auth/CompleteSecurity"; import CompleteSecurity from "./auth/CompleteSecurity";
import Welcome from "../views/auth/Welcome"; import Welcome from "../views/auth/Welcome";
@ -1629,18 +1628,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
room.setBlacklistUnverifiedDevices(blacklistEnabled); 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<void> => { cli.on(CryptoEvent.KeyBackupFailed, async (errcode): Promise<void> => {
let haveNewVersion: boolean | undefined; let haveNewVersion: boolean | undefined;
let newVersionInfo: KeyBackupInfo | null = null; let newVersionInfo: KeyBackupInfo | null = null;
@ -1674,10 +1661,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
}); });
cli.on(CryptoEvent.KeySignatureUploadFailure, (failures, source, continuation) => {
Modal.createDialog(KeySignatureUploadFailedDialog, { failures, source, continuation });
});
cli.on(CryptoEvent.VerificationRequestReceived, (request) => { cli.on(CryptoEvent.VerificationRequestReceived, (request) => {
if (request.verifier) { if (request.verifier) {
Modal.createDialog( Modal.createDialog(

View file

@ -428,7 +428,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
context.client.on(RoomStateEvent.Update, this.onRoomStateUpdate); context.client.on(RoomStateEvent.Update, this.onRoomStateUpdate);
context.client.on(RoomEvent.MyMembership, this.onMyMembership); context.client.on(RoomEvent.MyMembership, this.onMyMembership);
context.client.on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus); 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.UserTrustStatusChanged, this.onUserVerificationChanged);
context.client.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged); context.client.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted); context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
@ -974,7 +973,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.context.client.removeListener(RoomEvent.MyMembership, this.onMyMembership); this.context.client.removeListener(RoomEvent.MyMembership, this.onMyMembership);
this.context.client.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate); this.context.client.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
this.context.client.removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus); 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.UserTrustStatusChanged, this.onUserVerificationChanged);
this.context.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged); this.context.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
this.context.client.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted); this.context.client.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted);
@ -1438,14 +1436,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
); );
}; };
private onDeviceVerificationChanged = (userId: string): void => {
const room = this.state.room;
if (!room?.currentState.getMember(userId)) {
return;
}
this.updateE2EStatus(room);
};
private onUserVerificationChanged = (userId: string): void => { private onUserVerificationChanged = (userId: string): void => {
const room = this.state.room; const room = this.state.room;
if (!room || !room.currentState.getMember(userId)) { if (!room || !room.currentState.getMember(userId)) {

View file

@ -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<void>;
onFinished(): void;
}
const KeySignatureUploadFailedDialog: React.FC<IProps> = ({ 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<void> => {
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 = (
<div>
<p>{_t("encryption|key_signature_upload_failed_body", { brand })}</p>
<p>{reason}</p>
{retrying && <Spinner />}
<pre>{JSON.stringify(failures, null, 2)}</pre>
<DialogButtons
primaryButton="Retry"
hasCancel={true}
onPrimaryButtonClick={onRetry}
onCancel={onCancel.current}
primaryDisabled={retrying}
/>
</div>
);
} 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 = (
<div>
<span>{text}</span>
<DialogButtons primaryButton={_t("action|ok")} hasCancel={false} onPrimaryButtonClick={onFinished} />
</div>
);
}
return (
<BaseDialog
title={
success
? _t("encryption|key_signature_upload_success_title")
: _t("encryption|key_signature_upload_failed_title")
}
fixedWidth={false}
onFinished={() => {}}
>
{body}
</BaseDialog>
);
};
export default KeySignatureUploadFailedDialog;

View file

@ -1381,22 +1381,16 @@ export const useDevices = (userId: string): IDevice[] | undefined | null => {
if (!users.includes(userId)) return; if (!users.includes(userId)) return;
updateDevices(); updateDevices();
}; };
const onDeviceVerificationChanged = (_userId: string, deviceId: string): void => {
if (_userId !== userId) return;
updateDevices();
};
const onUserTrustStatusChanged = (_userId: string, trustLevel: UserVerificationStatus): void => { const onUserTrustStatusChanged = (_userId: string, trustLevel: UserVerificationStatus): void => {
if (_userId !== userId) return; if (_userId !== userId) return;
updateDevices(); updateDevices();
}; };
cli.on(CryptoEvent.DevicesUpdated, onDevicesUpdated); cli.on(CryptoEvent.DevicesUpdated, onDevicesUpdated);
cli.on(CryptoEvent.DeviceVerificationChanged, onDeviceVerificationChanged);
cli.on(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged); cli.on(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged);
// Handle being unmounted // Handle being unmounted
return () => { return () => {
cancel = true; cancel = true;
cli.removeListener(CryptoEvent.DevicesUpdated, onDevicesUpdated); cli.removeListener(CryptoEvent.DevicesUpdated, onDevicesUpdated);
cli.removeListener(CryptoEvent.DeviceVerificationChanged, onDeviceVerificationChanged);
cli.removeListener(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged); cli.removeListener(CryptoEvent.UserTrustStatusChanged, onUserTrustStatusChanged);
}; };
}, [cli, userId]); }, [cli, userId]);

View file

@ -385,7 +385,6 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
this.suppressReadReceiptAnimation = false; this.suppressReadReceiptAnimation = false;
const client = MatrixClientPeg.safeGet(); const client = MatrixClientPeg.safeGet();
if (!this.props.forExport) { if (!this.props.forExport) {
client.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
client.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); client.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
this.props.mxEvent.on(MatrixEventEvent.Decrypted, this.onDecrypted); this.props.mxEvent.on(MatrixEventEvent.Decrypted, this.onDecrypted);
this.props.mxEvent.on(MatrixEventEvent.Replaced, this.onReplaced); this.props.mxEvent.on(MatrixEventEvent.Replaced, this.onReplaced);
@ -425,7 +424,6 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
public componentWillUnmount(): void { public componentWillUnmount(): void {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
if (client) { if (client) {
client.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged); client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
client.removeListener(RoomEvent.Receipt, this.onRoomReceipt); client.removeListener(RoomEvent.Receipt, this.onRoomReceipt);
const room = client.getRoom(this.props.mxEvent.getRoomId()); const room = client.getRoom(this.props.mxEvent.getRoomId());
@ -564,12 +562,6 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
this.forceUpdate(this.props.onHeightChanged); 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 => { private onUserVerificationChanged = (userId: string, _trustStatus: UserVerificationStatus): void => {
if (userId === this.props.mxEvent.getSender()) { if (userId === this.props.mxEvent.getSender()) {
this.verifyEvent(); this.verifyEvent();

View file

@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import React from "react"; import React from "react";
import { RoomMember, RoomStateEvent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; 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 { CryptoEvent } from "matrix-js-sdk/src/crypto";
import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
@ -62,7 +61,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
}); });
if (isRoomEncrypted) { if (isRoomEncrypted) {
cli.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); cli.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged);
cli.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
this.updateE2EStatus(); this.updateE2EStatus();
} else { } else {
// Listen for room to become encrypted // Listen for room to become encrypted
@ -77,7 +75,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
if (cli) { if (cli) {
cli.removeListener(RoomStateEvent.Events, this.onRoomStateEvents); cli.removeListener(RoomStateEvent.Events, this.onRoomStateEvents);
cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged);
cli.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
} }
} }
@ -100,11 +97,6 @@ export default class MemberTile extends React.Component<IProps, IState> {
this.updateE2EStatus(); this.updateE2EStatus();
}; };
private onDeviceVerificationChanged = (userId: string, deviceId: string, deviceInfo: DeviceInfo): void => {
if (userId !== this.props.member.userId) return;
this.updateE2EStatus();
};
private async updateE2EStatus(): Promise<void> { private async updateE2EStatus(): Promise<void> {
const cli = MatrixClientPeg.safeGet(); const cli = MatrixClientPeg.safeGet();
const { userId } = this.props.member; const { userId } = this.props.member;

View file

@ -904,16 +904,6 @@
"incompatible_database_disable": "Continue With Encryption Disabled", "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_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", "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": { "messages_not_secure": {
"cause_1": "Your homeserver", "cause_1": "Your homeserver",
"cause_2": "The homeserver the user you're verifying is connected to", "cause_2": "The homeserver the user you're verifying is connected to",
@ -929,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." "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": "<not supported>", "not_supported": "<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": { "recovery_method_removed": {
"description_1": "This session has detected that your Security Phrase and key for Secure Messages have been 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.", "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.",