[NMM #1] React-router role authorization

Datetime:2016-08-22 23:24:15          Topic:          Share

With today’s article I will start a new series of blog posts. The series will be called “ NPM Module of the Month ” (NMM in short) and I will try to show you many interesting and useful (in my personal opinion) NPM modules in it. Today, as it is the first article in the series, I will show you an NPM module that I created myself �� Some of you may remember one of my previous posts where I described two components which can help you to deal with role authorization in React . After I wrote the post, I decided to put my solution into GitHub and then publish it to NPM (in myprevious article I showed you how to do it).

And now that it’s ready to use, I will present it to you!

What is the module for?

The reasons why I created these components are described in the mentioned article. That’s why here, I will only write that the module contains two React components which are helpful in role-based authorization.

The AuthorizedComponent is useful for limiting the access to some routes for specific roles, e.g. if we have a route /test we may want to allow access to this route only to users with the test role.

The RoleAwareComponent can help you in showing parts of the UI depending on user role. For example we could have the / route and several React components on it. We may want to show the Welcome component for users with the user role and the Admin component for users with the admin role.

Installation

Now that we know the purpose of the component, let’s move to the NPM package which contains the mentioned functionality. The package is named react-router-role-authorization . It is available on GitHub:

https://github.com/burczu/react-router-role-authorization

as well as on NPM:

https://www.npmjs.com/package/react-router-role-authorization

The installation of the module in your project is simple, as for every NPM module:

npm install --save-dev react-router-role-authorization

Usage

As I mentioned before, the package contains two React components: AuthorizedComponent and RoleAwareComponent . The usage of the module differs depending on the component you want to use. Let’s see how we can use each of them.

AuthorizedComponent

By using this component you can handle access to the route only for specific roles. Before you use the component, you have to configure the routes (using the react-router module):

ReactDOM.render((
  <Router history={browserHistory}>
    <Route component={AppContainer} path="/">
      <IndexRoute authorize={['user', 'admin']} component={HomeComponent} />
      <Route authorize={['admin']} component={RestrictedContainer}>
        <Route component={RestrictedPageComponent} path="/restricted" />
      </Route>
    </Route>
    <Route component={NotFoundComponent} path="/not-found" />
  </Router>
), document.getElementById('app'));

In the example above every main route is extended by the authorize component. It has an array of user roles assigned. These roles are the ones which allow the access to the route.

The second thing to do is to use the AuthorizedComponent . As you can see in the above code, the RestrictedContainer component is restricted only to users with the admin role. Let’s see, how this container looks:

import React from 'react';
import RouteHandler from './RouteHandler';
import { AuthorizedComponent } from 'react-router-role-authorization';
import Cookies from 'js-cookie';

class RestrictedContainer extends AuthorizedComponent {
  constructor(props) {
    super(props);

    this.userRoles = Cookies.get('user').roles;
    this.notAuthorizedPath = '/not-found';
  }

  render() {
    return (
      <div>
        <RouteHandler {...this.props} />
      </div>
    );
  }
}

export default RestrictedContainer;

The most important thing here is the inheritance from the AuthorizedComponent component. Then, in the constructor, you can get all the user roles (stored in the cookie in the example) and assign them the this.userRoles property. These roles will be compared (internally, by the AuthorizedComponent ) with the ones assigned to the authorized attribute of the route. Additionally, it is good to set up where to redirect when the route is not available for the user (look at the this.notAuthorizedPath'). And that's it - from now on, all child routes of the RestrictedComponent component will be available only for the admin` user role.

RoleAwareComponent

The second of the components available in the NPM module is the RoleAwareComponent component. It allows you to hide a component depending on the given user roles.

Please see below a sample implementation of such component:

import React from 'react';
import { RoleAwareComponent } from 'react-router-role-authorization';
import Cookies from 'js-cookie';

class BoxOne extends RoleAwareComponent {
  constructor(props) {
    super(props);

    this.allowedRoles = ['user'];
    this.userRoles = Cookies.get('user').roles;
  }

  render() {
    const jsx = (
      <div>
        Box One
      </div>
    );

    return this.rolesMatched() ? jsx : null;
  }
}

export default BoxOne;

In this case, we also use inheritance. The BoxOne component is extended by the RoleAwareComponent . And again, the most important things are done inside the constructor. First of all we have to set up which roles make the component visible by assigning a suitable array to the this.allowedRoles property. We also need to know what roles the user has – this is done by getting the data from the cookie and assigning it to the this.userRoles property.

This was only the set up. Now, we have to decide which part of the component’s UI will be visible depending on the user role. To achieve this, the component provides two methods: this.roleMatched and this.rolesMatchedExact . The first one finds the intersection of allowedRoles and userRoles arrays and returns true when at least one role is present among the available roles. The second one checks if these two arrays are exactly the same.

If you look at the render function of the above example, you can see that the UI of the component is shown depending on the value returned by the this.rolesMatched method. If it returns true , the render function returns markup, otherwise it returns null .

Summary

Ok, this is all for today. I hope this component will be useful to somebody.

P.S.

I plan to post about interesting NPM modules once a month, so you should expect the next post of the “NPM Module of the Month” before the end of September… So stay tuned :wink: And I promise that next time I will show you a module which is not made by me!