Refactor authentication with Context
This commit is contained in:
parent
ec65c3b9dd
commit
51ec69a3cb
32
src/App.js
32
src/App.js
@ -1,10 +1,12 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import 'rsuite/lib/styles/index.less';
|
import 'rsuite/lib/styles/index.less';
|
||||||
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
import PrivateRoute from './components/routes/PrivateRoute';
|
import { AuthContext } from './helpers/authContext';
|
||||||
import PublicRoute from './components/routes/PublicRoute';
|
|
||||||
|
|
||||||
|
import PrivateRoute from './components/Routes/PrivateRoute';
|
||||||
|
|
||||||
|
import Home from './screens/Home';
|
||||||
import Dashboard from './screens/Dashboard';
|
import Dashboard from './screens/Dashboard';
|
||||||
import Schedule from './screens/Schedule/Schedule';
|
import Schedule from './screens/Schedule/Schedule';
|
||||||
import Availability from './screens/Availability/Availability';
|
import Availability from './screens/Availability/Availability';
|
||||||
@ -12,21 +14,35 @@ import Invite from './screens/Invite/Invite';
|
|||||||
import Login from './screens/Login';
|
import Login from './screens/Login';
|
||||||
import Register from './screens/Register';
|
import Register from './screens/Register';
|
||||||
|
|
||||||
|
const existingToken = localStorage.getItem('token');
|
||||||
|
// const existingUser = JSON.parse(localStorage.getItem('user'));
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
const [authToken, setAuthToken] = useState(existingToken);
|
||||||
|
|
||||||
|
const setToken = (data) => {
|
||||||
|
localStorage.setItem('token', JSON.stringify(data));
|
||||||
|
setAuthToken(data);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<AuthContext.Provider value={{ authToken, setAuthToken: setToken }}>
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/' exact component={Login} />
|
<Route path='/' exact component={Home} />
|
||||||
|
<Route path='/login' component={Login} />
|
||||||
<PublicRoute path='/login' component={Login} />
|
<Route path='/register' component={Register} />
|
||||||
<PublicRoute path='/register' component={Register} />
|
|
||||||
|
|
||||||
<PrivateRoute path='/dashboard' component={Dashboard} />
|
<PrivateRoute path='/dashboard' component={Dashboard} />
|
||||||
<PrivateRoute path='/schedule' component={Schedule} />
|
<PrivateRoute path='/schedule' component={Schedule} />
|
||||||
<PrivateRoute path='/invite' component={Invite} />
|
<PrivateRoute path='/invite' component={Invite} />
|
||||||
<PrivateRoute path='/availability' component={Availability} />
|
<PrivateRoute
|
||||||
|
path='/availability'
|
||||||
|
component={Availability}
|
||||||
|
/>
|
||||||
<PrivateRoute path='/schedule' component={Schedule} />
|
<PrivateRoute path='/schedule' component={Schedule} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
|
</AuthContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { Nav, Icon, Dropdown, Popover, Whisper } from 'rsuite';
|
import { Nav, Icon, Dropdown, Popover, Whisper } from 'rsuite';
|
||||||
|
|
||||||
export default function MenuDropdown() {
|
export default function MenuDropdown() {
|
||||||
@ -12,18 +11,34 @@ export default function MenuDropdown() {
|
|||||||
triggerRef.current.hide();
|
triggerRef.current.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleLogout() {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
history.push('/');
|
||||||
|
}
|
||||||
|
|
||||||
const MenuPopover = ({ onSelect, ...rest }) => (
|
const MenuPopover = ({ onSelect, ...rest }) => (
|
||||||
<Popover {...rest} full>
|
<Popover {...rest} full>
|
||||||
<Dropdown.Menu onSelect={onSelect}>
|
<Dropdown.Menu onSelect={onSelect}>
|
||||||
<Dropdown.Item eventKey={'/'}>Dashboard</Dropdown.Item>
|
<Dropdown.Item eventKey={'/'}>Dashboard</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={'register'}>Register</Dropdown.Item>
|
<Dropdown.Item eventKey={'register'}>Register</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={'login'}>Login</Dropdown.Item>
|
<Dropdown.Item eventKey={'login'}>Login</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={'schedule'}>1 - Schedule a meeting</Dropdown.Item>
|
<Dropdown.Item eventKey={'schedule'}>
|
||||||
<Dropdown.Item eventKey={'invite'}>2 - Invite participants</Dropdown.Item>
|
1 - Schedule a meeting
|
||||||
<Dropdown.Item eventKey={'availability'}>3 - Add your availability</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={'confirm'}>4 - Confirm meeting date</Dropdown.Item>
|
<Dropdown.Item eventKey={'invite'}>
|
||||||
|
2 - Invite participants
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item eventKey={'availability'}>
|
||||||
|
3 - Add your availability
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item eventKey={'confirm'}>
|
||||||
|
4 - Confirm meeting date
|
||||||
|
</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={'settings'}>Settings</Dropdown.Item>
|
<Dropdown.Item eventKey={'settings'}>Settings</Dropdown.Item>
|
||||||
<Dropdown.Item eventKey={5}>Log Out</Dropdown.Item>
|
<Dropdown.Item eventKey={5} onSelect={() => handleLogout()}>
|
||||||
|
Log Out
|
||||||
|
</Dropdown.Item>
|
||||||
</Dropdown.Menu>
|
</Dropdown.Menu>
|
||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
|
19
src/components/Routes/PrivateRoute.js
Normal file
19
src/components/Routes/PrivateRoute.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Redirect, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useAuth } from '../../helpers/authContext';
|
||||||
|
|
||||||
|
const PrivateRoute = ({ component: Component, ...rest }) => {
|
||||||
|
const { authToken } = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route
|
||||||
|
{...rest}
|
||||||
|
render={(props) =>
|
||||||
|
authToken ? <Component {...props} /> : <Redirect to='/login' />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrivateRoute;
|
25
src/components/Routes/PublicRoute.js
Normal file
25
src/components/Routes/PublicRoute.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Redirect, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useAuth } from '../../helpers/authContext';
|
||||||
|
|
||||||
|
|
||||||
|
// TODO Make sure it's used, else delete it and remove message in App
|
||||||
|
const PublicRoute = ({ component: Component, ...rest }) => {
|
||||||
|
const isAuthenticated = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route
|
||||||
|
{...rest}
|
||||||
|
render={(props) =>
|
||||||
|
isAuthenticated ? (
|
||||||
|
<Redirect to='/dashboard' />
|
||||||
|
) : (
|
||||||
|
<Component {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PublicRoute;
|
@ -1,29 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Route, Redirect } from 'react-router-dom';
|
|
||||||
import { getToken } from '../../utils/common';
|
|
||||||
|
|
||||||
const isLoggedIn = getToken();
|
|
||||||
|
|
||||||
const PrivateRoute = ({ component: Component, user, ...rest }) => {
|
|
||||||
return (
|
|
||||||
<Route
|
|
||||||
{...rest}
|
|
||||||
render={(props) =>
|
|
||||||
isLoggedIn ? (
|
|
||||||
<Component {...rest} {...props} />
|
|
||||||
) : (
|
|
||||||
<Redirect
|
|
||||||
to={{
|
|
||||||
pathname: '/login',
|
|
||||||
state: {
|
|
||||||
from: props.location,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PrivateRoute;
|
|
@ -1,22 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Route, Redirect } from 'react-router-dom';
|
|
||||||
import { getToken } from '../../utils/common';
|
|
||||||
|
|
||||||
const isLoggedIn = getToken();
|
|
||||||
|
|
||||||
function PublicRoute({ component: Component, ...rest }) {
|
|
||||||
return (
|
|
||||||
<Route
|
|
||||||
{...rest}
|
|
||||||
render={(props) =>
|
|
||||||
!isLoggedIn ? (
|
|
||||||
<Component {...props} />
|
|
||||||
) : (
|
|
||||||
<Redirect to={{ pathname: '/dashboard' }} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PublicRoute;
|
|
7
src/helpers/authContext.js
Normal file
7
src/helpers/authContext.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
|
export const AuthContext = createContext();
|
||||||
|
|
||||||
|
export function useAuth() {
|
||||||
|
return useContext(AuthContext);
|
||||||
|
}
|
19
src/screens/Home.js
Normal file
19
src/screens/Home.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Panel } from 'rsuite';
|
||||||
|
|
||||||
|
import NavBar from '../components/Navbar/NavBar';
|
||||||
|
|
||||||
|
const boxStyle = {
|
||||||
|
margin: '50px 10px',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NavBar title='Meeting Planner' />
|
||||||
|
<Panel header={<h3>Home</h3>} bordered style={boxStyle}>
|
||||||
|
<p>This will be the home page</p>
|
||||||
|
</Panel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { Redirect } from 'react-router-dom';
|
||||||
import { backend } from '../utils/http-common';
|
|
||||||
import {
|
import {
|
||||||
Panel,
|
Panel,
|
||||||
Form,
|
Form,
|
||||||
@ -11,18 +10,19 @@ import {
|
|||||||
Message,
|
Message,
|
||||||
} from 'rsuite';
|
} from 'rsuite';
|
||||||
|
|
||||||
import { setUserSession } from '../utils/common';
|
|
||||||
import NavBar from './../components/Navbar/NavBar';
|
import NavBar from './../components/Navbar/NavBar';
|
||||||
|
import { backend } from '../helpers/http-common';
|
||||||
|
import { useAuth } from '../helpers/authContext';
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
const [credentials, setCredentials] = useState({
|
const [credentials, setCredentials] = useState({
|
||||||
email: '',
|
email: '',
|
||||||
password: '',
|
password: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { setAuthToken, authToken } = useAuth();
|
||||||
|
|
||||||
const handleChange = (value, evt) => {
|
const handleChange = (value, evt) => {
|
||||||
setCredentials({
|
setCredentials({
|
||||||
...credentials,
|
...credentials,
|
||||||
@ -34,16 +34,20 @@ export default function Login() {
|
|||||||
backend
|
backend
|
||||||
.post('/auth/login', credentials)
|
.post('/auth/login', credentials)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setUserSession(response.data.token, response.data.user);
|
setAuthToken(response.data.token);
|
||||||
history.push('/dashboard');
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.response.status === 401)
|
if (error.response.status === 401) {
|
||||||
setError('Incorrect credentials. Please try again.');
|
setError('The credentials provided were incorrect.');
|
||||||
else setError('Something went wrong. Please try again later.');
|
} else
|
||||||
|
setError('Something went wrong. Please try again later.');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (authToken) {
|
||||||
|
return <Redirect to='/dashboard' />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NavBar title='Login' />
|
<NavBar title='Login' />
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// Set/Remove user and token to local storage
|
|
||||||
export const setUserSession = (token, user) => {
|
|
||||||
localStorage.setItem('token', token);
|
|
||||||
localStorage.setItem('user', JSON.stringify(user));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getUser = () => {
|
|
||||||
const userJSON = localStorage.getItem('user');
|
|
||||||
|
|
||||||
if (userJSON) {
|
|
||||||
const user = JSON.parse(userJSON);
|
|
||||||
return user;
|
|
||||||
} else return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getToken = () => {
|
|
||||||
const token = localStorage.getItem('token');
|
|
||||||
|
|
||||||
if (token) return token;
|
|
||||||
else return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const removeUserSession = () => {
|
|
||||||
localStorage.removeItem('token');
|
|
||||||
localStorage.removeItem('user');
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user