Apply role based restrictions to custom routes

Viewed 186

I followed the marmelab documentation for applying role base restrictions: https://marmelab.com/react-admin/doc/3.4/Authorization.html.

I have successfully applied to my resources section:"Restricting Access To Resources or Views" and to my menu section:"Restricting Access to a Menu". However, on thing that I think is missing on the documentation and that I haven't yet found a solution was how to apply this type of restrictions to the customRoutes.

function App() {
  return (
  <Admin
      theme={MyTheme}
      layout={MyLayout}
      history={history}
      customRoutes={[
       <PrivateRoute
        exact
        path="/system-status"
        component={props => <SystemStatusScreen {...props} />}
       />,
       <PrivateRoute
        exact
        path="/social-media"
        component={props => <SocialMediaScreen {...props} />}
      />,
      }
      catchAll={NotFound}
      authProvider={authProvider}
      loginPage={LoginPage}
      dataProvider={dataProvider}
  >
...

React-admin allows to define a usePermissions function to retrieve permissions but those permissions are not loaded outside the tag thus I cannot precalculate the routes to pass to the Admin component as they are undefined.

Can someone help me on this issue?

Thank you in advance.

1 Answers

Hello there Daniel.

I found a solution for what you'd like to accomplish.

You should create a custom component like PrivateRoute and in order to prevent undefined comming from usePrivileges hook provided by React-Admin, you should check wheter or not the component is mounted.

import { FC } from 'react';
import { Route, Redirect, RouteProps } from 'react-router';
import { useAuthorization, useIsMounted } from 'src/lib';
import { Spinner } from 'src/components';
import { PrivateRouteProps } from './PrivateRoute.props';

const PrivateRoute: FC<PrivateRouteProps & RouteProps> = ({ privileges, ...props }) => {
  const { permissions: role } = useAuthorization();
  const isMounted = useIsMounted();

  if (!isMounted()) return <Spinner screen />;

  return privileges.includes(role) ? <Route {...props} /> : <Redirect to="/" />;
};

export default PrivateRoute;

The custom hook useIsMounted can be found here.

Extended: I'm checking if the role that the current user has is included in an array provided, to the component, of avaiable privileges.

Usage:

<PrivateRoute
  exact
  path="/add-user"
  component={CreateUser}
  key={1}
  privileges={['super', 'admin']}
/>
Related