[ARVADOS-WORKBENCH2] created: 1.4.1-51-g640e9ba2

Git user git at public.curoverse.com
Mon Oct 7 19:43:02 UTC 2019


        at  640e9ba2d458a1bdaadea09dfe2c92816601709d (commit)


commit 640e9ba2d458a1bdaadea09dfe2c92816601709d
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Mon Oct 7 15:37:46 2019 -0400

    15530: Fedlogin sends unsalted token
    
    When logging into the head of the federation, use unsalted token for
    authorizing to peer workbenches.
    
    Dispatch validateSessions on startup (to ensure that peers are
    "loggedIn" for multisite search.)

diff --git a/src/store/auth/auth-action-session.ts b/src/store/auth/auth-action-session.ts
index ca2e2326..6af72e0c 100644
--- a/src/store/auth/auth-action-session.ts
+++ b/src/store/auth/auth-action-session.ts
@@ -203,6 +203,7 @@ export const initSessions = (authService: AuthService, config: Config, user: Use
         const sessions = authService.buildSessions(config, user);
         authService.saveSessions(sessions);
         dispatch(authActions.SET_SESSIONS(sessions));
+        dispatch(validateSessions());
     };
 
 export const loadSiteManagerPanel = () =>
diff --git a/src/store/auth/auth-action.ts b/src/store/auth/auth-action.ts
index cccddb71..e273d18c 100644
--- a/src/store/auth/auth-action.ts
+++ b/src/store/auth/auth-action.ts
@@ -93,6 +93,7 @@ const init = (config: Config) => (dispatch: Dispatch, getState: () => RootState,
                 const remoteConfig = new Config();
                 remoteConfig.uuidPrefix = response.data.ClusterID;
                 remoteConfig.workbench2Url = response.data.Services.Workbench2.ExternalURL;
+                remoteConfig.loginCluster = response.data.Login.LoginCluster;
                 mapRemoteHosts(response.data, remoteConfig);
                 dispatch(authActions.REMOTE_CLUSTER_CONFIG({ config: remoteConfig }));
             });
