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

Update signInWithShortLivedToken to use API.Write instead of DeprecateAPI commands #13456

Merged
merged 19 commits into from
Dec 26, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2aa3759
update createTemporaryLogin to use API.write
NikkiWines Dec 8, 2022
c47a091
remove signInWithShortLivedToken function
NikkiWines Dec 8, 2022
f49f859
export createTemporaryLogin function
NikkiWines Dec 8, 2022
84d1ed7
remove cleanLoginListServerResponse and keepExpensifyPartners
NikkiWines Dec 8, 2022
e564601
remove getUserDetails()
NikkiWines Dec 9, 2022
47b67b3
remove unused imports, functions, and params
NikkiWines Dec 9, 2022
f0c7dfe
remove more unused imports and params
NikkiWines Dec 9, 2022
957c07a
replace createTemporaryLogin with signInWithShortLivedAuthToken
NikkiWines Dec 13, 2022
f023893
Merge branch 'main' of github.com:Expensify/App into nikki-remove-dep…
NikkiWines Dec 15, 2022
3b8c4ba
minor formatting and style updates
NikkiWines Dec 15, 2022
ae16c2d
Merge branch 'main' of github.com:Expensify/App into nikki-remove-dep…
NikkiWines Dec 19, 2022
77e74de
use ternary to prevent cannot read properties of null error
NikkiWines Dec 19, 2022
799ad8d
Merge branch 'main' of github.com:Expensify/App into nikki-remove-dep…
NikkiWines Dec 21, 2022
cb42542
set credentials to {} instead of null
NikkiWines Dec 21, 2022
9708d54
Merge branch 'main' of github.com:Expensify/App into nikki-remove-dep…
NikkiWines Dec 21, 2022
92c0649
fall back on {} if credentials value is null
NikkiWines Dec 21, 2022
83f661d
Merge branch 'main' of github.com:Expensify/App into nikki-remove-dep…
NikkiWines Dec 23, 2022
eec41c4
ensure we update the session token and signout when redirecting to ne…
NikkiWines Dec 23, 2022
45b35b9
if we're transitioning from oldDot to newDot with a different user, e…
NikkiWines Dec 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions src/libs/LoginUtils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import _ from 'underscore';
import CONST from '../CONST';

/**
Expand Down Expand Up @@ -31,29 +30,8 @@ function getPhoneNumberWithoutUSCountryCodeAndSpecialChars(phone) {
return getPhoneNumberWithoutSpecialChars(phone.replace(/^\+1/, ''));
}

/**
* Filter out all non-Expensify partners from login list
*
* @param {Object} loginList
* @returns {Object}
*/
function keepExpensifyPartners(loginList = {}) {
return _.pick(loginList, login => login.partnerName === CONST.EXPENSIFY_PARTNER_NAME);
}

/**
* Cleans login list that came from the server by only keeping logins with Expensify partner name
*
* @param {Object} loginList
* @returns {Object}
*/
function cleanLoginListServerResponse(loginList = {}) {
return keepExpensifyPartners(loginList);
}

