Skip to content
Permalink
Browse files

Web Folder - Protected routes, login and logout routines (#63)

Web Folder - Protected routes, login and logout routines
  • Loading branch information...
moul committed May 15, 2019
2 parents a1301b6 + 337f04f commit 3ce97219bded1da75c8cff98260c96992c477339
@@ -165,7 +165,13 @@
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
"@babel/plugin-proposal-class-properties",
[
"@babel/plugin-transform-runtime",
{
"regenerator": true
}
]
]
}
}
@@ -3,11 +3,12 @@ import Cookies from "js-cookie";
import {
PERFORM_LOGIN,
LOGIN_FAILED,
SET_USER_SESSION
SET_USER_SESSION,
PING_USER_SUCCESS,
PING_USER_FAILED
} from "../constants/actionTypes"
import { USER_SESSION_TOKEN_NAME } from "../constants/userSession";
import { history } from "../store/configureStore";
import { performLogin } from "../api/userSession"
import { performLogin, pingUser } from "../api/userSession"

export const performLoginAction = (email, password) => async dispatch => {
dispatch({
@@ -22,10 +23,26 @@ export const performLoginAction = (email, password) => async dispatch => {
payload: { activeUser: response.data }
});

// Cookies.set(USER_SESSION_TOKEN_NAME, response.data.token)

history.push("/dashboard");
Cookies.set(USER_SESSION_TOKEN_NAME, response.data.token)
} catch (error) {
dispatch({ type: LOGIN_FAILED, payload: { error } });
}
};

export const pingUserAction = () => async dispatch => {

try {
const response = await pingUser();
dispatch({
type: PING_USER_SUCCESS,
payload: {
isAuthenticated: response.data.isAuthenticated,
activeUser: response.data.user
}
});

Cookies.set(USER_SESSION_TOKEN_NAME, response.data.token)
} catch (error) {
dispatch({ type: PING_USER_FAILED, payload: { error } });
}
};
@@ -1,7 +1,9 @@
import axios from "axios";
import Cookies from "js-cookie";
import { USER_SESSION_TOKEN_NAME } from "../constants/userSession";