@@ -111,10 +112,10 @@ export const saveUser = (user: UserResource) => (dispatch: Dispatch, getState: (
 };
 
 export const login = (uuidPrefix: string, homeCluster: string, loginCluster: string,
-		      remoteHosts: { [key: string]: string }) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-    services.authService.login(uuidPrefix, homeCluster, loginCluster, remoteHosts);
-    dispatch(authActions.LOGIN());
-};
+    remoteHosts: { [key: string]: string }) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        services.authService.login(uuidPrefix, homeCluster, loginCluster, remoteHosts);
+        dispatch(authActions.LOGIN());
+    };
 
 export const logout = (deleteLinkData: boolean = false) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
     if (deleteLinkData) {
diff --git a/src/views/search-results-panel/search-results-panel-view.tsx b/src/views/search-results-panel/search-results-panel-view.tsx
index b82b1745..8cd25a5e 100644
--- a/src/views/search-results-panel/search-results-panel-view.tsx
+++ b/src/views/search-results-panel/search-results-panel-view.tsx
@@ -100,6 +100,7 @@ export const searchResultsPanelColumns: DataColumns<string> = [
 
 export const SearchResultsPanelView = (props: SearchResultsPanelProps) => {
     const homeCluster = props.user.uuid.substr(0, 5);
+    const loggedIn = props.sessions.filter((ss) => ss.loggedIn);
     return <DataExplorer
         id={SEARCH_RESULTS_PANEL_ID}
         onRowClick={props.onItemClick}
@@ -108,9 +109,9 @@ export const SearchResultsPanelView = (props: SearchResultsPanelProps) => {
         contextMenuColumn={false}
         hideSearchInput
         title={
-            props.localCluster === homeCluster ?
-                <div>Searching clusters: {props.sessions.filter((ss) => ss.loggedIn).map((ss) => <span key={ss.clusterId}> {ss.clusterId}</span>)}</div> :
-                <div>Searching local cluster {props.localCluster} only.  To search multiple clusters, <a href={props.remoteHostsConfig[homeCluster] && props.remoteHostsConfig[homeCluster].workbench2Url}> start from your home Workbench.</a></div>
+            (props.localCluster !== homeCluster && loggedIn.length === 1) ?
+                <div>Searching local cluster {props.localCluster} only.  To search multiple clusters, <a href={props.remoteHostsConfig[homeCluster] && props.remoteHostsConfig[homeCluster].workbench2Url}> start from your home Workbench.</a></div> :
+                <div>Searching clusters: {loggedIn.map((ss) => <span key={ss.clusterId}> {ss.clusterId}</span>)}</div>
         }
     />;
 };
diff --git a/src/views/workbench/fed-login.tsx b/src/views/workbench/fed-login.tsx
index 829fe17a..be543a64 100644
--- a/src/views/workbench/fed-login.tsx
+++ b/src/views/workbench/fed-login.tsx
@@ -41,7 +41,9 @@ export const FedLogin = connect(mapStateToProps)(
                             console.log(`Cluster ${k} does not define workbench2Url.  Federated login / cross-site linking to ${k} is unavailable.  Tell the admin of ${k} to set Services->Workbench2->ExternalURL in config.yml.`);
                             return;
                         }
-                        return <iframe key={k} src={`${remoteHostsConfig[k].workbench2Url}/fedtoken?api_token=${getSaltedToken(k, tokenUuid, token)}`} style={{
+                        const fedtoken = (remoteHostsConfig[k].loginCluster === localCluster)
+                            ? apiToken : getSaltedToken(k, tokenUuid, token);
+                        return <iframe key={k} src={`${remoteHostsConfig[k].workbench2Url}/fedtoken?api_token=${fedtoken}`} style={{
                             height: 0,
                             width: 0,
                             visibility: "hidden"

commit 29c0944feb7932889a5b6fcaf208eef9f5864a29
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Tue Sep 24 15:39:16 2019 -0400

    15530: When loading sessions, clear 'active' flag and revalidate.

diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts
index a80d89ba..359a78ec 100644
--- a/src/services/auth-service/auth-service.ts
+++ b/src/services/auth-service/auth-service.ts
@@ -114,10 +114,10 @@ export class AuthService {
         localStorage.removeItem(USER_PREFS);
     }
 
-    public login(uuidPrefix: string, homeCluster: string, remoteHosts: { [key: string]: string }) {
+    public login(uuidPrefix: string, homeCluster: string, loginCluster: string, remoteHosts: { [key: string]: string }) {
         const currentUrl = `${window.location.protocol}//${window.location.host}/token`;
         const homeClusterHost = remoteHosts[homeCluster];
-        window.location.assign(`https://${homeClusterHost}/login?${uuidPrefix !== homeCluster ? "remote=" + uuidPrefix + "&" : ""}return_to=${currentUrl}`);
+        window.location.assign(`https://${homeClusterHost}/login?${(uuidPrefix !== homeCluster && homeCluster !== loginCluster) ? "remote=" + uuidPrefix + "&" : ""}return_to=${currentUrl}`);
     }
 
     public logout() {
@@ -183,7 +183,12 @@ export class AuthService {
             active: true,
             status: SessionStatus.VALIDATED
         } as Session;
-        const localSessions = this.getSessions();
+        const localSessions = this.getSessions().map(s => ({
+            ...s,
+            active: false,
+            status: SessionStatus.INVALIDATED
+        }));
+
         const cfgSessions = Object.keys(cfg.remoteHosts).map(clusterId => {
             const remoteHost = cfg.remoteHosts[clusterId];
             return {
@@ -200,7 +205,8 @@ export class AuthService {
         });
         const sessions = [currentSession]
             .concat(localSessions)
-            .concat(cfgSessions);
+            .concat(cfgSessions)
+            .filter((r: Session) => r.clusterId !== "*");
 
         const uniqSessions = uniqBy(sessions, 'clusterId');
 
diff --git a/src/store/auth/auth-action.ts b/src/store/auth/auth-action.ts
index 4a4710de..cccddb71 100644
--- a/src/store/auth/auth-action.ts
+++ b/src/store/auth/auth-action.ts
@@ -110,8 +110,9 @@ export const saveUser = (user: UserResource) => (dispatch: Dispatch, getState: (
     dispatch(authActions.SAVE_USER(user));
 };
 
-export const login = (uuidPrefix: string, homeCluster: string, remoteHosts: { [key: string]: string }) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-    services.authService.login(uuidPrefix, homeCluster, remoteHosts);
+export const login = (uuidPrefix: string, homeCluster: string, loginCluster: string,
+		      remoteHosts: { [key: string]: string }) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+    services.authService.login(uuidPrefix, homeCluster, loginCluster, remoteHosts);
     dispatch(authActions.LOGIN());
 };
 
diff --git a/src/store/link-account-panel/link-account-panel-actions.ts b/src/store/link-account-panel/link-account-panel-actions.ts
index cdc99660..88d2a4ec 100644
--- a/src/store/link-account-panel/link-account-panel-actions.ts
+++ b/src/store/link-account-panel/link-account-panel-actions.ts
@@ -19,22 +19,27 @@ import { WORKBENCH_LOADING_SCREEN } from '~/store/workbench/workbench-actions';
 
 export const linkAccountPanelActions = unionize({
     LINK_INIT: ofType<{
-        targetUser: UserResource | undefined }>(),
+        targetUser: UserResource | undefined
+    }>(),
     LINK_LOAD: ofType<{
         originatingUser: OriginatingUser | undefined,
         targetUser: UserResource | undefined,
         targetUserToken: string | undefined,
         userToLink: UserResource | undefined,
-        userToLinkToken: string | undefined }>(),
+        userToLinkToken: string | undefined
+    }>(),
     LINK_INVALID: ofType<{
         originatingUser: OriginatingUser | undefined,
         targetUser: UserResource | undefined,
         userToLink: UserResource | undefined,
-        error: LinkAccountPanelError }>(),
+        error: LinkAccountPanelError
+    }>(),
     SET_SELECTED_CLUSTER: ofType<{
-        selectedCluster: string }>(),
+        selectedCluster: string
+    }>(),
     SET_IS_PROCESSING: ofType<{
-        isProcessing: boolean}>(),
+        isProcessing: boolean
+    }>(),
     HAS_SESSION_DATA: {}
 });
 
@@ -119,7 +124,7 @@ export const loadLinkAccountPanel = () =>
             dispatch(checkForLinkStatus());
 
             // Continue loading the link account panel
-            dispatch(setBreadcrumbs([{ label: 'Link account'}]));
+            dispatch(setBreadcrumbs([{ label: 'Link account' }]));
             const curUser = getState().auth.user;
             const curToken = getState().auth.apiToken;
             if (curUser && curToken) {
@@ -170,7 +175,8 @@ export const loadLinkAccountPanel = () =>
                             originatingUser: params.originatingUser,
                             targetUser: params.targetUser,
                             userToLink: params.userToLink,
-                            error}));
+                            error
+                        }));
                         return;
                     }
                 }