export {
getEmailWithoutMergedAccountPrefix,
getPhoneNumberWithoutSpecialChars,
getPhoneNumberWithoutUSCountryCodeAndSpecialChars,
cleanLoginListServerResponse,
};
2 changes: 1 addition & 1 deletion src/libs/Network/NetworkStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Onyx.connect({
Onyx.connect({
key: ONYXKEYS.CREDENTIALS,
callback: (val) => {
credentials = val || null;
credentials = val || {};
checkRequiredData();
},
});
Expand Down
130 changes: 33 additions & 97 deletions src/libs/actions/Session/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import Onyx from 'react-native-onyx';
import Str from 'expensify-common/lib/str';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import ONYXKEYS from '../../../ONYXKEYS';
import redirectToSignIn from '../SignInRedirect';
import * as DeprecatedAPI from '../../deprecatedAPI';
import CONFIG from '../../../CONFIG';
import Log from '../../Log';
import PushNotification from '../../Notification/PushNotification';
Expand All @@ -14,7 +12,6 @@ import * as Localize from '../../Localize';
import UnreadIndicatorUpdater from '../../UnreadIndicatorUpdater';
import Timers from '../../Timers';
import * as Pusher from '../../Pusher/pusher';
import * as User from '../User';
import * as Authentication from '../../Authentication';
import * as Welcome from '../Welcome';
import * as API from '../../API';
Expand All @@ -27,23 +24,6 @@ Onyx.connect({
callback: val => credentials = val,
});

/**
* Sets API data in the store when we make a successful "Authenticate"/"CreateLogin" request
*
* @param {Object} data
* @param {String} data.accountID
* @param {String} data.authToken
* @param {String} data.email
*/
function setSuccessfulSignInData(data) {
PushNotification.register(data.accountID);
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, this can't be removed, it needs to exist somewhere or push notifications don't work

Copy link
Contributor

Choose a reason for hiding this comment

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

Need to check if this code is enough

App/src/Expensify.js

Lines 122 to 124 in e1c6a2e

if (currentAccountID && (currentAccountID !== previousAccountID)) {
PushNotification.register(currentAccountID);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be fine, added a console log in to check

Screen.Recording.2022-12-21.at.15.13.55.mov

Copy link
Contributor

Choose a reason for hiding this comment

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

So odd, so that call was useless? You sure it is not used in some other flow? Like signing in normally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like it, runs on normal sign in as well

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh wow.... just to be sure, tagging @Julesssss, @arosiclair and @cristipaval that are probably familiar with this since they are working on the notifications doc.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah as long as the new accountID gets set on the session, the code @aimane-chnaif linked should register notifications.

Onyx.merge(ONYXKEYS.SESSION, {
errors: null,
..._.pick(data, 'authToken', 'accountID', 'email', 'encryptedAuthToken'),
});
Onyx.set(ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this safe to remove? Need to confirm it doesn't cause any regression regarding compose input display

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, good thought. We should be fine though because the internal PR created before this one sets the value for that onyx key.

}

/**
* Clears the Onyx store and redirects user to the sign in page
*/
Expand All @@ -59,7 +39,7 @@ function signOut() {
{
onyxMethod: CONST.ONYX.METHOD.SET,
key: ONYXKEYS.CREDENTIALS,
value: null,
value: {},
},
];
API.write('LogOut', {
Expand Down Expand Up @@ -159,64 +139,43 @@ function beginSignIn(login) {
}

/**
*
* Will create a temporary login for the user in the passed authenticate response which is used when
* re-authenticating after an authToken expires.
NikkiWines marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {String} authToken
* @param {String} email
* @return {Promise}
*/
function createTemporaryLogin(authToken, email) {
const autoGeneratedLogin = Str.guid('expensify.cash-');
const autoGeneratedPassword = Str.guid();
function signInWithShortLivedAuthToken(authToken) {
const optimisticData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.ACCOUNT,
value: {
...CONST.DEFAULT_ACCOUNT_DATA,
isLoading: true,
},
},
];

return DeprecatedAPI.CreateLogin({
authToken,
partnerName: CONFIG.EXPENSIFY.PARTNER_NAME,
partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD,
partnerUserID: autoGeneratedLogin,
partnerUserSecret: autoGeneratedPassword,
shouldRetry: false,
forceNetworkRequest: true,
email,
includeEncryptedAuthToken: true,
})
.then((createLoginResponse) => {
if (createLoginResponse.jsonCode !== 200) {
Onyx.merge(ONYXKEYS.ACCOUNT, {errors: {[DateUtils.getMicroseconds()]: Localize.translate('createLoginResponse.message')}});
return createLoginResponse;
}

setSuccessfulSignInData(createLoginResponse);

// If we have an old generated login for some reason
// we should delete it before storing the new details
if (credentials && credentials.autoGeneratedLogin) {
DeprecatedAPI.DeleteLogin({
partnerUserID: credentials.autoGeneratedLogin,
partnerName: CONFIG.EXPENSIFY.PARTNER_NAME,
partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD,
shouldRetry: false,
})
.then((response) => {
if (response.jsonCode === CONST.JSON_CODE.SUCCESS) {
return;
}

Log.hmmm('[Session] Unable to delete login', false, {message: response.message, jsonCode: response.jsonCode});
});
}

Onyx.merge(ONYXKEYS.CREDENTIALS, {
autoGeneratedLogin,
autoGeneratedPassword,
});
return createLoginResponse;
})
.finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {isLoading: false});
});
const successData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.ACCOUNT,
value: {
isLoading: false,
},
},
];

const failureData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.ACCOUNT,
value: {
isLoading: false,
},
},
];
API.write('SignInWithShortLivedAuthToken', {authToken, oldPartnerUserID: credentials.autoGeneratedLogin || ''}, {optimisticData, successData, failureData});
}

/**
Expand Down Expand Up @@ -262,29 +221,6 @@ function signIn(password, twoFactorAuthCode) {
API.write('SigninUser', {email: credentials.login, password, twoFactorAuthCode}, {optimisticData, successData, failureData});
}

/**
* Uses a short lived authToken to continue a user's session from OldDot
*
* @param {String} email
* @param {String} shortLivedAuthToken
* @param {String} exitTo
*/
function signInWithShortLivedAuthToken(email, shortLivedAuthToken) {
Onyx.merge(ONYXKEYS.ACCOUNT, {...CONST.DEFAULT_ACCOUNT_DATA, isLoading: true});

createTemporaryLogin(shortLivedAuthToken, email)
.then((response) => {
if (response.jsonCode !== CONST.JSON_CODE.SUCCESS) {
return;
}

User.getUserDetails();
Onyx.merge(ONYXKEYS.ACCOUNT, {success: true});
}).finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {isLoading: false});
});
}

