How to implement Role based restrictions/permissions in react redux app?

老子叫甜甜 提交于 2020-02-21 03:12:11

问题


I have a React-Redux-KoaJs application with multiple components. I have few user roles as well. Now i want to display few buttons, tables and div to only specific roles and hide those from others. Please remember i dont want to hide the whole component, but just a part of the components. Can anyone help me? Thanks in advance.


回答1:


Be careful with that. If the actions of some roles are important you should always validate them at your backend. It's easy to change the values stored in redux at frontend allowing malicious use of the roles if there is no proper validation.

If you want to proceed on a possible approach is this:

  • Save the roles at your reducer
  • Bind the reducer to the component:
function mapStateToProps(state) {
  const { user_roles } = state;
  return { user_roles };
}

export default connect(mapStateToProps)(YourComponent);
  • Then at your component, you can check the user_roles and render the actions accordingly:
render() {
    return (
      <div>
        {this.props.user_roles.role === "YOUR_ROLE_TO_CHECK" && <ActionsComponent />}
      </div>
    );
  }

This will render the ActionsComponent only when the role is equal to the desired one.

Again, always validate the roles at your backend!




回答2:


You can check the role or permission in every component as @Eudald Arranz proposed. Or you can write a component that will checks permissions for you. For example:

import PropTypes from 'prop-types';
import { connect } from 'react-redux';

const ShowForPermissionComponent = (props) => {
    const couldShow = props.userPermissions.includes(props.permission);
    return couldShow ? props.children : null;
};

ShowForPermissionComponent.propTypes = {
    permission: PropTypes.string.isRequired,
    userPermissions: PropTypes.array.isRequired
};


const mapStateToProps = state => ({
    userPermissions: state.user.permission //<--- here you will get permissions for your user from Redux store
});

export const ShowForPermission = connect(mapStateToProps)(ShowForPermissionComponent);

and then you can use this component like this:

import React from 'react';
import { ShowForPermission } from './ShowForPermission';

cons MyComponent = props => {
   return (
        <div>
            <ShowForPermission permission="DELETE">
                <button>Delete</button>
            </ShowForPermission>
        </div>
   );
}




回答3:


So, I have figured out there is an alternate and easy approach to implement role based access (RBAC) on frontend.

In your redux store state, create a object called permissions (or you can name it whatever you like) like this:

const InitialState = {
  permissions: {}
};

Then on your login action, setup the permissions that you want to provide like this:

InitialState['permissions'] ={
  canViewProfile: (role!=='visitor'),
  canDeleteUser: (role === 'coordinator' || role === 'admin')
  // Add more permissions as you like
}

In the first permission you are saying that you can view profile if you are not a visitor. In the second permission you are saying that you can delete a user only if you are an admin or a coordinator. and these variables will hold either true or false on the basis of the role of the logged in user. So in your store state u will have a permission object with keys that represent permissions and their value will be decided on the basis of what your role is.

Then in your component use the store state to get the permission object. You can do this using connect like:

const mapStateToProps = (state) => {
  permissions : state.permissions
}

and then connect these props to your Component like:

export default connect(mapStateToProps,null)(ComponentName);

Then you can use these props inside your component on any particular element which you want to show conditionally like this:

{(this.props.permissions.canDeleteUser) && <button onClick={this.deleteUser}>Delete User</button>}

The above code will make sure that the delete user button is rendered only if you have permissions to delete user i.e. in your store state permissions object, the value of canDeleteUser is true.

That's it, you have appplied a role based access. You can use this approach as it is easily scalable and mutable, since you will have all permsisions according to roles at one place.

Hope, this helps! If i missed out something please help me in the comments. :-)




回答4:


The best practice to solve this Problem is, simply prevent the app to generate unnecessary routes, rather checking current user role on each route it is great to generate only the routes that user have access.

So The Normal reouting is: To control the whole view:

const App = () => (
  <BrowserRouter history={history}>
    <Switch>
      <Route path="/Account" component={PrivateAccount} />
      <Route path="/Home" component={Home} />
    </Switch>
  </BrowserRouter>
  export default App;
);

Routing based on user role:

import { connect } from 'react-redux'
   // other imports ...
   const App = () => (
      <BrowserRouter history={history}>
        <Switch>
        {
          this.props.currentUser.role === 'admin' ?
            <>
          <Route path="/Account" exact component={PrivateAccount} />
          <Route path="/Home" exact component={Home} />
            </> 
            : 
          <Route path="/Home" exact component={Home} />
        }
        <Route component={fourOFourErroPage} />

        </Switch>
      </BrowserRouter>
      
const mapStateToProps = (state) => {
  return {
    currentUser: state.currentUser,
  }
}
export default connect(mapStateToProps)(App);

So the user with an Admin role will have access to the Account page and for other users will have access to the Home page Only! and if any user try to access to another route, the 404 page error will appear. I hope I've given a helpful solution.

For advanced details about this approach you can check this repo on github: Role-based-access-control with react

To hide just a presentational component:

{this.props.currentUser.role === 'admin' && <DeleteUser id={this.props.userId} /> }


来源:https://stackoverflow.com/questions/56004504/how-to-implement-role-based-restrictions-permissions-in-react-redux-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!