Skip to content

Commit ef62f0f

Browse files
Authentication (#54)
Add authentication Signed-off-by: ChamseddineBhd <[email protected]>
1 parent 53d8901 commit ef62f0f

File tree

15 files changed

+428
-32
lines changed

15 files changed

+428
-32
lines changed

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
REACT_APP_API_STUDY_SERVER=api/study-server
22
REACT_APP_API_CASE_SERVER=api/case-server
3+
4+
REACT_APP_USE_AUTHENTICATION=true

.env.development

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
REACT_APP_USE_AUTHENTICATION=false

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"react-window": "^1.8.5",
2626
"redux": "^4.0.5",
2727
"typeface-roboto": "0.0.75",
28+
"oidc-client": "^1.10.1",
2829
"react-virtualized": "^9.21.2"
2930
},
3031
"scripts": {

public/idpSettings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"authority" : "#",
3+
"client_id" : "#",
4+
"redirect_uri": "#",
5+
"post_logout_redirect_uri" : "#",
6+
"scope" : "#"
7+
}

src/components/app.js

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import React from 'react';
8+
import React, {useEffect, useState} from 'react';
99

10-
import {useSelector} from 'react-redux'
10+
import {useDispatch, useSelector} from 'react-redux'
1111

1212
import {Route, Switch, useHistory, useLocation} from 'react-router-dom';
1313

@@ -18,6 +18,8 @@ import StudyManager from './study-manager';
1818
import TopBar from './top-bar';
1919
import {LIGHT_THEME} from '../redux/actions'
2020
import Parameters from "./parameters";
21+
import {userManagerPromise, login, logout, handleSigninCallback} from '../utils/authentication/AuthService';
22+
import Authentication from "./authentication";
2123

