Convert SecureBackupPanel to TS
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>pull/21833/head
parent
9051df45c1
commit
0bae01c824
|
@ -27,13 +27,29 @@ import QuestionDialog from '../dialogs/QuestionDialog';
|
||||||
import RestoreKeyBackupDialog from '../dialogs/security/RestoreKeyBackupDialog';
|
import RestoreKeyBackupDialog from '../dialogs/security/RestoreKeyBackupDialog';
|
||||||
import { accessSecretStorage } from '../../../SecurityManager';
|
import { accessSecretStorage } from '../../../SecurityManager';
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup";
|
||||||
|
import { TrustInfo } from "matrix-js-sdk/src/crypto/backup";
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
loading: boolean;
|
||||||
|
error: null;
|
||||||
|
backupKeyStored: boolean;
|
||||||
|
backupKeyCached: boolean;
|
||||||
|
backupKeyWellFormed: boolean;
|
||||||
|
secretStorageKeyInAccount: boolean;
|
||||||
|
secretStorageReady: boolean;
|
||||||
|
backupInfo: IKeyBackupInfo;
|
||||||
|
backupSigStatus: TrustInfo;
|
||||||
|
sessionsRemaining: number;
|
||||||
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.settings.SecureBackupPanel")
|
@replaceableComponent("views.settings.SecureBackupPanel")
|
||||||
export default class SecureBackupPanel extends React.PureComponent {
|
export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
||||||
constructor(props) {
|
private unmounted = false;
|
||||||
|
|
||||||
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this._unmounted = false;
|
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: true,
|
loading: true,
|
||||||
error: null,
|
error: null,
|
||||||
|
@ -48,42 +64,42 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
public componentDidMount(): void {
|
||||||
this._checkKeyBackupStatus();
|
this.checkKeyBackupStatus();
|
||||||
|
|
||||||
MatrixClientPeg.get().on('crypto.keyBackupStatus', this._onKeyBackupStatus);
|
MatrixClientPeg.get().on('crypto.keyBackupStatus', this.onKeyBackupStatus);
|
||||||
MatrixClientPeg.get().on(
|
MatrixClientPeg.get().on(
|
||||||
'crypto.keyBackupSessionsRemaining',
|
'crypto.keyBackupSessionsRemaining',
|
||||||
this._onKeyBackupSessionsRemaining,
|
this.onKeyBackupSessionsRemaining,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
public componentWillUnmount(): void {
|
||||||
this._unmounted = true;
|
this.unmounted = true;
|
||||||
|
|
||||||
if (MatrixClientPeg.get()) {
|
if (MatrixClientPeg.get()) {
|
||||||
MatrixClientPeg.get().removeListener('crypto.keyBackupStatus', this._onKeyBackupStatus);
|
MatrixClientPeg.get().removeListener('crypto.keyBackupStatus', this.onKeyBackupStatus);
|
||||||
MatrixClientPeg.get().removeListener(
|
MatrixClientPeg.get().removeListener(
|
||||||
'crypto.keyBackupSessionsRemaining',
|
'crypto.keyBackupSessionsRemaining',
|
||||||
this._onKeyBackupSessionsRemaining,
|
this.onKeyBackupSessionsRemaining,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyBackupSessionsRemaining = (sessionsRemaining) => {
|
private onKeyBackupSessionsRemaining = (sessionsRemaining: number): void => {
|
||||||
this.setState({
|
this.setState({
|
||||||
sessionsRemaining,
|
sessionsRemaining,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
_onKeyBackupStatus = () => {
|
private onKeyBackupStatus = (): void => {
|
||||||
// This just loads the current backup status rather than forcing
|
// This just loads the current backup status rather than forcing
|
||||||
// a re-check otherwise we risk causing infinite loops
|
// a re-check otherwise we risk causing infinite loops
|
||||||
this._loadBackupStatus();
|
this.loadBackupStatus();
|
||||||
}
|
};
|
||||||
|
|
||||||
async _checkKeyBackupStatus() {
|
private async checkKeyBackupStatus(): Promise<void> {
|
||||||
this._getUpdatedDiagnostics();
|
this.getUpdatedDiagnostics();
|
||||||
try {
|
try {
|
||||||
const { backupInfo, trustInfo } = await MatrixClientPeg.get().checkKeyBackup();
|
const { backupInfo, trustInfo } = await MatrixClientPeg.get().checkKeyBackup();
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -94,7 +110,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Unable to fetch check backup status", e);
|
console.log("Unable to fetch check backup status", e);
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
error: e,
|
error: e,
|
||||||
|
@ -104,13 +120,13 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _loadBackupStatus() {
|
private async loadBackupStatus(): Promise<void> {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
this._getUpdatedDiagnostics();
|
this.getUpdatedDiagnostics();
|
||||||
try {
|
try {
|
||||||
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
|
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
|
||||||
const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo);
|
const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo);
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
@ -119,7 +135,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Unable to fetch key backup status", e);
|
console.log("Unable to fetch key backup status", e);
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
error: e,
|
error: e,
|
||||||
|
@ -129,7 +145,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getUpdatedDiagnostics() {
|
private async getUpdatedDiagnostics(): Promise<void> {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const secretStorage = cli.crypto.secretStorage;
|
const secretStorage = cli.crypto.secretStorage;
|
||||||
|
|
||||||
|
@ -140,7 +156,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
const secretStorageKeyInAccount = await secretStorage.hasKey();
|
const secretStorageKeyInAccount = await secretStorage.hasKey();
|
||||||
const secretStorageReady = await cli.isSecretStorageReady();
|
const secretStorageReady = await cli.isSecretStorageReady();
|
||||||
|
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
backupKeyStored,
|
backupKeyStored,
|
||||||
backupKeyCached,
|
backupKeyCached,
|
||||||
|
@ -150,18 +166,18 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_startNewBackup = () => {
|
private startNewBackup = (): void => {
|
||||||
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
|
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
|
||||||
import('../../../async-components/views/dialogs/security/CreateKeyBackupDialog'),
|
import('../../../async-components/views/dialogs/security/CreateKeyBackupDialog'),
|
||||||
{
|
{
|
||||||
onFinished: () => {
|
onFinished: () => {
|
||||||
this._loadBackupStatus();
|
this.loadBackupStatus();
|
||||||
},
|
},
|
||||||
}, null, /* priority = */ false, /* static = */ true,
|
}, null, /* priority = */ false, /* static = */ true,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
_deleteBackup = () => {
|
private deleteBackup = (): void => {
|
||||||
Modal.createTrackedDialog('Delete Backup', '', QuestionDialog, {
|
Modal.createTrackedDialog('Delete Backup', '', QuestionDialog, {
|
||||||
title: _t('Delete Backup'),
|
title: _t('Delete Backup'),
|
||||||
description: _t(
|
description: _t(
|
||||||
|
@ -174,33 +190,33 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
if (!proceed) return;
|
if (!proceed) return;
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
MatrixClientPeg.get().deleteKeyBackupVersion(this.state.backupInfo.version).then(() => {
|
MatrixClientPeg.get().deleteKeyBackupVersion(this.state.backupInfo.version).then(() => {
|
||||||
this._loadBackupStatus();
|
this.loadBackupStatus();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
_restoreBackup = async () => {
|
private restoreBackup = async (): Promise<void> => {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Restore Backup', '', RestoreKeyBackupDialog, null, null,
|
'Restore Backup', '', RestoreKeyBackupDialog, null, null,
|
||||||
/* priority = */ false, /* static = */ true,
|
/* priority = */ false, /* static = */ true,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
_resetSecretStorage = async () => {
|
private resetSecretStorage = async (): Promise<void> => {
|
||||||
this.setState({ error: null });
|
this.setState({ error: null });
|
||||||
try {
|
try {
|
||||||
await accessSecretStorage(() => { }, /* forceReset = */ true);
|
await accessSecretStorage(async () => { }, /* forceReset = */ true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error resetting secret storage", e);
|
console.error("Error resetting secret storage", e);
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this.setState({ error: e });
|
this.setState({ error: e });
|
||||||
}
|
}
|
||||||
if (this._unmounted) return;
|
if (this.unmounted) return;
|
||||||
this._loadBackupStatus();
|
this.loadBackupStatus();
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
public render(): JSX.Element {
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
|
@ -261,7 +277,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let backupSigStatuses = backupSigStatus.sigs.map((sig, i) => {
|
let backupSigStatuses: React.ReactNode = backupSigStatus.sigs.map((sig, i) => {
|
||||||
const deviceName = sig.device ? (sig.device.getDisplayName() || sig.device.deviceId) : null;
|
const deviceName = sig.device ? (sig.device.getDisplayName() || sig.device.deviceId) : null;
|
||||||
const validity = sub =>
|
const validity = sub =>
|
||||||
<span className={sig.valid ? 'mx_SecureBackupPanel_sigValid' : 'mx_SecureBackupPanel_sigInvalid'}>
|
<span className={sig.valid ? 'mx_SecureBackupPanel_sigValid' : 'mx_SecureBackupPanel_sigInvalid'}>
|
||||||
|
@ -369,14 +385,14 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
</>;
|
</>;
|
||||||
|
|
||||||
actions.push(
|
actions.push(
|
||||||
<AccessibleButton key="restore" kind="primary" onClick={this._restoreBackup}>
|
<AccessibleButton key="restore" kind="primary" onClick={this.restoreBackup}>
|
||||||
{ restoreButtonCaption }
|
{ restoreButtonCaption }
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isSecureBackupRequired()) {
|
if (!isSecureBackupRequired()) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<AccessibleButton key="delete" kind="danger" onClick={this._deleteBackup}>
|
<AccessibleButton key="delete" kind="danger" onClick={this.deleteBackup}>
|
||||||
{ _t("Delete Backup") }
|
{ _t("Delete Backup") }
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
);
|
);
|
||||||
|
@ -390,7 +406,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
<p>{ _t("Back up your keys before signing out to avoid losing them.") }</p>
|
<p>{ _t("Back up your keys before signing out to avoid losing them.") }</p>
|
||||||
</>;
|
</>;
|
||||||
actions.push(
|
actions.push(
|
||||||
<AccessibleButton key="setup" kind="primary" onClick={this._startNewBackup}>
|
<AccessibleButton key="setup" kind="primary" onClick={this.startNewBackup}>
|
||||||
{ _t("Set up") }
|
{ _t("Set up") }
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
);
|
);
|
||||||
|
@ -398,7 +414,7 @@ export default class SecureBackupPanel extends React.PureComponent {
|
||||||
|
|
||||||
if (secretStorageKeyInAccount) {
|
if (secretStorageKeyInAccount) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<AccessibleButton key="reset" kind="danger" onClick={this._resetSecretStorage}>
|
<AccessibleButton key="reset" kind="danger" onClick={this.resetSecretStorage}>
|
||||||
{ _t("Reset") }
|
{ _t("Reset") }
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
);
|
);
|
Loading…
Reference in New Issue