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

Allow users to login with validate code and be redirected to Workspace/Card modal #4519

Merged
merged 36 commits into from
Aug 20, 2021

Conversation

TomatoToaster
Copy link
Contributor

@TomatoToaster TomatoToaster commented Aug 10, 2021

@mountiny, please review when you get the chance
CC: @timszot, @chiragsalian, @tgolen since you've all recently worked on this (no need to review, just in case you have strong opinions on what I changed here)

Details

Makes this "Login With Validate Code" generic so other routes (in this case, workspace/card) can also use the same component to do the login and redirect logic. Also updated some constant's names to be in line with this.

I've also introduced a areAllPoliciesLoaded onyx key. In the current freePlan beta, we only load policies after we have loaded the betas and can make sure the user is in the freePlan beta. This becomes an issue for logging in with a validateCode and then being redirected to workspace/card because that component would be loaded before all the user's policies have been loaded. This makes it seem like the policy we're looking for in src/pages/workspace/WorkspaceSidebar.js will almost never be loaded in time and will always create a new policy. To prevent this, we'll only create a new policy there after we're SURE all the policies a user has is already loaded.

Also as pointed out here in this comment "Validate Login" is kind of inaccurate, so I've renamed the components to LoginWithValidateCodePage and LoginWithValidateCode2FAPage accordingly.

HOLD on

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/172892

Tests

Web QA done locally. Make sure you are on the latest for Web-E

If you would like to test the beta properly remove the isDevelopment() || in this line:

return isDevelopment() || _.contains(betas, CONST.BETAS.ALL);

This shows why the areAllPoliciesLoaded is relevant. The betas will have to be loaded from the api as ['all'] like it would be in production and and replicates the behavior where policies are loaded after the betas have been loaded.

QA Steps

  1. With an account in the Free Plan beta, create a workspace in NewDot:
    image

  2. Log out of NewDot or open an incognito window and log into OldDot with the same account.

  3. Go to Settings -> Policies and verify you see the Workspace there:
    image

  4. Click on that policy's name and verify that a new tab opens up in NewDot where you are logged in automatically and you are redirected to your workspace's settings page like this:
    image

  5. Go back to the OldDot Settings -> Policy tab and click it again. Verify another tab is opened to the same Workspace.

  6. Test steps 1-5 again with an account that has 2FA enabled as well (make sure to log out of NewDot first!)

  7. On the NewDot tab, look at the url for the Workspace/Card page. It should be something like staging.new.expensify.com/workspace/71648CB0DB905D52/card. Change the number (i.e. 71648CB0DB905D52) a little bit and go to that url. Verify that you see the error growl and a new policy is created.
    image

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

N/A Screenshots for web (only relevant platform) in issue.

@TomatoToaster TomatoToaster self-assigned this Aug 10, 2021
@TomatoToaster TomatoToaster changed the title Amal validate code reuse Allow users to login with validate code and be redirected to workspace_card page Aug 10, 2021
@TomatoToaster TomatoToaster changed the title Allow users to login with validate code and be redirected to workspace_card page Allow users to login with validate code and be redirected to Workspace/Card modal Aug 10, 2021
@TomatoToaster TomatoToaster changed the title Allow users to login with validate code and be redirected to Workspace/Card modal [HOLD] Allow users to login with validate code and be redirected to Workspace/Card modal Aug 10, 2021
@TomatoToaster TomatoToaster changed the title [HOLD] Allow users to login with validate code and be redirected to Workspace/Card modal Allow users to login with validate code and be redirected to Workspace/Card modal Aug 11, 2021
@TomatoToaster TomatoToaster marked this pull request as ready for review August 13, 2021 02:33
@TomatoToaster TomatoToaster requested a review from a team as a code owner August 13, 2021 02:33
@MelvinBot MelvinBot requested review from mountiny and removed request for a team August 13, 2021 02:33
@mountiny
Copy link
Contributor

@TomatoToaster I am not sure what I am doing wrong here when testing this locally, but I have made sure to get up-to-date Web-E and run composer there. If I click on the newly created workspace name in OldDot I get to NewDot sign in page :/ I dont see anything relevant in console.

Is there not any other step I need to do for testing?

@TomatoToaster TomatoToaster changed the title [WIP]Allow users to login with validate code and be redirected to Workspace/Card modal Allow users to login with validate code and be redirected to Workspace/Card modal Aug 17, 2021
@TomatoToaster
Copy link
Contributor Author

This is ready for another review @tgolen @mountiny. Let me know if the comments I've added to the rerouteToRelevantPage component are clear enough. I tried to incorporate "why are we doing this" in the comments, and it reads clear to me, but I have also been looking at this for a while 😅 .

Also I got rid of the are_all_policies_loaded onyx key and used the existing collection as suggested. I left a comment so that when the freeplan beta is done, that allPolicies !== null logic can be removed because there won't be any delayed loading of policies. I think we should eventually do that since it's kind of expensive to load all the policies for that component when we don't need them anymore. Let me know if you think that should be altered or maybe I should do something else.

@mountiny mountiny self-requested a review August 17, 2021 10:11
mountiny
mountiny previously approved these changes Aug 17, 2021
}, [policy]);
// After all the policies have loaded, we can know if the given policyID points to a nonexistant workspace
// When free plan is out of beta and Permissions.canUseFreePlan() gets removed,
// all code involving 'allPolicies' can be removed since policy loading will no longer be delayed on 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: I feel like it would be nice to use dome keyword like TODO: in places where we know for certain we will make a change in future to maybe keep track of it and find it more easily in future. WDYT?

Of course, if we would decide to use some keyword, then it will be properly useful only if we use it in all the places like this. Let me know what you think about this?

Copy link
Contributor Author

@TomatoToaster TomatoToaster Aug 17, 2021

Choose a reason for hiding this comment

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

I like TODO because if we miss it, someone will definitely notice it's off when they see that comment still there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, let's add a // @TODO (this is our standard format) and then also create a GH issue to do the removal and make sure it happens.

Copy link
Contributor Author

@TomatoToaster TomatoToaster Aug 18, 2021

Choose a reason for hiding this comment

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

I created a GH issue and also made a note to reexamine if the two components LoginWith can be consolidated. I think they can be and it'll be good to reexamine when this is out of beta.

Issue here: https://github.com/Expensify/Expensify/issues/174109

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if everyone still agrees with this but we've historically discouraged the use of TODO comments and just use GH issues. TODO comments tend to live forever in the code, and pollute the code as they become outdated, or because there's usually no timeline for when they need to be done, etc.

Is there anything that the GH issue doesn't solve, that we need the TODO comment for?

Copy link
Contributor

Choose a reason for hiding this comment

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

image
image
image
image

Copy link
Contributor

Choose a reason for hiding this comment

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

Wow, interesting, did not realize this at all. If there is such an experience with using it, it might good decision to just omit it this time and we will make the change needed once the time comes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I wish github would bump down these comments so they're easier to see. Since we have the issue created I don't feel strongly about keepign it as as TODO. I'll remove it.

mountiny
mountiny previously approved these changes Aug 17, 2021
Copy link
Contributor

@mountiny mountiny left a comment

Choose a reason for hiding this comment

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

Great job, Amal!

Copy link
Contributor

@tgolen tgolen left a comment

Choose a reason for hiding this comment

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

Thanks for the changes! I think that helps. I'm still a little confused on the race condition with the betas loaded, so maybe my comments about checking that the betas have been loaded is too paranoid.

} else {
componentDidUpdate() {
// Betas can be loaded a little after a user is authenticated, so check again if the betas have been updated
if (this.props.session.authToken && Permissions.canUseFreePlan(this.props.betas)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this also check that this.props.betas exists before calling canUseFreePlan()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will always exist because of the default props of this component having it set to []. We could check if it's empty, but Permissions.canUseFreePlan doesn't need the argument to be a non-empty array so I feel like that check might be redundant.

Copy link
Contributor

Choose a reason for hiding this comment

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

Here is a better description of why I thought this could have been a problem:

  1. Component mounts
  2. Component is updated with a session auth token, but betas haven't loaded yet
  3. Permission check happens with an empty beta list
  4. Betas finish loading
  5. Now the beta check from 3 was stale and wrong because of the race condition

It's possible this isn't actually a problem because the first permission check would always return false if the beta array is empty, and there would be no redirect. Then, once the betas finish loading, there would be another component update with the proper beta data and the permission check would run and return true and then the redirect happens.

I think we are OK? It's quite the "gotcha" though and relies on the first permission check returning false with an empty beta array. If someone were to ever implement a permission check that did opposite logic (like cannotUseFreePlan, then the race condition would happen).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we are ok! And ahh yeah I haven't seen the cannotUse type of beta checks, so I didn't consider them. Your reasoning around the beta checks is right and the component loads endlessly Until we CAN prove the user is in the beta. Hypothetically a user who isn't in any betas who landed on this page would see an endless loader, but such a user shouldn't be able to access the link that brings them here in the first place.

break;

case SCREENS.LOGIN_WITH_VALIDATE_CODE_2FA_NEW_WORKSPACE:
// Creating a policy will reroute the user to the settings page afterwards
create();
Copy link
Contributor

Choose a reason for hiding this comment

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

Seeing this in the surrounding context, it's hard to know what this does. I would suggest changing the import to be import * as Policy from.... then change this reference to Policy.create() so that it helps add context about what's getting created without having to check the imports.

componentDidMount() {
// If the user has an active session already, they need to be redirected straight to the relevant page
if (this.props.session.authToken) {
// In order to navigate to a modal, we first have to dismiss the current modal. But there is no current
Copy link
Contributor

Choose a reason for hiding this comment

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

NAB At some point, I think we need to DRY up these two components since they share about 90% of the same code.

// and by calling dismissModal(), the /v/... route is removed from history so the user will get taken to `/`
// if they cancel out of the new workspace modal.
Navigation.dismissModal();
if (Permissions.canUseFreePlan(this.props.betas)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, do we need to check that betas exist first before checking permissions?


componentDidUpdate() {
// Betas can be loaded a little after a user is authenticated, so check again if the betas have been updated
if (this.props.session.authToken && Permissions.canUseFreePlan(this.props.betas)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same

src/pages/workspace/WorkspaceSidebar.js Show resolved Hide resolved
@TomatoToaster
Copy link
Contributor Author

@tgolen, addressed some comments and I think this is ready for another look!

@TomatoToaster
Copy link
Contributor Author

TODO has been removed since the issue has been already created to take care of this later.

@mountiny mountiny self-requested a review August 19, 2021 15:43
Copy link
Contributor

@tgolen tgolen left a comment

Choose a reason for hiding this comment

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

Just this one little thing and we're good to merge.

src/pages/workspace/WorkspaceSidebar.js Outdated Show resolved Hide resolved
} else {
componentDidUpdate() {
// Betas can be loaded a little after a user is authenticated, so check again if the betas have been updated
if (this.props.session.authToken && Permissions.canUseFreePlan(this.props.betas)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here is a better description of why I thought this could have been a problem:

  1. Component mounts
  2. Component is updated with a session auth token, but betas haven't loaded yet
  3. Permission check happens with an empty beta list
  4. Betas finish loading
  5. Now the beta check from 3 was stale and wrong because of the race condition

It's possible this isn't actually a problem because the first permission check would always return false if the beta array is empty, and there would be no redirect. Then, once the betas finish loading, there would be another component update with the proper beta data and the permission check would run and return true and then the redirect happens.

I think we are OK? It's quite the "gotcha" though and relies on the first permission check returning false with an empty beta array. If someone were to ever implement a permission check that did opposite logic (like cannotUseFreePlan, then the race condition would happen).

@TomatoToaster
Copy link
Contributor Author

I think I got the changes you requested (just in the time you were doing the review!) @tgolen, could you take another look?

@tgolen tgolen merged commit cefb82a into main Aug 20, 2021
@tgolen tgolen deleted the amal-validate-code-reuse branch August 20, 2021 14:06
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to production by @roryabraham in version: 1.0.88-2 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 failure ❌
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants