From c331c8cdce120fc46e412deea700141267c832e6 Mon Sep 17 00:00:00 2001 From: Stephen Smith Date: Thu, 16 Sep 2021 15:45:49 -0400 Subject: [PATCH] 17229: Webshell use localstorage if available Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- public/webshell/index.html | 4 ++++ src/services/auth-service/auth-service.ts | 9 +++++++++ src/store/auth/auth-action.ts | 5 +++-- src/store/auth/auth-reducer.ts | 5 ++++- .../virtual-machine-user-panel.tsx | 11 ++++++++++- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/public/webshell/index.html b/public/webshell/index.html index 77800137..ce903aa0 100644 --- a/public/webshell/index.html +++ b/public/webshell/index.html @@ -43,6 +43,10 @@ var token = urlParams.get('token'); if (token) { history.replaceState(null, "", `/webshell/?host=${encodeURIComponent(urlParams.get('host'))}&login=${encodeURIComponent(urlParams.get('login'))}`) + } else if (localStorage.getItem('apiToken')) { + token = localStorage.getItem('apiToken'); + } else { + // No token } // change this text when PAM is reconfigured to present a // password prompt that we can wait for. diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts index 362f7b51..5b975969 100644 --- a/src/services/auth-service/auth-service.ts +++ b/src/services/auth-service/auth-service.ts @@ -22,6 +22,8 @@ export const USER_IS_ACTIVE = 'isActive'; export const USER_USERNAME = 'username'; export const USER_PREFS = 'prefs'; export const HOME_CLUSTER = 'homeCluster'; +export const LOCAL_STORAGE = 'localStorage'; +export const SESSION_STORAGE = 'sessionStorage'; export interface UserDetailsResponse { email: string; @@ -50,6 +52,13 @@ export class AuthService { return localStorage; } + public getStorageType() { + if (this.useSessionStorage) { + return SESSION_STORAGE; + } + return LOCAL_STORAGE; + } + public saveApiToken(token: string) { this.removeApiToken(); this.getStorage().setItem(API_TOKEN_KEY, token); diff --git a/src/store/auth/auth-action.ts b/src/store/auth/auth-action.ts index 1bdb15d1..c7074704 100644 --- a/src/store/auth/auth-action.ts +++ b/src/store/auth/auth-action.ts @@ -24,7 +24,7 @@ export const authActions = unionize({ SET_CONFIG: ofType<{ config: Config }>(), SET_EXTRA_TOKEN: ofType<{ extraApiToken: string, extraApiTokenExpiration?: Date }>(), RESET_EXTRA_TOKEN: {}, - INIT_USER: ofType<{ user: User, token: string, tokenExpiration?: Date }>(), + INIT_USER: ofType<{ user: User, token: string, tokenExpiration?: Date, tokenLocation?: string }>(), USER_DETAILS_REQUEST: {}, USER_DETAILS_SUCCESS: ofType(), SET_SSH_KEYS: ofType(), @@ -97,7 +97,8 @@ export const saveApiToken = (token: string) => async (dispatch: Dispatch, getSta const user = await svc.authService.getUserDetails(); const client = await svc.apiClientAuthorizationService.get('current'); const tokenExpiration = client.expiresAt ? new Date(client.expiresAt) : undefined; - dispatch(authActions.INIT_USER({ user, token, tokenExpiration })); + const tokenLocation = await svc.authService.getStorageType(); + dispatch(authActions.INIT_USER({ user, token, tokenExpiration, tokenLocation })); } catch (e) { dispatch(authActions.LOGOUT({ deleteLinkData: false })); } diff --git a/src/store/auth/auth-reducer.ts b/src/store/auth/auth-reducer.ts index b8746ca5..ce836a55 100644 --- a/src/store/auth/auth-reducer.ts +++ b/src/store/auth/auth-reducer.ts @@ -13,6 +13,7 @@ export interface AuthState { user?: User; apiToken?: string; apiTokenExpiration?: Date; + apiTokenLocation?: string; extraApiToken?: string; extraApiTokenExpiration?: Date; sshKeys: SshKeyResource[]; @@ -29,6 +30,7 @@ const initialState: AuthState = { user: undefined, apiToken: undefined, apiTokenExpiration: undefined, + apiTokenLocation: undefined, extraApiToken: undefined, extraApiTokenExpiration: undefined, sshKeys: [], @@ -71,11 +73,12 @@ export const authReducer = (services: ServiceRepository) => (state = initialStat ({ ...state, extraApiToken, extraApiTokenExpiration }), RESET_EXTRA_TOKEN: () => ({ ...state, extraApiToken: undefined, extraApiTokenExpiration: undefined }), - INIT_USER: ({ user, token, tokenExpiration }) => + INIT_USER: ({ user, token, tokenExpiration, tokenLocation = state.apiTokenLocation }) => ({ ...state, user, apiToken: token, apiTokenExpiration: tokenExpiration, + apiTokenLocation: tokenLocation, homeCluster: user.uuid.substr(0, 5) }), LOGIN: () => state, diff --git a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx index 44631ce3..196cba16 100644 --- a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx +++ b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx @@ -12,10 +12,13 @@ import { saveRequestedDate, loadVirtualMachinesUserData } from 'store/virtual-ma import { RootState } from 'store/store'; import { ListResults } from 'services/common-service/common-service'; import { HelpIcon } from 'components/icon/icon'; +import { SESSION_STORAGE } from "services/auth-service/auth-service"; // import * as CopyToClipboard from 'react-copy-to-clipboard'; type CssRules = 'button' | 'codeSnippet' | 'link' | 'linkIcon' | 'rightAlign' | 'cardWithoutMachines' | 'icon'; +const EXTRA_TOKEN = "exra"; + const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ button: { marginTop: theme.spacing.unit, @@ -62,6 +65,7 @@ const mapStateToProps = (state: RootState) => { helpText: state.auth.config.clusterConfig.Workbench.SSHHelpPageHTML, hostSuffix: state.auth.config.clusterConfig.Workbench.SSHHelpHostSuffix || "", token: state.auth.extraApiToken || state.auth.apiToken || '', + tokenLocation: state.auth.extraApiToken ? EXTRA_TOKEN : (state.auth.apiTokenLocation || ''), webshellUrl: state.auth.config.clusterConfig.Services.WebShell.ExternalURL, ...state.virtualMachines }; @@ -80,6 +84,7 @@ interface VirtualMachinesPanelDataProps { helpText: string; hostSuffix: string; token: string; + tokenLocation: string, webshellUrl: string; } @@ -176,6 +181,10 @@ const virtualMachinesTable = (props: VirtualMachineProps) => if (lk.tailUuid === props.userUuid) { const username = lk.properties.username; const command = `ssh ${username}@${it.hostname}${props.hostSuffix}`; + let tokenParam = ""; + if (props.tokenLocation === SESSION_STORAGE || props.tokenLocation === EXTRA_TOKEN) { + tokenParam = `&token=${encodeURIComponent(props.token)}`; + } return {it.hostname} {username} @@ -183,7 +192,7 @@ const virtualMachinesTable = (props: VirtualMachineProps) => {command} - + Log in as {username} -- 2.30.2