@@ -192,18 +198,18 @@ export const loadLinkAccountPanel = () =>
 
 export const startLinking = (t: LinkAccountType) =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
-        const accountToLink = {type: t, userUuid: services.authService.getUuid(), token: services.authService.getApiToken()} as AccountToLink;
+        const accountToLink = { type: t, userUuid: services.authService.getUuid(), token: services.authService.getApiToken() } as AccountToLink;
         services.linkAccountService.saveAccountToLink(accountToLink);
 
         const auth = getState().auth;
-        const isLocalUser = auth.user!.uuid.substring(0,5) === auth.localCluster;
+        const isLocalUser = auth.user!.uuid.substring(0, 5) === auth.localCluster;
         let homeCluster = auth.localCluster;
         if (isLocalUser && t === LinkAccountType.ACCESS_OTHER_REMOTE_ACCOUNT) {
             homeCluster = getState().linkAccountPanel.selectedCluster!;
         }
 
         dispatch(logout());
-        dispatch(login(auth.localCluster, homeCluster, auth.remoteHosts));
+        dispatch(login(auth.localCluster, homeCluster, auth.loginCluster, auth.remoteHosts));
     };
 
 export const getAccountLinkData = () =>
@@ -265,7 +271,7 @@ export const linkAccount = () =>
                 services.linkAccountService.saveLinkOpStatus(LinkAccountStatus.SUCCESS);
                 location.reload();
             }
