6

I have an application with multi user login functionality. Now, I created the redux store for the login function. If User logged in, based on their type, it will redirect to the particular dashboard. If student user logged in, he should be able to only access student dashboard, he should not able to access other dashboards. Same applies for others. But, now, if any user logged in, they can able to access other user dashboards. How can i prevent them to use only their dashboards.

Updated With Proper Code

/***AppRouter***/
    import React, {Component} from 'react';
    import { BrowserRouter, Route, Switch } from 'react-router-dom';
    import StuDashboard from '../views/ed/dashboard/Dashboard.js';
    import AdminDashboard from '../views/biz/dashboard/Dashboard.js';
    import OrgDashboard from '../views/org/dashboard/Dashboard.js';
    import SupAdDashboard from '../views/me/dashboard/Dashboard.js';
    import UserLogin from '../views/loginUser/Login.js';
    import history from '../history/history.js';
    import { PrivateRoute } from './PrivateRoute.js';
    import NotFoundPage from '../views/NotFoundPage.js';
    import Authorization from './Authorization';



    class AppRouter extends Component {
      render () {
        return(

          <BrowserRouter history={history}>
            <Switch>
              <Route path="/" component={Landing} exact />
              <Route path="/confirmation" component={EmailCon}/>
              <PrivateRoute path="/student/dashboard" component={Authorization(StuDashboard),["Student"]}/>
              <PrivateRoute path="/admin/dashboard" component={Authorization(AdminDashboard),["Admin"}/>
              <PrivateRoute path="/org/dashboard" component={Authorization(OrgDashboard),["Org"]}/>
              <PrivateRoute path="/SuperAdmin/dashboard" component={Authorization(SupAdDashboard),["SuperAdmin"]}/>
              <Route path="/login" component={UserLogin}/>  
              <Route path="" component={NotFoundPage} />
            </Switch>
          </BrowserRouter>

        );
      }
    }

    export default AppRouter;

/***PrivateRoute***/
import React from 'react';
import { Route, Redirect } from 'react-router-dom';

export const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        localStorage.getItem('token')
            ? <Component {...props} />
            : <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
    )} />
)

/***Authorization***/
    import React, { Component } from 'react';
import { connect } from "react-redux";

const Authorization = (WrappedComponent, allowedRoles) =>{
   class WithAuthorization extends Component {
       render() {

     const userType = this.props.user
      if (allowedRoles.includes(userType)) {
        return <WrappedComponent {...this.props} />
      } else {
        return <h1>You are not allowed to view this page!</h1>
      }
    }
  }
const mapStateToProps = state => ({ user: state.login.userName, userType: state.login.userType })
return connect(mapStateToProps)(WithAuthorization);
}
export  default  Authorization;

/***Action.js***/
import axios from "axios";
import { LOGIN_PENDING, LOGIN_COMPLETED, LOGIN_ERROR, LOGOUT } from "./types";
import ApiUrl from "../../constants/ApiUrl.js";
import qs from "qs";
import history from '../../history/history.js';


const startLogin = () => {
  return {
    type: LOGIN_PENDING
  };
};

const loginComplete = data => ({
  type: LOGIN_COMPLETED,
  data
});

const loginError = err => ({
  type: LOGIN_ERROR,  
  err
});

export const loginUser = (email, password) => {
  return dispatch => {
    dispatch(startLogin());

    let headers = {
      "Content-Type": "application/x-www-form-urlencoded"
    };

    const data = qs.stringify({
      grant_type: "password",
      username: email,
      password: password,
    });

    axios
      .post(`${ApiUrl}/Token`, data, {
        headers: headers
      })

      .then(function (resp) {

        dispatch(loginComplete(resp.data));


       localStorage.setItem("token", resp.data.access_token);
      switch (resp.data.userType) {
        case 'Admin': {
          history.push('/admin/dashboard');
          break;
        }
        case 'Student': {
          history.push('/student/dashboard');
          break;
        }
        case 'Organization': {
          history.push('/org/dashboard');
          break;
        }
        case 'SuperAdmin': {
          history.push('/SuperAdmin/dashboard');
          break;
        }
        default:
         history.push('/');
      }
      window.location.reload();
      return;


})
      .catch(err => dispatch(loginError(err)));
  };
};

export const logOut = () => {
  localStorage.clear();
  return {
    type: LOGOUT,
  };
}
1
  • Maybe instead of having one Private Route....create two route definitions based on the user logging in? For example create a PrivateStudent Route and a route for others... Commented May 24, 2019 at 13:46

1 Answer 1

3

I added an Authorization HOC to cater for access control. So you just pass the component, and the allowed role to the Authorization HOC.First i assume your user has a property userType. check out this URL.

  /***Authorization***/
import React, { Component } from "react";
import { connect } from "react-redux";

const Authorization = (WrappedComponent, allowedRoles) => {
  class WithAuthorization extends Component {
    render() {
      const userType  = this.props.userType;
      if (allowedRoles.includes(userType)) {
        return <WrappedComponent {...this.props} />;
      } else {
        return <h1>You are not allowed to view this page!</h1>;
      }
    }
  }
  const mapStateToProps = state => ({ user: state.login.userName, userType: state.login.userType })
  return connect(mapStateToProps)(WithAuthorization);
};
export default Authorization;

your router will then look this way

      <BrowserRouter history={history}>
        <Switch>
          <Route path="/" component={Landing} exact />
          <Route path="/confirmation" component={EmailCon}/>
          <PrivateRoute path="/student/dashboard" component={Authorization(StuDashboard,["Student"])}/>
          <PrivateRoute path="/admin/dashboard" component={Authorization(AdminDashboard,["Admin"])}/>
          <PrivateRoute path="/org/dashboard" component={ Authorization(OrgDashboard,["Organization"])}/>
          <PrivateRoute path="/SuperAdmin/dashboard" component={Authorization(SupAdDashboard,["SuperAdmin"])}/>
          <Route path="/login" component={UserLogin}/>  
          <Route path="" component={NotFoundPage} />
        </Switch>
      </BrowserRouter>
Sign up to request clarification or add additional context in comments.

8 Comments

Hi, I have updated the code, as per your suggestions. Still getting error "TypeError: Cannot set property 'props' of undefined". I have also updated my code above. Please check @Obed
I have fixed the bug, Let me know if you would prefer a functional component instead, I can provide an answer for it too.
I have updated the code and checked on that. If you check my updated code above. I am getting userName and userType from the Store and passed in the component. After, I login with any user type. It will show the "you are not allowed to view this condition" condition. I don't get, where i am making mistake. Yeah, please share the functional component method, it will be useful to grow my knowledge in react. Thanks for your patience @Obed
You are getting the username into the user which i guess is just a string, so there is no user.userType on user(userName). I have updated the code to correct that
I updated the code. But, it still showing the same. @Obed
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.