https://github.com/thesoftwarehouse/react-router-permissions
react-router-permissions - abstraction layer for handling authorization with react-router
https://github.com/thesoftwarehouse/react-router-permissions
Last synced: about 1 year ago
JSON representation
react-router-permissions - abstraction layer for handling authorization with react-router
- Host: GitHub
- URL: https://github.com/thesoftwarehouse/react-router-permissions
- Owner: TheSoftwareHouse
- License: mit
- Created: 2019-04-09T13:57:09.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2022-12-09T23:26:07.000Z (over 3 years ago)
- Last Synced: 2025-04-15T07:19:38.023Z (about 1 year ago)
- Language: JavaScript
- Homepage:
- Size: 1.48 MB
- Stars: 18
- Watchers: 7
- Forks: 3
- Open Issues: 40
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Status
[](https://travis-ci.org/TheSoftwareHouse/react-router-permissions) [](https://codecov.io/gh/TheSoftwareHouse/react-router-permissions) [](https://github.com/TheSoftwareHouse/react-router-permissions/blob/master/LICENSE.md) [](https://www.npmjs.com/package/@tshio/react-router-permissions)
# react-router-permissions
## Installation
Using [yarn](https://yarnpkg.com/lang/en/):
$ yarn add @tshio/react-router-permissions
Using [npm](https://www.npmjs.com/):
$ npm install --save @tshio/react-router-permissions
## Usage
Goal of this package is to provide abstraction layer for handling authorization with react-router.
The only requirement for `AuthorizedRoute` to work is to have any kind `Router` and at least one `PermissionsProvider`
higher in your component tree.
A [codesandbox example](https://codesandbox.io/s/github/TheSoftwareHouse/react-router-permissions/tree/master/example/) is available.
[](https://codesandbox.io/s/github/TheSoftwareHouse/react-router-permissions/tree/master/example/?fontsize=14)
```js
import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom';
const store = createStore(state => ({ ...state }), {
authorization: {
roles: ['USER', 'ADMIN'],
},
});
const authorizationStrategy = (roles, requirement) => {
return roles.find(role => role === requirement);
};
// it's possible to override strategy for single route
const loginAuthorizationStrategy = (roles, requirement) => {
return roles && roles.length;
};
class App extends React.Component {
render() {
return (
{({ isAuthorized }) => (isAuthorized ? : )}
{({ isAuthorized }) => (isAuthorized ? : )}
);
}
}
```
`authorizationStrategy` is a function that gets called each time user either tries to access authorized content. It is called
with `permissions` passed to `PermissionsProvider` as first argument and `requirement` passed to `AuthorizedRoute` as second.
It's result is stored in isAuthorized property on ChildrenAsFunction Function used by `AuthorizedRoute`.
User is not bound to using role base authorization strategies. To showcase that we would need to make following changes to our example:
```js
const store = createStore(
state => ({...state}), {
authorization: {
permissions: {
"access-home": true,
"access-users-list": false,
},
}
});
const authorizationStrategy = (permissions, requirement) => {
return permissions[requirement];
};
...
...
```
There are some strategies provided with the package out of the box. Those are:
- Role based strategy
```js
const permissions = ['MODERATOR', 'PREMIUM_USER'];
...
// authorization will pass
...
...
// authorization will fail
...
```
* Permissions based strategy
```js
const permissions = {
canReadPosts: true,
canManagePosts: true,
canManageUsers: false,
};
...
// authorization will pass
...
...
// authorization will fail
...
```
* At least one strategy
```js
const permissions = {
canReadPosts: true,
canManagePosts: false,
canManageUsers: false,
canViewUsers: false,
};
...
// authorization will pass
...
...
// authorization will fail
...
```
We also provide authorized section to cover cases where we need authorization but want to be route agnostic
```js
class Home extends React.Component {
render() {
return (
{({ isAuthorized }) => (isAuthorized ? : null)}
);
}
}
```
This works exactly like AuthorizedRoute but will attempt access regardless of active route.
Since permissions are being fetched from context, it is possible to override them for certain section of our application
using nested `PermissionsProvider`. Result of `authorizationStrategy` does not need to be boolean too.
While most of the time it being a boolean might be convenient. It is possible for `authorizationStrategy`
to return complex object that we can utilize in our component.
```js
const store = createStore(
state => ({...state}), {
permissions: {
...,
"nested-permissions": {
"user-name": {
create: true,
read: true,
update: false,
delete: false,
}
},
...,
}
});
const authorizationStrategy = (permissions, requirement) => {
return permissions[requirement];
};
class Header extends React.Component {
render() {
return (
{({isAuthorized}) => (
isAuthorized.read ? (
Name
Matt Murdock
{isAuthorized.create && (
Add
)}
{isAuthorized.delete && (
Delete
)}
) : null
)}
);
}
}
```
We decided to use hooks in our library. Therefore, we are introducing 2 our hooks: `useAuthorize` which one is returning a value of authorization.
```js
export const AdminSection = ({ requires, authorizationStrategy }) => {
const isAuthorized = useAuthorize(requires, authorizationStrategy);
return isAuthorized ?
Admin New's
: null;
};
```
Second hook is `usePermission` which one is returning an object with `permissions` and `authorizationStrategy` from the nearest `PermissionsProvider`.
```js
export const PermissionsRoles = () => {
const { permissions } = usePermissions();
return Roles length: {permissions.length} ;
};
```
## Config options
### PermissionsProvider
| Property name | Type | Required | Description |
| --------------------- | --------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| permissions | `Array or Object` | `true` | Permissions granted to user throughout the application. Can take any shape or form |
| authorizationStrategy | `(permissions, requirement) => *` | `true` | Function that is aware of permissions format and is called for each authorization attempt with permissions and given requirement |
### AuthorizedRoute
| Property name | Type | Required | Description |
| --------------------- | --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| path | `string` | `true` | Path that when accessed in by browser, will trigger authorization attempt |
| requires | `*` | `false` | Requirement that will be used in access attempt call |
| authorizationStrategy | `(permissions, requirement) => *` | `false` | Function that if passed will override `authorizationStrategy` passed to nearest `PermissionsProvider` |
### AuthorizedSection
| Property name | Type | Required | Description |
| --------------------- | --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| requires | `*` | `true` | Requirement that will be used in access attempt call |
| authorizationStrategy | `(permissions, requirement) => *` | `false` | Function that if passed will override `authorizationStrategy` passed to nearest `PermissionsProvider` |
### Hooks
| Hook's name | Arguments | Description |
| -------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| usePermissions | `null` | Returns context of nearest Permissions Provider |
| useAuthorize | `(requirement, authorizationStrategy?) => *` | Returns a value of authorization. AuthorizationStrategy argument is optional. If passed, will override existing strategy. |
## Development
We welcome all contributions. Please read our [CONTRIBUTING.md](https://github.com/TheSoftwareHouse/react-router-permissions/blob/master/CONTRIBUTING.md) first.
You can submit any ideas as [GitHub issues](https://github.com/TheSoftwareHouse/react-router-permissions/issues).