diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js index 87228b4733..104419f2ef 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.js +++ b/src/components/views/dialogs/DeactivateAccountDialog.js @@ -33,10 +33,21 @@ export default class DeactivateAccountDialog extends React.Component { this._onOk = this._onOk.bind(this); this._onCancel = this._onCancel.bind(this); this._onPasswordFieldChange = this._onPasswordFieldChange.bind(this); + this._onEraseFieldChange = this._onEraseFieldChange.bind(this); + + const deactivationPreferences = + MatrixClientPeg.get().getAccountData('im.riot.account_deactivation_preferences'); + + const shouldErase = ( + deactivationPreferences && + deactivationPreferences.getContent() && + deactivationPreferences.getContent().shouldErase + ) || false; this.state = { confirmButtonEnabled: false, busy: false, + shouldErase, errStr: null, }; } @@ -47,19 +58,55 @@ export default class DeactivateAccountDialog extends React.Component { }); } - _onOk() { - // This assumes that the HS requires password UI auth - // for this endpoint. In reality it could be any UI auth. + _onEraseFieldChange(ev) { + this.setState({ + shouldErase: ev.target.checked, + }); + } + + async _onOk() { this.setState({busy: true}); - MatrixClientPeg.get().deactivateAccount({ - type: 'm.login.password', - user: MatrixClientPeg.get().credentials.userId, - password: this._passwordField.value, - }).done(() => { - Analytics.trackEvent('Account', 'Deactivate Account'); - Lifecycle.onLoggedOut(); - this.props.onFinished(false); - }, (err) => { + + // Before we deactivate the account insert an event into + // the user's account data indicating that they wish to be + // erased from the homeserver. + // + // We do this because the API for erasing after deactivation + // might not be supported by the connected homeserver. Leaving + // an indication in account data is only best-effort, and + // in the worse case, the HS maintainer would have to run a + // script to erase deactivated accounts that have shouldErase + // set to true in im.riot.account_deactivation_preferences. + // + // Note: The preferences are scoped to Riot, hence the + // "im.riot..." event type. + // + // Note: This may have already been set on previous attempts + // where, for example, the user entered the wrong password. + // This is fine because the UI always indicates the preference + // prior to us calling `deactivateAccount`. + try { + await MatrixClientPeg.get().setAccountData('im.riot.account_deactivation_preferences', { + shouldErase: this.state.shouldErase, + }); + } catch (err) { + this.setState({ + busy: false, + errStr: _t('Failed to indicate account erasure'), + }); + return; + } + + try { + // This assumes that the HS requires password UI auth + // for this endpoint. In reality it could be any UI auth. + const auth = { + type: 'm.login.password', + user: MatrixClientPeg.get().credentials.userId, + password: this._passwordField.value, + }; + await MatrixClientPeg.get().deactivateAccount(auth, this.state.shouldErase); + } catch (err) { let errStr = _t('Unknown error'); // https://matrix.org/jira/browse/SYN-744 if (err.httpStatus == 401 || err.httpStatus == 403) { @@ -70,7 +117,12 @@ export default class DeactivateAccountDialog extends React.Component { busy: false, errStr: errStr, }); - }); + return; + } + + Analytics.trackEvent('Account', 'Deactivate Account'); + Lifecycle.onLoggedOut(); + this.props.onFinished(false); } _onCancel() { @@ -105,21 +157,56 @@ export default class DeactivateAccountDialog extends React.Component { onFinished={this.props.onFinished} onEnterPressed={this.onOk} titleClass="danger" - title={_t("Deactivate Account")}> + title={_t("Deactivate Account")} + >
{ _t("This will make your account permanently unusable. You will not be able to re-register the same user ID.") }
+{ _t( + "This will make your account permanently unusable. " + + "You will not be able to log in, and no one will be able " + + "to re-register the same user ID. " + + "This action is irreversible.", + {}, + { b: (sub) => { sub } }, + ) }
-{ _t("This action is irreversible.") }
+{ _t( + "Deactivating your account does not by default erase messages you have sent. " + + "If you would like to erase your messages, please tick the box below.", + {}, + { b: (sub) => { sub } }, + ) }
-{ _t("To continue, please enter your password.") }
+{ _t( + "Message visibility in Matrix is similar to email. " + + "Erasing your messages means that messages have you sent will not be shared with " + + "any new or unregistered users, but registered users who already had access to " + + "these messages will still have access to their copy.", + ) }
-{ _t("Password") }:
+{ _t("To continue, please enter your password:") }
{this._passwordField = e;}} className={passwordBoxClass} /> + ++ +
+ { error }