-            catch(e) {
+            catch (e) {
                 // If the link operation fails, delete the previously made project
                 try {
                     setAuthorizationHeader(services, linkState.targetUserToken);
@@ -277,4 +283,4 @@ export const linkAccount = () =>
                 throw e;
             }
         }
-    };
\ No newline at end of file
+    };
diff --git a/src/views-components/main-app-bar/anonymous-menu.tsx b/src/views-components/main-app-bar/anonymous-menu.tsx
index 15329a43..be280675 100644
--- a/src/views-components/main-app-bar/anonymous-menu.tsx
+++ b/src/views-components/main-app-bar/anonymous-menu.tsx
@@ -11,6 +11,6 @@ export const AnonymousMenu = connect()(
     ({ dispatch }: DispatchProp<any>) =>
         <Button
             color="inherit"
-            onClick={() => dispatch(login("", "", {}))}>
+            onClick={() => dispatch(login("", "", "", {}))}>
             Sign in
         </Button>);
diff --git a/src/views/login-panel/login-panel.tsx b/src/views/login-panel/login-panel.tsx
index 70a673bb..16b8b0bb 100644
--- a/src/views/login-panel/login-panel.tsx
+++ b/src/views/login-panel/login-panel.tsx
@@ -95,7 +95,7 @@ export const LoginPanel = withStyles(styles)(
 
                 <Typography component="div" align="right">
                     <Button variant="contained" color="primary" style={{ margin: "1em" }} className={classes.button}
-                        onClick={() => dispatch(login(uuidPrefix, homeCluster, remoteHosts))}>
+                        onClick={() => dispatch(login(uuidPrefix, homeCluster, loginCluster, remoteHosts))}>
                         Log in to {uuidPrefix}
                         {uuidPrefix !== homeCluster &&
                             <span> with user from {homeCluster}</span>}
diff --git a/src/views/site-manager-panel/site-manager-panel-root.tsx b/src/views/site-manager-panel/site-manager-panel-root.tsx
index 684e35b4..36349774 100644
--- a/src/views/site-manager-panel/site-manager-panel-root.tsx
+++ b/src/views/site-manager-panel/site-manager-panel-root.tsx
@@ -33,8 +33,8 @@ type CssRules = 'root' | 'link' | 'buttonContainer' | 'table' | 'tableRow' |
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
-       width: '100%',
-       overflow: 'auto'
+        width: '100%',
+        overflow: 'auto'
     },
     link: {
         color: theme.palette.primary.main,
@@ -106,7 +106,7 @@ const submitSession = (remoteHost: string) =>
     };
 
 export const SiteManagerPanelRoot = compose(
-    reduxForm<{remoteHost: string}>({
+    reduxForm<{ remoteHost: string }>({
         form: SITE_MANAGER_FORM_NAME,
         touchOnBlur: false,
         onSubmit: (data, dispatch) => {
@@ -119,9 +119,9 @@ export const SiteManagerPanelRoot = compose(
             <CardContent>
                 <Grid container direction="row">
                     <Grid item xs={12}>
-                        <Typography  paragraph={true} >
+                        <Typography paragraph={true} >
                             You can log in to multiple Arvados sites here, then use the multi-site search page to search collections and projects on all sites at once.
-                        </Typography>
+                    </Typography>
                     </Grid>
                 </Grid>
                 <Grid item xs={12}>
@@ -129,6 +129,7 @@ export const SiteManagerPanelRoot = compose(
                         <TableHead>
                             <TableRow className={classes.tableRow}>
                                 <TableCell>Cluster ID</TableCell>
+                                <TableCell>Host</TableCell>
                                 <TableCell>Username</TableCell>
                                 <TableCell>Email</TableCell>
                                 <TableCell>Status</TableCell>
@@ -139,8 +140,9 @@ export const SiteManagerPanelRoot = compose(
                                 const validating = session.status === SessionStatus.BEING_VALIDATED;
                                 return <TableRow key={index} className={classes.tableRow}>
                                     <TableCell>{session.clusterId}</TableCell>
-                                    <TableCell>{validating ? <CircularProgress size={20}/> : session.username}</TableCell>
-                                    <TableCell>{validating ? <CircularProgress size={20}/> : session.email}</TableCell>
+                                    <TableCell>{session.remoteHost}</TableCell>
+                                    <TableCell>{validating ? <CircularProgress size={20} /> : session.username}</TableCell>
+                                    <TableCell>{validating ? <CircularProgress size={20} /> : session.email}</TableCell>
                                     <TableCell className={classes.statusCell}>
                                         <Button fullWidth
                                             disabled={validating || session.status === SessionStatus.INVALIDATED || session.active}
@@ -157,9 +159,9 @@ export const SiteManagerPanelRoot = compose(
                 <form onSubmit={handleSubmit}>
                     <Grid container direction="row">
                         <Grid item xs={12}>
-                            <Typography  paragraph={true} className={classes.remoteSiteInfo}>
+                            <Typography paragraph={true} className={classes.remoteSiteInfo}>
                                 To add a remote Arvados site, paste the remote site's host here (see "ARVADOS_API_HOST" on the "current token" page).
-                            </Typography>
+                        </Typography>
                         </Grid>
                         <Grid item xs={8}>
                             <Field
@@ -169,7 +171,7 @@ export const SiteManagerPanelRoot = compose(
                                 placeholder="zzzz.arvadosapi.com"
                                 margin="normal"
                                 label="New cluster"
-                                autoFocus/>
+                                autoFocus />
                         </Grid>
                         <Grid item xs={3}>
                             <Button type="submit" variant="contained" color="primary"

commit 04446cedce14583b0ad11f6f0d989bf834a27d04
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Tue Sep 24 10:58:13 2019 -0400

    15530: Set homeCluster to LoginCluster

diff --git a/src/common/config.ts b/src/common/config.ts
index 496b0b78..3dc34ce5 100644
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@ -45,6 +45,9 @@ export interface ClusterConfigJSON {
         VocabularyURL: string;
         FileViewersConfigURL: string;
     };
+    Login: {
+        LoginCluster: string;
+    };
 }
 
 export class Config {
@@ -60,6 +63,7 @@ export class Config {
     workbench2Url: string;
     vocabularyUrl: string;
     fileViewersConfigUrl: string;
+    loginCluster: string;
 }
 
 export const fetchConfig = () => {
@@ -111,6 +115,7 @@ remove the entire ${varName} entry from ${WORKBENCH_CONFIG_URL}`);
                 config.workbench2Url = clusterConfigJSON.Services.Workbench2.ExternalURL;
                 config.workbenchUrl = clusterConfigJSON.Services.Workbench1.ExternalURL;
                 config.keepWebServiceUrl = clusterConfigJSON.Services.WebDAV.ExternalURL;
+                config.loginCluster = clusterConfigJSON.Login.LoginCluster;
                 mapRemoteHosts(clusterConfigJSON, config);
 
                 return { config, apiHost: workbenchConfig.API_HOST };
@@ -135,7 +140,8 @@ export const mockConfig = (config: Partial<Config>): Config => ({
     workbenchUrl: "",
     workbench2Url: "",
     vocabularyUrl: "",
-    fileViewersConfigUrl: ""
+    fileViewersConfigUrl: "",
+    loginCluster: ""
 });
 
 const getDefaultConfig = (): WorkbenchConfig => {
@@ -157,4 +163,4 @@ const getDefaultConfig = (): WorkbenchConfig => {
 
 export const ARVADOS_API_PATH = "arvados/v1";
 export const CLUSTER_CONFIG_URL = "arvados/v1/config";
-export const getClusterConfigURL = (apiHost: string) => `${window.location.protocol}//${apiHost}/${CLUSTER_CONFIG_URL}?nocache=${(new Date()).getTime()}`;
\ No newline at end of file
+export const getClusterConfigURL = (apiHost: string) => `${window.location.protocol}//${apiHost}/${CLUSTER_CONFIG_URL}?nocache=${(new Date()).getTime()}`;
diff --git a/src/store/auth/auth-action.ts b/src/store/auth/auth-action.ts
index b889adf5..4a4710de 100644
--- a/src/store/auth/auth-action.ts
+++ b/src/store/auth/auth-action.ts
@@ -72,7 +72,7 @@ const init = (config: Config) => (dispatch: Dispatch, getState: () => RootState,
         setAuthorizationHeader(services, token);
     }
     dispatch(authActions.CONFIG({ config }));
-    dispatch(authActions.SET_HOME_CLUSTER(homeCluster || config.uuidPrefix));
+    dispatch(authActions.SET_HOME_CLUSTER(config.loginCluster || homeCluster || config.uuidPrefix));
     if (token && user) {
         dispatch(authActions.INIT({ user, token }));
         dispatch<any>(initSessions(services.authService, config, user));
@@ -94,7 +94,7 @@ const init = (config: Config) => (dispatch: Dispatch, getState: () => RootState,
                 remoteConfig.uuidPrefix = response.data.ClusterID;
                 remoteConfig.workbench2Url = response.data.Services.Workbench2.ExternalURL;
                 mapRemoteHosts(response.data, remoteConfig);
-                dispatch(authActions.REMOTE_CLUSTER_CONFIG({ config: remoteConfig}));
+                dispatch(authActions.REMOTE_CLUSTER_CONFIG({ config: remoteConfig }));
             });
     });
 };
diff --git a/src/store/auth/auth-reducer.ts b/src/store/auth/auth-reducer.ts
index cded9f0e..b4e73e1e 100644
--- a/src/store/auth/auth-reducer.ts
+++ b/src/store/auth/auth-reducer.ts
@@ -16,6 +16,7 @@ export interface AuthState {
     sessions: Session[];
     localCluster: string;
     homeCluster: string;
+    loginCluster: string;
     remoteHosts: { [key: string]: string };
     remoteHostsConfig: { [key: string]: Config };
 }
@@ -27,6 +28,7 @@ const initialState: AuthState = {
     sessions: [],
     localCluster: "",
     homeCluster: "",
+    loginCluster: "",
     remoteHosts: {},
     remoteHostsConfig: {}
 };
@@ -37,14 +39,15 @@ export const authReducer = (services: ServiceRepository) => (state = initialStat
             return { ...state, apiToken: token };
         },
         SAVE_USER: (user: UserResource) => {
-            return { ...state, user};
+            return { ...state, user };
         },
         CONFIG: ({ config }) => {
             return {
                 ...state,
                 localCluster: config.uuidPrefix,
                 remoteHosts: { ...config.remoteHosts, [config.uuidPrefix]: new URL(config.rootUrl).host },
-                homeCluster: config.uuidPrefix
+                homeCluster: config.loginCluster || config.uuidPrefix,
+                loginCluster: config.loginCluster
             };
         },
         REMOTE_CLUSTER_CONFIG: ({ config }) => {
diff --git a/src/views/login-panel/login-panel.tsx b/src/views/login-panel/login-panel.tsx
index debede12..70a673bb 100644
--- a/src/views/login-panel/login-panel.tsx
+++ b/src/views/login-panel/login-panel.tsx
@@ -52,15 +52,17 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 type LoginPanelProps = DispatchProp<any> & WithStyles<CssRules> & {
     remoteHosts: { [key: string]: string },
     homeCluster: string,
-    uuidPrefix: string
+    uuidPrefix: string,
+    loginCluster: string
 };
 
 export const LoginPanel = withStyles(styles)(
     connect((state: RootState) => ({
         remoteHosts: state.auth.remoteHosts,
         homeCluster: state.auth.homeCluster,
-        uuidPrefix: state.auth.localCluster
-    }))(({ classes, dispatch, remoteHosts, homeCluster, uuidPrefix }: LoginPanelProps) =>
+        uuidPrefix: state.auth.localCluster,
+        loginCluster: state.auth.loginCluster
+    }))(({ classes, dispatch, remoteHosts, homeCluster, uuidPrefix, loginCluster }: LoginPanelProps) =>
         <Grid container justify="center" alignItems="center"
             className={classes.root}
             style={{ marginTop: 56, overflowY: "auto", height: "100%" }}>
@@ -82,7 +84,7 @@ export const LoginPanel = withStyles(styles)(
                     Arvados Workbench uses your name and email address only for identification, and does not retrieve any other personal information from Google.
 		</Typography>
 
-                {Object.keys(remoteHosts).length > 1 &&
+                {Object.keys(remoteHosts).length > 1 && loginCluster === "" &&
                     <Typography component="div" align="right">
                         <label>Please select the cluster that hosts your user account:</label>
                         <Select native value={homeCluster} style={{ margin: "1em" }}

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list