Support HS-preferred Secure Backup setup methods

This adds support for the `secure_backup_setup_methods` key, which allows HS
admins to state that Element should simplify down to only one setup method,
rather than offering both.

Fixes https://github.com/vector-im/element-web/issues/15238
This commit is contained in:
J. Ryan Stinnett 2020-09-21 15:48:47 +01:00
parent 8ec7e7c714
commit 115c7ccd4e
3 changed files with 67 additions and 29 deletions

View file

@ -31,7 +31,7 @@ import AccessibleButton from "../../../../components/views/elements/AccessibleBu
import DialogButtons from "../../../../components/views/elements/DialogButtons"; import DialogButtons from "../../../../components/views/elements/DialogButtons";
import InlineSpinner from "../../../../components/views/elements/InlineSpinner"; import InlineSpinner from "../../../../components/views/elements/InlineSpinner";
import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog"; import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog";
import { isSecureBackupRequired } from '../../../../utils/WellKnownUtils'; import { getSecureBackupSetupMethods, isSecureBackupRequired } from '../../../../utils/WellKnownUtils';
const PHASE_LOADING = 0; const PHASE_LOADING = 0;
const PHASE_LOADERROR = 1; const PHASE_LOADERROR = 1;
@ -87,10 +87,16 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
canUploadKeysWithPasswordOnly: null, canUploadKeysWithPasswordOnly: null,
accountPassword: props.accountPassword || "", accountPassword: props.accountPassword || "",
accountPasswordCorrect: null, accountPasswordCorrect: null,
passPhraseKeySelected: CREATE_STORAGE_OPTION_KEY,
canSkip: !isSecureBackupRequired(), canSkip: !isSecureBackupRequired(),
}; };
const setupMethods = getSecureBackupSetupMethods();
if (setupMethods.includes("key")) {
this.state.passPhraseKeySelected = CREATE_STORAGE_OPTION_KEY;
} else {
this.state.passPhraseKeySelected = CREATE_STORAGE_OPTION_PASSPHRASE;
}
this._passphraseField = createRef(); this._passphraseField = createRef();
this._fetchBackupInfo(); this._fetchBackupInfo();
@ -441,39 +447,55 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
}); });
} }
_renderOptionKey() {
return (
<StyledRadioButton
key={CREATE_STORAGE_OPTION_KEY}
value={CREATE_STORAGE_OPTION_KEY}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATE_STORAGE_OPTION_KEY}
outlined
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_secureBackup"></span>
{_t("Generate a Security Key")}
</div>
<div>{_t("Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.")}</div>
</StyledRadioButton>
);
}
_renderOptionPassphrase() {
return (
<StyledRadioButton
key={CREATE_STORAGE_OPTION_PASSPHRASE}
value={CREATE_STORAGE_OPTION_PASSPHRASE}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATE_STORAGE_OPTION_PASSPHRASE}
outlined
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_securePhrase"></span>
{_t("Enter a Security Phrase")}
</div>
<div>{_t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.")}</div>
</StyledRadioButton>
);
}
_renderPhaseChooseKeyPassphrase() { _renderPhaseChooseKeyPassphrase() {
const setupMethods = getSecureBackupSetupMethods();
const optionKey = setupMethods.includes("key") ? this._renderOptionKey() : null;
const optionPassphrase = setupMethods.includes("passphrase") ? this._renderOptionPassphrase() : null;
return <form onSubmit={this._onChooseKeyPassphraseFormSubmit}> return <form onSubmit={this._onChooseKeyPassphraseFormSubmit}>
<p className="mx_CreateSecretStorageDialog_centeredBody">{_t( <p className="mx_CreateSecretStorageDialog_centeredBody">{_t(
"Safeguard against losing access to encrypted messages & data by " + "Safeguard against losing access to encrypted messages & data by " +
"backing up encryption keys on your server.", "backing up encryption keys on your server.",
)}</p> )}</p>
<div className="mx_CreateSecretStorageDialog_primaryContainer" role="radiogroup" onChange={this._onKeyPassphraseChange}> <div className="mx_CreateSecretStorageDialog_primaryContainer" role="radiogroup" onChange={this._onKeyPassphraseChange}>
<StyledRadioButton {optionKey}
key={CREATE_STORAGE_OPTION_KEY} {optionPassphrase}
value={CREATE_STORAGE_OPTION_KEY}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATE_STORAGE_OPTION_KEY}
outlined
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_secureBackup"></span>
{_t("Generate a Security Key")}
</div>
<div>{_t("Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.")}</div>
</StyledRadioButton>
<StyledRadioButton
key={CREATE_STORAGE_OPTION_PASSPHRASE}
value={CREATE_STORAGE_OPTION_PASSPHRASE}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATE_STORAGE_OPTION_PASSPHRASE}
outlined
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_securePhrase"></span>
{_t("Enter a Security Phrase")}
</div>
<div>{_t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.")}</div>
</StyledRadioButton>
</div> </div>
<DialogButtons <DialogButtons
primaryButton={_t("Continue")} primaryButton={_t("Continue")}

View file

@ -2266,11 +2266,11 @@
"Success!": "Success!", "Success!": "Success!",
"Create key backup": "Create key backup", "Create key backup": "Create key backup",
"Unable to create key backup": "Unable to create key backup", "Unable to create key backup": "Unable to create key backup",
"Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.",
"Generate a Security Key": "Generate a Security Key", "Generate a Security Key": "Generate a Security Key",
"Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.": "Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.", "Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.": "Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.",
"Enter a Security Phrase": "Enter a Security Phrase", "Enter a Security Phrase": "Enter a Security Phrase",
"Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Use a secret phrase only you know, and optionally save a Security Key to use for backup.", "Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Use a secret phrase only you know, and optionally save a Security Key to use for backup.",
"Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.",
"Enter your account password to confirm the upgrade:": "Enter your account password to confirm the upgrade:", "Enter your account password to confirm the upgrade:": "Enter your account password to confirm the upgrade:",
"Restore your key backup to upgrade your encryption": "Restore your key backup to upgrade your encryption", "Restore your key backup to upgrade your encryption": "Restore your key backup to upgrade your encryption",
"Restore": "Restore", "Restore": "Restore",

View file

@ -38,3 +38,19 @@ export function isSecureBackupRequired(): boolean {
const wellKnown = getE2EEWellKnown(); const wellKnown = getE2EEWellKnown();
return wellKnown && wellKnown["secure_backup_required"] === true; return wellKnown && wellKnown["secure_backup_required"] === true;
} }
export function getSecureBackupSetupMethods(): string[] {
const wellKnown = getE2EEWellKnown();
if (
!wellKnown ||
!wellKnown["secure_backup_setup_methods"] ||
!wellKnown["secure_backup_setup_methods"].length ||
!(
wellKnown["secure_backup_setup_methods"].includes("key") ||
wellKnown["secure_backup_setup_methods"].includes("passphrase")
)
) {
return ["key", "passphrase"];
}
return wellKnown["secure_backup_setup_methods"];
}