VerificationPanel: avoid use of `getStoredDevice` (#11129)
* VerificationPanel: avoid use of `getStoredDevice` This is deprecated and doesn't work with the rust-sdk. * fix typespull/28217/head
parent
358c37ad69
commit
36c81f6416
|
@ -18,15 +18,15 @@ import React from "react";
|
||||||
import { verificationMethods } from "matrix-js-sdk/src/crypto";
|
import { verificationMethods } from "matrix-js-sdk/src/crypto";
|
||||||
import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
|
import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||||
import {
|
import {
|
||||||
VerificationRequest,
|
|
||||||
VerificationPhase as Phase,
|
VerificationPhase as Phase,
|
||||||
|
VerificationRequest,
|
||||||
VerificationRequestEvent,
|
VerificationRequestEvent,
|
||||||
} from "matrix-js-sdk/src/crypto-api";
|
} from "matrix-js-sdk/src/crypto-api";
|
||||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||||
import { User } from "matrix-js-sdk/src/models/user";
|
import { User } from "matrix-js-sdk/src/models/user";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
|
|
||||||
import { ShowQrCodeCallbacks, ShowSasCallbacks, VerifierEvent } from "matrix-js-sdk/src/crypto-api/verification";
|
import { ShowQrCodeCallbacks, ShowSasCallbacks, VerifierEvent } from "matrix-js-sdk/src/crypto-api/verification";
|
||||||
|
import { Device } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
|
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
|
||||||
|
@ -52,11 +52,21 @@ interface IState {
|
||||||
emojiButtonClicked?: boolean;
|
emojiButtonClicked?: boolean;
|
||||||
reciprocateButtonClicked?: boolean;
|
reciprocateButtonClicked?: boolean;
|
||||||
reciprocateQREvent: ShowQrCodeCallbacks | null;
|
reciprocateQREvent: ShowQrCodeCallbacks | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details of the other device involved in the transaction.
|
||||||
|
*
|
||||||
|
* `undefined` if there is not (yet) another device in the transaction, or if we do not know about it.
|
||||||
|
*/
|
||||||
|
otherDeviceDetails?: Device;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class VerificationPanel extends React.PureComponent<IProps, IState> {
|
export default class VerificationPanel extends React.PureComponent<IProps, IState> {
|
||||||
private hasVerifier: boolean;
|
private hasVerifier: boolean;
|
||||||
|
|
||||||
|
/** have we yet tried to check the other device's info */
|
||||||
|
private haveCheckedDevice = false;
|
||||||
|
|
||||||
public constructor(props: IProps) {
|
public constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { sasEvent: null, reciprocateQREvent: null };
|
this.state = { sasEvent: null, reciprocateQREvent: null };
|
||||||
|
@ -201,14 +211,25 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
|
||||||
this.state.reciprocateQREvent?.cancel();
|
this.state.reciprocateQREvent?.cancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
private getDevice(): DeviceInfo | null {
|
/**
|
||||||
|
* Get details of the other device involved in the verification, if we haven't before, and store in the state.
|
||||||
|
*/
|
||||||
|
private async maybeGetOtherDevice(): Promise<void> {
|
||||||
|
if (this.haveCheckedDevice) return;
|
||||||
|
|
||||||
|
const client = MatrixClientPeg.safeGet();
|
||||||
const deviceId = this.props.request?.otherDeviceId;
|
const deviceId = this.props.request?.otherDeviceId;
|
||||||
const userId = MatrixClientPeg.safeGet().getUserId();
|
const userId = client.getUserId();
|
||||||
if (deviceId && userId) {
|
if (!deviceId || !userId) {
|
||||||
return MatrixClientPeg.safeGet().getStoredDevice(userId, deviceId);
|
return;
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
this.haveCheckedDevice = true;
|
||||||
|
|
||||||
|
const deviceMap = await client.getCrypto()?.getUserDeviceInfo([userId]);
|
||||||
|
if (!deviceMap) return;
|
||||||
|
const userDevices = deviceMap.get(userId);
|
||||||
|
if (!userDevices) return;
|
||||||
|
this.setState({ otherDeviceDetails: userDevices.get(deviceId) });
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderQRReciprocatePhase(): JSX.Element {
|
private renderQRReciprocatePhase(): JSX.Element {
|
||||||
|
@ -272,7 +293,7 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
|
||||||
|
|
||||||
let description: string;
|
let description: string;
|
||||||
if (request.isSelfVerification) {
|
if (request.isSelfVerification) {
|
||||||
const device = this.getDevice();
|
const device = this.state.otherDeviceDetails;
|
||||||
if (!device) {
|
if (!device) {
|
||||||
// This can happen if the device is logged out while we're still showing verification
|
// This can happen if the device is logged out while we're still showing verification
|
||||||
// UI for it.
|
// UI for it.
|
||||||
|
@ -280,8 +301,8 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
|
||||||
description = _t("You've successfully verified your device!");
|
description = _t("You've successfully verified your device!");
|
||||||
} else {
|
} else {
|
||||||
description = _t("You've successfully verified %(deviceName)s (%(deviceId)s)!", {
|
description = _t("You've successfully verified %(deviceName)s (%(deviceId)s)!", {
|
||||||
deviceName: device ? device.getDisplayName() : "",
|
deviceName: device.displayName,
|
||||||
deviceId: this.props.request.otherDeviceId,
|
deviceId: device.deviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -356,7 +377,7 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
|
||||||
const emojis = this.state.sasEvent ? (
|
const emojis = this.state.sasEvent ? (
|
||||||
<VerificationShowSas
|
<VerificationShowSas
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
device={this.getDevice() ?? undefined}
|
otherDeviceDetails={this.state.otherDeviceDetails}
|
||||||
sas={this.state.sasEvent.sas}
|
sas={this.state.sasEvent.sas}
|
||||||
onCancel={this.onSasMismatchesClick}
|
onCancel={this.onSasMismatchesClick}
|
||||||
onDone={this.onSasMatchesClick}
|
onDone={this.onSasMatchesClick}
|
||||||
|
@ -410,6 +431,10 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
|
||||||
|
|
||||||
private onRequestChange = async (): Promise<void> => {
|
private onRequestChange = async (): Promise<void> => {
|
||||||
const { request } = this.props;
|
const { request } = this.props;
|
||||||
|
|
||||||
|
// if we have a device ID and did not have one before, fetch the device's details
|
||||||
|
this.maybeGetOtherDevice();
|
||||||
|
|
||||||
const hadVerifier = this.hasVerifier;
|
const hadVerifier = this.hasVerifier;
|
||||||
this.hasVerifier = !!request.verifier;
|
this.hasVerifier = !!request.verifier;
|
||||||
if (!hadVerifier && this.hasVerifier) {
|
if (!hadVerifier && this.hasVerifier) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { DeviceInfo } from "matrix-js-sdk/src//crypto/deviceinfo";
|
import { Device } from "matrix-js-sdk/src/matrix";
|
||||||
import { GeneratedSas } from "matrix-js-sdk/src/crypto-api/verification";
|
import { GeneratedSas } from "matrix-js-sdk/src/crypto-api/verification";
|
||||||
|
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
|
@ -26,7 +26,10 @@ import { fixupColorFonts } from "../../../utils/FontManager";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
pending?: boolean;
|
pending?: boolean;
|
||||||
displayName?: string; // required if pending is true
|
displayName?: string; // required if pending is true
|
||||||
device?: DeviceInfo;
|
|
||||||
|
/** Details of the other device involved in the verification, if known */
|
||||||
|
otherDeviceDetails?: Device;
|
||||||
|
|
||||||
onDone: () => void;
|
onDone: () => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
sas: GeneratedSas;
|
sas: GeneratedSas;
|
||||||
|
@ -111,10 +114,11 @@ export default class VerificationShowSas extends React.Component<IProps, IState>
|
||||||
let text;
|
let text;
|
||||||
// device shouldn't be null in this situation but it can be, eg. if the device is
|
// device shouldn't be null in this situation but it can be, eg. if the device is
|
||||||
// logged out during verification
|
// logged out during verification
|
||||||
if (this.props.device) {
|
const otherDevice = this.props.otherDeviceDetails;
|
||||||
|
if (otherDevice) {
|
||||||
text = _t("Waiting for you to verify on your other device, %(deviceName)s (%(deviceId)s)…", {
|
text = _t("Waiting for you to verify on your other device, %(deviceName)s (%(deviceId)s)…", {
|
||||||
deviceName: this.props.device ? this.props.device.getDisplayName() : "",
|
deviceName: otherDevice.displayName,
|
||||||
deviceId: this.props.device ? this.props.device.deviceId : "",
|
deviceId: otherDevice.deviceId,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
text = _t("Waiting for you to verify on your other device…");
|
text = _t("Waiting for you to verify on your other device…");
|
||||||
|
|
|
@ -18,24 +18,27 @@ import { act, render, waitFor } from "@testing-library/react";
|
||||||
import React, { ComponentProps } from "react";
|
import React, { ComponentProps } from "react";
|
||||||
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
|
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
|
||||||
import { User } from "matrix-js-sdk/src/models/user";
|
import { User } from "matrix-js-sdk/src/models/user";
|
||||||
import { Mocked } from "jest-mock";
|
import { mocked, Mocked } from "jest-mock";
|
||||||
import {
|
import {
|
||||||
EmojiMapping,
|
EmojiMapping,
|
||||||
ShowSasCallbacks,
|
ShowSasCallbacks,
|
||||||
Verifier,
|
|
||||||
VerifierEvent,
|
|
||||||
VerifierEventHandlerMap,
|
|
||||||
VerificationPhase as Phase,
|
VerificationPhase as Phase,
|
||||||
VerificationRequest,
|
VerificationRequest,
|
||||||
VerificationRequestEvent,
|
VerificationRequestEvent,
|
||||||
|
Verifier,
|
||||||
|
VerifierEvent,
|
||||||
|
VerifierEventHandlerMap,
|
||||||
} from "matrix-js-sdk/src/crypto-api/verification";
|
} from "matrix-js-sdk/src/crypto-api/verification";
|
||||||
|
import { Device, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import VerificationPanel from "../../../../src/components/views/right_panel/VerificationPanel";
|
import VerificationPanel from "../../../../src/components/views/right_panel/VerificationPanel";
|
||||||
import { stubClient } from "../../../test-utils";
|
import { flushPromises, stubClient } from "../../../test-utils";
|
||||||
|
|
||||||
describe("<VerificationPanel />", () => {
|
describe("<VerificationPanel />", () => {
|
||||||
|
let client: MatrixClient;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stubClient();
|
client = stubClient();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("'Ready' phase (dialog mode)", () => {
|
describe("'Ready' phase (dialog mode)", () => {
|
||||||
|
@ -130,6 +133,51 @@ describe("<VerificationPanel />", () => {
|
||||||
expect(emoji).toHaveTextContent("🦄Unicorn");
|
expect(emoji).toHaveTextContent("🦄Unicorn");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("'Verify own device' flow", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
Object.defineProperty(mockRequest, "isSelfVerification", { get: () => true });
|
||||||
|
Object.defineProperty(mockRequest, "otherDeviceId", { get: () => "other_device" });
|
||||||
|
|
||||||
|
const otherDeviceDetails = new Device({
|
||||||
|
algorithms: [],
|
||||||
|
deviceId: "other_device",
|
||||||
|
keys: new Map(),
|
||||||
|
userId: "",
|
||||||
|
displayName: "my other device",
|
||||||
|
});
|
||||||
|
|
||||||
|
mocked(client.getCrypto()!).getUserDeviceInfo.mockResolvedValue(
|
||||||
|
new Map([[client.getSafeUserId(), new Map([["other_device", otherDeviceDetails]])]]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show 'Waiting for you to verify' after confirming", async () => {
|
||||||
|
const rendered = renderComponent({
|
||||||
|
request: mockRequest,
|
||||||
|
phase: Phase.Started,
|
||||||
|
});
|
||||||
|
|
||||||
|
// wait for the device to be looked up
|
||||||
|
await act(() => flushPromises());
|
||||||
|
|
||||||
|
// fire the ShowSas event
|
||||||
|
const sasEvent = makeMockSasCallbacks();
|
||||||
|
mockVerifier.getShowSasCallbacks.mockReturnValue(sasEvent);
|
||||||
|
act(() => {
|
||||||
|
mockVerifier.emit(VerifierEvent.ShowSas, sasEvent);
|
||||||
|
});
|
||||||
|
|
||||||
|
// confirm
|
||||||
|
act(() => {
|
||||||
|
rendered.getByRole("button", { name: "They match" }).click();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(rendered.container).toHaveTextContent(
|
||||||
|
"Waiting for you to verify on your other device, my other device (other_device)…",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue