16314: Fix syntax.
[arvados-workbench2.git] / src / views / login-panel / login-panel.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { connect, DispatchProp } from 'react-redux';
7 import { Grid, Typography, Button, Select } from '@material-ui/core';
8 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
9 import { login, authActions } from '~/store/auth/auth-action';
10 import { ArvadosTheme } from '~/common/custom-theme';
11 import { RootState } from '~/store/store';
12 import { LoginForm } from '~/views-components/login-form/login-form';
13 import Axios from 'axios';
14 import { Config } from '~/common/config';
15
16 type CssRules = 'root' | 'container' | 'title' | 'content' | 'content__bolder' | 'button';
17
18 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
19     root: {
20         position: 'relative',
21         backgroundColor: theme.palette.grey["200"],
22         '&::after': {
23             content: `''`,
24             position: 'absolute',
25             top: 0,
26             left: 0,
27             bottom: 0,
28             right: 0,
29             opacity: 0.2,
30         }
31     },
32     container: {
33         width: '560px',
34         zIndex: 10
35     },
36     title: {
37         marginBottom: theme.spacing.unit * 6,
38         color: theme.palette.grey["800"]
39     },
40     content: {
41         marginBottom: theme.spacing.unit * 3,
42         lineHeight: '1.2rem',
43         color: theme.palette.grey["800"]
44     },
45     'content__bolder': {
46         fontWeight: 'bolder'
47     },
48     button: {
49         boxShadow: 'none'
50     }
51 });
52
53 const doPasswordLogin = (url: string) => (username: string, password: string) => {
54     const formData = [];
55     formData.push('username='+encodeURIComponent(username));
56     formData.push('password='+encodeURIComponent(password));
57     return Axios.post(`${url}/arvados/v1/users/authenticate`, formData.join('&'), {
58         headers: {
59             'Content-Type': 'application/x-www-form-urlencoded'
60         },
61     });
62 };
63
64 type LoginPanelProps = DispatchProp<any> & WithStyles<CssRules> & {
65     remoteHosts: { [key: string]: string },
66     homeCluster: string,
67     localCluster: string,
68     loginCluster: string,
69     welcomePage: string,
70     passwordLogin: boolean,
71 };
72
73 const requirePasswordLogin = (config: Config): boolean => {
74     if (config && config.clusterConfig) {
75         return config.clusterConfig.Login.LDAP.Enable || config.clusterConfig.Login.PAM.Enable || config.clusterConfig.Login.Test.Enable || false;
76     }
77     return false;
78 };
79
80 export const LoginPanel = withStyles(styles)(
81     connect((state: RootState) => ({
82         remoteHosts: state.auth.remoteHosts,
83         homeCluster: state.auth.homeCluster,
84         localCluster: state.auth.localCluster,
85         loginCluster: state.auth.loginCluster,
86         welcomePage: state.auth.config.clusterConfig.Workbench.WelcomePageHTML,
87         passwordLogin: requirePasswordLogin(state.auth.remoteHostsConfig[state.auth.loginCluster || state.auth.homeCluster]),
88         }))(({ classes, dispatch, remoteHosts, homeCluster, localCluster, loginCluster, welcomePage, passwordLogin }: LoginPanelProps) => {
89         const loginBtnLabel = `Log in${(localCluster !== homeCluster && loginCluster !== homeCluster) ? " to "+localCluster+" with user from "+homeCluster : ''}`;
90
91         return (<Grid container justify="center" alignItems="center"
92             className={classes.root}
93             style={{ marginTop: 56, overflowY: "auto", height: "100%" }}>
94             <Grid item className={classes.container}>
95                 <Typography component="div">
96                     <div dangerouslySetInnerHTML={{ __html: welcomePage }} style={{ margin: "1em" }} />
97                 </Typography>
98                 {Object.keys(remoteHosts).length > 1 && loginCluster === "" &&
99
100                     <Typography component="div" align="right">
101                         <label>Please select the cluster that hosts your user account:</label>
102                         <Select native value={homeCluster} style={{ margin: "1em" }}
103                             onChange={(event) => dispatch(authActions.SET_HOME_CLUSTER(event.target.value))}>
104                             {Object.keys(remoteHosts).map((k) => <option key={k} value={k}>{k}</option>)}
105                         </Select>
106                     </Typography>}
107
108                 {passwordLogin
109                 ? <Typography component="div">
110                     <LoginForm dispatch={dispatch}
111                         loginLabel={loginBtnLabel}
112                         handleSubmit={doPasswordLogin(`https://${remoteHosts[loginCluster || homeCluster]}`)}/>
113                 </Typography>
114                 : <Typography component="div" align="right">
115                     <Button variant="contained" color="primary" style={{ margin: "1em" }}
116                         className={classes.button}
117                         onClick={() => dispatch(login(localCluster, homeCluster, loginCluster, remoteHosts))}>
118                         {loginBtnLabel}
119                     </Button>
120                 </Typography>}
121             </Grid>
122         </Grid >);}
123     ));