From 9f39f10958385bc370d9efbe6eb76044deb16d31 Mon Sep 17 00:00:00 2001 From: Thor Arne Johansen Date: Thu, 14 Mar 2024 16:46:05 +0100 Subject: [PATCH] Taj/cryptosetup (#12) * Changed call sites from customisations/security to ModuleRunner.extensions * Updated depenndecy and added tests * Fixed style and formatting with prettier --- test/modules/MockModule.ts | 68 +++++++++++++++++++++++++++++++ test/modules/ModuleRunner-test.ts | 28 ++++++++++++- yarn.lock | 31 ++------------ 3 files changed, 98 insertions(+), 29 deletions(-) diff --git a/test/modules/MockModule.ts b/test/modules/MockModule.ts index ab29b025086..84d074292d6 100644 --- a/test/modules/MockModule.ts +++ b/test/modules/MockModule.ts @@ -16,6 +16,13 @@ limitations under the License. import { RuntimeModule } from "@matrix-org/react-sdk-module-api/lib/RuntimeModule"; import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi"; +import { AllExtensions } from "@matrix-org/react-sdk-module-api/lib/types/extensions"; +import { + CryptoSetupExtensionsBase, + ExtendedMatrixClientCreds, + SecretStorageKeyDescriptionAesV1, + CryptoSetupArgs, +} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions"; import { ModuleRunner } from "../../src/modules/ModuleRunner"; @@ -43,3 +50,64 @@ export function registerMockModule(): MockModule { } return module; } + +export class MockModuleWithCryptoSetupExtension extends RuntimeModule { + public get apiInstance(): ModuleApi { + return this.moduleApi; + } + + moduleName: string = MockModuleWithCryptoSetupExtension.name; + + extensions: AllExtensions = { + cryptoSetup: new (class extends CryptoSetupExtensionsBase { + SHOW_ENCRYPTION_SETUP_UI = true; + + examineLoginResponse(response: any, credentials: ExtendedMatrixClientCreds): void { + throw new Error("Method not implemented."); + } + persistCredentials(credentials: ExtendedMatrixClientCreds): void { + throw new Error("Method not implemented."); + } + getSecretStorageKey(): Uint8Array | null { + return Uint8Array.from([0x11, 0x22, 0x99]); + } + createSecretStorageKey(): Uint8Array | null { + throw new Error("Method not implemented."); + } + catchAccessSecretStorageError(e: Error): void { + throw new Error("Method not implemented."); + } + setupEncryptionNeeded(args: CryptoSetupArgs): boolean { + throw new Error("Method not implemented."); + } + getDehydrationKeyCallback(): + | (( + keyInfo: SecretStorageKeyDescriptionAesV1, + checkFunc: (key: Uint8Array) => void, + ) => Promise) + | null { + throw new Error("Method not implemented."); + } + })(), + }; + + public constructor(moduleApi: ModuleApi) { + super(moduleApi); + } +} + +export function registerMockModuleWithCryptoSetupExtension(): MockModuleWithCryptoSetupExtension { + let module: MockModuleWithCryptoSetupExtension | undefined; + + ModuleRunner.instance.registerModule((api) => { + if (module) { + throw new Error("State machine error: ModuleRunner created the module twice"); + } + module = new MockModuleWithCryptoSetupExtension(api); + return module; + }); + if (!module) { + throw new Error("State machine error: ModuleRunner did not create module"); + } + return module; +} diff --git a/test/modules/ModuleRunner-test.ts b/test/modules/ModuleRunner-test.ts index 175c62c9e6b..737ff885dd6 100644 --- a/test/modules/ModuleRunner-test.ts +++ b/test/modules/ModuleRunner-test.ts @@ -16,7 +16,7 @@ limitations under the License. import { RoomPreviewOpts, RoomViewLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle"; -import { MockModule, registerMockModule } from "./MockModule"; +import { MockModule, registerMockModule, registerMockModuleWithCryptoSetupExtension } from "./MockModule"; import { ModuleRunner } from "../../src/modules/ModuleRunner"; describe("ModuleRunner", () => { @@ -49,4 +49,30 @@ describe("ModuleRunner", () => { ]); }); }); + + describe("extensions", () => { + it("should return default values when no crypto-setup extensions are provided by a registered module", async () => { + registerMockModule(); + const result = ModuleRunner.instance.extensions.cryptoSetup?.getSecretStorageKey(); + expect(result).toBeNull(); + }); + + it("should return default values when no experimental extensions are provided by a registered module", async () => { + registerMockModule(); + const result = ModuleRunner.instance.extensions?.experimental?.experimentalMethod(); + expect(result).toBeNull(); + }); + + it("should return value from crypto-setup-extensions provided by a registered module", async () => { + registerMockModuleWithCryptoSetupExtension(); + const result = ModuleRunner.instance.extensions.cryptoSetup?.getSecretStorageKey(); + expect(result).toEqual(Uint8Array.from([0x11, 0x22, 0x99])); + }); + + it("must not allow multiple modules to provide a given extension", async () => { + registerMockModuleWithCryptoSetupExtension(); + const t = () => registerMockModuleWithCryptoSetupExtension(); + expect(t).toThrow(Error); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 84e87730dc7..ce60176a7a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8483,16 +8483,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== @@ -8567,14 +8558,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== @@ -9355,7 +9339,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== @@ -9373,15 +9357,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"