Secure backup prompt
This commit is contained in:
parent
cf52974e09
commit
b8f6bd1664
3 changed files with 56 additions and 13 deletions
|
@ -292,13 +292,20 @@ export default class DeviceListener {
|
||||||
await crypto.getUserDeviceInfo([cli.getSafeUserId()]);
|
await crypto.getUserDeviceInfo([cli.getSafeUserId()]);
|
||||||
|
|
||||||
// cross signing isn't enabled - nag to enable it
|
// cross signing isn't enabled - nag to enable it
|
||||||
// There are 2 different toasts for:
|
// There are 3 different toasts for:
|
||||||
if (!(await crypto.getCrossSigningKeyId()) && (await crypto.userHasCrossSigningKeys())) {
|
if (!(await crypto.getCrossSigningKeyId()) && (await crypto.userHasCrossSigningKeys())) {
|
||||||
// Cross-signing on account but this device doesn't trust the master key (verify this session)
|
// Toast 1. Cross-signing on account but this device doesn't trust the master key (verify this session)
|
||||||
showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION);
|
showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION);
|
||||||
this.checkKeyBackupStatus();
|
this.checkKeyBackupStatus();
|
||||||
} else {
|
} else {
|
||||||
// No cross-signing or key backup on account (set up encryption)
|
const backupInfo = await this.getKeyBackupInfo();
|
||||||
|
if (backupInfo) {
|
||||||
|
// Toast 2: Key backup is enabled but recovery (4S) is not set up: prompt user to set up recovery.
|
||||||
|
// Since we now enable key backup at registration time, this will be the common case for
|
||||||
|
// new users.
|
||||||
|
showSetupEncryptionToast(SetupKind.SET_UP_RECOVERY);
|
||||||
|
} else {
|
||||||
|
// Toast 3: No cross-signing or key backup on account (set up encryption)
|
||||||
await cli.waitForClientWellKnown();
|
await cli.waitForClientWellKnown();
|
||||||
if (isSecureBackupRequired(cli) && isLoggedIn()) {
|
if (isSecureBackupRequired(cli) && isLoggedIn()) {
|
||||||
// If we're meant to set up, and Secure Backup is required,
|
// If we're meant to set up, and Secure Backup is required,
|
||||||
|
@ -310,6 +317,7 @@ export default class DeviceListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This needs to be done after awaiting on getUserDeviceInfo() above, so
|
// This needs to be done after awaiting on getUserDeviceInfo() above, so
|
||||||
// we make sure we get the devices after the fetch is done.
|
// we make sure we get the devices after the fetch is done.
|
||||||
|
|
|
@ -912,6 +912,9 @@
|
||||||
"warning": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings."
|
"warning": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings."
|
||||||
},
|
},
|
||||||
"reset_all_button": "Forgotten or lost all recovery methods? <a>Reset all</a>",
|
"reset_all_button": "Forgotten or lost all recovery methods? <a>Reset all</a>",
|
||||||
|
"set_up_recovery": "Set up recovery",
|
||||||
|
"set_up_recovery_later": "Not now",
|
||||||
|
"set_up_recovery_toast_title": "Set up recovery to protect your account",
|
||||||
"set_up_toast_description": "Safeguard against losing access to encrypted messages & data",
|
"set_up_toast_description": "Safeguard against losing access to encrypted messages & data",
|
||||||
"set_up_toast_title": "Set up Secure Backup",
|
"set_up_toast_title": "Set up Secure Backup",
|
||||||
"setup_secure_backup": {
|
"setup_secure_backup": {
|
||||||
|
|
|
@ -6,6 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import KeyboardIcon from "@vector-im/compound-design-tokens/assets/web/icons/key";
|
||||||
|
import { ComponentType } from "react";
|
||||||
|
|
||||||
import Modal from "../Modal";
|
import Modal from "../Modal";
|
||||||
import { _t } from "../languageHandler";
|
import { _t } from "../languageHandler";
|
||||||
import DeviceListener from "../DeviceListener";
|
import DeviceListener from "../DeviceListener";
|
||||||
|
@ -23,33 +26,61 @@ const getTitle = (kind: Kind): string => {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind.SET_UP_ENCRYPTION:
|
case Kind.SET_UP_ENCRYPTION:
|
||||||
return _t("encryption|set_up_toast_title");
|
return _t("encryption|set_up_toast_title");
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return _t("encryption|set_up_recovery_toast_title");
|
||||||
case Kind.VERIFY_THIS_SESSION:
|
case Kind.VERIFY_THIS_SESSION:
|
||||||
return _t("encryption|verify_toast_title");
|
return _t("encryption|verify_toast_title");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getIcon = (kind: Kind): string => {
|
const getIcon = (kind: Kind): string | undefined => {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind.SET_UP_ENCRYPTION:
|
case Kind.SET_UP_ENCRYPTION:
|
||||||
return "secure_backup";
|
return "secure_backup";
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return undefined;
|
||||||
case Kind.VERIFY_THIS_SESSION:
|
case Kind.VERIFY_THIS_SESSION:
|
||||||
return "verification_warning";
|
return "verification_warning";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Gets the icon displayed on the prinary button
|
||||||
|
const getPrimaryIcon = (kind: Kind): ComponentType<React.SVGAttributes<SVGElement>> | undefined => {
|
||||||
|
switch (kind) {
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return KeyboardIcon;
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getSetupCaption = (kind: Kind): string => {
|
const getSetupCaption = (kind: Kind): string => {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind.SET_UP_ENCRYPTION:
|
case Kind.SET_UP_ENCRYPTION:
|
||||||
return _t("action|continue");
|
return _t("action|continue");
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return _t("encryption|set_up_recovery");
|
||||||
case Kind.VERIFY_THIS_SESSION:
|
case Kind.VERIFY_THIS_SESSION:
|
||||||
return _t("action|verify");
|
return _t("action|verify");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSecondaryButtonLabel = (kind: Kind): string => {
|
||||||
|
switch (kind) {
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return _t("encryption|set_up_recovery_later");
|
||||||
|
case Kind.SET_UP_ENCRYPTION:
|
||||||
|
case Kind.VERIFY_THIS_SESSION:
|
||||||
|
return _t("encryption|verification|unverified_sessions_toast_reject");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getDescription = (kind: Kind): string => {
|
const getDescription = (kind: Kind): string => {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind.SET_UP_ENCRYPTION:
|
case Kind.SET_UP_ENCRYPTION:
|
||||||
return _t("encryption|set_up_toast_description");
|
return _t("encryption|set_up_toast_description");
|
||||||
|
case Kind.SET_UP_RECOVERY:
|
||||||
|
return _t("encryption|set_up_recovery_toast_title");
|
||||||
case Kind.VERIFY_THIS_SESSION:
|
case Kind.VERIFY_THIS_SESSION:
|
||||||
return _t("encryption|verify_toast_description");
|
return _t("encryption|verify_toast_description");
|
||||||
}
|
}
|
||||||
|
@ -57,6 +88,7 @@ const getDescription = (kind: Kind): string => {
|
||||||
|
|
||||||
export enum Kind {
|
export enum Kind {
|
||||||
SET_UP_ENCRYPTION = "set_up_encryption",
|
SET_UP_ENCRYPTION = "set_up_encryption",
|
||||||
|
SET_UP_RECOVERY = "set_up_recovery",
|
||||||
VERIFY_THIS_SESSION = "verify_this_session",
|
VERIFY_THIS_SESSION = "verify_this_session",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +133,9 @@ export const showToast = (kind: Kind): void => {
|
||||||
description: getDescription(kind),
|
description: getDescription(kind),
|
||||||
primaryLabel: getSetupCaption(kind),
|
primaryLabel: getSetupCaption(kind),
|
||||||
onPrimaryClick: onAccept,
|
onPrimaryClick: onAccept,
|
||||||
secondaryLabel: _t("encryption|verification|unverified_sessions_toast_reject"),
|
secondaryLabel: getSecondaryButtonLabel(kind),
|
||||||
onSecondaryClick: onReject,
|
onSecondaryClick: onReject,
|
||||||
destructive: "secondary",
|
PrimaryIcon: getPrimaryIcon(kind),
|
||||||
},
|
},
|
||||||
component: GenericToast,
|
component: GenericToast,
|
||||||
priority: kind === Kind.VERIFY_THIS_SESSION ? 95 : 40,
|
priority: kind === Kind.VERIFY_THIS_SESSION ? 95 : 40,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue