-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Conversation
…ing with validate code
79d5e77
to
4b5c433
Compare
@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? |
This is ready for another review @tgolen @mountiny. Let me know if the comments I've added to the Also I got rid of the |
}, [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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job, Amal!
There was a problem hiding this 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)) { |
There was a problem hiding this comment.
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()
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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:
- Component mounts
- Component is updated with a session auth token, but betas haven't loaded yet
- Permission check happens with an empty beta list
- Betas finish loading
- 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).
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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)) { |
There was a problem hiding this comment.
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)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same
@tgolen, addressed some comments and I think this is ready for another look! |
TODO has been removed since the issue has been already created to take care of this later. |
There was a problem hiding this 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.
} 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)) { |
There was a problem hiding this comment.
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:
- Component mounts
- Component is updated with a session auth token, but betas haven't loaded yet
- Permission check happens with an empty beta list
- Betas finish loading
- 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).
I think I got the changes you requested (just in the time you were doing the review!) @tgolen, could you take another look? |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to production by @roryabraham in version: 1.0.88-2 🚀
|
@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 insrc/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
andLoginWithValidateCode2FAPage
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:App/src/libs/Permissions.js
Line 11 in b2d03e1
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
With an account in the Free Plan beta, create a workspace in NewDot:
Log out of NewDot or open an incognito window and log into OldDot with the same account.
Go to Settings -> Policies and verify you see the Workspace there:
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:
Go back to the OldDot Settings -> Policy tab and click it again. Verify another tab is opened to the same Workspace.
Test steps 1-5 again with an account that has 2FA enabled as well (make sure to log out of NewDot first!)
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.Tested On
Screenshots
N/A Screenshots for web (only relevant platform) in issue.