-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Pass user session information when opening the electron app from web platform #16043
Conversation
return; | ||
} | ||
const exitTo = `${window.location.pathname}${window.location.search}${window.location.hash}`; | ||
Authentication.getNewAuthToken().then((response) => { |
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.
We should just get the session in the Onyx
or use Authenticate
api to get a new session like currently?
If the request fails, the electron app will not be opened.
} | ||
this.setState({deeplinkMatch: true}); | ||
const expensifyUrl = new URL(CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL); | ||
if (!this.props.authenticated) { |
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.
Do we have some public links to open the desktop app?
And if so, do we need to clear the session information in the electron app when opening desktop app via these links?
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.
@ntdiary I think if you direct user to /transition
, LogOutPreviousUserPage
is used. I haven't looked into this component closely, but I believe the session info for the previous user will be cleared, too.
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.
@ntdiary We have a custom URL scheme. new-expensify://
.
I think somewhere in the code, if the app is running on a desktop, the app is registering that URL schema with Mac OS, telling the OS that if OS detects user opening any URL that starts with new-expensify://
, please let the desktop app handle what to do with the URL.
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.
yeh, now when we click 'Open the app in Electron', it will always go to the /transition
page first. 😄
Hi, @thesahindia, @hayata-suenaga , there may be a few points we need to confirm, I added the comments above first. 🙂 |
@ntdiary I'm looking at your questions right now. I'll get back to you after I get insights into these. |
@ntdiary FYI the deep link is not working on production and staging right now. local NewDot webpage -> local desktop app seems to be working correctly. |
@hayata-suenaga @thesahindia One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
@thesahindia @hayata-suenaga hi, please feel free to let me know if anything is not expected or needs to be improved. 🙂 |
I'm looking at your comment now I have to be offline now and I'm OOO today, but if I can find a time tonight, I'll get back to you. |
@ntdiary thank you for checking on auth token lifespan.
Is it possible for us to intercept the event of clicking on |
@hayata-suenaga, I'm afraid not, this confirmation box is opened by the browser itself when we navigate to the deep link. chrome source code: https://github.com/chromium/chromium/blob/676a4420834ca68ead67cb4e659db7da4fbbf63d/chrome/browser/ui/views/external_protocol_dialog.cc#L93-L94 |
@ntdiary what do you think is the best way to deal with the possibility that the user's auth token might expire while waiting for them to click the "Open Electron App" button? |
I think we can show a screen, telling the user that their auth token has expired. |
@ntdiary does the user have to sign in again? not just refreshing the screen? |
The |
I think we should confirm this with @shawnborton.
|
I'll wait @shawnborton's response but shouldn't we display "Please refresh again" instead? And @ntdiary how do you suggest we trigger the change of the screen when the token expires? |
@hayata-suenaga this screen is displayed in the desktop app. If the |
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.
ohhh I completely misunderstood. yes it makes sense to prompt the user to log in again on the desktop side. let's wait for @shawnborton's review but otherwise LGTM!
Eh, sorry, I seem to have clicked something wrong, which caused the reviewers to change. 😅 |
@hayata-suenaga hi, is there anything else I can do? 🙂 |
@ntdiary I'm waiting for @thesahindia's review. |
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 looks good to me @hayata-suenaga
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.
LGTM!
@hayata-suenaga, only in my test case. I'm not sure if it still useful in the original scenario. So maybe it's good to leave it as it is. (instead of removing it)😂 |
✋ 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 staging by https://github.com/pecanoro in version: 1.2.94-0 🚀
|
🚀 Deployed to production by https://github.com/thienlnam in version: 1.2.94-3 🚀
|
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.
Hi, I'm sorry to be coming into this late, but someone asked me about some of the code implemented in this PR and I had many questions about it.
@@ -29,27 +44,18 @@ class DeeplinkWrapper extends PureComponent { | |||
appInstallationCheckStatus: (this.isMacOSWeb() && CONFIG.ENVIRONMENT !== CONST.ENVIRONMENT.DEV) | |||
? CONST.DESKTOP_DEEPLINK_APP_STATE.CHECKING : CONST.DESKTOP_DEEPLINK_APP_STATE.NOT_INSTALLED, | |||
}; | |||
this.focused = true; |
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.
Please add a code comment to explain what this is used for, or update the name of the property to this.isBrowserWindowFocused
.
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.
let focused = true; |
It comes from the original
focus
variable. I think we can safely remove it now, after the redirection screen is removed, I think we don't need it anymore.
this.openRouteInDesktopApp(expensifyDeeplinkUrl); | ||
return; | ||
} | ||
Authentication.getShortLivedAuthToken().then((shortLivedAuthToken) => { |
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.
Promise chains should be EXPLICITLY avoided in code. We did a ton of work to remove all the API chaining that we should not see these reintroduced back into the code (and if Authentication
would have been an action file as opposed to a lib file, ESLint would have thrown an error).
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.
Thank you for pointing this out. It has been removed.
const expensifyUrl = new URL(CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL); | ||
const expensifyDeeplinkUrl = `${CONST.DEEPLINK_BASE_URL}${expensifyUrl.host}${window.location.pathname}${window.location.search}${window.location.hash}`; | ||
updateAppInstallationCheckStatus() { | ||
setTimeout(() => { |
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.
Why is there a setTimeout()
here? I see this is moving some of the original code, but we should NEVER EVER have a setTimeout()
in the code without a thorough code comment explaining it's necessity.
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.
Yeah. I guess it was originally intended to check the focus with a delay. But it's not needed now since the redirection screen has been removed.
this.setState({appInstallationCheckStatus: CONST.DESKTOP_DEEPLINK_APP_STATE.INSTALLED}); | ||
} else { | ||
this.setState({appInstallationCheckStatus: CONST.DESKTOP_DEEPLINK_APP_STATE.NOT_INSTALLED}); |
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 appears to me that these values aren't used anywhere? The only thing I see looking at this value is in the render method and it's only looking for the value of CHECKING
.
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.
Yeah, it's not needed now since the redirection screen has been removed, and we can replace appInstallationCheckStatus
with isShortLivedAuthTokenLoading
, the latter is clearer.
@@ -105,7 +105,17 @@ function reauthenticate(command = '') { | |||
}); | |||
} | |||
|
|||
function getShortLivedAuthToken() { | |||
return Network.post('OpenOldDotLink', {shouldRetry: false}).then((response) => { |
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.
Why is Network.post()
used here? This is considered a deprecated method (and sorry if it was never marked as such, but we've been trying to remove this for the past year).
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 also used to think that using the onyx to retrieve short live token would be a little weird, but based on your discussions, this should no longer be an issue. And if we can create the BeginDeepLinkRedirect
new command, then we can also no longer call makeRequestWithSideEffects
.
if (response && response.shortLivedAuthToken) { | ||
return Promise.resolve(response.shortLivedAuthToken); | ||
} | ||
return Promise.reject(); |
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.
What does this failure mean? It looks like it sets a state property in the deeplink component that either indicates that the desktop app is or isn't installed (yet, the state property is never checked for that).
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.
Yep, it's no longer needed either. We can remove it after we replace the appInstallationCheckStatus
with isShortLivedAuthTokenLoading
.
@@ -239,6 +240,11 @@ function signInWithShortLivedAuthToken(email, authToken) { | |||
isLoading: true, | |||
}, | |||
}, | |||
{ | |||
onyxMethod: CONST.ONYX.METHOD.MERGE, | |||
key: ONYXKEYS.IS_TOKEN_VALID, |
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.
This looks like it's only used for showing a loading indicator in LogInWithShortLivedAuthTokenPage
and has nothing to do with a token being valid or invalid. Please change the name to IS_TOKEN_LOADING
. However, this is already ONYXKEYS.ACCOUNT.isLoading
so why is there a need for both?
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 saw ONYXKEYS.ACCOUNT.isLoading
being used in the login form, not sure if it can be used in other scenarios.
And replace IS_TOKEN_VALID
with ONYXKEYS.ACCOUNT.isLoading
in the new followup PR.
if (response) { | ||
return; | ||
} | ||
Navigation.navigate(); |
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 seems like this might have something to do with one of the above scenarios, but it is not clear what. Can you please add a code comment to explain why this is here and why there is no way that this can be done optimistically before the response 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.
For example, if a request fails due to a sudden disconnection, we need to redirect the user to the login page instead of leaving them stuck on the transition page. I tried using network.isOffline
to handle this situation in the new PR and left a todo comment for review.
@hayata-suenaga, of course, this is my responsibility. @tgolen, thanks you very much for these comments and sorry for the confusion. |
Great, thank you so much for addressing these! It's gonna make this code a lot cleaner. 👍 |
Details
Fixed Issues
$ #15651
PROPOSAL: #15651 (comment)
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
chrome.mp4
Mobile Web - Chrome
N/AMobile Web - Safari
N/ADesktop
N/AiOS
N/AAndroid
N/A