2224
const lightTheme = createMuiTheme({
2325
palette: {
@@ -41,23 +43,50 @@ const getMuiTheme = (theme) => {
4143
}
4244
};
4345

44-
const App = () => {
46+
const SignInCallback = (props) => {
47+
useEffect(() => {
48+
if (props.userManager.instance !== null) {
49+
props.handleSigninCallback();
50+
}
51+
}, [props.userManager]);
52+
53+
return (
54+
<h1> </h1>
55+
)
56+
};
4557

58+
const noUserManager = {instance: null, error: null};
59+
60+
const App = () => {
4661
const theme = useSelector(state => state.theme);
4762

63+
const user = useSelector(state => state.user);
64+
65+
const [userManager, setUserManager] = useState(noUserManager);
66+
4867
const history = useHistory();
4968

69+
const dispatch = useDispatch();
70+
5071
const location = useLocation();
5172

73+
useEffect(() => {
74+
userManagerPromise
75+
.then(userManager => {
76+
setUserManager({instance : userManager, error : null });
77+
})
78+
.catch(function(error) {
79+
setUserManager({instance : null, error : error.message});
80+
console.debug("error when importing the idp settings")
81+
});
82+
}, []);
83+
5284
function studyClickHandler(studyName) {
5385
history.push("/studies/" + studyName);
5486
}
5587

5688
function showParameters() {
57-
if (location.pathname === "/parameters") {
58-
// if already at parameters go back to study
59-
history.goBack();
60-
} else {
89+
if (location.pathname !== "/parameters") {
6190
history.push("/parameters");
6291
}
6392
}
@@ -66,21 +95,33 @@ const App = () => {
6695
<ThemeProvider theme={getMuiTheme(theme)}>
6796
<React.Fragment>
6897
<CssBaseline />
69-
<TopBar onParametersClick={ () => showParameters() }/>
70-
<Switch>
71-
<Route exact path="/">
72-
<StudyManager onStudyClick={ name => studyClickHandler(name) }/>
73-
</Route>
74-
<Route exact path="/studies/:studyName">
75-
<StudyPane/>
76-
</Route>
77-
<Route exact path="/parameters">
78-
<Parameters/>
79-
</Route>
80-
<Route>
81-
<h1>Error: bad URL; No matched Route.</h1>
82-
</Route>
83-
</Switch>
98+
<TopBar onParametersClick={() => showParameters()} onLogoutClick={() => logout(dispatch, userManager.instance)}/>
99+
{ user !== null ? (
100+
<Switch>
101+
<Route exact path="/">
102+
<StudyManager onStudyClick={name => studyClickHandler(name)}/>)
103+
</Route>
104+
<Route exact path="/studies/:studyName">
105+
<StudyPane/>
106+
</Route>
107+
<Route exact path="/parameters">
108+
<Parameters/>
109+
</Route>
110+
<Route>
111+
<h1>Error: bad URL; No matched Route.</h1>
112+
</Route>
113+
</Switch>)
114+
: (
115+
<Switch>
116+
<Route exact path="/sign-in-callback">
117+
<SignInCallback userManager={userManager} handleSigninCallback={() => handleSigninCallback(dispatch, history, userManager.instance)}/>
118+
</Route>
119+
<Route>
120+
{userManager.error !== null && (<h1>Error : Getting userManager; {userManager.error}</h1>)}
121+
{userManager.error === null && (<Authentication disabled={userManager.instance === null} onLoginClick={() => login(location, userManager.instance)}/>)}
122+
</Route>
123+
</Switch>
124+
)}
84125
</React.Fragment>
85126
</ThemeProvider>
86127
)

src/components/authentication.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Copyright (c) 2020, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
import React, {useEffect} from 'react';
9+
import Avatar from '@material-ui/core/Avatar';
10+
import Button from '@material-ui/core/Button';
11+
import CssBaseline from '@material-ui/core/CssBaseline';
12+
import Link from '@material-ui/core/Link';
13+
import Box from '@material-ui/core/Box';
14+
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
15+
import Typography from '@material-ui/core/Typography';
16+
import { makeStyles } from '@material-ui/core/styles';
17+
import Container from '@material-ui/core/Container';
18+
import {FormattedMessage} from "react-intl";
19+
20+
const useStyles = makeStyles((theme) => ({
21+
paper: {
22+
marginTop: theme.spacing(8),
23+
display: 'flex',
24+
flexDirection: 'column',
25+
alignItems: 'center',
26+
},
27+
avatar: {
28+
margin: theme.spacing(1),
29+
backgroundColor: theme.palette.secondary.main,
30+
},
31+
submit: {
32+
margin: theme.spacing(3, 0, 2),
33+
borderRadius: '30px'
34+
},
35+
logo: {
36+
width: 64,
37+
height: 64,
38+
},
39+
}));
40+
41+
42+
const Authentication = (props) => {
43+
const classes = useStyles();
44+
45+
function Copyright() {
46+
return (
47+
<Typography variant="body2" color="textSecondary" align="center">
48+
{'Copyright © '}
49+
<Link color="inherit" href="#">
50+
Grid Suite
51+
</Link>{' '}
52+
{new Date().getFullYear()}
53+
{'.'}
54+
</Typography>
55+
);
56+
}
57+
58+
return (
59+
<Container component="main" maxWidth="xs">
60+
<CssBaseline />
61+
<div className={classes.paper}>
62+
<Avatar className={classes.avatar}>
63+
<LockOutlinedIcon />
64+
</Avatar>
65+
<Typography component="h1" variant="h5">
66+
<FormattedMessage id="login"/> ?
67+
</Typography>
68+
69+
<Button
70+
disabled={props.disabled}
71+
fullWidth
72+
variant="contained"
73+
color="primary"
74+
className={classes.submit}
75+
onClick={props.onLoginClick}
76+
>
77+
<FormattedMessage id="connection"/>
78+
</Button>
79+
</div>
80+
<Box mt={2}>
81+
<Copyright />
82+
</Box>
83+
</Container>
84+
);
85+
};
86+
87+
export default Authentication;

src/components/study-manager.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {ReactComponent as IeeeLogo} from '../images/ieee_logo.svg';
3434
import {loadStudiesSuccess} from '../redux/actions';
3535
import {fetchStudies, deleteStudy} from '../utils/rest-api';
3636
import CreateStudyForm from "./create-study-form";
37+
3738
import {CardHeader} from "@material-ui/core";
3839
import IconButton from "@material-ui/core/IconButton";
3940
import MoreVertIcon from '@material-ui/icons/MoreVert';
@@ -248,7 +249,6 @@ const StudyCard = ({study, onClick}) => {
248249
};
249250

250251
const StudyManager = ({onStudyClick}) => {
251-
252252
const dispatch = useDispatch();
253253

254254
useEffect(() => {
@@ -265,12 +265,12 @@ const StudyManager = ({onStudyClick}) => {
265265

266266
return (
267267
<Container maxWidth="lg">
268-
<CreateStudyForm />
268+
<CreateStudyForm/>
269269
<Grid container spacing={2} className={classes.grid}>
270270
{
271271
studies.map(study =>
272272
<Grid item xs={12} sm={6} md={3} key={study.studyName}>
273-
<StudyCard study={study} onClick={() => onStudyClick(study.studyName)} />
273+
<StudyCard study={study} onClick={() => onStudyClick(study.studyName)}/>
274274
</Grid>
275275
)
276276
}

0 commit comments

Comments
 (0)