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 { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||
|
||||
import PrivateRoute from './components/routes/PrivateRoute';
|
||||
import PublicRoute from './components/routes/PublicRoute';
|
||||
import { AuthContext } from './helpers/authContext';
|
||||
|
||||
import PrivateRoute from './components/Routes/PrivateRoute';
|
||||
|
||||
import Home from './screens/Home';
|
||||
import Dashboard from './screens/Dashboard';
|
||||
import Schedule from './screens/Schedule/Schedule';
|
||||
import Availability from './screens/Availability/Availability';
|
||||
@ -12,21 +14,35 @@ import Invite from './screens/Invite/Invite';
|
||||
import Login from './screens/Login';
|
||||
import Register from './screens/Register';
|
||||
|
||||
const existingToken = localStorage.getItem('token');
|
||||
// const existingUser = JSON.parse(localStorage.getItem('user'));
|
||||
|
||||
export default function App() {
|
||||
const [authToken, setAuthToken] = useState(existingToken);
|
||||
|
||||
const setToken = (data) => {
|
||||
localStorage.setItem('token', JSON.stringify(data));
|
||||
setAuthToken(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ authToken, setAuthToken: setToken }}>
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path='/' exact component={Login} />
|
||||
|
||||
<PublicRoute path='/login' component={Login} />
|
||||
<PublicRoute path='/register' component={Register} />
|
||||
<Route path='/' exact component={Home} />
|
||||
<Route path='/login' component={Login} />
|
||||
<Route path='/register' component={Register} />
|
||||
|
||||
<PrivateRoute path='/dashboard' component={Dashboard} />
|
||||
<PrivateRoute path='/schedule' component={Schedule} />
|
||||
<PrivateRoute path='/invite' component={Invite} />
|
||||
<PrivateRoute path='/availability' component={Availability} />
|
||||
<PrivateRoute
|
||||
path='/availability'
|
||||
component={Availability}
|
||||
/>
|
||||
<PrivateRoute path='/schedule' component={Schedule} />
|
||||
</Switch>
|
||||
</Router>
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { Nav, Icon, Dropdown, Popover, Whisper } from 'rsuite';
|
||||
|
||||
export default function MenuDropdown() {
|
||||
@ -12,18 +11,34 @@ export default function MenuDropdown() {
|
||||
triggerRef.current.hide();
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
history.push('/');
|
||||
}
|
||||
|
||||
const MenuPopover = ({ onSelect, ...rest }) => (
|
||||
<Popover {...rest} full>
|
||||
<Dropdown.Menu onSelect={onSelect}>
|
||||
<Dropdown.Item eventKey={'/'}>Dashboard</Dropdown.Item>
|
||||
<Dropdown.Item eventKey={'register'}>Register</Dropdown.Item>
|
||||
<Dropdown.Item eventKey={'login'}>Login</Dropdown.Item>
|
||||
<Dropdown.Item eventKey={'schedule'}>1 - Schedule a meeting</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={'schedule'}>
|
||||
1 - Schedule a meeting
|
||||
</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={5}>Log Out</Dropdown.Item>
|
||||
<Dropdown.Item eventKey={5} onSelect={() => handleLogout()}>
|
||||
Log Out
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</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 { useHistory } from 'react-router-dom';
|
||||
import { backend } from '../utils/http-common';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import {
|
||||
Panel,
|
||||
Form,
|
||||
@ -11,18 +10,19 @@ import {
|
||||
Message,
|
||||
} from 'rsuite';
|
||||
|
||||
import { setUserSession } from '../utils/common';
|
||||
import NavBar from './../components/Navbar/NavBar';
|
||||
import { backend } from '../helpers/http-common';
|
||||
import { useAuth } from '../helpers/authContext';
|
||||
|
||||
export default function Login() {
|
||||
const history = useHistory();
|
||||
|
||||
const [error, setError] = useState(false);
|
||||
const [credentials, setCredentials] = useState({
|
||||
email: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
const { setAuthToken, authToken } = useAuth();
|
||||
|
||||
const handleChange = (value, evt) => {
|
||||
setCredentials({
|
||||
...credentials,
|
||||
@ -34,16 +34,20 @@ export default function Login() {
|
||||
backend
|
||||
.post('/auth/login', credentials)
|
||||
.then((response) => {
|
||||
setUserSession(response.data.token, response.data.user);
|
||||
history.push('/dashboard');
|
||||
setAuthToken(response.data.token);
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status === 401)
|
||||
setError('Incorrect credentials. Please try again.');
|
||||
else setError('Something went wrong. Please try again later.');
|
||||
if (error.response.status === 401) {
|
||||
setError('The credentials provided were incorrect.');
|
||||
} else
|
||||
setError('Something went wrong. Please try again later.');
|
||||
});
|
||||
};
|
||||
|
||||
if (authToken) {
|
||||
return <Redirect to='/dashboard' />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<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