From d5bf1022e9c9f38ec4080451ce4a1b8797039b42 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Mon, 29 Apr 2024 13:18:57 -0400 Subject: [PATCH] Use a different error message for UTDs when you weren't in the room. (#12453) * Use different messages for UTDs sent before login * Playwright test for historical events * Add some tests * initial work on pre-join UTDs * add playwright tests and remove old pre-join UTD logic * run i18n script * fix type error * use different error code in PostHog for pre-join UTD * don't remove old pre-join UTD logic yet --------- Co-authored-by: Richard van der Hoff --- package.json | 2 +- src/DecryptionFailureTracker.ts | 2 + .../views/messages/DecryptionFailureBody.tsx | 3 + src/i18n/strings/en_EN.json | 1 + test/DecryptionFailureTracker-test.ts | 56 +++++++++++++++++++ .../messages/DecryptionFailureBody-test.tsx | 14 +++++ yarn.lock | 39 +++---------- 7 files changed, 84 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index e19463d337..37d48159e3 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/analytics-events": "^0.19.0", + "@matrix-org/analytics-events": "^0.20.0", "@matrix-org/emojibase-bindings": "^1.1.2", "@matrix-org/matrix-wysiwyg": "2.17.0", "@matrix-org/olm": "3.2.15", diff --git a/src/DecryptionFailureTracker.ts b/src/DecryptionFailureTracker.ts index 9914704550..c842e55ec4 100644 --- a/src/DecryptionFailureTracker.ts +++ b/src/DecryptionFailureTracker.ts @@ -58,6 +58,8 @@ export class DecryptionFailureTracker { case DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED: case DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP: return "HistoricalMessage"; + case DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED: + return "ExpectedDueToMembership"; default: return "UnknownError"; } diff --git a/src/components/views/messages/DecryptionFailureBody.tsx b/src/components/views/messages/DecryptionFailureBody.tsx index 37caf69161..718fa492e2 100644 --- a/src/components/views/messages/DecryptionFailureBody.tsx +++ b/src/components/views/messages/DecryptionFailureBody.tsx @@ -36,6 +36,9 @@ function getErrorMessage(mxEvent: MatrixEvent, isVerified: boolean | undefined): } // otherwise, use the default. break; + + case DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED: + return _t("timeline|decryption_failure|historical_event_user_not_joined"); } return _t("timeline|decryption_failure|unable_to_decrypt"); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3e136846ca..816f909ec3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3214,6 +3214,7 @@ "blocked": "The sender has blocked you from receiving this message", "historical_event_no_key_backup": "Historical messages are not available on this device", "historical_event_unverified_device": "You need to verify this device for access to historical messages", + "historical_event_user_not_joined": "You don't have access to this message", "unable_to_decrypt": "Unable to decrypt message" }, "disambiguated_profile": "%(displayName)s (%(matrixId)s)", diff --git a/test/DecryptionFailureTracker-test.ts b/test/DecryptionFailureTracker-test.ts index 7a0bf65f81..305692fce8 100644 --- a/test/DecryptionFailureTracker-test.ts +++ b/test/DecryptionFailureTracker-test.ts @@ -388,4 +388,60 @@ describe("DecryptionFailureTracker", function () { // should track remapped error code expect(counts["XEDNI_EGASSEM_NWONKNU_MLO"]).toBe(1); }); + + it("default error code mapper maps error codes correctly", async () => { + const errorCodes: string[] = []; + + // @ts-ignore access to private constructor + const tracker = new DecryptionFailureTracker( + (total: number, errorCode: string) => { + errorCodes.push(errorCode); + }, + // @ts-ignore access to private member + DecryptionFailureTracker.instance.errorCodeMapFn, + ); + + const event1 = await createFailedDecryptionEvent(DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID); + tracker.addVisibleEvent(event1); + tracker.eventDecrypted(event1); + + const event2 = await createFailedDecryptionEvent(DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX); + tracker.addVisibleEvent(event2); + tracker.eventDecrypted(event2); + + const event3 = await createFailedDecryptionEvent(DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP); + tracker.addVisibleEvent(event3); + tracker.eventDecrypted(event3); + + const event4 = await createFailedDecryptionEvent(DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED); + tracker.addVisibleEvent(event4); + tracker.eventDecrypted(event4); + + const event5 = await createFailedDecryptionEvent(DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP); + tracker.addVisibleEvent(event5); + tracker.eventDecrypted(event5); + + const event6 = await createFailedDecryptionEvent(DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED); + tracker.addVisibleEvent(event6); + tracker.eventDecrypted(event6); + + const event7 = await createFailedDecryptionEvent(DecryptionFailureCode.UNKNOWN_ERROR); + tracker.addVisibleEvent(event7); + tracker.eventDecrypted(event7); + + // Pretend "now" is Infinity + tracker.checkFailures(Infinity); + + tracker.trackFailures(); + + expect(errorCodes).toEqual([ + "OlmKeysNotSentError", + "OlmIndexError", + "HistoricalMessage", + "HistoricalMessage", + "HistoricalMessage", + "ExpectedDueToMembership", + "UnknownError", + ]); + }); }); diff --git a/test/components/views/messages/DecryptionFailureBody-test.tsx b/test/components/views/messages/DecryptionFailureBody-test.tsx index b01bbb7729..6b0177a916 100644 --- a/test/components/views/messages/DecryptionFailureBody-test.tsx +++ b/test/components/views/messages/DecryptionFailureBody-test.tsx @@ -100,4 +100,18 @@ describe("DecryptionFailureBody", () => { ); }, ); + + it("should handle undecryptable pre-join messages", async () => { + // When + const event = await mkDecryptionFailureMatrixEvent({ + code: DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED, + msg: "Not joined", + roomId: "fakeroom", + sender: "fakesender", + }); + const { container } = customRender(event); + + // Then + expect(container).toHaveTextContent("You don't have access to this message"); + }); }); diff --git a/yarn.lock b/yarn.lock index f9a0ee7e63..7f812ab866 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1858,10 +1858,10 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== -"@matrix-org/analytics-events@^0.19.0": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.19.1.tgz#304d48b7b8e51117dfd9c1cf46a65e8bee9f46cb" - integrity sha512-bYWJIkOzl4Jt02fg1+XoQv5xZ3mP6qBzNmytt1UVfKLaGgLBSvlk9gXx2/3GhSuPBq99/CljEX/zABJ//mexAw== +"@matrix-org/analytics-events@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.20.0.tgz#062a532ddcf0e2e5eb64c5576cd212cb32a11ccf" + integrity sha512-YCRbZrpZU9q+nrB6RsfPZ4NlKs31ySjP2F7GFUZNPKv96GcbihrnMK086td480SJOYpjPv2vttDJC+S67SFe2w== "@matrix-org/emojibase-bindings@^1.1.2": version "1.1.3" @@ -8652,16 +8652,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8755,14 +8746,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9555,7 +9539,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9573,15 +9557,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"