Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Allow user to control if they are signed out of all sessions when res…
Browse files Browse the repository at this point in the history
…etting password
  • Loading branch information
hughns committed Apr 8, 2022
1 parent 03d0969 commit 9825e44
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 28 deletions.
11 changes: 9 additions & 2 deletions src/PasswordReset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default class PasswordReset {
private clientSecret: string;
private password: string;
private sessionId: string;
private logoutDevices: boolean;

/**
* Configure the endpoints for password resetting.
Expand All @@ -50,10 +51,16 @@ export default class PasswordReset {
* sending an email to the provided email address.
* @param {string} emailAddress The email address
* @param {string} newPassword The new password for the account.
* @param {boolean} logoutDevices Should all devices be signed out after the reset? Defaults to `true`.
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
*/
public resetPassword(emailAddress: string, newPassword: string): Promise<IRequestTokenResponse> {
public resetPassword(
emailAddress: string,
newPassword: string,
logoutDevices = true,
): Promise<IRequestTokenResponse> {
this.password = newPassword;
this.logoutDevices = logoutDevices;
return this.client.requestPasswordEmailToken(emailAddress, this.clientSecret, 1).then((res) => {
this.sessionId = res.sid;
return res;
Expand Down Expand Up @@ -90,7 +97,7 @@ export default class PasswordReset {
// See https://github.com/matrix-org/matrix-doc/issues/2220
threepid_creds: creds,
threepidCreds: creds,
}, this.password);
}, this.password, this.logoutDevices);
} catch (err) {
if (err.httpStatus === 401) {
err.message = _t('Failed to verify email address: make sure you clicked the link in the email');
Expand Down
66 changes: 41 additions & 25 deletions src/components/structures/auth/ForgotPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import AuthHeader from "../../views/auth/AuthHeader";
import AuthBody from "../../views/auth/AuthBody";
import PassphraseConfirmField from "../../views/auth/PassphraseConfirmField";
import AccessibleButton from '../../views/elements/AccessibleButton';
import StyledCheckbox from '../../views/elements/StyledCheckbox';

enum Phase {
// Show the forgot password inputs
Expand Down Expand Up @@ -72,6 +73,8 @@ interface IState {
serverDeadError: string;

currentHttpRequest?: Promise<any>;

logout_devices: boolean;
}

enum ForgotPasswordField {
Expand All @@ -97,6 +100,7 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
serverIsAlive: true,
serverErrorIsFatal: false,
serverDeadError: "",
logout_devices: false,
};

public componentDidMount() {
Expand Down Expand Up @@ -129,12 +133,12 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
}
}

public submitPasswordReset(email: string, password: string): void {
public submitPasswordReset(email: string, password: string, logoutDevices = true): void {
this.setState({
phase: Phase.SendingEmail,
});
this.reset = new PasswordReset(this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl);
this.reset.resetPassword(email, password).then(() => {
this.reset.resetPassword(email, password, logoutDevices).then(() => {
this.setState({
phase: Phase.EmailSent,
});
Expand Down Expand Up @@ -174,24 +178,28 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
return;
}

Modal.createTrackedDialog('Forgot Password Warning', '', QuestionDialog, {
title: _t('Warning!'),
description:
<div>
{ _t(
"Changing your password will reset any end-to-end encryption keys " +
"on all of your sessions, making encrypted chat history unreadable. Set up " +
"Key Backup or export your room keys from another session before resetting your " +
"password.",
) }
</div>,
button: _t('Continue'),
onFinished: (confirmed) => {
if (confirmed) {
this.submitPasswordReset(this.state.email, this.state.password);
}
},
});
if (this.state.logout_devices) {
Modal.createTrackedDialog('Forgot Password Warning', '', QuestionDialog, {
title: _t('Warning!'),
description:
<div>
{ _t(
"Signing out all sessions will reset the end-to-end encryption keys " +
"making encrypted chat history unreadable. Set up " +
"Key Backup or export your room keys from another session before resetting your " +
"password.",
) }
</div>,
button: _t('Continue'),
onFinished: (confirmed) => {
if (confirmed) {
this.submitPasswordReset(this.state.email, this.state.password, this.state.logout_devices);
}
},
});
} else {
this.submitPasswordReset(this.state.email, this.state.password, this.state.logout_devices);
}
};

private async verifyFieldsBeforeSubmit() {
Expand Down Expand Up @@ -314,6 +322,11 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
autoComplete="new-password"
/>
</div>
<div className="mx_AuthBody_fieldRow">
<StyledCheckbox onChange={() => this.setState({ logout_devices: !this.state.logout_devices })} checked={this.state.logout_devices}>
{ _t("Sign out all sessions") }
</StyledCheckbox>
</div>
<span>{ _t(
'A verification email will be sent to your inbox to confirm ' +
'setting your new password.',
Expand Down Expand Up @@ -353,11 +366,14 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
renderDone() {
return <div>
<p>{ _t("Your password has been reset.") }</p>
<p>{ _t(
"You have been logged out of all sessions and will no longer receive " +
"push notifications. To re-enable notifications, sign in again on each " +
"device.",
) }</p>
{ this.state.logout_devices ?
<p>{ _t(
"You have been logged out of all sessions and will no longer receive " +
"push notifications. To re-enable notifications, sign in again on each " +
"device.",
) }</p>
: null
}
<input
className="mx_Login_submit"
type="button"
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3137,11 +3137,12 @@
"Really reset verification keys?": "Really reset verification keys?",
"Skip verification for now": "Skip verification for now",
"Failed to send email": "Failed to send email",
"Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.",
"Signing out all sessions will reset the end-to-end encryption keys making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Signing out all sessions will reset the end-to-end encryption keys making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.",
"The email address linked to your account must be entered.": "The email address linked to your account must be entered.",
"The email address doesn't appear to be valid.": "The email address doesn't appear to be valid.",
"A new password must be entered.": "A new password must be entered.",
"New passwords must match each other.": "New passwords must match each other.",
"Sign out all sessions": "Sign out all sessions",
"A verification email will be sent to your inbox to confirm setting your new password.": "A verification email will be sent to your inbox to confirm setting your new password.",
"Send Reset Email": "Send Reset Email",
"Sign in instead": "Sign in instead",
Expand Down

0 comments on commit 9825e44

Please sign in to comment.