--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { mount, configure } from 'enzyme';
+import Adapter from "enzyme-adapter-react-16";
+import { CustomTheme } from 'common/custom-theme';
+import { InactivePanelStateProps, CssRules, InactivePanelRoot } from './inactive-panel';
+import { MuiThemeProvider, StyledComponentProps } from '@material-ui/core';
+
+configure({ adapter: new Adapter() });
+
+describe('InactivePanel', () => {
+ let props: InactivePanelStateProps & StyledComponentProps<CssRules>;
+
+ beforeEach(() => {
+ props = {
+ classes: {
+ root: 'root',
+ title: 'title',
+ ontop: 'ontop',
+ },
+ isLoginClusterFederation: false,
+ inactivePageText: 'Inactive page content',
+ };
+ });
+
+ it('should render content and link account option', () => {
+ // given
+ const expectedMessage = "Inactive page content";
+ const expectedLinkAccountText = 'If you would like to use this login to access another account click "Link Account"';
+
+ // when
+ const wrapper = mount(
+ <MuiThemeProvider theme={CustomTheme}>
+ <InactivePanelRoot {...props} />
+ </MuiThemeProvider>
+ );
+
+ // then
+ expect(wrapper.find('p').first().text()).toContain(expectedMessage);
+ expect(wrapper.find('p').at(1).text()).toContain(expectedLinkAccountText);
+ })
+
+ it('should render content and link account warning on LoginCluster federations', () => {
+ // given
+ props.isLoginClusterFederation = true;
+ const expectedMessage = "Inactive page content";
+ const expectedLinkAccountText = 'If you would like to use this login to access another account, please contact your administrator';
+
+ // when
+ const wrapper = mount(
+ <MuiThemeProvider theme={CustomTheme}>
+ <InactivePanelRoot {...props} />
+ </MuiThemeProvider>
+ );
+
+ // then
+ expect(wrapper.find('p').first().text()).toContain(expectedMessage);
+ expect(wrapper.find('p').at(1).text()).toContain(expectedLinkAccountText);
+ })
+});
\ No newline at end of file
import { navigateToLinkAccount } from 'store/navigation/navigation-action';
import { RootState } from 'store/store';
-type CssRules = 'root' | 'ontop' | 'title';
+export type CssRules = 'root' | 'ontop' | 'title';
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
root: {
}
});
+const mapStateToProps = (state: RootState): InactivePanelStateProps => ({
+ inactivePageText: state.auth.config.clusterConfig.Workbench.InactivePageHTML,
+ isLoginClusterFederation: state.auth.config.clusterConfig.Login.LoginCluster !== '',
+});
+
export interface InactivePanelStateProps {
inactivePageText: string;
+ isLoginClusterFederation: boolean;
}
type InactivePanelProps = WithStyles<CssRules> & InactivePanelActionProps & InactivePanelStateProps;
-export const InactivePanel = connect((state: RootState) => ({
- inactivePageText: state.auth.config.clusterConfig.Workbench.InactivePageHTML
-}), mapDispatchToProps)(withStyles(styles)((({ classes, startLinking, inactivePageText }: InactivePanelProps) =>
+
+export const InactivePanelRoot = ({ classes, startLinking, inactivePageText, isLoginClusterFederation }: InactivePanelProps) =>
<Grid container justify="center" alignItems="center" direction="column" spacing={24}
className={classes.root}
style={{ marginTop: 56, height: "100%" }}>
<Grid item>
<Typography>
- <div dangerouslySetInnerHTML={{ __html: inactivePageText }} style={{ margin: "1em" }} />
+ <span dangerouslySetInnerHTML={{ __html: inactivePageText }} style={{ margin: "1em" }} />
</Typography>
</Grid>
- <Grid item>
+ { !isLoginClusterFederation
+ ? <><Grid item>
<Typography align="center">
- If you would like to use this login to access another account click "Link Account".
- </Typography>
+ If you would like to use this login to access another account click "Link Account".
+ </Typography>
</Grid>
<Grid item>
<Button className={classes.ontop} color="primary" variant="contained" onClick={() => startLinking()}>
Link Account
- </Button>
- </Grid>
- </Grid >
-)));
+ </Button>
+ </Grid></>
+ : <><Grid item>
+ <Typography align="center">
+ If you would like to use this login to access another account, please contact your administrator.
+ </Typography>
+ </Grid></> }
+ </Grid >;
+
+export const InactivePanel = connect(mapStateToProps, mapDispatchToProps)(
+ withStyles(styles)(InactivePanelRoot));
export const LinkAccountPanelRoot = withStyles(styles)(
({ classes, targetUser, userToLink, status, isProcessing, error, startLinking, cancelLinking, linkAccount,
remoteHostsConfig, hasRemoteHosts, selectedCluster, setSelectedCluster, localCluster, loginCluster }: LinkAccountPanelRootProps) => {
- return <Card className={classes.root}>
- <CardContent>
- {isProcessing && <Grid container item direction="column" alignContent="center" spacing={24}>
- <Grid item>
- Loading user info. Please wait.
- </Grid>
- <Grid item style={{ alignSelf: 'center' }}>
- <CircularProgress />
+
+ // If a LoginFederation is configured, the self-serve account linking is not
+ // currently available.
+ if (loginCluster !== "") {
+ return <Card className={classes.root}><CardContent>
+ <Grid container spacing={16}>
+ <Grid item xs={12}>
+ If you would like to link this account to another one, please contact your administrator.
</Grid>
- </Grid>}
- {!isProcessing && status === LinkAccountPanelStatus.INITIAL && targetUser && <div>
- {isLocalUser(targetUser.uuid, localCluster) ? <Grid container spacing={24}>
- <Grid container item direction="column" spacing={24}>
- <Grid item>
- You are currently logged in as {displayUser(targetUser, true)}
- </Grid>
- <Grid item>
- You can link Arvados accounts. After linking, either login will take you to the same account.
- </Grid >
+ </Grid>
+ </CardContent></Card>;
+ }
+ return <Card className={classes.root}><CardContent>
+ { isProcessing && <Grid container item direction="column" alignContent="center" spacing={24}>
+ <Grid item>
+ Loading user info. Please wait.
+ </Grid>
+ <Grid item style={{ alignSelf: 'center' }}>
+ <CircularProgress />
+ </Grid>
+ </Grid> }
+
+ { !isProcessing && status === LinkAccountPanelStatus.INITIAL && targetUser && <div>
+ { isLocalUser(targetUser.uuid, localCluster)
+ ? <Grid container spacing={24}>
+ <Grid container item direction="column" spacing={24}>
+ <Grid item>
+ You are currently logged in as {displayUser(targetUser, true)}
</Grid>
- <Grid container item direction="row" spacing={24}>
- <Grid item>
- <Button disabled={!targetUser.isActive} color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ADD_OTHER_LOGIN)}>
- Add another login to this account
- </Button>
- </Grid>
- <Grid item>
- <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ACCESS_OTHER_ACCOUNT)}>
- Use this login to access another account
- </Button>
- </Grid>
+ <Grid item>
+ You can link Arvados accounts. After linking, either login will take you to the same account.
+ </Grid >
+ </Grid>
+ <Grid container item direction="row" spacing={24}>
+ <Grid item>
+ <Button disabled={!targetUser.isActive} color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ADD_OTHER_LOGIN)}>
+ Add another login to this account
+ </Button>
</Grid>
- {hasRemoteHosts && selectedCluster && <Grid container item direction="column" spacing={24}>
- <Grid item>
- You can also link {displayUser(targetUser, false)} with an account from a remote cluster.
- </Grid>
- <Grid item>
- Please select the cluster that hosts the account you want to link with:
- <Select id="remoteHostsDropdown" native defaultValue={selectedCluster} style={{ marginLeft: "1em" }}
- onChange={(event) => setSelectedCluster(event.target.value)}>
- {Object.keys(remoteHostsConfig).map((k) => k !== localCluster ? <option key={k} value={k}>{k}</option> : null)}
- </Select>
- </Grid>
+ <Grid item>
+ <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ACCESS_OTHER_ACCOUNT)}>
+ Use this login to access another account
+ </Button>
+ </Grid>
+ </Grid>
+ {hasRemoteHosts && selectedCluster && <Grid container item direction="column" spacing={24}>
+ <Grid item>
+ You can also link {displayUser(targetUser, false)} with an account from a remote cluster.
+ </Grid>
+ <Grid item>
+ Please select the cluster that hosts the account you want to link with:
+ <Select id="remoteHostsDropdown" native defaultValue={selectedCluster} style={{ marginLeft: "1em" }}
+ onChange={(event) => setSelectedCluster(event.target.value)}>
+ {Object.keys(remoteHostsConfig).map((k) => k !== localCluster ? <option key={k} value={k}>{k}</option> : null)}
+ </Select>
+ </Grid>
+ <Grid item>
+ <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ACCESS_OTHER_REMOTE_ACCOUNT)}>
+ Link with an account on {hasRemoteHosts ? <label>{selectedCluster} </label> : null}
+ </Button>
+ </Grid>
+ </Grid>}
+ </Grid>
+ : <Grid container spacing={24}>
+ <Grid container item direction="column" spacing={24}>
+ <Grid item>
+ You are currently logged in as {displayUser(targetUser, true, true)}
+ </Grid>
+ { targetUser.isActive
+ ? (loginCluster === ""
+ ? <> <Grid item>
+ This a remote account. You can link a local Arvados account to this one.
+ After linking, you can access the local account's data by logging into the
+ <b>{localCluster}</b> cluster as user <b>{targetUser.email}</b>
+ from <b>{targetUser.uuid.substring(0, 5)}</b>.
+ </Grid >
<Grid item>
- <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ACCESS_OTHER_REMOTE_ACCOUNT)}>
- Link with an account on {hasRemoteHosts ? <label>{selectedCluster} </label> : null}
+ <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ADD_LOCAL_TO_REMOTE)}>
+ Link an account from {localCluster} to this account
</Button>
- </Grid>
- </Grid>}
- </Grid> :
- <Grid container spacing={24}>
- <Grid container item direction="column" spacing={24}>
- <Grid item>
- You are currently logged in as {displayUser(targetUser, true, true)}
- </Grid>
- {targetUser.isActive ?
- (loginCluster === "" ?
- <> <Grid item>
- This a remote account. You can link a local Arvados account to this one.
- After linking, you can access the local account's data by logging into the
- <b>{localCluster}</b> cluster as user <b>{targetUser.email}</b>
- from <b>{targetUser.uuid.substring(0, 5)}</b>.
- </Grid >
- <Grid item>
- <Button color="primary" variant="contained" onClick={() => startLinking(LinkAccountType.ADD_LOCAL_TO_REMOTE)}>
- Link an account from {localCluster} to this account
- </Button>
- </Grid> </>
- : <Grid item>Please visit cluster
- <a href={remoteHostsConfig[loginCluster].workbench2Url + "/link_account"}>{loginCluster}</a>
- to perform account linking.</Grid>
- )
- : <Grid item>
- This an inactive remote account. An administrator must activate your
- account before you can proceed. After your accounts is activated,
- you can link a local Arvados account hosted by the <b>{localCluster}</b>
- cluster to this one.
- </Grid >}
- </Grid>
- </Grid>}
- </div>}
- {!isProcessing && (status === LinkAccountPanelStatus.LINKING || status === LinkAccountPanelStatus.ERROR) && userToLink && targetUser &&
- <Grid container spacing={24}>
- {status === LinkAccountPanelStatus.LINKING && <Grid container item direction="column" spacing={24}>
- <Grid item>
- Clicking 'Link accounts' will link {displayUser(userToLink, true, !isLocalUser(targetUser.uuid, localCluster))} to {displayUser(targetUser, true, !isLocalUser(targetUser.uuid, localCluster))}.
- </Grid>
- {(isLocalUser(targetUser.uuid, localCluster)) && <Grid item>
- After linking, logging in as {displayUser(userToLink)} will log you into the same account as {displayUser(targetUser)}.
- </Grid>}
- <Grid item>
- Any object owned by {displayUser(userToLink)} will be transfered to {displayUser(targetUser)}.
- </Grid>
- {!isLocalUser(targetUser.uuid, localCluster) && <Grid item>
- You can access <b>{userToLink.email}</b> data by logging into <b>{localCluster}</b> with the <b>{targetUser.email}</b> account.
- </Grid>}
+ </Grid></>
+ : <Grid item>Please visit cluster
+ <a href={remoteHostsConfig[loginCluster].workbench2Url + "/link_account"}>{loginCluster}</a> to perform account linking.
+ </Grid> )
+ : <Grid item>
+ This an inactive remote account. An administrator must activate your
+ account before you can proceed. After your accounts is activated,
+ you can link a local Arvados account hosted by the <b>{localCluster}</b> cluster to this one.
+ </Grid> }
+ </Grid>
+ </Grid> }
+ </div> }
+
+ {!isProcessing && (status === LinkAccountPanelStatus.LINKING || status === LinkAccountPanelStatus.ERROR) && userToLink && targetUser &&
+ <Grid container spacing={24}>
+ {status === LinkAccountPanelStatus.LINKING && <Grid container item direction="column" spacing={24}>
+ <Grid item>
+ Clicking 'Link accounts' will link {displayUser(userToLink, true, !isLocalUser(targetUser.uuid, localCluster))} to {displayUser(targetUser, true, !isLocalUser(targetUser.uuid, localCluster))}.
+ </Grid>
+ {(isLocalUser(targetUser.uuid, localCluster)) && <Grid item>
+ After linking, logging in as {displayUser(userToLink)} will log you into the same account as {displayUser(targetUser)}.
</Grid>}
- {error === LinkAccountPanelError.NON_ADMIN && <Grid item>
- Cannot link admin account {displayUser(userToLink)} to non-admin account {displayUser(targetUser)}.
- </Grid>}
- {error === LinkAccountPanelError.SAME_USER && <Grid item>
- Cannot link {displayUser(targetUser)} to the same account.
- </Grid>}
- {error === LinkAccountPanelError.INACTIVE && <Grid item>
- Cannot link account {displayUser(userToLink)} to inactive account {displayUser(targetUser)}.
- </Grid>}
- <Grid container item direction="row" spacing={24}>
- <Grid item>
- <Button variant="contained" onClick={() => cancelLinking()}>
- Cancel
- </Button>
- </Grid>
- <Grid item>
- <Button disabled={status === LinkAccountPanelStatus.ERROR} color="primary" variant="contained" onClick={() => linkAccount()}>
- Link accounts
- </Button>
- </Grid>
+ <Grid item>
+ Any object owned by {displayUser(userToLink)} will be transfered to {displayUser(targetUser)}.
</Grid>
+ {!isLocalUser(targetUser.uuid, localCluster) && <Grid item>
+ You can access <b>{userToLink.email}</b> data by logging into <b>{localCluster}</b> with the <b>{targetUser.email}</b> account.
+ </Grid>}
+ </Grid>}
+ {error === LinkAccountPanelError.NON_ADMIN && <Grid item>
+ Cannot link admin account {displayUser(userToLink)} to non-admin account {displayUser(targetUser)}.
+ </Grid>}
+ {error === LinkAccountPanelError.SAME_USER && <Grid item>
+ Cannot link {displayUser(targetUser)} to the same account.
+ </Grid>}
+ {error === LinkAccountPanelError.INACTIVE && <Grid item>
+ Cannot link account {displayUser(userToLink)} to inactive account {displayUser(targetUser)}.
</Grid>}
- </CardContent>
- </Card>;
+ <Grid container item direction="row" spacing={24}>
+ <Grid item>
+ <Button variant="contained" onClick={() => cancelLinking()}>
+ Cancel
+ </Button>
+ </Grid>
+ <Grid item>
+ <Button disabled={status === LinkAccountPanelStatus.ERROR} color="primary" variant="contained" onClick={() => linkAccount()}>
+ Link accounts
+ </Button>
+ </Grid>
+ </Grid>
+ </Grid>}
+ </CardContent></Card>;
});