Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed call sites from customisations/security to ModuleRunner.exten… #2

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { MINIMUM_MATRIX_VERSION, SUPPORTED_MATRIX_VERSIONS } from "matrix-js-sdk/src/version-support";

import { IMatrixClientCreds, MatrixClientPeg } from "./MatrixClientPeg";
import SecurityCustomisations from "./customisations/Security";
import { ModuleRunner } from "./modules/ModuleRunner";
import EventIndexPeg from "./indexing/EventIndexPeg";
import createMatrixClient from "./utils/createMatrixClient";
import Notifier from "./Notifier";
Expand Down Expand Up @@ -921,7 +921,8 @@ async function persistCredentials(credentials: IMatrixClientCreds): Promise<void
localStorage.setItem("mx_device_id", credentials.deviceId);
}

SecurityCustomisations.persistCredentials?.(credentials);
//SecurityCustomisations.persistCredentials?.(credentials);
ModuleRunner.instance.extensions?.cryptoSetup?.persistCredentials(credentials);

logger.log(`Session persisted for ${credentials.userId}`);
}
Expand Down
5 changes: 3 additions & 2 deletions src/Login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { logger } from "matrix-js-sdk/src/logger";

import { IMatrixClientCreds } from "./MatrixClientPeg";
import SecurityCustomisations from "./customisations/Security";
import { ModuleRunner } from "./modules/ModuleRunner";
import { getOidcClientId } from "./utils/oidc/registerClient";
import { IConfigOptions } from "./IConfigOptions";
import SdkConfig from "./SdkConfig";
Expand Down Expand Up @@ -294,7 +294,8 @@ export async function sendLoginRequest(
accessToken: data.access_token,
};

SecurityCustomisations.examineLoginResponse?.(data, creds);
// SecurityCustomisations.examineLoginResponse?.(data, creds);
ModuleRunner.instance.extensions.cryptoSetup?.examineLoginResponse(data, creds);

return creds;
}
13 changes: 10 additions & 3 deletions src/MatrixClientPeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB
import * as StorageManager from "./utils/StorageManager";
import IdentityAuthClient from "./IdentityAuthClient";
import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from "./SecurityManager";
import SecurityCustomisations from "./customisations/Security";
import { ModuleRunner } from "./modules/ModuleRunner";
import { SlidingSyncManager } from "./SlidingSyncManager";
import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog";
import { _t, UserFriendlyError } from "./languageHandler";
Expand Down Expand Up @@ -464,8 +464,15 @@ class MatrixClientPegClass implements IMatrixClientPeg {
},
};

if (SecurityCustomisations.getDehydrationKey) {
opts.cryptoCallbacks!.getDehydrationKey = SecurityCustomisations.getDehydrationKey;
// if (SecurityCustomisations.getDehydrationKey) {
// opts.cryptoCallbacks!.getDehydrationKey = SecurityCustomisations.getDehydrationKey;
// }

console.log("CryptoSetupExtensions: Executing getDehydrationKeyCallback...")
const dehydrationKeyCallback = ModuleRunner.instance.extensions.cryptoSetup?.getDehydrationKeyCallback();
console.log("CryptoSetupExtensions: Executing getDehydrationKeyCallback...Done")
if (dehydrationKeyCallback) {
opts.cryptoCallbacks!.getDehydrationKey = dehydrationKeyCallback;
}

this.matrixClient = createMatrixClient(opts);
Expand Down
15 changes: 9 additions & 6 deletions src/SecurityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { isSecureBackupRequired } from "./utils/WellKnownUtils";
import AccessSecretStorageDialog, { KeyParams } from "./components/views/dialogs/security/AccessSecretStorageDialog";
import RestoreKeyBackupDialog from "./components/views/dialogs/security/RestoreKeyBackupDialog";
import SettingsStore from "./settings/SettingsStore";
import SecurityCustomisations from "./customisations/Security";
import { ModuleRunner } from "./modules/ModuleRunner";
import QuestionDialog from "./components/views/dialogs/QuestionDialog";
import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog";

Expand Down Expand Up @@ -130,9 +130,10 @@ async function getSecretStorageKey({
}
}

const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
// const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup?.getSecretStorageKey();
if (keyFromCustomisations) {
logger.log("Using key from security customisations (secret storage)");
logger.log("CryptoSetupExtension: Using key from extension (secret storage)");
cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations);
return [keyId, keyFromCustomisations];
}
Expand Down Expand Up @@ -180,9 +181,10 @@ export async function getDehydrationKey(
keyInfo: ISecretStorageKeyInfo,
checkFunc: (data: Uint8Array) => void,
): Promise<Uint8Array> {
const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
// const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.();
const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup?.getSecretStorageKey();
if (keyFromCustomisations) {
logger.log("Using key from security customisations (dehydration)");
logger.log("CryptoSetupExtension: Using key from extension (dehydration)");
return keyFromCustomisations;
}

Expand Down Expand Up @@ -419,7 +421,8 @@ async function doAccessSecretStorage(func: () => Promise<void>, forceReset: bool
// inner operation completes.
return await func();
} catch (e) {
SecurityCustomisations.catchAccessSecretStorageError?.(e);
// SecurityCustomisations.catchAccessSecretStorageError?.(e as Error);
ModuleRunner.instance.extensions.cryptoSetup?.catchAccessSecretStorageError(e as Error);
logger.error(e);
// Re-throw so that higher level logic can abort as needed
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
isSecureBackupRequired,
SecureBackupSetupMethod,
} from "../../../../utils/WellKnownUtils";
import SecurityCustomisations from "../../../../customisations/Security";
import { ModuleRunner } from "../../../../modules/ModuleRunner";
import Field from "../../../../components/views/elements/Field";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import Spinner from "../../../../components/views/elements/Spinner";
Expand Down Expand Up @@ -181,9 +181,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
}

