Remove automatic rageshakes on UTD labs feature (#32778)
* Remove automatic rageshakes on UTD feature * remove unused setting name * Remove unused lab group * Reduce count by 1
This commit is contained in:
@@ -18,7 +18,6 @@
|
|||||||
"https://scalar-staging.vector.im/api"
|
"https://scalar-staging.vector.im/api"
|
||||||
],
|
],
|
||||||
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
|
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
|
||||||
"uisi_autorageshake_app": "element-auto-uisi",
|
|
||||||
"show_labs_settings": false,
|
"show_labs_settings": false,
|
||||||
"room_directory": {
|
"room_directory": {
|
||||||
"servers": ["matrix.org", "gitter.im"]
|
"servers": ["matrix.org", "gitter.im"]
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
"https://scalar-staging.vector.im/api"
|
"https://scalar-staging.vector.im/api"
|
||||||
],
|
],
|
||||||
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
|
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
|
||||||
"uisi_autorageshake_app": "element-auto-uisi",
|
|
||||||
"show_labs_settings": true,
|
"show_labs_settings": true,
|
||||||
"room_directory": {
|
"room_directory": {
|
||||||
"servers": ["matrix.org", "gitter.im"]
|
"servers": ["matrix.org", "gitter.im"]
|
||||||
|
|||||||
Vendored
-2
@@ -39,7 +39,6 @@ import { type SetupEncryptionStore } from "../stores/SetupEncryptionStore";
|
|||||||
import { type RoomScrollStateStore } from "../stores/RoomScrollStateStore";
|
import { type RoomScrollStateStore } from "../stores/RoomScrollStateStore";
|
||||||
import { type ConsoleLogger, type IndexedDBLogStore } from "../rageshake/rageshake";
|
import { type ConsoleLogger, type IndexedDBLogStore } from "../rageshake/rageshake";
|
||||||
import type ActiveWidgetStore from "../stores/ActiveWidgetStore";
|
import type ActiveWidgetStore from "../stores/ActiveWidgetStore";
|
||||||
import type AutoRageshakeStore from "../stores/AutoRageshakeStore";
|
|
||||||
import { type IConfigOptions } from "../IConfigOptions";
|
import { type IConfigOptions } from "../IConfigOptions";
|
||||||
import { type MatrixDispatcher } from "../dispatcher/dispatcher";
|
import { type MatrixDispatcher } from "../dispatcher/dispatcher";
|
||||||
import { type DeepReadonly } from "./common";
|
import { type DeepReadonly } from "./common";
|
||||||
@@ -85,7 +84,6 @@ declare global {
|
|||||||
matrixChat?: MatrixChat;
|
matrixChat?: MatrixChat;
|
||||||
mxSendSentryReport: (userText: string, issueUrl: string, error: Error) => Promise<void>;
|
mxSendSentryReport: (userText: string, issueUrl: string, error: Error) => Promise<void>;
|
||||||
mxLoginWithAccessToken: (hsUrl: string, accessToken: string) => Promise<void>;
|
mxLoginWithAccessToken: (hsUrl: string, accessToken: string) => Promise<void>;
|
||||||
mxAutoRageshakeStore?: AutoRageshakeStore;
|
|
||||||
mxDispatcher: MatrixDispatcher;
|
mxDispatcher: MatrixDispatcher;
|
||||||
mxMatrixClientPeg: IMatrixClientPeg;
|
mxMatrixClientPeg: IMatrixClientPeg;
|
||||||
mxReactSdkConfig: DeepReadonly<IConfigOptions>;
|
mxReactSdkConfig: DeepReadonly<IConfigOptions>;
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ export interface IConfigOptions {
|
|||||||
* Bug report endpoint URL. "local" means the logs should not be uploaded.
|
* Bug report endpoint URL. "local" means the logs should not be uploaded.
|
||||||
*/
|
*/
|
||||||
bug_report_endpoint_url?: typeof BugReportEndpointURLLocal | string; // omission disables bug reporting
|
bug_report_endpoint_url?: typeof BugReportEndpointURLLocal | string; // omission disables bug reporting
|
||||||
uisi_autorageshake_app?: string; // defaults to "element-auto-uisi"
|
|
||||||
sentry?: {
|
sentry?: {
|
||||||
dsn: string;
|
dsn: string;
|
||||||
environment?: string; // "production", etc
|
environment?: string; // "production", etc
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export const DEFAULTS: DeepReadonly<IConfigOptions> = {
|
|||||||
help_key_storage_url: "https://element.io/help#encryption5",
|
help_key_storage_url: "https://element.io/help#encryption5",
|
||||||
integrations_ui_url: "https://scalar.vector.im/",
|
integrations_ui_url: "https://scalar.vector.im/",
|
||||||
integrations_rest_url: "https://scalar.vector.im/api",
|
integrations_rest_url: "https://scalar.vector.im/api",
|
||||||
uisi_autorageshake_app: "element-auto-uisi",
|
|
||||||
show_labs_settings: false,
|
show_labs_settings: false,
|
||||||
force_verification: false,
|
force_verification: false,
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import * as Rooms from "../../Rooms";
|
|||||||
import * as Lifecycle from "../../Lifecycle";
|
import * as Lifecycle from "../../Lifecycle";
|
||||||
// LifecycleStore is not used but does listen to and dispatch actions
|
// LifecycleStore is not used but does listen to and dispatch actions
|
||||||
import "../../stores/LifecycleStore";
|
import "../../stores/LifecycleStore";
|
||||||
import "../../stores/AutoRageshakeStore";
|
|
||||||
import PageType from "../../PageTypes";
|
import PageType from "../../PageTypes";
|
||||||
import createRoom, { type IOpts } from "../../createRoom";
|
import createRoom, { type IOpts } from "../../createRoom";
|
||||||
import { _t, _td } from "../../languageHandler";
|
import { _t, _td } from "../../languageHandler";
|
||||||
|
|||||||
@@ -75,16 +75,6 @@ export default class LabsUserSettingsTab extends React.Component<EmptyObject> {
|
|||||||
.getOrCreate(LabGroup.Experimental, [])
|
.getOrCreate(LabGroup.Experimental, [])
|
||||||
.push(<SettingsFlag key="lowBandwidth" name="lowBandwidth" level={SettingLevel.DEVICE} />);
|
.push(<SettingsFlag key="lowBandwidth" name="lowBandwidth" level={SettingLevel.DEVICE} />);
|
||||||
|
|
||||||
groups
|
|
||||||
.getOrCreate(LabGroup.Analytics, [])
|
|
||||||
.push(
|
|
||||||
<SettingsFlag
|
|
||||||
key="automaticDecryptionErrorReporting"
|
|
||||||
name="automaticDecryptionErrorReporting"
|
|
||||||
level={SettingLevel.DEVICE}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
labsSections = (
|
labsSections = (
|
||||||
<>
|
<>
|
||||||
{sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
|
{sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
|
||||||
|
|||||||
@@ -1495,7 +1495,6 @@
|
|||||||
},
|
},
|
||||||
"labs": {
|
"labs": {
|
||||||
"ask_to_join": "Enable ask to join",
|
"ask_to_join": "Enable ask to join",
|
||||||
"automatic_debug_logs_decryption": "Automatically send debug logs on decryption errors",
|
|
||||||
"beta_description": "What's next for %(brand)s? Labs are the best way to get things early, test out new features and help shape them before they actually launch.",
|
"beta_description": "What's next for %(brand)s? Labs are the best way to get things early, test out new features and help shape them before they actually launch.",
|
||||||
"beta_feature": "This is a beta feature",
|
"beta_feature": "This is a beta feature",
|
||||||
"beta_feedback_leave_button": "To leave the beta, visit your settings.",
|
"beta_feedback_leave_button": "To leave the beta, visit your settings.",
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ export enum LabGroup {
|
|||||||
Threads,
|
Threads,
|
||||||
VoiceAndVideo,
|
VoiceAndVideo,
|
||||||
Moderation,
|
Moderation,
|
||||||
Analytics,
|
|
||||||
Themes,
|
Themes,
|
||||||
Encryption,
|
Encryption,
|
||||||
Experimental,
|
Experimental,
|
||||||
@@ -110,7 +109,6 @@ export const labGroupNames: Record<LabGroup, TranslationKey> = {
|
|||||||
[LabGroup.Threads]: _td("labs|group_threads"),
|
[LabGroup.Threads]: _td("labs|group_threads"),
|
||||||
[LabGroup.VoiceAndVideo]: _td("labs|group_voip"),
|
[LabGroup.VoiceAndVideo]: _td("labs|group_voip"),
|
||||||
[LabGroup.Moderation]: _td("labs|group_moderation"),
|
[LabGroup.Moderation]: _td("labs|group_moderation"),
|
||||||
[LabGroup.Analytics]: _td("common|analytics"),
|
|
||||||
[LabGroup.Themes]: _td("labs|group_themes"),
|
[LabGroup.Themes]: _td("labs|group_themes"),
|
||||||
[LabGroup.Encryption]: _td("labs|group_encryption"),
|
[LabGroup.Encryption]: _td("labs|group_encryption"),
|
||||||
[LabGroup.Experimental]: _td("labs|group_experimental"),
|
[LabGroup.Experimental]: _td("labs|group_experimental"),
|
||||||
@@ -348,7 +346,6 @@ export interface Settings {
|
|||||||
"Spaces.enabledMetaSpaces": IBaseSetting<Partial<Record<MetaSpace, boolean>>>;
|
"Spaces.enabledMetaSpaces": IBaseSetting<Partial<Record<MetaSpace, boolean>>>;
|
||||||
"Spaces.showPeopleInSpace": IBaseSetting<boolean>;
|
"Spaces.showPeopleInSpace": IBaseSetting<boolean>;
|
||||||
"developerMode": IBaseSetting<boolean>;
|
"developerMode": IBaseSetting<boolean>;
|
||||||
"automaticDecryptionErrorReporting": IBaseSetting<boolean>;
|
|
||||||
"debug_scroll_panel": IBaseSetting<boolean>;
|
"debug_scroll_panel": IBaseSetting<boolean>;
|
||||||
"debug_timeline_panel": IBaseSetting<boolean>;
|
"debug_timeline_panel": IBaseSetting<boolean>;
|
||||||
"debug_registration": IBaseSetting<boolean>;
|
"debug_registration": IBaseSetting<boolean>;
|
||||||
@@ -1307,12 +1304,6 @@ export const SETTINGS: Settings = {
|
|||||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"automaticDecryptionErrorReporting": {
|
|
||||||
displayName: _td("labs|automatic_debug_logs_decryption"),
|
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
|
||||||
default: false,
|
|
||||||
controller: new ReloadOnChangeController(),
|
|
||||||
},
|
|
||||||
"debug_scroll_panel": {
|
"debug_scroll_panel": {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||||
default: false,
|
default: false,
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
ClientEvent,
|
|
||||||
type MatrixEvent,
|
|
||||||
MatrixEventEvent,
|
|
||||||
type SyncStateData,
|
|
||||||
type SyncState,
|
|
||||||
ToDeviceMessageId,
|
|
||||||
} from "matrix-js-sdk/src/matrix";
|
|
||||||
import { sleep } from "matrix-js-sdk/src/utils";
|
|
||||||
import { v4 as uuidv4 } from "uuid";
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
|
||||||
|
|
||||||
import SdkConfig from "../SdkConfig";
|
|
||||||
import sendBugReport from "../rageshake/submit-rageshake";
|
|
||||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
|
||||||
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
|
||||||
import { type ActionPayload } from "../dispatcher/payloads";
|
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
|
||||||
|
|
||||||
// Minimum interval of 1 minute between reports
|
|
||||||
const RAGESHAKE_INTERVAL = 60000;
|
|
||||||
// Before rageshaking, wait 5 seconds and see if the message has successfully decrypted
|
|
||||||
const GRACE_PERIOD = 5000;
|
|
||||||
// Event type for to-device messages requesting sender auto-rageshakes
|
|
||||||
const AUTO_RS_REQUEST = "im.vector.auto_rs_request";
|
|
||||||
|
|
||||||
interface IState {
|
|
||||||
reportedSessionIds: Set<string>;
|
|
||||||
lastRageshakeTime: number;
|
|
||||||
initialSyncCompleted: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watches for decryption errors to auto-report if the relevant lab is
|
|
||||||
* enabled, and keeps track of session IDs that have already been
|
|
||||||
* reported.
|
|
||||||
*/
|
|
||||||
export default class AutoRageshakeStore extends AsyncStoreWithClient<IState> {
|
|
||||||
private static readonly internalInstance = (() => {
|
|
||||||
const instance = new AutoRageshakeStore();
|
|
||||||
instance.start();
|
|
||||||
return instance;
|
|
||||||
})();
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
super(defaultDispatcher, {
|
|
||||||
reportedSessionIds: new Set<string>(),
|
|
||||||
lastRageshakeTime: 0,
|
|
||||||
initialSyncCompleted: false,
|
|
||||||
});
|
|
||||||
this.onDecryptionAttempt = this.onDecryptionAttempt.bind(this);
|
|
||||||
this.onDeviceMessage = this.onDeviceMessage.bind(this);
|
|
||||||
this.onSyncStateChange = this.onSyncStateChange.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static get instance(): AutoRageshakeStore {
|
|
||||||
return AutoRageshakeStore.internalInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async onAction(_payload: ActionPayload): Promise<void> {}
|
|
||||||
|
|
||||||
protected async onReady(): Promise<void> {
|
|
||||||
if (!SettingsStore.getValue("automaticDecryptionErrorReporting")) return;
|
|
||||||
|
|
||||||
if (this.matrixClient) {
|
|
||||||
this.matrixClient.on(MatrixEventEvent.Decrypted, this.onDecryptionAttempt);
|
|
||||||
this.matrixClient.on(ClientEvent.ToDeviceEvent, this.onDeviceMessage);
|
|
||||||
this.matrixClient.on(ClientEvent.Sync, this.onSyncStateChange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async onNotReady(): Promise<void> {
|
|
||||||
if (this.matrixClient) {
|
|
||||||
this.matrixClient.removeListener(ClientEvent.ToDeviceEvent, this.onDeviceMessage);
|
|
||||||
this.matrixClient.removeListener(MatrixEventEvent.Decrypted, this.onDecryptionAttempt);
|
|
||||||
this.matrixClient.removeListener(ClientEvent.Sync, this.onSyncStateChange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onDecryptionAttempt = async (ev: MatrixEvent): Promise<void> => {
|
|
||||||
if (!this.state.initialSyncCompleted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wireContent = ev.getWireContent();
|
|
||||||
const sessionId = wireContent.session_id;
|
|
||||||
if (ev.isDecryptionFailure() && !this.state.reportedSessionIds.has(sessionId)) {
|
|
||||||
await sleep(GRACE_PERIOD);
|
|
||||||
if (!ev.isDecryptionFailure()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newReportedSessionIds = new Set(this.state.reportedSessionIds);
|
|
||||||
await this.updateState({ reportedSessionIds: newReportedSessionIds.add(sessionId) });
|
|
||||||
|
|
||||||
const now = new Date().getTime();
|
|
||||||
if (now - this.state.lastRageshakeTime < RAGESHAKE_INTERVAL) {
|
|
||||||
logger.info(
|
|
||||||
`Not sending recipient-side autorageshake for event ${ev.getId()}/session ${sessionId}: last rageshake was too recent`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.updateState({ lastRageshakeTime: now });
|
|
||||||
|
|
||||||
const senderUserId = ev.getSender()!;
|
|
||||||
const eventInfo = {
|
|
||||||
event_id: ev.getId(),
|
|
||||||
room_id: ev.getRoomId(),
|
|
||||||
session_id: sessionId,
|
|
||||||
device_id: wireContent.device_id,
|
|
||||||
user_id: senderUserId,
|
|
||||||
sender_key: wireContent.sender_key,
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info(`Sending recipient-side autorageshake for event ${ev.getId()}/session ${sessionId}`);
|
|
||||||
// XXX: the rageshake server returns the URL for the github issue... which is typically absent for
|
|
||||||
// auto-uisis, because we've disabled creation of GH issues for them. So the `recipient_rageshake`
|
|
||||||
// field is broken.
|
|
||||||
const rageshakeURL = await sendBugReport(SdkConfig.get().bug_report_endpoint_url, {
|
|
||||||
userText: "Auto-reporting decryption error (recipient)",
|
|
||||||
sendLogs: true,
|
|
||||||
labels: ["Z-UISI", "web", "uisi-recipient"],
|
|
||||||
customApp: SdkConfig.get().uisi_autorageshake_app,
|
|
||||||
customFields: { auto_uisi: JSON.stringify(eventInfo) },
|
|
||||||
});
|
|
||||||
|
|
||||||
const messageContent = {
|
|
||||||
...eventInfo,
|
|
||||||
recipient_rageshake: rageshakeURL,
|
|
||||||
[ToDeviceMessageId]: uuidv4(),
|
|
||||||
};
|
|
||||||
this.matrixClient?.sendToDevice(
|
|
||||||
AUTO_RS_REQUEST,
|
|
||||||
new Map([[senderUserId, new Map([[messageContent.device_id, messageContent]])]]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private onSyncStateChange = async (
|
|
||||||
_state: SyncState,
|
|
||||||
_prevState: SyncState | null,
|
|
||||||
data?: SyncStateData,
|
|
||||||
): Promise<void> => {
|
|
||||||
if (!this.state.initialSyncCompleted) {
|
|
||||||
await this.updateState({ initialSyncCompleted: !!data?.nextSyncToken });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private onDeviceMessage = async (ev: MatrixEvent): Promise<void> => {
|
|
||||||
if (ev.getType() !== AUTO_RS_REQUEST) return;
|
|
||||||
const messageContent = ev.getContent();
|
|
||||||
const recipientRageshake = messageContent["recipient_rageshake"] || "";
|
|
||||||
const now = new Date().getTime();
|
|
||||||
if (now - this.state.lastRageshakeTime > RAGESHAKE_INTERVAL) {
|
|
||||||
await this.updateState({ lastRageshakeTime: now });
|
|
||||||
logger.info(
|
|
||||||
`Sending sender-side autorageshake for event ${messageContent["event_id"]}/session ${messageContent["session_id"]}`,
|
|
||||||
);
|
|
||||||
await sendBugReport(SdkConfig.get().bug_report_endpoint_url, {
|
|
||||||
userText: `Auto-reporting decryption error (sender)\nRecipient rageshake: ${recipientRageshake}`,
|
|
||||||
sendLogs: true,
|
|
||||||
labels: ["Z-UISI", "web", "uisi-sender"],
|
|
||||||
customApp: SdkConfig.get().uisi_autorageshake_app,
|
|
||||||
customFields: {
|
|
||||||
recipient_rageshake: recipientRageshake,
|
|
||||||
auto_uisi: JSON.stringify(messageContent),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
logger.info(
|
|
||||||
`Not sending sender-side autorageshake for event ${messageContent["event_id"]}/session ${messageContent["session_id"]}: last rageshake was too recent`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
window.mxAutoRageshakeStore = AutoRageshakeStore.instance;
|
|
||||||
+1
-1
@@ -48,6 +48,6 @@ describe("<LabsUserSettingsTab />", () => {
|
|||||||
// non-beta labs section
|
// non-beta labs section
|
||||||
expect(screen.getByText("Early previews")).toBeInTheDocument();
|
expect(screen.getByText("Early previews")).toBeInTheDocument();
|
||||||
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
|
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
|
||||||
expect(labsSections).toHaveLength(10);
|
expect(labsSections).toHaveLength(9);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { mocked } from "jest-mock";
|
|
||||||
import {
|
|
||||||
ClientEvent,
|
|
||||||
EventType,
|
|
||||||
type MatrixClient,
|
|
||||||
type MatrixEvent,
|
|
||||||
MatrixEventEvent,
|
|
||||||
SyncState,
|
|
||||||
} from "matrix-js-sdk/src/matrix";
|
|
||||||
|
|
||||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
|
||||||
import AutoRageshakeStore from "../../../src/stores/AutoRageshakeStore";
|
|
||||||
import { mkEvent, stubClient } from "../../test-utils";
|
|
||||||
|
|
||||||
jest.mock("../../../src/rageshake/submit-rageshake");
|
|
||||||
jest.mock("../../../src/stores/WidgetStore");
|
|
||||||
jest.mock("../../../src/stores/widgets/WidgetLayoutStore");
|
|
||||||
|
|
||||||
const TEST_SENDER = "@sender@example.com";
|
|
||||||
|
|
||||||
describe("AutoRageshakeStore", () => {
|
|
||||||
const roomId = "!room:example.com";
|
|
||||||
let client: MatrixClient;
|
|
||||||
let utdEvent: MatrixEvent;
|
|
||||||
let autoRageshakeStore: AutoRageshakeStore;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
jest.useFakeTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
|
|
||||||
|
|
||||||
client = stubClient();
|
|
||||||
|
|
||||||
// @ts-ignore bypass private ctor for tests
|
|
||||||
autoRageshakeStore = new AutoRageshakeStore();
|
|
||||||
autoRageshakeStore.start();
|
|
||||||
|
|
||||||
utdEvent = mkEvent({
|
|
||||||
event: true,
|
|
||||||
content: {},
|
|
||||||
room: roomId,
|
|
||||||
user: TEST_SENDER,
|
|
||||||
type: EventType.RoomMessage,
|
|
||||||
});
|
|
||||||
jest.spyOn(utdEvent, "isDecryptionFailure").mockReturnValue(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.restoreAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when the initial sync completed", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
client.emit(ClientEvent.Sync, SyncState.Syncing, SyncState.Stopped, { nextSyncToken: "abc123" });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and an undecryptable event occurs", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
client.emit(MatrixEventEvent.Decrypted, utdEvent);
|
|
||||||
// simulate event grace period
|
|
||||||
jest.advanceTimersByTime(5500);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should send a to-device message", () => {
|
|
||||||
expect(mocked(client).sendToDevice.mock.calls).toEqual([
|
|
||||||
[
|
|
||||||
"im.vector.auto_rs_request",
|
|
||||||
new Map([
|
|
||||||
[
|
|
||||||
TEST_SENDER,
|
|
||||||
new Map([
|
|
||||||
[
|
|
||||||
undefined,
|
|
||||||
{
|
|
||||||
"device_id": undefined,
|
|
||||||
"event_id": utdEvent.getId(),
|
|
||||||
"org.matrix.msgid": expect.any(String),
|
|
||||||
"recipient_rageshake": undefined,
|
|
||||||
"room_id": "!room:example.com",
|
|
||||||
"sender_key": undefined,
|
|
||||||
"session_id": undefined,
|
|
||||||
"user_id": TEST_SENDER,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
+2
-5
@@ -407,11 +407,8 @@ If you run your own rageshake server to collect bug reports, the following optio
|
|||||||
not present in the config, the app will disable all rageshake functionality. Set to `https://rageshakes.element.io/api/submit` to submit
|
not present in the config, the app will disable all rageshake functionality. Set to `https://rageshakes.element.io/api/submit` to submit
|
||||||
rageshakes to us, or use your own rageshake server.
|
rageshakes to us, or use your own rageshake server.
|
||||||
You may also set the value to `"local"` if you wish to only store logs locally, in order to download them for debugging.
|
You may also set the value to `"local"` if you wish to only store logs locally, in order to download them for debugging.
|
||||||
2. `uisi_autorageshake_app`: If a user has enabled the "automatically send debug logs on decryption errors" flag, this option will be sent
|
2. `existing_issues_url`: URL for where to find existing issues.
|
||||||
alongside the rageshake so the rageshake server can filter them by app name. By default, this will be `element-auto-uisi`
|
3. `new_issue_url`: URL for where to submit new issues.
|
||||||
(in contrast to other rageshakes submitted by the app, which use `element-web`).
|
|
||||||
3. `existing_issues_url`: URL for where to find existing issues.
|
|
||||||
4. `new_issue_url`: URL for where to submit new issues.
|
|
||||||
|
|
||||||
If you would like to use [Sentry](https://sentry.io/) for rageshake data, add a `sentry` object to your config with the following values:
|
If you would like to use [Sentry](https://sentry.io/) for rageshake data, add a `sentry` object to your config with the following values:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user