From be8b7695428a2e11ecc98223817040cbcd5ed967 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:34:25 +0000 Subject: [PATCH 1/9] Update typescript-eslint monorepo to v6.19.0 (#4029) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 98 +++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/yarn.lock b/yarn.lock index 775d537ed08..5b49bca5487 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2082,15 +2082,15 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^6.0.0": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz#0df881a47da1c1a9774f39495f5f7052f86b72e0" - integrity sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA== + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz#bb0676af940bc23bf299ca58dbdc6589c2548c2e" + integrity sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/type-utils" "6.18.1" - "@typescript-eslint/utils" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" + "@typescript-eslint/scope-manager" "6.19.1" + "@typescript-eslint/type-utils" "6.19.1" + "@typescript-eslint/utils" "6.19.1" + "@typescript-eslint/visitor-keys" "6.19.1" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -2099,14 +2099,14 @@ ts-api-utils "^1.0.1" "@typescript-eslint/parser@^6.0.0": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.18.1.tgz#3c3987e186b38c77b30b6bfa5edf7c98ae2ec9d3" - integrity sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA== - dependencies: - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/typescript-estree" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.19.1.tgz#68a87bb21afaf0b1689e9cdce0e6e75bc91ada78" + integrity sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ== + dependencies: + "@typescript-eslint/scope-manager" "6.19.1" + "@typescript-eslint/types" "6.19.1" + "@typescript-eslint/typescript-estree" "6.19.1" + "@typescript-eslint/visitor-keys" "6.19.1" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -2117,21 +2117,21 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz#28c31c60f6e5827996aa3560a538693cb4bd3848" - integrity sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw== +"@typescript-eslint/scope-manager@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz#2f527ee30703a6169a52b31d42a1103d80acd51b" + integrity sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w== dependencies: - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" + "@typescript-eslint/types" "6.19.1" + "@typescript-eslint/visitor-keys" "6.19.1" -"@typescript-eslint/type-utils@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz#115cf535f8b39db8301677199ce51151e2daee96" - integrity sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q== +"@typescript-eslint/type-utils@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz#6a130e3afe605a4898e043fa9f72e96309b54935" + integrity sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg== dependencies: - "@typescript-eslint/typescript-estree" "6.18.1" - "@typescript-eslint/utils" "6.18.1" + "@typescript-eslint/typescript-estree" "6.19.1" + "@typescript-eslint/utils" "6.19.1" debug "^4.3.4" ts-api-utils "^1.0.1" @@ -2140,10 +2140,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.18.1.tgz#91617d8080bcd99ac355d9157079970d1d49fefc" - integrity sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw== +"@typescript-eslint/types@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.1.tgz#2d4c9d492a63ede15e7ba7d129bdf7714b77f771" + integrity sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -2158,13 +2158,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz#a12b6440175b4cbc9d09ab3c4966c6b245215ab4" - integrity sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA== +"@typescript-eslint/typescript-estree@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz#796d88d88882f12e85bb33d6d82d39e1aea54ed1" + integrity sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA== dependencies: - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/visitor-keys" "6.18.1" + "@typescript-eslint/types" "6.19.1" + "@typescript-eslint/visitor-keys" "6.19.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -2172,17 +2172,17 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.18.1.tgz#3451cfe2e56babb6ac657e10b6703393d4b82955" - integrity sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ== +"@typescript-eslint/utils@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.1.tgz#df93497f9cfddde2bcc2a591da80536e68acd151" + integrity sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.18.1" - "@typescript-eslint/types" "6.18.1" - "@typescript-eslint/typescript-estree" "6.18.1" + "@typescript-eslint/scope-manager" "6.19.1" + "@typescript-eslint/types" "6.19.1" + "@typescript-eslint/typescript-estree" "6.19.1" semver "^7.5.4" "@typescript-eslint/utils@^5.10.0": @@ -2207,12 +2207,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@6.18.1": - version "6.18.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz#704d789bda2565a15475e7d22f145b8fe77443f4" - integrity sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA== +"@typescript-eslint/visitor-keys@6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz#2164073ed4fc34a5ff3b5e25bb5a442100454c4c" + integrity sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ== dependencies: - "@typescript-eslint/types" "6.18.1" + "@typescript-eslint/types" "6.19.1" eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": From dc406ee2e8b9203f9bb1cee489daf126bbd05368 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 21:10:43 +0000 Subject: [PATCH 2/9] Update dependency @types/node to v18.19.8 (#4028) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5b49bca5487..1b16a8c9372 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2023,9 +2023,9 @@ undici-types "~5.26.4" "@types/node@18": - version "18.19.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.6.tgz#537beece2c8ad4d9abdaa3b0f428e601eb57dac8" - integrity sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg== + version "18.19.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.8.tgz#c1e42b165e5a526caf1f010747e0522cb2c9c36a" + integrity sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg== dependencies: undici-types "~5.26.4" From 8e01b654bc7f795f5da495920236524a25a64c88 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:23:28 +0000 Subject: [PATCH 3/9] Update all non-major dependencies (#4027) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/downstream-artifacts.yml | 2 +- package.json | 2 +- spec/unit/crypto/verification/sas.spec.ts | 10 ++++++---- src/@types/extensible_events.ts | 5 ++--- src/models/event-timeline-set.ts | 5 +++-- src/webrtc/call.ts | 10 ++++++---- tsconfig.json | 6 +++--- yarn.lock | 14 +++++++------- 8 files changed, 29 insertions(+), 25 deletions(-) diff --git a/.github/workflows/downstream-artifacts.yml b/.github/workflows/downstream-artifacts.yml index f49d5df25d3..cf57c3af216 100644 --- a/.github/workflows/downstream-artifacts.yml +++ b/.github/workflows/downstream-artifacts.yml @@ -16,7 +16,7 @@ concurrency: jobs: build-element-web: name: Build element-web - uses: matrix-org/matrix-react-sdk/.github/workflows/element-web.yaml@v3.88.0 + uses: matrix-org/matrix-react-sdk/.github/workflows/element-web.yaml@v3.90.0 with: matrix-js-sdk-sha: ${{ github.sha }} react-sdk-repository: matrix-org/matrix-react-sdk diff --git a/package.json b/package.json index accf1fcfa01..66453a493d2 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "jest-mock": "^29.0.0", "lint-staged": "^15.0.2", "matrix-mock-request": "^2.5.0", - "prettier": "3.1.1", + "prettier": "3.2.4", "rimraf": "^5.0.0", "ts-node": "^10.9.1", "typedoc": "^0.24.0", diff --git a/spec/unit/crypto/verification/sas.spec.ts b/spec/unit/crypto/verification/sas.spec.ts index a37a104d7c6..ba73ced6a3e 100644 --- a/spec/unit/crypto/verification/sas.spec.ts +++ b/spec/unit/crypto/verification/sas.spec.ts @@ -189,10 +189,12 @@ describe("SAS verification", function () { const origSendToDevice = bob.client.sendToDevice.bind(bob.client); bob.client.sendToDevice = async (type, map) => { if (type === "m.key.verification.accept") { - macMethod = map.get(alice.client.getUserId()!)?.get(alice.client.deviceId!) - ?.message_authentication_code; - keyAgreement = map.get(alice.client.getUserId()!)?.get(alice.client.deviceId!) - ?.key_agreement_protocol; + macMethod = map + .get(alice.client.getUserId()!) + ?.get(alice.client.deviceId!)?.message_authentication_code; + keyAgreement = map + .get(alice.client.getUserId()!) + ?.get(alice.client.deviceId!)?.key_agreement_protocol; } return origSendToDevice(type, map); }; diff --git a/src/@types/extensible_events.ts b/src/@types/extensible_events.ts index db9ea1806bd..9b16e0e437e 100644 --- a/src/@types/extensible_events.ts +++ b/src/@types/extensible_events.ts @@ -23,9 +23,8 @@ import { isProvided } from "../extensible_events_v1/utilities"; /** * Represents the stable and unstable values of a given namespace. */ -export type TSNamespace = N extends NamespacedValue - ? TSNamespaceValue | TSNamespaceValue - : never; +export type TSNamespace = + N extends NamespacedValue ? TSNamespaceValue | TSNamespaceValue : never; /** * Represents a namespaced value, if the value is a string. Used to extract provided types diff --git a/src/models/event-timeline-set.ts b/src/models/event-timeline-set.ts index 6175ac9aec0..b23b5ca169e 100644 --- a/src/models/event-timeline-set.ts +++ b/src/models/event-timeline-set.ts @@ -1003,8 +1003,9 @@ export class EventTimelineSet extends TypedEventEmitter track.kind === "video"); - const sender = this.transceivers.get(getTransceiverKey(SDPStreamMetadataPurpose.Usermedia, "video")) - ?.sender; + const sender = this.transceivers.get( + getTransceiverKey(SDPStreamMetadataPurpose.Usermedia, "video"), + )?.sender; sender?.replaceTrack(track ?? null); @@ -1326,8 +1327,9 @@ export class MatrixCall extends TypedEventEmitter track.kind === "video"); - const sender = this.transceivers.get(getTransceiverKey(SDPStreamMetadataPurpose.Usermedia, "video")) - ?.sender; + const sender = this.transceivers.get( + getTransceiverKey(SDPStreamMetadataPurpose.Usermedia, "video"), + )?.sender; sender?.replaceTrack(track ?? null); this.client.getMediaHandler().stopScreensharingStream(this.localScreensharingStream!); diff --git a/tsconfig.json b/tsconfig.json index 13fed86c47b..f55a2c991a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,12 +8,12 @@ "noUnusedLocals": true, "noEmit": true, "declaration": true, - "strict": true + "strict": true, }, "include": ["./src/**/*.ts", "./spec/**/*.ts"], "typedocOptions": { "entryPoints": ["src/matrix.ts"], "excludeExternals": true, - "out": "_docs" - } + "out": "_docs", + }, } diff --git a/yarn.lock b/yarn.lock index 1b16a8c9372..0d45f7b15fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3306,9 +3306,9 @@ eslint-plugin-import@^2.26.0: tsconfig-paths "^3.15.0" eslint-plugin-jest@^27.1.6: - version "27.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.6.2.tgz#8e69404fcd5dfeac03cac478f0ebb9bf2d8db56b" - integrity sha512-CI1AlKrsNhYFoP48VU8BVWOi7+qHTq4bRxyUlGjeU8SfFt8abjXhjOuDzUoMp68DoXIx17KpNpIkMrl4s4ZW0g== + version "27.6.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz#8acb8b1e45597fe1f4d4cf25163d90119efc12be" + integrity sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -5526,10 +5526,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" - integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== +prettier@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.4.tgz#4723cadeac2ce7c9227de758e5ff9b14e075f283" + integrity sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ== pretty-format@^28.1.3: version "28.1.3" From c4d32a3292cba650828aab2e5d5f2e6b4e2317f3 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:35:35 +0000 Subject: [PATCH 4/9] Bump matrix-sdk-crypto-wasm to 4.0.1 (#4025) * Bump matrix-sdk-crypto-wasm to 4.0.1 * Fix some tests * more test fixes * yet more fixes * update comments --- package.json | 2 +- spec/integ/crypto/cross-signing.spec.ts | 3 ++- spec/integ/crypto/crypto.spec.ts | 16 ++++++++++------ spec/integ/crypto/megolm-backup.spec.ts | 3 ++- spec/integ/crypto/verification.spec.ts | 11 ++++++----- spec/unit/rust-crypto/rust-crypto.spec.ts | 9 ++++++++- yarn.lock | 8 ++++---- 7 files changed, 33 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 66453a493d2..337cb1d20aa 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ ], "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/matrix-sdk-crypto-wasm": "^4.0.0", + "@matrix-org/matrix-sdk-crypto-wasm": "^4.0.1", "another-json": "^0.2.0", "bs58": "^5.0.0", "content-type": "^1.0.4", diff --git a/spec/integ/crypto/cross-signing.spec.ts b/spec/integ/crypto/cross-signing.spec.ts index a06efd20621..a0518d827f3 100644 --- a/spec/integ/crypto/cross-signing.spec.ts +++ b/spec/integ/crypto/cross-signing.spec.ts @@ -398,7 +398,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("cross-signing (%s)", (backend: s describe("crossSignDevice", () => { beforeEach(async () => { - jest.useFakeTimers(); + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // make sure that there is another device which we can sign e2eKeyResponder.addDeviceKeys(SIGNED_TEST_DEVICE_DATA); diff --git a/spec/integ/crypto/crypto.spec.ts b/spec/integ/crypto/crypto.spec.ts index bac0c46315c..e819cb7cb18 100644 --- a/spec/integ/crypto/crypto.spec.ts +++ b/spec/integ/crypto/crypto.spec.ts @@ -1063,8 +1063,9 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, await startClientAndAwaitFirstSync(); const p2pSession = await establishOlmSession(aliceClient, keyReceiver, syncResponder, testOlmAccount); - // We need to fake the timers to advance the time - jest.useFakeTimers(); + // We need to fake the timers to advance the time, but the wasm bindings of matrix-sdk-crypto rely on a + // working `queueMicrotask` + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); const syncResponse = getSyncResponse(["@bob:xyz"]); @@ -2189,7 +2190,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, describe("key upload request", () => { beforeEach(() => { - jest.useFakeTimers(); + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); }); afterEach(() => { @@ -2389,8 +2391,9 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, expect(devicesInfo.get(user)?.size).toBeFalsy(); }); - it("Get devices from tacked users", async () => { - jest.useFakeTimers(); + it("Get devices from tracked users", async () => { + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} }); await startClientAndAwaitFirstSync(); @@ -2745,7 +2748,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, describe("Manage Key Backup", () => { beforeEach(async () => { - jest.useFakeTimers(); + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); }); afterEach(() => { diff --git a/spec/integ/crypto/megolm-backup.spec.ts b/spec/integ/crypto/megolm-backup.spec.ts index f6bd53ef476..11e1c2eb705 100644 --- a/spec/integ/crypto/megolm-backup.spec.ts +++ b/spec/integ/crypto/megolm-backup.spec.ts @@ -129,7 +129,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe let e2eKeyResponder: E2EKeyResponder; beforeEach(async () => { - jest.useFakeTimers(); + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // anything that we don't have a specific matcher for silently returns a 404 fetchMock.catch(404); diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index d95097fcfd8..243fd510d58 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -85,7 +85,8 @@ import { encodeBase64 } from "../../../src/base64"; // The verification flows use javascript timers to set timeouts. We tell jest to use mock timer implementations // to ensure that we don't end up with dangling timeouts. -jest.useFakeTimers(); +// But the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. +jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); beforeAll(async () => { // we use the libolm primitives in the test, so init the Olm library @@ -1285,7 +1286,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await new Promise((resolve) => { setTimeout(resolve, 500); }); - jest.useFakeTimers(); + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // the backup secret should not be cached const cachedKey = await aliceClient.getCrypto()!.getSessionBackupPrivateKey(); @@ -1309,7 +1310,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await new Promise((resolve) => { setTimeout(resolve, 500); }); - jest.useFakeTimers(); + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // the backup secret should not be cached const cachedKey = await aliceClient.getCrypto()!.getSessionBackupPrivateKey(); @@ -1334,7 +1335,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await new Promise((resolve) => { setTimeout(resolve, 500); }); - jest.useFakeTimers(); + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // the backup secret should not be cached const cachedKey = await aliceClient.getCrypto()!.getSessionBackupPrivateKey(); @@ -1355,7 +1356,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st await new Promise((resolve) => { setTimeout(resolve, 500); }); - jest.useFakeTimers(); + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); // the backup secret should not be cached const cachedKey = await aliceClient.getCrypto()!.getSessionBackupPrivateKey(); diff --git a/spec/unit/rust-crypto/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts index dbcf0df88c2..68effb2f93b 100644 --- a/spec/unit/rust-crypto/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -75,6 +75,12 @@ import { CryptoStore, SecretStorePrivateKeys } from "../../../src/crypto/store/b const TEST_USER = "@alice:example.com"; const TEST_DEVICE_ID = "TEST_DEVICE"; +beforeAll(async () => { + // Load the WASM upfront, before any of the tests. This can take some time, and doing it here means that it gets + // a separate timeout. + await RustSdkCryptoJs.initAsync(); +}, 15000); + afterEach(() => { fetchMock.reset(); jest.restoreAllMocks(); @@ -997,7 +1003,8 @@ describe("RustCrypto", () => { }); it("should wait for a keys/query before returning devices", async () => { - jest.useFakeTimers(); + // We want to use fake timers, but the wasm bindings of matrix-sdk-crypto rely on a working `queueMicrotask`. + jest.useFakeTimers({ doNotFake: ["queueMicrotask"] }); fetchMock.post("path:/_matrix/client/v3/keys/upload", { one_time_key_counts: {} }); fetchMock.post("path:/_matrix/client/v3/keys/query", { diff --git a/yarn.lock b/yarn.lock index 0d45f7b15fc..19b24992816 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1674,10 +1674,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@matrix-org/matrix-sdk-crypto-wasm@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-4.0.0.tgz#b33bae9c418c5516d0dbce29662c6db803003626" - integrity sha512-a883HchJViPo6ukM0fEDmBgvMI6lWEujqAjMZgwaKEYNZTPgezN5PQvSNz2d+b96/R1y4QOC71zXM1yNylXA6Q== +"@matrix-org/matrix-sdk-crypto-wasm@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-4.0.1.tgz#b1d3848a6adc120622e5225045330d253273b117" + integrity sha512-0B4QQ9kop8AocmQDcOfROCQ6QyGZeogpsvTYfEB9ZIBtndCCwy/C3mkxzJD6+gEo1bJ4TdYnblhN7hEQlAG50g== "@matrix-org/olm@3.2.15": version "3.2.15" From ab217bdc3552d9711c51e0e711d2f0ba86565e48 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 24 Jan 2024 03:30:51 -0700 Subject: [PATCH 5/9] Support optional MSC3860 redirects (#4007) * Support optional MSC3860 redirects See `allow_redirect` across the media endpoints: https://spec.matrix.org/v1.9/client-server-api/#client-behaviour-7 * Update the tests * Appease the linter * Add test to appease SonarCloud * Only add `allow_redirect` if the parameter is specified rather than defaulting to `false` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- spec/unit/content-repo.spec.ts | 15 +++++++++++++++ spec/unit/matrix-client.spec.ts | 16 ++++++++++++++++ src/client.ts | 6 +++++- src/content-repo.ts | 9 +++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/spec/unit/content-repo.spec.ts b/spec/unit/content-repo.spec.ts index 91953945ac7..33eeab12d5e 100644 --- a/spec/unit/content-repo.spec.ts +++ b/spec/unit/content-repo.spec.ts @@ -37,6 +37,21 @@ describe("ContentRepo", function () { ); }); + it("should allow redirects when requested on download URLs", function () { + const mxcUri = "mxc://server.name/resourceid"; + expect(getHttpUriForMxc(baseUrl, mxcUri, undefined, undefined, undefined, false, true)).toEqual( + baseUrl + "/_matrix/media/v3/download/server.name/resourceid?allow_redirect=true", + ); + }); + + it("should allow redirects when requested on thumbnail URLs", function () { + const mxcUri = "mxc://server.name/resourceid"; + expect(getHttpUriForMxc(baseUrl, mxcUri, 32, 32, "scale", false, true)).toEqual( + baseUrl + + "/_matrix/media/v3/thumbnail/server.name/resourceid?width=32&height=32&method=scale&allow_redirect=true", + ); + }); + it("should return the empty string for null input", function () { expect(getHttpUriForMxc(null as any, "")).toEqual(""); }); diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index 920bec55804..8f87d6f8cc6 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -55,6 +55,7 @@ import { RuleId, IPushRule, ConditionKind, + getHttpUriForMxc, } from "../../src"; import { supportsMatrixCall } from "../../src/webrtc/call"; import { makeBeaconEvent } from "../test-utils/beacon"; @@ -369,6 +370,21 @@ describe("MatrixClient", function () { client.stopClient(); }); + describe("mxcUrlToHttp", () => { + it("should call getHttpUriForMxc", () => { + const mxc = "mxc://server/example"; + expect(client.mxcUrlToHttp(mxc)).toBe(getHttpUriForMxc(client.baseUrl, mxc)); + expect(client.mxcUrlToHttp(mxc, 32)).toBe(getHttpUriForMxc(client.baseUrl, mxc, 32)); + expect(client.mxcUrlToHttp(mxc, 32, 46)).toBe(getHttpUriForMxc(client.baseUrl, mxc, 32, 46)); + expect(client.mxcUrlToHttp(mxc, 32, 46, "scale")).toBe( + getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale"), + ); + expect(client.mxcUrlToHttp(mxc, 32, 46, "scale", false, true)).toBe( + getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale", false, true), + ); + }); + }); + describe("timestampToEvent", () => { const roomId = "!room:server.org"; const eventId = "$eventId:example.org"; diff --git a/src/client.ts b/src/client.ts index 3acc0135209..bb294f87e38 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5805,6 +5805,9 @@ export class MatrixClient extends TypedEventEmitter= 0) { From 19494e093bde2f57c1228620f743b75ea7d867af Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:47:13 +0000 Subject: [PATCH 6/9] Fix crypto migration for megolm sessions with no sender key (#4024) Fixes https://github.com/element-hq/element-web/issues/26894 Requires https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/89 (or rather, an update to a version of matrix-rust-sdk-crypto-wasm) which includes it). --- spec/unit/rust-crypto/rust-crypto.spec.ts | 73 +++++++++++++++++++---- src/crypto/OlmDevice.ts | 2 +- src/rust-crypto/libolm_migration.ts | 8 ++- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/spec/unit/rust-crypto/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts index 68effb2f93b..52916b43642 100644 --- a/spec/unit/rust-crypto/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -167,6 +167,21 @@ describe("initRustCrypto", () => { }); describe("libolm migration", () => { + let mockStore: RustSdkCryptoJs.StoreHandle; + + beforeEach(() => { + // Stub out a bunch of stuff in the Rust library + mockStore = { free: jest.fn() } as unknown as StoreHandle; + jest.spyOn(StoreHandle, "open").mockResolvedValue(mockStore); + + jest.spyOn(Migration, "migrateBaseData").mockResolvedValue(undefined); + jest.spyOn(Migration, "migrateOlmSessions").mockResolvedValue(undefined); + jest.spyOn(Migration, "migrateMegolmSessions").mockResolvedValue(undefined); + + const testOlmMachine = makeTestOlmMachine(); + jest.spyOn(OlmMachine, "initFromStore").mockResolvedValue(testOlmMachine); + }); + it("migrates data from a legacy crypto store", async () => { const PICKLE_KEY = "pickle1234"; const legacyStore = new MemoryCryptoStore(); @@ -186,17 +201,6 @@ describe("initRustCrypto", () => { createMegolmSessions(legacyStore, nDevices, nSessionsPerDevice); await legacyStore.markSessionsNeedingBackup([{ senderKey: pad43("device5"), sessionId: "session5" }]); - // Stub out a bunch of stuff in the Rust library - const mockStore = { free: jest.fn() } as unknown as StoreHandle; - jest.spyOn(StoreHandle, "open").mockResolvedValue(mockStore); - - jest.spyOn(Migration, "migrateBaseData").mockResolvedValue(undefined); - jest.spyOn(Migration, "migrateOlmSessions").mockResolvedValue(undefined); - jest.spyOn(Migration, "migrateMegolmSessions").mockResolvedValue(undefined); - - const testOlmMachine = makeTestOlmMachine(); - jest.spyOn(OlmMachine, "initFromStore").mockResolvedValue(testOlmMachine); - fetchMock.get("path:/_matrix/client/v3/room_keys/version", { version: "45" }); function legacyMigrationProgressListener(progress: number, total: number): void { @@ -275,12 +279,59 @@ describe("initRustCrypto", () => { expect(session.senderKey).toEqual(pad43(`device${i}`)); expect(session.pickle).toEqual("sessionPickle"); expect(session.roomId!.toString()).toEqual("!room:id"); + expect(session.senderSigningKey).toEqual("sender_signing_key"); + // only one of the sessions needs backing up expect(session.backedUp).toEqual(i !== 5 || j !== 5); } } }, 10000); + it("handles megolm sessions with no `keysClaimed`", async () => { + const legacyStore = new MemoryCryptoStore(); + legacyStore.storeAccount({}, "not a real account"); + + legacyStore.storeEndToEndInboundGroupSession( + pad43(`device1`), + `session1`, + { + forwardingCurve25519KeyChain: [], + room_id: "!room:id", + session: "sessionPickle", + }, + undefined, + ); + + const PICKLE_KEY = "pickle1234"; + await initRustCrypto({ + logger, + http: makeMatrixHttpApi(), + userId: TEST_USER, + deviceId: TEST_DEVICE_ID, + secretStorage: {} as ServerSideSecretStorage, + cryptoCallbacks: {} as CryptoCallbacks, + storePrefix: "storePrefix", + storePassphrase: "storePassphrase", + legacyCryptoStore: legacyStore, + legacyPickleKey: PICKLE_KEY, + }); + + expect(Migration.migrateMegolmSessions).toHaveBeenCalledTimes(1); + expect(Migration.migrateMegolmSessions).toHaveBeenCalledWith( + expect.any(Array), + new Uint8Array(Buffer.from(PICKLE_KEY)), + mockStore, + ); + const megolmSessions: PickledInboundGroupSession[] = mocked(Migration.migrateMegolmSessions).mock + .calls[0][0]; + expect(megolmSessions.length).toEqual(1); + const session = megolmSessions[0]; + expect(session.senderKey).toEqual(pad43(`device1`)); + expect(session.pickle).toEqual("sessionPickle"); + expect(session.roomId!.toString()).toEqual("!room:id"); + expect(session.senderSigningKey).toBe(undefined); + }, 10000); + async function encryptAndStoreSecretKey(type: string, key: Uint8Array, pickleKey: string, store: CryptoStore) { const encryptedKey = await encryptAES(encodeBase64(key), Buffer.from(pickleKey), type); store.storeSecretStorePrivateKey(undefined, type as keyof SecretStorePrivateKeys, encryptedKey); diff --git a/src/crypto/OlmDevice.ts b/src/crypto/OlmDevice.ts index 45706d91c70..28c4e4cd689 100644 --- a/src/crypto/OlmDevice.ts +++ b/src/crypto/OlmDevice.ts @@ -64,7 +64,7 @@ export interface InboundGroupSessionData { room_id: string; // eslint-disable-line camelcase /** pickled Olm.InboundGroupSession */ session: string; - keysClaimed: Record; + keysClaimed?: Record; /** Devices involved in forwarding this session to us (normally empty). */ forwardingCurve25519KeyChain: string[]; /** whether this session is untrusted. */ diff --git a/src/rust-crypto/libolm_migration.ts b/src/rust-crypto/libolm_migration.ts index e03d401cc93..8a34aac4b43 100644 --- a/src/rust-crypto/libolm_migration.ts +++ b/src/rust-crypto/libolm_migration.ts @@ -232,11 +232,13 @@ async function migrateMegolmSessions( logger.debug(`Migrating batch of ${batch.length} megolm sessions`); const migrationData: RustSdkCryptoJs.PickledInboundGroupSession[] = []; for (const session of batch) { + const sessionData = session.sessionData!; + const pickledSession = new RustSdkCryptoJs.PickledInboundGroupSession(); - pickledSession.pickle = session.sessionData!.session; - pickledSession.roomId = new RustSdkCryptoJs.RoomId(session.sessionData!.room_id); + pickledSession.pickle = sessionData.session; + pickledSession.roomId = new RustSdkCryptoJs.RoomId(sessionData.room_id); pickledSession.senderKey = session.senderKey; - pickledSession.senderSigningKey = session.sessionData!.keysClaimed["ed25519"]; + pickledSession.senderSigningKey = sessionData.keysClaimed?.["ed25519"]; pickledSession.backedUp = !session.needsBackup; // Not sure if we can reliably distinguish imported vs not-imported sessions in the libolm database. From 5e2acb558b40059c833e0a094bd28236790c544b Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 24 Jan 2024 22:43:50 -0500 Subject: [PATCH 7/9] Implement getting verification cancellation info in Rust crypto (#3947) * implement verification cancellation info in Rust crypto * fix type info * use string cancel code and add test * simplify code Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --------- Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- spec/integ/crypto/verification.spec.ts | 2 ++ src/rust-crypto/verification.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 243fd510d58..ae9ebcd5961 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -744,6 +744,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st expect(toDeviceMessage.transaction_id).toEqual(transactionId); expect(toDeviceMessage.code).toEqual("m.user"); expect(request.phase).toEqual(VerificationPhase.Cancelled); + expect(request.cancellationCode).toEqual("m.user"); + expect(request.cancellingUserId).toEqual("@alice:localhost"); }); it("can cancel during the SAS phase", async () => { diff --git a/src/rust-crypto/verification.ts b/src/rust-crypto/verification.ts index cca1b4aa6b4..a8b733c5fe0 100644 --- a/src/rust-crypto/verification.ts +++ b/src/rust-crypto/verification.ts @@ -426,7 +426,7 @@ export class RustVerificationRequest * this verification. */ public get cancellationCode(): string | null { - throw new Error("not implemented"); + return this.inner.cancelInfo?.cancelCode() ?? null; } /** @@ -435,7 +435,14 @@ export class RustVerificationRequest * Only defined when phase is Cancelled */ public get cancellingUserId(): string | undefined { - throw new Error("not implemented"); + const cancelInfo = this.inner.cancelInfo; + if (!cancelInfo) { + return undefined; + } else if (cancelInfo.cancelledbyUs()) { + return this.olmMachine.userId.toString(); + } else { + return this.inner.otherUserId.toString(); + } } } From 99b3cf2279484cdc864349d6b28529f448373b71 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Thu, 25 Jan 2024 08:38:02 +0000 Subject: [PATCH 8/9] Introduce `Room.hasEncryptionStateEvent` (#4030) ... and replace a lot of calls to `MatrixClient.isRoomEncrypted` with it. This is a lesser check (since it can be tricked by servers withholding the state event), but for most cases it is sufficient. At the end of the day, if the server witholds the state, the room is pretty much bricked anyway. The one thing we *mustn't* do is allow users to send *unencrypted* events to the room. --- spec/unit/matrix-client.spec.ts | 18 +----------------- src/client.ts | 7 +++---- src/models/room.ts | 23 +++++++++++++++++++---- src/sliding-sync-sdk.ts | 2 +- src/sync.ts | 4 ++-- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index 8f87d6f8cc6..2a79293e2ad 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -1450,23 +1450,7 @@ describe("MatrixClient", function () { const mockRoom = { getMyMembership: () => "join", updatePendingEvent: (event: MatrixEvent, status: EventStatus) => event.setStatus(status), - currentState: { - getStateEvents: (eventType, stateKey) => { - if (eventType === EventType.RoomCreate) { - expect(stateKey).toEqual(""); - return new MatrixEvent({ - content: { - [RoomCreateTypeField]: RoomType.Space, - }, - }); - } else if (eventType === EventType.RoomEncryption) { - expect(stateKey).toEqual(""); - return new MatrixEvent({ content: {} }); - } else { - throw new Error("Unexpected event type or state key"); - } - }, - } as Room["currentState"], + hasEncryptionStateEvent: jest.fn().mockReturnValue(true), } as unknown as Room; let event: MatrixEvent; diff --git a/src/client.ts b/src/client.ts index bb294f87e38..44d9fbd33a9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1445,7 +1445,7 @@ export class MatrixClient extends TypedEventEmitter { - if (room && this.isRoomEncrypted(room.roomId)) { + if (room?.hasEncryptionStateEvent()) { // Figure out if we've read something or if it's just informational const content = event.getContent(); const isSelf = @@ -3268,8 +3268,7 @@ export class MatrixClient extends TypedEventEmitter { // that this function is only called once (unless loading the members // fails), since loadMembersIfNeeded always returns this.membersPromise // if set, which will be the result of the first (successful) call. - if (rawMembersEvents === null || (this.client.isCryptoEnabled() && this.client.isRoomEncrypted(this.roomId))) { + if (rawMembersEvents === null || this.hasEncryptionStateEvent()) { fromServer = true; rawMembersEvents = await this.loadMembersFromServer(); logger.log(`LL: got ${rawMembersEvents.length} ` + `members from server for room ${this.roomId}`); @@ -1275,9 +1275,12 @@ export class Room extends ReadReceipt { * error will be thrown. * * @returns the result + * + * @deprecated Not supported under rust crypto. Instead, call {@link Room.getEncryptionTargetMembers}, + * {@link CryptoApi.getUserDeviceInfo}, and {@link CryptoApi.getDeviceVerificationStatus}. */ public async hasUnverifiedDevices(): Promise { - if (!this.client.isRoomEncrypted(this.roomId)) { + if (!this.hasEncryptionStateEvent()) { return false; } const e2eMembers = await this.getEncryptionTargetMembers(); @@ -2565,7 +2568,7 @@ export class Room extends ReadReceipt { .filter((event) => { // Filter out the unencrypted messages if the room is encrypted const isEventEncrypted = event.type === EventType.RoomMessageEncrypted; - const isRoomEncrypted = this.client.isRoomEncrypted(this.roomId); + const isRoomEncrypted = this.hasEncryptionStateEvent(); return isEventEncrypted || !isRoomEncrypted; }); @@ -3170,7 +3173,7 @@ export class Room extends ReadReceipt { public maySendMessage(): boolean { return ( this.getMyMembership() === "join" && - (this.client.isRoomEncrypted(this.roomId) + (this.hasEncryptionStateEvent() ? this.currentState.maySendEvent(EventType.RoomMessageEncrypted, this.myUserId) : this.currentState.maySendEvent(EventType.RoomMessage, this.myUserId)) ); @@ -3672,6 +3675,18 @@ export class Room extends ReadReceipt { public compareEventOrdering(leftEventId: string, rightEventId: string): number | null { return compareEventOrdering(this, leftEventId, rightEventId); } + + /** + * Return true if this room has an `m.room.encryption` state event. + * + * If this returns `true`, events sent to this room should be encrypted (and `MatrixClient.sendEvent` and friends + * will encrypt outgoing events). + */ + public hasEncryptionStateEvent(): boolean { + return Boolean( + this.getLiveTimeline().getState(EventTimeline.FORWARDS)?.getStateEvents(EventType.RoomEncryption, ""), + ); + } } // a map from current event status to a list of allowed next statuses diff --git a/src/sliding-sync-sdk.ts b/src/sliding-sync-sdk.ts index eea6656d98f..bfe32448bd2 100644 --- a/src/sliding-sync-sdk.ts +++ b/src/sliding-sync-sdk.ts @@ -615,7 +615,7 @@ export class SlidingSyncSdk { } } - const encrypted = this.client.isRoomEncrypted(room.roomId); + const encrypted = room.hasEncryptionStateEvent(); // we do this first so it's correct when any of the events fire if (roomData.notification_count != null) { room.setUnreadNotificationCount(NotificationCountType.Total, roomData.notification_count); diff --git a/src/sync.ts b/src/sync.ts index 57afaff24c4..372260d5615 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1760,11 +1760,11 @@ export class SyncApi { return events?.find((e) => e.getType() === EventType.RoomEncryption && e.getStateKey() === ""); } - // When processing the sync response we cannot rely on MatrixClient::isRoomEncrypted before we actually + // When processing the sync response we cannot rely on Room.hasEncryptionStateEvent we actually // inject the events into the room object, so we have to inspect the events themselves. private isRoomEncrypted(room: Room, stateEventList: MatrixEvent[], timelineEventList?: MatrixEvent[]): boolean { return ( - this.client.isRoomEncrypted(room.roomId) || + room.hasEncryptionStateEvent() || !!this.findEncryptionEvent(stateEventList) || !!this.findEncryptionEvent(timelineEventList) ); From 5bf29ef543a985776cdcda839701a56e9168c418 Mon Sep 17 00:00:00 2001 From: Jan Jurzitza Date: Thu, 25 Jan 2024 10:47:27 +0100 Subject: [PATCH 9/9] fix IndexedDBStore API documentation (#3987) * fix IndexedDBStore API documentation changes the changelog entry to include since when this change is needed fix #3986 Signed-off-by: Jan Jurzitza * retroactively add breaking change note to changelog entry Signed-off-by: Jan Jurzitza --------- Signed-off-by: Jan Jurzitza --- CHANGELOG.md | 1 + src/store/indexeddb.ts | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aff0c3582c9..f4a897632f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ Changes in [30.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v30 ## 🚨 BREAKING CHANGES * Refactor & make base64 functions browser-safe ([\#3818](https://github.com/matrix-org/matrix-js-sdk/pull/3818)). + * `IndexedDBStore.startup()` must be called after using it on `sdk.createClient` now. ## 🦖 Deprecations * Deprecate `MatrixEvent.toJSON` ([\#3801](https://github.com/matrix-org/matrix-js-sdk/pull/3801)). diff --git a/src/store/indexeddb.ts b/src/store/indexeddb.ts index 33453b25db4..33132a17bde 100644 --- a/src/store/indexeddb.ts +++ b/src/store/indexeddb.ts @@ -90,10 +90,10 @@ export class IndexedDBStore extends MemoryStore { * ``` * let opts = { indexedDB: window.indexedDB, localStorage: window.localStorage }; * let store = new IndexedDBStore(opts); - * await store.startup(); // load from indexed db * let client = sdk.createClient({ * store: store, * }); + * await store.startup(); // load from indexed db, must be called after createClient * client.startClient(); * client.on("sync", function(state, prevState, data) { * if (state === "PREPARED") { @@ -140,7 +140,9 @@ export class IndexedDBStore extends MemoryStore { logger.log(`IndexedDBStore.startup: processing presence events`); userPresenceEvents.forEach(([userId, rawEvent]) => { if (!this.createUser) { - throw new Error("createUser is undefined, it should be set with setUserCreator()!"); + throw new Error( + "`IndexedDBStore.startup` must be called after assigning it to the client, not before!", + ); } const u = this.createUser(userId); if (rawEvent) {