private getInitialPhase(): void {
const keyFromCustomisations = SecurityCustomisations.createSecretStorageKey?.();
//const keyFromCustomisations = SecurityCustomisations.createSecretStorageKey?.();
const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup?.createSecretStorageKey();
if (keyFromCustomisations) {
logger.log("Created key via customisations, jumping to bootstrap step");
logger.log("CryptoSetupExtension: Created key via extension, jumping to bootstrap step");
this.recoveryKey = {
privateKey: keyFromCustomisations,
};
Expand Down
10 changes: 7 additions & 3 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import { showToast as showMobileGuideToast } from "../../toasts/MobileGuideToast
import { shouldUseLoginForWelcome } from "../../utils/pages";
import RoomListStore from "../../stores/room-list/RoomListStore";
import { RoomUpdateCause } from "../../stores/room-list/models";
import SecurityCustomisations from "../../customisations/Security";
import { ModuleRunner } from "../../modules/ModuleRunner";
import Spinner from "../views/elements/Spinner";
import QuestionDialog from "../views/dialogs/QuestionDialog";
import UserSettingsDialog from "../views/dialogs/UserSettingsDialog";
Expand Down Expand Up @@ -443,8 +443,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (crossSigningIsSetUp) {
// if the user has previously set up cross-signing, verify this device so we can fetch the
// private keys.
if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
this.onLoggedIn();


// if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
const cryptoExtension = ModuleRunner.instance.extensions.cryptoSetup;
if (cryptoExtension !== undefined && cryptoExtension.SHOW_ENCRYPTION_SETUP_UI == false) {
this.onLoggedIn();
} else {
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
}
Expand Down
71 changes: 71 additions & 0 deletions src/modules/ModuleRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
import { safeSet } from "matrix-js-sdk/src/utils";
import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations";
import { AnyLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/types";
import { AllExtensions } from "@matrix-org/react-sdk-module-api/lib/types/extensions";

Check failure on line 20 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/types/extensions' or its corresponding type declarations.

Check failure on line 20 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/types/extensions' or its corresponding type declarations.
import { DefaultCryptoSetupExtensions } from "@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions";

Check failure on line 21 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions' or its corresponding type declarations.

Check failure on line 21 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions' or its corresponding type declarations.
import { DefaultExperimentalExtensions } from "@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions";

Check failure on line 22 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions' or its corresponding type declarations.

Check failure on line 22 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions' or its corresponding type declarations.
import { RuntimeModule } from "@matrix-org/react-sdk-module-api";

import { AppModule } from "./AppModule";
import { ModuleFactory } from "./ModuleFactory";
Expand All @@ -29,6 +33,13 @@
export class ModuleRunner {
public static readonly instance = new ModuleRunner();

public className: string = ModuleRunner.name;

public extensions: AllExtensions = {
cryptoSetup: new DefaultCryptoSetupExtensions(),
experimental: new DefaultExperimentalExtensions(),
};

private modules: AppModule[] = [];

private constructor() {
Expand All @@ -42,6 +53,11 @@
*/
public reset(): void {
this.modules = [];

this.extensions = {
cryptoSetup: new DefaultCryptoSetupExtensions(),
experimental: new DefaultExperimentalExtensions(),
};
}

/**
Expand All @@ -66,13 +82,68 @@
return merged;
}


/**
* Ensure we register extensions provided by the modules
*/
private updateExtensions(): void {
const cryptoSetupExtensions: Array<RuntimeModule> = [];
const experimentalExtensions: Array<RuntimeModule> = [];

this.modules.forEach((m) => {
/* Record the cryptoSetup extensions if any */
if (m.module.extensions?.cryptoSetup) {

Check failure on line 95 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.

Check failure on line 95 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.
cryptoSetupExtensions.push(m.module);
}

/* Record the experimantal extensions if any */
if (m.module.extensions?.experimental) {

Check failure on line 100 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.

Check failure on line 100 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.
experimentalExtensions.push(m.module);
}
});

/* Enforce rule that only a single module may provide a given extension */
if (cryptoSetupExtensions.length > 1) {
throw new Error(
`cryptoSetup extension is provided by modules ${cryptoSetupExtensions
.map((m) => m.moduleName)

Check failure on line 109 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'moduleName' does not exist on type 'RuntimeModule'.

Check failure on line 109 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'moduleName' does not exist on type 'RuntimeModule'.
.join(", ")}, but can only be provided by a single module`,
);
}
if (experimentalExtensions.length > 1) {
throw new Error(
`experimental extension is provided by modules ${experimentalExtensions
.map((m) => m.moduleName)

Check failure on line 116 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'moduleName' does not exist on type 'RuntimeModule'.

Check failure on line 116 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'moduleName' does not exist on type 'RuntimeModule'.
.join(", ")}, but can only be provided by a single module`,
);
}

/* Override the default extension if extension was provided by a module */
if (cryptoSetupExtensions.length == 1) {
this.extensions.cryptoSetup = cryptoSetupExtensions[0].extensions?.cryptoSetup;

Check failure on line 123 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.

Check failure on line 123 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.
}

if (experimentalExtensions.length == 1) {
this.extensions.experimental = cryptoSetupExtensions[0].extensions?.experimental;

Check failure on line 127 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.

Check failure on line 127 in src/modules/ModuleRunner.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'extensions' does not exist on type 'RuntimeModule'.
}
}

/**
* Registers a factory which creates a module for later loading. The factory
* will be called immediately.
* @param factory The module factory.
*/
public registerModule(factory: ModuleFactory): void {
this.modules.push(new AppModule(factory));

/**
* Check if the new module provides any extensions, and also ensure a given extension is only provided by a single runtime module
* Slightly inefficient to do this on each registration, but avoids changes to element-web installer code
* Also note that this require that the statement in the comment above, about immediately calling the factory, is in fact true
* (otherwise wrapped RuntimeModules will not be available)
*/

this.updateExtensions();
}

/**
Expand Down
12 changes: 10 additions & 2 deletions src/toasts/SetupEncryptionToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import SetupEncryptionDialog from "../components/views/dialogs/security/SetupEnc
import { accessSecretStorage } from "../SecurityManager";
import ToastStore from "../stores/ToastStore";
import GenericToast from "../components/views/toasts/GenericToast";
import SecurityCustomisations from "../customisations/Security";
import { ModuleRunner } from "../modules/ModuleRunner";
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
import Spinner from "../components/views/elements/Spinner";

const TOAST_KEY = "setupencryption";
Expand Down Expand Up @@ -79,7 +80,14 @@ const onReject = (): void => {
};

export const showToast = (kind: Kind): void => {
if (SecurityCustomisations.setupEncryptionNeeded?.(kind)) {
// if (SecurityCustomisations.setupEncryptionNeeded?.(kind)) {
// return;
// }

if (ModuleRunner.instance.extensions.cryptoSetup?.setupEncryptionNeeded({
kind: kind as any,
storeProvider: { getInstance: () => SetupEncryptionStore.sharedInstance() },
})) {
return;
}

Expand Down
Loading