From cfe482b731fe4a59b757a5d2453e6e06e34819a2 Mon Sep 17 00:00:00 2001 From: Grzegorz Zdunek Date: Tue, 10 Dec 2024 16:11:05 +0100 Subject: [PATCH] Display warning if a user that wants to authorize a web session is not logged in Connect (#49836) * Display warning if a user that wants to authorize a web session is not logged in Connect * Make the instructions more specific * Fix types * Convert the story to use controls * Fix test name --- .../DocumentAuthorizeWebSession.story.tsx | 57 ++++++++++--------- .../DocumentAuthorizeWebSession.test.tsx | 26 ++++++++- .../DocumentAuthorizeWebSession.tsx | 32 ++++++++++- .../ui/services/deepLinks/deepLinksService.ts | 1 + .../documentsService/types.ts | 1 + .../workspacesService.test.ts | 1 + 6 files changed, 88 insertions(+), 30 deletions(-) diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx index 7b697092f7c62..1ffe93e4cb080 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { Meta } from '@storybook/react'; import { wait } from 'shared/utils/wait'; import { MockAppContextProvider } from 'teleterm/ui/fixtures/MockAppContextProvider'; @@ -33,39 +34,41 @@ import { DocumentAuthorizeWebSession } from './DocumentAuthorizeWebSession'; export default { title: 'Teleterm/DocumentAuthorizeWebSession', -}; - -const doc: types.DocumentAuthorizeWebSession = { - uri: '/docs/e2hyt5', - rootClusterUri: rootClusterUri, - kind: 'doc.authorize_web_session', - title: 'Authorize Web Session', - webSessionRequest: { - redirectUri: '', - token: '', - id: '', + component: Story, + argTypes: { + isDeviceTrusted: { control: { type: 'boolean' } }, + isRequestedUserLoggedIn: { control: { type: 'boolean' } }, + }, + args: { + isDeviceTrusted: true, + isRequestedUserLoggedIn: true, }, -}; +} satisfies Meta; -export function DeviceNotTrusted() { - const rootCluster = makeRootCluster(); - const appContext = new MockAppContext(); - appContext.clustersService.setState(draftState => { - draftState.clusters.set(rootCluster.uri, rootCluster); - }); - return ( - - - - - - ); +interface StoryProps { + isDeviceTrusted: boolean; + isRequestedUserLoggedIn: boolean; } -export function DeviceTrusted() { +export function Story(props: StoryProps) { const rootCluster = makeRootCluster({ - loggedInUser: makeLoggedInUser({ isDeviceTrusted: true }), + loggedInUser: makeLoggedInUser({ isDeviceTrusted: props.isDeviceTrusted }), }); + const doc: types.DocumentAuthorizeWebSession = { + uri: '/docs/e2hyt5', + rootClusterUri: rootClusterUri, + kind: 'doc.authorize_web_session', + title: 'Authorize Web Session', + webSessionRequest: { + redirectUri: '', + token: '', + id: '', + username: props.isRequestedUserLoggedIn + ? rootCluster.loggedInUser.name + : 'bob', + }, + }; + const appContext = new MockAppContext(); appContext.clustersService.setState(draftState => { draftState.clusters.set(rootCluster.uri, rootCluster); diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx index c06ff109ff93c..67f47026cde36 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx @@ -40,10 +40,11 @@ const doc: types.DocumentAuthorizeWebSession = { redirectUri: '', token: '', id: '', + username: 'alice', }, }; -test('authorize button is disabled when device is not trusted', async () => { +test('warning is visible and authorize button is disabled when device is not trusted', async () => { const rootCluster = makeRootCluster({ loggedInUser: makeLoggedInUser({ isDeviceTrusted: false }), }); @@ -64,6 +65,29 @@ test('authorize button is disabled when device is not trusted', async () => { expect(await screen.findByText(/Authorize Session/)).toBeDisabled(); }); +test('warning is visible and authorize button is disabled when requested user is not logged in', async () => { + const rootCluster = makeRootCluster({ + loggedInUser: makeLoggedInUser({ isDeviceTrusted: true, name: 'bob' }), + }); + const appContext = new MockAppContext(); + appContext.clustersService.setState(draftState => { + draftState.clusters.set(rootCluster.uri, rootCluster); + }); + + render( + + + + + + ); + + expect( + await screen.findByText(/Requested user is not logged in/) + ).toBeVisible(); + expect(await screen.findByText(/Authorize Session/)).toBeDisabled(); +}); + test('authorizing a session opens its URL and closes document', async () => { jest.spyOn(window, 'open').mockImplementation(); const rootCluster = makeRootCluster({ diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx index 461a8de679ae4..18ff95e499575 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx @@ -50,7 +50,10 @@ export function DocumentAuthorizeWebSession(props: { return confirmationToken; }); const clusterName = routing.parseClusterName(props.doc.rootClusterUri); - const canAuthorize = rootCluster.loggedInUser?.isDeviceTrusted; + const isDeviceTrusted = rootCluster.loggedInUser?.isDeviceTrusted; + const isRequestedUserLoggedIn = + props.doc.webSessionRequest.username === rootCluster.loggedInUser?.name; + const canAuthorize = isDeviceTrusted && isRequestedUserLoggedIn; async function authorizeAndCloseDocument() { const [confirmationToken, error] = await authorize(); @@ -95,7 +98,7 @@ export function DocumentAuthorizeWebSession(props: {

Authorize Web Session

{/*It's technically possible to open a deep link to authorize a session on a device that is not enrolled.*/} - {!canAuthorize && ( + {!isDeviceTrusted && ( )} + {!isRequestedUserLoggedIn && ( + { + ctx.commandLauncher.executeCommand('cluster-logout', { + clusterUri: rootCluster.uri, + }); + }, + }} + details={ + <> + You are logged in as {rootCluster.loggedInUser?.name}. + To authorize this web session request, please log out in + Teleport Connect and log in again as{' '} + {props.doc.webSessionRequest.username}. +
+ Then click Launch Teleport Connect again in the browser. + + } + > + Requested user is not logged in +
+ )} {authorizeAttempt.status === 'error' && ( Could not authorize the session diff --git a/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts b/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts index 6083df679f626..ea98c9a51ef40 100644 --- a/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts +++ b/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts @@ -117,6 +117,7 @@ export class DeepLinksService { webSessionRequest: { id, token, + username: url.username, redirectUri: redirect_uri, }, }); diff --git a/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts b/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts index 0c7fd36952285..00238ae5b35fd 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts @@ -237,6 +237,7 @@ export interface DocumentAuthorizeWebSession extends DocumentBase { export interface WebSessionRequest { id: string; token: string; + username: string; redirectUri: string; } diff --git a/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts b/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts index ded2d08080df5..ccb1add834217 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts @@ -218,6 +218,7 @@ describe('state persistence', () => { id: '', token: '', redirectUri: '', + username: '', }, }, ],