2 * ============LICENSE_START========================================================================
3 * ONAP : ccsdk feature sdnr wt odlux
4 * =================================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6 * =================================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
16 * ============LICENSE_END==========================================================================
18 import React, { FC, useEffect, useState } from 'react';
19 import { RouteComponentProps, withRouter } from 'react-router-dom';
21 import Alert from '@mui/material/Alert';
22 import Avatar from '@mui/material/Avatar';
23 import Button from '@mui/material/Button';
24 import CssBaseline from '@mui/material/CssBaseline';
25 import FormControl from '@mui/material/FormControl';
26 import Input from '@mui/material/Input';
27 import InputLabel from '@mui/material/InputLabel';
28 import Paper from '@mui/material/Paper';
29 import { Theme } from '@mui/material/styles';
30 import Typography from '@mui/material/Typography';
32 import { makeStyles } from '@mui/styles';
34 import { useApplicationDispatch, useSelectApplicationState } from '../flux/connect';
35 import authenticationService from '../services/authenticationService';
37 import { loginUserAction, UpdatePolicies } from '../actions/authentication';
38 import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider';
40 import { AuthPolicy, AuthToken, User } from '../models/authentication';
42 const loginIcon = require('../assets/icons/User.svg');
44 const styles = makeStyles((theme: Theme) =>{
48 display: 'block', // Fix IE11 issue.
49 marginLeft: theme.spacing(3),
50 marginRight: theme.spacing(3),
51 [theme.breakpoints.up(400 + Number(theme.spacing(3).replace('px','')) * 2)]: {
58 marginTop: theme.spacing(8),
60 flexDirection: 'column',
62 padding: `${theme.spacing(2)} ${theme.spacing(3)} ${theme.spacing(3)}`,
65 margin: theme.spacing(1),
66 backgroundColor: theme.palette.secondary.main,
69 width: '100%', // Fix IE11 issue.
70 marginTop: theme.spacing(1),
73 marginTop: theme.spacing(3),
78 borderBottom: '1px solid grey',
85 backgroundColor: 'white',
93 type LoginProps = RouteComponentProps;
95 // todo: ggf. redirect to einbauen
96 const LoginComponent: FC<LoginProps> = (props) => {
98 const search = useSelectApplicationState(state => state.framework.navigationState.search);
99 const authentication = useSelectApplicationState(state => state.framework.applicationState.authentication);
100 const externalLoginProviders = useSelectApplicationState(state => state.framework.applicationState.externalLoginProviders);
102 const dispatch = useApplicationDispatch();
103 const updateExternalProviders = () => dispatch(updateExternalLoginProviderAsyncActionCreator());
104 const updateAuthentication = (token: AuthToken | null) => {
105 const user = token && new User(token) || undefined;
106 dispatch(loginUserAction(user));
108 const updatePolicies = (policies?: AuthPolicy[]) => {
109 return dispatch(new UpdatePolicies(policies));
112 const [isBusy, setBusy] = useState(false);
113 const [username, setUsername] = useState("");
114 const [password, setPassword] = useState("");
115 const [scope, setScope] = useState("sdn");
116 const [message, setMessage] = useState("");
117 const [isServerReady, setIsServerReady] = useState(false);
120 if (authentication === "oauth" && (externalLoginProviders == null || externalLoginProviders.length === 0)){
121 updateExternalProviders();
124 authenticationService.getServerReadyState().then(result =>{
125 setIsServerReady(result);
129 const onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
130 event.preventDefault();
134 const token = authentication === "oauth"
135 ? await authenticationService.authenticateUserOAuth(username, password, scope)
136 : await authenticationService.authenticateUserBasicAuth(username, password, scope);
138 updateAuthentication(token);
142 const query = search && search.replace(/^\?/, "").split('&').map(e => e.split("="));
143 const returnTo = query && query.find(e => e[0] === "returnTo");
144 props.history.replace(returnTo && returnTo[1] || "/");
149 const ready = await authenticationService.getServerReadyState();
151 setIsServerReady(true);
153 setMessage("Login is currently not possible. Please re-try in a few minutes. If the problem persists, ask your administrator for assistance.");
157 setMessage("Could not log in. Please check your credentials or ask your administrator for assistance.");
163 const classes = styles();
164 const areProvidersAvailable = externalLoginProviders && externalLoginProviders.length > 0;
169 <main className={classes.layout}>
170 <Paper className={classes.paper}>
171 <Avatar className={classes.avatar}>
172 <img src={loginIcon} alt="loginIcon" />
174 <Typography variant="caption">Sign in</Typography>
175 <form className={classes.form}>
176 {areProvidersAvailable &&
179 externalLoginProviders!.map((provider, index) => (
181 aria-controls="externalLogin"
182 aria-label={"external-login-identity-provider-" + (index + 1)}
187 className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}>
191 <div className={classes.lineContainer}>
192 <span className={classes.thirdPartyDivider}>
198 <FormControl variant="standard" margin="normal" required fullWidth>
199 <InputLabel htmlFor="username">Username</InputLabel>
200 <Input id="username" name="username" autoComplete="username" autoFocus
203 onChange={event => { setUsername(event.target.value); }} />
205 <FormControl variant="standard" margin="normal" required fullWidth>
206 <InputLabel htmlFor="password">Password</InputLabel>
211 autoComplete="current-password"
214 onChange={event => { setPassword(event.target.value); }}
217 <FormControl variant="standard" margin="normal" required fullWidth>
218 <InputLabel htmlFor="password">Domain</InputLabel>
225 onChange={event => { setScope(event.target.value); }}
229 aria-label="login-button"
235 className={classes.submit}
242 {message && <Alert severity="error">{message}</Alert>}
249 export const Login = withRouter(LoginComponent);
250 export default Login;