aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt-odlux/odlux/framework/src/views/login.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt-odlux/odlux/framework/src/views/login.tsx')
-rw-r--r--sdnr/wt-odlux/odlux/framework/src/views/login.tsx250
1 files changed, 250 insertions, 0 deletions
diff --git a/sdnr/wt-odlux/odlux/framework/src/views/login.tsx b/sdnr/wt-odlux/odlux/framework/src/views/login.tsx
new file mode 100644
index 000000000..46c0872bc
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/framework/src/views/login.tsx
@@ -0,0 +1,250 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import React, { FC, useEffect, useState } from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Alert from '@mui/material/Alert';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CssBaseline from '@mui/material/CssBaseline';
+import FormControl from '@mui/material/FormControl';
+import Input from '@mui/material/Input';
+import InputLabel from '@mui/material/InputLabel';
+import Paper from '@mui/material/Paper';
+import { Theme } from '@mui/material/styles';
+import Typography from '@mui/material/Typography';
+
+import { makeStyles } from '@mui/styles';
+
+import { useApplicationDispatch, useSelectApplicationState } from '../flux/connect';
+import authenticationService from '../services/authenticationService';
+
+import { loginUserAction, UpdatePolicies } from '../actions/authentication';
+import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider';
+
+import { AuthPolicy, AuthToken, User } from '../models/authentication';
+
+const loginIcon = require('../assets/icons/User.svg');
+
+const styles = makeStyles((theme: Theme) =>{
+ return{
+ layout: {
+ width: 'auto',
+ display: 'block', // Fix IE11 issue.
+ marginLeft: theme.spacing(3),
+ marginRight: theme.spacing(3),
+ [theme.breakpoints.up(400 + Number(theme.spacing(3).replace('px','')) * 2)]: {
+ width: 400,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ },
+ },
+ paper: {
+ marginTop: theme.spacing(8),
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ padding: `${theme.spacing(2)} ${theme.spacing(3)} ${theme.spacing(3)}`,
+ },
+ avatar: {
+ margin: theme.spacing(1),
+ backgroundColor: theme.palette.secondary.main,
+ },
+ form: {
+ width: '100%', // Fix IE11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ marginTop: theme.spacing(3),
+ },
+ lineContainer:{
+ width: '100%',
+ height: 10,
+ borderBottom: '1px solid grey',
+ textAlign: 'center',
+ marginTop:15,
+ marginBottom:5
+ },
+ thirdPartyDivider:{
+ fontSize: 15,
+ backgroundColor: 'white',
+ padding: '0 10px',
+ color: 'grey'
+ }
+};
+});
+
+
+type LoginProps = RouteComponentProps;
+
+// todo: ggf. redirect to einbauen
+const LoginComponent: FC<LoginProps> = (props) => {
+
+ const search = useSelectApplicationState(state => state.framework.navigationState.search);
+ const authentication = useSelectApplicationState(state => state.framework.applicationState.authentication);
+ const externalLoginProviders = useSelectApplicationState(state => state.framework.applicationState.externalLoginProviders);
+
+ const dispatch = useApplicationDispatch();
+ const updateExternalProviders = () => dispatch(updateExternalLoginProviderAsyncActionCreator());
+ const updateAuthentication = (token: AuthToken | null) => {
+ const user = token && new User(token) || undefined;
+ dispatch(loginUserAction(user));
+ }
+ const updatePolicies = (policies?: AuthPolicy[]) => {
+ return dispatch(new UpdatePolicies(policies));
+ }
+
+ const [isBusy, setBusy] = useState(false);
+ const [username, setUsername] = useState("");
+ const [password, setPassword] = useState("");
+ const [scope, setScope] = useState("sdn");
+ const [message, setMessage] = useState("");
+ const [isServerReady, setIsServerReady] = useState(false);
+
+ useEffect(()=>{
+ if (authentication === "oauth" && (externalLoginProviders == null || externalLoginProviders.length === 0)){
+ updateExternalProviders();
+ }
+
+ authenticationService.getServerReadyState().then(result =>{
+ setIsServerReady(result);
+ })
+ },[]);
+
+ const onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
+ event.preventDefault();
+
+ setBusy(true);
+
+ const token = authentication === "oauth"
+ ? await authenticationService.authenticateUserOAuth(username, password, scope)
+ : await authenticationService.authenticateUserBasicAuth(username, password, scope);
+
+ updateAuthentication(token);
+ setBusy(false);
+
+ if (token) {
+ const query = search && search.replace(/^\?/, "").split('&').map(e => e.split("="));
+ const returnTo = query && query.find(e => e[0] === "returnTo");
+ props.history.replace(returnTo && returnTo[1] || "/");
+ }
+ else {
+
+ if(!isServerReady){
+ const ready = await authenticationService.getServerReadyState();
+ if(ready){
+ setIsServerReady(true);
+ }else{
+ setMessage("Login is currently not possible. Please re-try in a few minutes. If the problem persists, ask your administrator for assistance.");
+ }
+
+ }else{
+ setMessage("Could not log in. Please check your credentials or ask your administrator for assistance.");
+ setPassword("");
+ }
+ }
+ }
+
+ const classes = styles();
+ const areProvidersAvailable = externalLoginProviders && externalLoginProviders.length > 0;
+
+ return (
+ <>
+ <CssBaseline />
+ <main className={classes.layout}>
+ <Paper className={classes.paper}>
+ <Avatar className={classes.avatar}>
+ <img src={loginIcon} alt="loginIcon" />
+ </Avatar>
+ <Typography variant="caption">Sign in</Typography>
+ <form className={classes.form}>
+ {areProvidersAvailable &&
+ <>
+ {
+ externalLoginProviders!.map((provider, index) => (
+ <Button
+ aria-controls="externalLogin"
+ aria-label={"external-login-identity-provider-" + (index + 1)}
+ aria-haspopup="true"
+ fullWidth
+ variant="contained"
+ color="inherit"
+ className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}>
+ {provider.title}
+ </Button>))
+ }
+ <div className={classes.lineContainer}>
+ <span className={classes.thirdPartyDivider}>
+ OR
+ </span>
+ </div>
+ </>
+ }
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="username">Username</InputLabel>
+ <Input id="username" name="username" autoComplete="username" autoFocus
+ disabled={isBusy}
+ value={username}
+ onChange={event => { setUsername(event.target.value); }} />
+ </FormControl>
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Password</InputLabel>
+ <Input
+ name="password"
+ type="password"
+ id="password"
+ autoComplete="current-password"
+ disabled={isBusy}
+ value={password}
+ onChange={event => { setPassword(event.target.value); }}
+ />
+ </FormControl>
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Domain</InputLabel>
+ <Input
+ name="scope"
+ type="scope"
+ id="scope"
+ disabled={isBusy}
+ value={scope}
+ onChange={event => { setScope(event.target.value); }}
+ />
+ </FormControl>
+ <Button
+ aria-label="login-button"
+ type="submit"
+ fullWidth
+ variant="contained"
+ color="inherit"
+ disabled={isBusy}
+ className={classes.submit}
+ onClick={onSignIn}
+ >
+ Sign in
+ </Button>
+
+ </form>
+ {message && <Alert severity="error">{message}</Alert>}
+ </Paper>
+ </main>
+ </>
+ );
+}
+
+export const Login = withRouter(LoginComponent);
+export default Login; \ No newline at end of file