Acquire a new session before enacting deactivation

Fixes https://github.com/vector-im/riot-web/issues/13645

Every time the checkbox value changes we acquire a new session now. This avoids us asking the server to change its direction partway through the request.

This causes a bit of UI jerk as the dialog goes from auth -> loading -> auth, however it's better than the alternative of reworking the entire UIA structure to support the `authData` dict changing. Originally this commit consisted of a `disabled` flag on the `InteractiveAuth` component which carried through to the stage's component, however it turns out that stack doesn't respect changes to the `authData` prop, which means the session ID we eventually send down is wrong (`erase: false` instead of the one with `erase: true`). Therefore, we do some logic to ensure we remount `InteractiveAuth` completely.

Further work in this area is described in https://github.com/vector-im/riot-web/issues/13646
This commit is contained in:
Travis Ralston 2020-05-12 17:17:17 -06:00
parent 5783a9359e
commit c0632d0195

View file

@ -34,6 +34,7 @@ export default class DeactivateAccountDialog extends React.Component {
shouldErase: false,
errStr: null,
authData: null, // for UIA
authEnabled: true, // see usages for information
// A few strings that are passed to InteractiveAuth for design or are displayed
// next to the InteractiveAuth component.
@ -42,21 +43,7 @@ export default class DeactivateAccountDialog extends React.Component {
continueKind: null,
};
MatrixClientPeg.get().deactivateAccount(null, false).then(r => {
// If we got here, oops. The server didn't require any auth.
// Our application lifecycle will catch the error and do the logout bits.
// We'll try to log something in an vain attempt to record what happened (storage
// is also obliterated on logout).
console.warn("User's account got deactivated without confirmation: Server had no auth");
this.setState({errStr: _t("Server did not require any authentication")});
}).catch(e => {
if (e && e.httpStatus === 401 && e.data) {
// Valid UIA response
this.setState({authData: e.data});
} else {
this.setState({errStr: _t("Server did not return valid authentication information.")});
}
});
this._initAuth(/* shouldErase= */false);
}
_onStagePhaseChange = (stage, phase) => {
@ -124,13 +111,40 @@ export default class DeactivateAccountDialog extends React.Component {
_onEraseFieldChange = (ev) => {
this.setState({
shouldErase: ev.target.checked,
// Disable the auth form because we're going to have to reinitialize the auth
// information. We do this because we can't modify the parameters in the UIA
// session, and the user will have selected something which changes the request.
// Therefore, we throw away the last auth session and try a new one.
authEnabled: false,
});
// As mentioned above, set up for auth again to get updated UIA session info
this._initAuth(/* shouldErase= */ev.target.checked);
};
_onCancel() {
this.props.onFinished(false);
}
_initAuth(shouldErase) {
MatrixClientPeg.get().deactivateAccount(null, shouldErase).then(r => {
// If we got here, oops. The server didn't require any auth.
// Our application lifecycle will catch the error and do the logout bits.
// We'll try to log something in an vain attempt to record what happened (storage
// is also obliterated on logout).
console.warn("User's account got deactivated without confirmation: Server had no auth");
this.setState({errStr: _t("Server did not require any authentication")});
}).catch(e => {
if (e && e.httpStatus === 401 && e.data) {
// Valid UIA response
this.setState({authData: e.data, authEnabled: true});
} else {
this.setState({errStr: _t("Server did not return valid authentication information.")});
}
});
};
render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
@ -142,7 +156,7 @@ export default class DeactivateAccountDialog extends React.Component {
}
let auth = <div>{_t("Loading...")}</div>;
if (this.state.authData) {
if (this.state.authData && this.state.authEnabled) {
auth = (
<div>
{this.state.bodyText}