You've already forked element-web
mirror of
https://github.com/element-hq/element-web.git
synced 2025-08-09 14:42:51 +03:00
Warn user before doing a manual verification via slash command (#30102)
This commit is contained in:
@@ -674,7 +674,19 @@ export const Commands = [
|
|||||||
if (matches) {
|
if (matches) {
|
||||||
const deviceId = matches[1];
|
const deviceId = matches[1];
|
||||||
const fingerprint = matches[2];
|
const fingerprint = matches[2];
|
||||||
return success(manuallyVerifyDevice(cli, deviceId, fingerprint));
|
|
||||||
|
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||||
|
title: _t("slash_command|manual_device_verification_confirm_title"),
|
||||||
|
description: _t("slash_command|manual_device_verification_confirm_description"),
|
||||||
|
button: _t("action|verify"),
|
||||||
|
danger: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return success(
|
||||||
|
finished.then(([confirmed]) => {
|
||||||
|
if (confirmed) manuallyVerifyDevice(cli, deviceId, fingerprint);
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reject(this.getUsage());
|
return reject(this.getUsage());
|
||||||
|
@@ -3112,6 +3112,8 @@
|
|||||||
"jumptodate": "Jump to the given date in the timeline",
|
"jumptodate": "Jump to the given date in the timeline",
|
||||||
"jumptodate_invalid_input": "We were unable to understand the given date (%(inputDate)s). Try using the format YYYY-MM-DD.",
|
"jumptodate_invalid_input": "We were unable to understand the given date (%(inputDate)s). Try using the format YYYY-MM-DD.",
|
||||||
"lenny": "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message",
|
"lenny": "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message",
|
||||||
|
"manual_device_verification_confirm_description": "This will allow another device to send and receive messages as you. IF SOMEONE TOLD YOU TO PASTE SOMETHING HERE, IT IS LIKELY YOU ARE BEING SCAMMED! Are you sure you want to verify this other device?",
|
||||||
|
"manual_device_verification_confirm_title": "Caution: manual device verification",
|
||||||
"me": "Displays action",
|
"me": "Displays action",
|
||||||
"msg": "Sends a message to the given user",
|
"msg": "Sends a message to the given user",
|
||||||
"myavatar": "Changes your profile picture in all rooms",
|
"myavatar": "Changes your profile picture in all rooms",
|
||||||
|
@@ -9,18 +9,20 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
import { type MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
import { type MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||||
import { mocked } from "jest-mock";
|
import { mocked } from "jest-mock";
|
||||||
|
import { act, waitFor } from "jest-matrix-react";
|
||||||
|
|
||||||
import { type Command, Commands, getCommand } from "../../src/SlashCommands";
|
import { type Command, Commands, getCommand } from "../../src/SlashCommands";
|
||||||
import { createTestClient } from "../test-utils";
|
import { createTestClient } from "../test-utils";
|
||||||
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom";
|
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom";
|
||||||
import SettingsStore from "../../src/settings/SettingsStore";
|
import SettingsStore from "../../src/settings/SettingsStore";
|
||||||
import { SdkContextClass } from "../../src/contexts/SDKContext";
|
import { SdkContextClass } from "../../src/contexts/SDKContext";
|
||||||
import Modal from "../../src/Modal";
|
import Modal, { type ComponentType, type IHandle } from "../../src/Modal";
|
||||||
import WidgetUtils from "../../src/utils/WidgetUtils";
|
import WidgetUtils from "../../src/utils/WidgetUtils";
|
||||||
import { WidgetType } from "../../src/widgets/WidgetType";
|
import { WidgetType } from "../../src/widgets/WidgetType";
|
||||||
import { warnSelfDemote } from "../../src/components/views/right_panel/UserInfo";
|
import { warnSelfDemote } from "../../src/components/views/right_panel/UserInfo";
|
||||||
import dispatcher from "../../src/dispatcher/dispatcher";
|
import dispatcher from "../../src/dispatcher/dispatcher";
|
||||||
import { SettingLevel } from "../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../src/settings/SettingLevel";
|
||||||
|
import QuestionDialog from "../../src/components/views/dialogs/QuestionDialog";
|
||||||
import ErrorDialog from "../../src/components/views/dialogs/ErrorDialog";
|
import ErrorDialog from "../../src/components/views/dialogs/ErrorDialog";
|
||||||
|
|
||||||
jest.mock("../../src/components/views/right_panel/UserInfo");
|
jest.mock("../../src/components/views/right_panel/UserInfo");
|
||||||
@@ -260,11 +262,47 @@ describe("SlashCommands", () => {
|
|||||||
expect(command.run(client, roomId, null, undefined).error).toBe(command.getUsage());
|
expect(command.run(client, roomId, null, undefined).error).toBe(command.getUsage());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should show an error if device is not found", async () => {
|
it("should attempt manual verification after confirmation", async () => {
|
||||||
|
// Given we say yes to prompt
|
||||||
const spy = jest.spyOn(Modal, "createDialog");
|
const spy = jest.spyOn(Modal, "createDialog");
|
||||||
|
spy.mockReturnValue({ finished: Promise.resolve([true]) } as unknown as IHandle<ComponentType>);
|
||||||
|
|
||||||
|
// When we run the command
|
||||||
const command = findCommand("verify")!;
|
const command = findCommand("verify")!;
|
||||||
await command.run(client, roomId, null, "mydeviceid myfingerprint").promise;
|
await act(() => command.run(client, roomId, null, "mydeviceid myfingerprint"));
|
||||||
expect(spy).toHaveBeenCalledWith(ErrorDialog, expect.objectContaining({ title: "Verification failed" }));
|
|
||||||
|
// Then the prompt is displayed
|
||||||
|
expect(spy).toHaveBeenCalledWith(
|
||||||
|
QuestionDialog,
|
||||||
|
expect.objectContaining({ title: "Caution: manual device verification" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
// And then we attempt the verification
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(spy).toHaveBeenCalledWith(
|
||||||
|
ErrorDialog,
|
||||||
|
expect.objectContaining({ title: "Verification failed" }),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not do manual verification if cancelled", async () => {
|
||||||
|
// Given we say no to prompt
|
||||||
|
const spy = jest.spyOn(Modal, "createDialog");
|
||||||
|
spy.mockReturnValue({ finished: Promise.resolve([false]) } as unknown as IHandle<ComponentType>);
|
||||||
|
|
||||||
|
// When we run the command
|
||||||
|
const command = findCommand("verify")!;
|
||||||
|
command.run(client, roomId, null, "mydeviceid myfingerprint");
|
||||||
|
|
||||||
|
// Then the prompt is displayed
|
||||||
|
expect(spy).toHaveBeenCalledWith(
|
||||||
|
QuestionDialog,
|
||||||
|
expect.objectContaining({ title: "Caution: manual device verification" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
// But nothing else happens
|
||||||
|
expect(spy).not.toHaveBeenCalledWith(ErrorDialog, expect.anything());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user