-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Prevent activation of previous workspace when launching Connect via deep link to a different cluster #50063
Conversation
…spaceDefaultState`
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.
So far I only looked through the code, I'll try to test this on Monday.
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/documentsService/documentsService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
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 did a scan of the code but tested locally and it works. Leaving premp approval because I'm out next week
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
web/packages/teleterm/src/ui/AppInitializer/AppInitializer.test.tsx
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
await this.clustersService.syncRootClustersAndCatchErrors(); | ||
this.workspacesService.restorePersistedState(); |
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.
If I close the app while I'm in workspace A with a valid cert and open it again through a deep link to workspace B, I can close the login modal and continue to use workspace A without making a decision wrt restored state. The user should be forced to make an action before interacting with a workspace.
valid-cert-on-launch.mov
How do we fix this? I almost feel like DeepLinksService
should always bail out to the "Connect" screen. As in, when loginAndSetActiveWorkspace
is called, we check if the current workspace is equal to the workspace from the URL. If not, then we always zero rootClusterUri
in WorkspacesService
to force the user back to cluster choice. Otherwise, I feel it kind of makes little sense to launch the app through a link to workspace B, interact with a modal about workspace B (the login modal), then close it and be back at workspace A, just because it was the last used workspace before the app was closed.
I'm just not sure at this point how this is going to interact with the rest of the app.
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.
At first it seemed like a good idea, but then I realized that setting rootClusterUri
to undefined unmounts the workspaces, so all the state kept in tabs will be lost :/ And since a deep link can be opened while you work on something, you would loose it.
Because of that, I decided to keep it as is.
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.
At first it seemed like a good idea, but then I realized that setting
rootClusterUri
to undefined unmounts the workspaces, so all the state kept in tabs will be lost :/
That sounds like a behavior that we can change. But I'll look at the changes in this PR and the other PR first.
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Show resolved
Hide resolved
// the next time you would navigate to the workspace. | ||
// TODO(gzdunek): Consider replacing the document reopen dialog with an action in the UI that | ||
// could reopen the previous session at any time. | ||
if ( |
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 too happy with this check but it was the only simple workaround that came to my mind.
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 feel like allowing this situation to happen (where documents-reopen gets closed by cluster-login to another workspace which is then closed) makes reasoning about previousDocuments
/currentDocuments
quite difficult. It adds another state those two can be in and the situation in which this can happen is in itself quite unusual.
We'd remove a lot of complexity if we didn't let that happen, but I don't think it makes sense to stack even more changes in this PR.
If it's not possible to set rootClusterUri
to undefined for reasons described in #50063 (comment), then perhaps another solution would be to make the deep link handler re-execute setActiveWorkspace
with the workspace that was active at the time when the deep link handler was called.
Just like with many other changes regarding the startup flow, I'm not 100% sure if it won't break anything else, but it seems to make sense. 🙃
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 feel like allowing this situation to happen (where documents-reopen gets closed by cluster-login to another workspace which is then closed) makes reasoning about previousDocuments/currentDocuments quite difficult. It adds another state those two can be in and the situation in which this can happen is in itself quite unusual.
Agree, the startup flow became even more complex with changes from this PR :/
If it's not possible to set rootClusterUri to undefined for reasons described in #50063 (comment), then perhaps another solution would be to make the deep link handler re-execute setActiveWorkspace with the workspace that was active at the time when the deep link handler was called.
I feel that rendering workspaces when rootClusterUri is undefined may require many changes and testing, and I'm afraid that I will spend too much time on it.
Re-executing setActiveWorkspace when we didn't manage to set the correct workspace feels really simple, and should solve the problem the problem with this additional check, since we will always end up setting a workspace.
I can push a one more commit here that will fix 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.
Yeah definitely, I agree.
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.
Ok, I realized that the logic around documentsRestoredOrDiscarded
was broken from the beginning, so that I need that additional check.
We can't verify if we have documents to reopen every time we change the workspace - it must happen at the moment we restore previous workspaces. Otherwise, you can start a session with the default document (so documentsRestoredOrDiscarded: false
) and then open a new one. Then you change a workspace, and come back. In setActiveWorkspace
we would check if you have something to restore and this condition:
!arrayObjectIsEqual(
omitUriAndTitle(previousDocuments),
omitUriAndTitle(currentDocuments)
)
would say yes.
I just fixed this, I promise it was the last change in this PR!
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 got to a point where this should get merged despite some scenarios not being handled in the perfect way. But let me look at the other PR first.
web/packages/teleterm/src/ui/AppInitializer/AppInitializer.test.tsx
Outdated
Show resolved
Hide resolved
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
// the next time you would navigate to the workspace. | ||
// TODO(gzdunek): Consider replacing the document reopen dialog with an action in the UI that | ||
// could reopen the previous session at any time. | ||
if ( |
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 feel like allowing this situation to happen (where documents-reopen gets closed by cluster-login to another workspace which is then closed) makes reasoning about previousDocuments
/currentDocuments
quite difficult. It adds another state those two can be in and the situation in which this can happen is in itself quite unusual.
We'd remove a lot of complexity if we didn't let that happen, but I don't think it makes sense to stack even more changes in this PR.
If it's not possible to set rootClusterUri
to undefined for reasons described in #50063 (comment), then perhaps another solution would be to make the deep link handler re-execute setActiveWorkspace
with the workspace that was active at the time when the deep link handler was called.
Just like with many other changes regarding the startup flow, I'm not 100% sure if it won't break anything else, but it seems to make sense. 🙃
web/packages/teleterm/src/ui/services/workspacesService/workspacesService.ts
Outdated
Show resolved
Hide resolved
* Allow passing abortSignal to `open*Modal` methods, allow closing everything at once * Close all dialogs when activating a deep link * Allow only one `setActiveWorkspace` execution at a time * Review comments * Always unregister event listeners when a dialog is closed * Lint * Add a diagram for launching a deep link * Remove checking if the signal is aborted in `openImportantDialog`, rename it
…eep link to a different cluster (#50063) * Refactor `setActiveWorkspace` to async/await * Keep all the logic that restores a single workspace state in `getWorkspaceDefaultState` * Separate restoring state from setting active workspace * Allow the dialog to reopen documents to be closed without any decision * Add a test that verifies if the correct workspace is activated * Docs improvements * Return early if there's no restoredWorkspace * Fix logger name * Improve test name * Make restored state immutable * Fix comment * Do not wait for functions to be called in tests * Add tests for discarding documents reopen dialog * Move setting `isInitialized` to a separate method * Remove restored workspace when logging out so that we won't try to restore it when logging in again * Do not try to restore previous documents if the user already opened new ones * Do not close dialog in test * Improve `isInitialized` comment * Call `setActiveWorkspace` again when we fail to change the workspace * Fix the logic around restoring previous documents * Try to reopen documents also after `cluster-connect` is canceled * canRestoreDocuments -> hasDocumentsToReopen * Disallow parallel `setActiveWorkspace` calls (#50384) * Allow passing abortSignal to `open*Modal` methods, allow closing everything at once * Close all dialogs when activating a deep link * Allow only one `setActiveWorkspace` execution at a time * Review comments * Always unregister event listeners when a dialog is closed * Lint * Add a diagram for launching a deep link * Remove checking if the signal is aborted in `openImportantDialog`, rename it (cherry picked from commit 8e9b004)
…eep link to a different cluster (#50063) * Refactor `setActiveWorkspace` to async/await * Keep all the logic that restores a single workspace state in `getWorkspaceDefaultState` * Separate restoring state from setting active workspace * Allow the dialog to reopen documents to be closed without any decision * Add a test that verifies if the correct workspace is activated * Docs improvements * Return early if there's no restoredWorkspace * Fix logger name * Improve test name * Make restored state immutable * Fix comment * Do not wait for functions to be called in tests * Add tests for discarding documents reopen dialog * Move setting `isInitialized` to a separate method * Remove restored workspace when logging out so that we won't try to restore it when logging in again * Do not try to restore previous documents if the user already opened new ones * Do not close dialog in test * Improve `isInitialized` comment * Call `setActiveWorkspace` again when we fail to change the workspace * Fix the logic around restoring previous documents * Try to reopen documents also after `cluster-connect` is canceled * canRestoreDocuments -> hasDocumentsToReopen * Disallow parallel `setActiveWorkspace` calls (#50384) * Allow passing abortSignal to `open*Modal` methods, allow closing everything at once * Close all dialogs when activating a deep link * Allow only one `setActiveWorkspace` execution at a time * Review comments * Always unregister event listeners when a dialog is closed * Lint * Add a diagram for launching a deep link * Remove checking if the signal is aborted in `openImportantDialog`, rename it (cherry picked from commit 8e9b004)
… via deep link to a different cluster (#50733) * Prevent activation of previous workspace when launching Connect via deep link to a different cluster (#50063) * Refactor `setActiveWorkspace` to async/await * Keep all the logic that restores a single workspace state in `getWorkspaceDefaultState` * Separate restoring state from setting active workspace * Allow the dialog to reopen documents to be closed without any decision * Add a test that verifies if the correct workspace is activated * Docs improvements * Return early if there's no restoredWorkspace * Fix logger name * Improve test name * Make restored state immutable * Fix comment * Do not wait for functions to be called in tests * Add tests for discarding documents reopen dialog * Move setting `isInitialized` to a separate method * Remove restored workspace when logging out so that we won't try to restore it when logging in again * Do not try to restore previous documents if the user already opened new ones * Do not close dialog in test * Improve `isInitialized` comment * Call `setActiveWorkspace` again when we fail to change the workspace * Fix the logic around restoring previous documents * Try to reopen documents also after `cluster-connect` is canceled * canRestoreDocuments -> hasDocumentsToReopen * Disallow parallel `setActiveWorkspace` calls (#50384) * Allow passing abortSignal to `open*Modal` methods, allow closing everything at once * Close all dialogs when activating a deep link * Allow only one `setActiveWorkspace` execution at a time * Review comments * Always unregister event listeners when a dialog is closed * Lint * Add a diagram for launching a deep link * Remove checking if the signal is aborted in `openImportantDialog`, rename it (cherry picked from commit 8e9b004) * Fix tests
…eep link to a different cluster (#50063) (#50732) * Refactor `setActiveWorkspace` to async/await * Keep all the logic that restores a single workspace state in `getWorkspaceDefaultState` * Separate restoring state from setting active workspace * Allow the dialog to reopen documents to be closed without any decision * Add a test that verifies if the correct workspace is activated * Docs improvements * Return early if there's no restoredWorkspace * Fix logger name * Improve test name * Make restored state immutable * Fix comment * Do not wait for functions to be called in tests * Add tests for discarding documents reopen dialog * Move setting `isInitialized` to a separate method * Remove restored workspace when logging out so that we won't try to restore it when logging in again * Do not try to restore previous documents if the user already opened new ones * Do not close dialog in test * Improve `isInitialized` comment * Call `setActiveWorkspace` again when we fail to change the workspace * Fix the logic around restoring previous documents * Try to reopen documents also after `cluster-connect` is canceled * canRestoreDocuments -> hasDocumentsToReopen * Disallow parallel `setActiveWorkspace` calls (#50384) * Allow passing abortSignal to `open*Modal` methods, allow closing everything at once * Close all dialogs when activating a deep link * Allow only one `setActiveWorkspace` execution at a time * Review comments * Always unregister event listeners when a dialog is closed * Lint * Add a diagram for launching a deep link * Remove checking if the signal is aborted in `openImportantDialog`, rename it (cherry picked from commit 8e9b004)
Closes #40962
Problem
Connect always tries to restore the previous workspace, even when it is run via a deep link. This is incorrect behavior- if the user wants to authorize a session for cluster A, we shouldn't force him to log in to a cluster B first.
Solution
Currently, restoring the workspaces from disk also actives the previously active workspace (this includes showing a login dialog if certs expired). Opening a deep link waits for that state to be restored, so it also waits for that dialog to be completed.
We don't want this, so we need to decouple workspace restoration from activating the previously active workspace. This will allow us to signal the frontend interface readiness before the login dialog finishes. When the frontend is ready, a deep link can be processed to activate its corresponding workspace.
Our modal service allows only one regular dialog is active at any time, so opening a new dialog will automatically cancel an existing one.
In other words:
While working on this fix, I cleaned up some code in
workspacesService
anddocumentsService
:setActiveWorkspace
had a mix of async/await and.then
, it has been rewritten to the newer syntax.previous
field in the workspace state. Instead, I store the entire restored state in a separate variable. I needed this, because if we don't restore the previousrootClusterUri
immediately, it is overwritten withundefined
insetState
. I think this approach is actually simpler than what we had before.