/**
* User forgot the password so let's send them the link to reset their password
*/
Expand Down Expand Up @@ -361,7 +297,7 @@ function invalidateAuthToken() {
function clearSignInData() {
Onyx.multiSet({
[ONYXKEYS.ACCOUNT]: null,
[ONYXKEYS.CREDENTIALS]: null,
[ONYXKEYS.CREDENTIALS]: {},
});
}

Expand Down
46 changes: 1 addition & 45 deletions src/libs/actions/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ import NetworkConnection from '../NetworkConnection';
import Growl from '../Growl';
import * as Localize from '../Localize';
import * as Link from './Link';
import getSkinToneEmojiFromIndex from '../../components/EmojiPicker/getSkinToneEmojiFromIndex';
import * as SequentialQueue from '../Network/SequentialQueue';
import PusherUtils from '../PusherUtils';
import * as LoginUtils from '../LoginUtils';

let currentUserAccountID = '';
Onyx.connect({
Expand Down Expand Up @@ -89,46 +87,6 @@ function closeAccount(message) {
});
}

/**
* Fetches the data needed for user settings
*/
function getUserDetails() {
DeprecatedAPI.Get({
returnValueList: 'account, loginList, nameValuePairs',
nvpNames: [
CONST.NVP.PAYPAL_ME_ADDRESS,
CONST.NVP.PREFERRED_EMOJI_SKIN_TONE,
CONST.NVP.FREQUENTLY_USED_EMOJIS,
CONST.NVP.BLOCKED_FROM_CONCIERGE,
].join(','),
})
.then((response) => {
// Update the User onyx key
const isSubscribedToNewsletter = lodashGet(response, 'account.subscribed', true);
const validatedStatus = lodashGet(response, 'account.validated', false);
Onyx.merge(ONYXKEYS.USER, {isSubscribedToNewsletter: !!isSubscribedToNewsletter, validated: !!validatedStatus});

// Update login list
const loginList = LoginUtils.cleanLoginListServerResponse(response.loginList);
Onyx.set(ONYXKEYS.LOGIN_LIST, loginList);

// Update the nvp_payPalMeAddress NVP
const payPalMeAddress = lodashGet(response, `nameValuePairs.${CONST.NVP.PAYPAL_ME_ADDRESS}`, '');
Onyx.merge(ONYXKEYS.NVP_PAYPAL_ME_ADDRESS, payPalMeAddress);

// Update the blockedFromConcierge NVP
const blockedFromConcierge = lodashGet(response, `nameValuePairs.${CONST.NVP.BLOCKED_FROM_CONCIERGE}`, {});
Onyx.merge(ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, blockedFromConcierge);

const preferredSkinTone = lodashGet(response, `nameValuePairs.${CONST.NVP.PREFERRED_EMOJI_SKIN_TONE}`, {});
Onyx.merge(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
getSkinToneEmojiFromIndex(preferredSkinTone).skinTone);

const frequentlyUsedEmojis = lodashGet(response, `nameValuePairs.${CONST.NVP.FREQUENTLY_USED_EMOJIS}`, []);
Onyx.set(ONYXKEYS.FREQUENTLY_USED_EMOJIS, frequentlyUsedEmojis);
});
}

/**
* Resends a validation link to a given login
*
Expand Down Expand Up @@ -179,8 +137,7 @@ function setSecondaryLoginAndNavigate(login, password) {
password,
}).then((response) => {
if (response.jsonCode === 200) {
const loginList = LoginUtils.cleanLoginListServerResponse(response.loginList);
Onyx.set(ONYXKEYS.LOGIN_LIST, loginList);
Onyx.set(ONYXKEYS.LOGIN_LIST, response.loginList);
Navigation.navigate(ROUTES.SETTINGS_PROFILE);
return;
}
Expand Down Expand Up @@ -481,7 +438,6 @@ function generateStatementPDF(period) {
export {
updatePassword,
closeAccount,
getUserDetails,
resendValidateCode,
updateNewsletterSubscription,
setSecondaryLoginAndNavigate,
Expand Down
6 changes: 1 addition & 5 deletions src/pages/LogInWithShortLivedAuthTokenPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@ const propTypes = {
params: PropTypes.shape({
/** Short lived authToken to sign in a user */
shortLivedAuthToken: PropTypes.string,

/** The email of the transitioning user */
email: PropTypes.string,
}),
}).isRequired,
};

class LogInWithShortLivedAuthTokenPage extends Component {
componentDidMount() {
const email = lodashGet(this.props, 'route.params.email', '');
const shortLivedAuthToken = lodashGet(this.props, 'route.params.shortLivedAuthToken', '');
Session.signInWithShortLivedAuthToken(email, shortLivedAuthToken);
Session.signInWithShortLivedAuthToken(shortLivedAuthToken);
}

render() {
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/NetworkTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ describe('NetworkTests', () => {
// Given a simulated a condition where the credentials have not yet been read from storage and we are offline
return Onyx.multiSet({
[ONYXKEYS.NETWORK]: {isOffline: true},
[ONYXKEYS.CREDENTIALS]: null,
[ONYXKEYS.CREDENTIALS]: {},
[ONYXKEYS.SESSION]: null,
})
.then(() => {
Expand Down