Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logic to support closed account receiving a link to set password and for unvalidated and closed accounts to get the email the moment they log into ecash #2745

Merged
merged 9 commits into from
May 13, 2021
2 changes: 0 additions & 2 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,6 @@ export default {
},
resendValidationForm: {
linkHasBeenResent: 'Link has been re-sent',
accountUnvalidated: 'Account is unvalidated',
accountForgotPassword: 'Account forgot password: Sending reset password link.',
weSentYouMagicSignInLink: 'We\'ve sent you a magic sign in link – just click on it to log in!',
resendLink: 'Resend Link',
},
Expand Down
13 changes: 13 additions & 0 deletions src/libs/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function isAuthTokenRequired(command) {
'User_SignUp',
'ResendValidateCode',
'ResetPassword',
'User_ReopenAccount',
'ValidateEmail',
], command);
}
Expand Down Expand Up @@ -622,6 +623,17 @@ function User_GetBetas() {
return Network.post('User_GetBetas');
}

/**
* @param {Object} parameters
* @param {String} parameters.email
* @returns {Promise}
*/
function User_ReopenAccount(parameters) {
const commandName = 'User_ReopenAccount';
requireParameters(['email'], parameters, commandName);
return Network.post(commandName, parameters);
}

/**
* @param {Object} parameters
* @param {String} parameters.email
Expand Down Expand Up @@ -733,6 +745,7 @@ export {
UpdateAccount,
User_SignUp,
User_GetBetas,
User_ReopenAccount,
User_SecondaryLogin_Send,
User_UploadAvatar,
reauthenticate,
Expand Down
44 changes: 32 additions & 12 deletions src/libs/actions/Session.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,32 @@ function signOut() {
.catch(error => Onyx.merge(ONYXKEYS.SESSION, {error: error.message}));
}

/**
* Reopen the account and send the user a link to set password
*
* @param {String} [login]
*/
function reopenAccount(login = credentials.login) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB; Why are we defaulting login to credentials.login here and in resendValidationLink? Rephrased: When / why would a passed-in login string be different from what's stored in credentials.login?

I believe this has to do with unvalidated / closed accounts (the topic of your PR), but I think it would be useful to make this clear in the function comment

Copy link
Contributor Author

@chiragsalian chiragsalian May 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when you enter an email it hits this flow - https://github.com/Expensify/Expensify.cash/pull/2745/files#diff-283c48b7349b0bf7aba66da8891bc8a9f9df70664bd06e7a875f56b19c6c02f9R126 and credentials.login is not set yet that's why we pass the provided email.

But when you click resent link, it hits this flow - https://github.com/Expensify/Expensify.cash/pull/2745/files#diff-c075eec38f8adc854c238b1d4cfeba1ed3e5de0aa740aa78a658ffe3a53814f9R62 and does not need to pass an email since its in credentials.login. Does that make sense?

Onyx.merge(ONYXKEYS.ACCOUNT, {loading: true});
API.User_ReopenAccount({email: login})
.finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: false});
});
}

/**
* Resend the validation link to the user that is validating their account
*
* @param {String} [login]
*/
function resendValidationLink(login = credentials.login) {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: true});
API.ResendValidateCode({email: login})
.finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: false});
});
}

/**
* Checks the API to see if an account exists for the given login
*
Expand All @@ -89,11 +115,16 @@ function fetchAccountDetails(login) {
accountExists: response.accountExists,
requiresTwoFactorAuth: response.requiresTwoFactorAuth,
validated: response.validated,
closed: response.isClosed,
forgotPassword: false,
});

if (!response.accountExists) {
createAccount(login);
} else if (response.isClosed) {
reopenAccount(login);
} else if (!response.validated) {
resendValidationLink(login);
}
}
Onyx.merge(ONYXKEYS.ACCOUNT, {error: response.message});
Expand Down Expand Up @@ -185,18 +216,6 @@ function signIn(password, twoFactorAuthCode) {
});
}

/**
* Resend the validation link to the user that is validating their account
* this happens in the createAccount() flow
*/
function resendValidationLink() {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: true});
API.ResendValidateCode({email: credentials.login})
.finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: false});
});
}

/**
* User forgot the password so let's send them the link to reset their password
*/
Expand Down Expand Up @@ -251,6 +270,7 @@ export {
setPassword,
signIn,
signOut,
reopenAccount,
resendValidationLink,
resetPassword,
restartSignin,
Expand Down
13 changes: 8 additions & 5 deletions src/pages/signin/ResendValidationForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import _ from 'underscore';
import styles from '../../styles/styles';
import ButtonWithLoader from '../../components/ButtonWithLoader';
import {resendValidationLink, resetPassword} from '../../libs/actions/Session';
import {reopenAccount, resendValidationLink, resetPassword} from '../../libs/actions/Session';
import ONYXKEYS from '../../ONYXKEYS';
import ChangeExpensifyLoginLink from './ChangeExpensifyLoginLink';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
Expand All @@ -19,8 +19,11 @@ const propTypes = {
// Whether or not a sign on form is loading (being submitted)
loading: PropTypes.bool,

// Weather or not the account is validated
// Whether or not the account is validated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄

validated: PropTypes.bool,

// Whether or not the account is closed
closed: PropTypes.bool,
}),

...withLocalizePropTypes,
Expand Down Expand Up @@ -55,12 +58,12 @@ class ResendValidationForm extends React.Component {
formSuccess: this.props.translate('resendValidationForm.linkHasBeenResent'),
});

if (!this.props.account.validated) {
if (this.props.account.closed) {
reopenAccount();
} else if (!this.props.account.validated) {
resendValidationLink();
console.debug(this.props.translate('resendValidationForm.accountUnvalidated'));
} else {
resetPassword();
console.debug(this.props.translate('resendValidationForm.accountForgotPassword'));
}

this.successMessageTimer = setTimeout(() => {
Expand Down