const withToken = function(config) {
const token = "jwtToken";
const token = Cookies.get(USER_SESSION_TOKEN_NAME);
if (token) {
config.headers.Authorization = token;
}
@@ -1,9 +1,40 @@
/* eslint-disable no-unused-vars */
// import { baseApi } from "./index";
import axios from "axios";
import Cookies from "js-cookie";
import { USER_SESSION_TOKEN_NAME } from "../constants/userSession";
import { history } from "../store/configureStore";

export function performLogin(email, password) {
return axios.get("https://gist.githubusercontent.com/moul/826ef89d52651570a396ef3210a72e40/raw/e95d0e0391abca995949ab1258d5569e0b5ec356/GET%2520user-session.json")
// Uncomment line to use base api with auth token
// return baseApi.post(`/user-session`, { email, password });
}

export function performLogout() {
Cookies.remove(USER_SESSION_TOKEN_NAME);
history.push("/login");
}

export function pingUser() {

const apiForExample = axios.create();
apiForExample.interceptors.response.use((response) => {
// eslint-disable-next-line no-console
let interceptedResponse = {
...response,
data: {
isAuthenticated: true,
user: response.data,
token: "token"
}
}

return interceptedResponse;
// eslint-disable-next-line no-console
}, (error) => { console.log(error) });

return apiForExample.get("https://gist.githubusercontent.com/moul/826ef89d52651570a396ef3210a72e40/raw/e95d0e0391abca995949ab1258d5569e0b5ec356/GET%2520user-session.json");
// Uncomment line to use base api with auth token
// return baseApi.get("/ping")
}
@@ -3,8 +3,10 @@ import { Route, Switch } from "react-router-dom";
import PropTypes from "prop-types";
import React from "react";
import { hot } from "react-hot-loader";
import ProtectedRoute from "./ProtectedRoute";
import DashboardPage from "./pages/DashboardPage";
import LoginPage from "./pages/LoginPage";
import LogoutPage from "./pages/LogoutPage";
import NotFoundPage from "./pages/NotFoundPage";
import CompetitionPage from "./pages/CompetitionPage";

@@ -13,10 +15,11 @@ class App extends React.Component {
return (
<div>
<Switch>
<Route exact path="/" component={LoginPage} />
<ProtectedRoute exact path="/" component={DashboardPage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/dashboard" component={DashboardPage} />
<Route exact path="/competition" component={CompetitionPage} />
<ProtectedRoute exact path="/dashboard" component={DashboardPage} />
<ProtectedRoute exact path="/competition" component={CompetitionPage} />
<Route path="/logout" component={LogoutPage} />
<Route component={NotFoundPage} />
</Switch>
</div>
@@ -0,0 +1,35 @@
import * as React from "react";
import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";

class ProtectedRoute extends React.PureComponent {


render() {
const { component: Component, userSession, ...rest } = this.props;

return(
<Route {...rest} render={props => (
userSession.isAuthenticated
? <Component {...props}/>
: <Redirect to={{
pathname: "/login",
state: { from: props.location }
}} />
)} />

)
}
}


const mapStateToProps = state => ({
userSession: state.userSession
});

const mapDispatchToProps = {};

export default connect(
mapStateToProps,
mapDispatchToProps
)(ProtectedRoute);
@@ -40,7 +40,7 @@ const accountDropdownProps = ({activeUser}) => {
{ icon: "settings", value: "Settings" },
{ isDivider: true },
{ icon: "help-circle", value: "Need help?" },
{ icon: "log-out", value: "Sign out" },
{ icon: "log-out", value: "Sign out", to: "/logout" },
],
}
};
@@ -32,7 +32,7 @@ const LevelCardPreview = (props) => {
<Card title={level.name} key={level.metadata.id}
isCollapsible
statusColor="orange"
body={<LevelBody key={level.metadata.id} author={level.author} description={level.description} locale={level.locale} />}
body={<LevelBody author={level.author} description={level.description} locale={level.locale} />}
/>)
}

@@ -1,15 +1,37 @@
import * as React from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import PropTypes from "prop-types";
import { Formik } from "formik";
import { LoginPage as TablerLoginPage } from "tabler-react";
import Cookies from "js-cookie";

import { performLoginAction } from "../../actions/userSession";
import { LoginPage as TablerLoginPage } from "tabler-react";
import { performLoginAction, pingUserAction } from "../../actions/userSession";
import { USER_SESSION_TOKEN_NAME } from "../../constants/userSession";

class LoginPage extends React.PureComponent {

state = {
redirectToReferrer: false
}

componentDidMount() {
const { pingUserAction } = this.props;
const token = Cookies.get(USER_SESSION_TOKEN_NAME);
if(token) {
pingUserAction();
}
}

render() {
const { performLoginAction } = this.props;
const self = this;
const { performLoginAction, userSession, location } = this.props;
const { redirectToReferrer } = this.state;
const { from } = location.state || { from: { pathname: '/' } }

if (redirectToReferrer === true || userSession.isAuthenticated) {
return ( <Redirect to={from} /> )
}

return (
<Formik
@@ -28,8 +50,10 @@ class LoginPage extends React.PureComponent {
}
return errors;
}}
onSubmit={(values) => {
performLoginAction(values.email, values.password);
onSubmit={ async (values) => {
await performLoginAction(values.email, values.password).then(() => {
self.setState({ redirectToReferrer: true })
});
}}
render={({
values,
@@ -54,13 +78,19 @@ class LoginPage extends React.PureComponent {
}

LoginPage.propTypes = {
performLoginAction: PropTypes.func
userSession: PropTypes.object,
location: PropTypes.object,
performLoginAction: PropTypes.func,
pingUserAction: PropTypes.func
};

const mapStateToProps = () => ({});
const mapStateToProps = state => ({
userSession: state.userSession
});

const mapDispatchToProps = {
performLoginAction: (email, password) => performLoginAction(email, password)
performLoginAction: (email, password) => performLoginAction(email, password),
pingUserAction: () => pingUserAction()
};

export default connect(
@@ -0,0 +1,15 @@
import * as React from "react";
import { performLogout } from "../../api/userSession";

class LogoutPage extends React.PureComponent {

logoutRoutine() {
performLogout();
}

render() {
return (<React.Fragment>{ this.logoutRoutine() }</React.Fragment>)
}
}

export default LogoutPage;
@@ -2,7 +2,9 @@
//Login / Session
export const PERFORM_LOGIN = "PERFORM_LOGIN";
export const LOGIN_FAILED = "LOGIN_FAILED";
export const SET_USER_SESSION = 'SET_USER_SESSION';
export const SET_USER_SESSION = "SET_USER_SESSION";
export const PING_USER_SUCCESS = "PING_USER_SUCCESS";
export const PING_USER_FAILED = "PING_USER_FAILED";

//Teams
export const GET_USER_TEAMS = "GET_USER_TEAMS";
@@ -1,7 +1,9 @@
import {
PERFORM_LOGIN,
LOGIN_FAILED,
SET_USER_SESSION
SET_USER_SESSION,
PING_USER_SUCCESS,
PING_USER_FAILED
} from '../constants/actionTypes';

const initialState = {
@@ -29,7 +31,7 @@ export default function userSessionReducer(state = initialState.session, action)
fetching: false,
activeUser: null,
isAuthenticated: false,
error: action.payload
error: action.payload.error
} ;

case SET_USER_SESSION:
@@ -40,6 +42,20 @@ export default function userSessionReducer(state = initialState.session, action)
isAuthenticated: true
};

case PING_USER_SUCCESS:
return {
...state,
isAuthenticated: action.payload.isAuthenticated,
activeUser: action.payload.activeUser
}

case PING_USER_FAILED:
return {
...state,
isAuthenticated: false,
error: action.payload.error
}

default:
return state;
}

0 comments on commit 3ce9721

Please sign in to comment.
You can’t perform that action at this time.