Skip to content

stephenliu1944/easytool-react-permission

Repository files navigation

@easytool/react-permission

Easy to handle react component permissions.

Install

npm install -S @easytool/react-permission

Usage

import Permission from '@easytool/react-permission';
import React from 'react';
import { render } from 'react-dom';

render(
    <Permission hasPermission={[1, 2, 3, 4]}>
        <div permission="1">1</div>
        <div permission="1, 2">1, 2</div>
        <div permission={[1, 2, 3]}>1, 2, 3</div>
        <MyComponent permission={4}>4</MyComponent>
    </Permission>,
    document.getElementById('app')
);

Asynchronous setting permission

var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve([1, 2, 3]);
    }, 3000);
});

render(
    <Permission hasPermission={promise}>
        <div permission="1">1</div>
        <div permission="2">2</div>
        <div permission="3">3</div>
    </Permission>,
    document.getElementById('app')
);

onLoad

var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve([1, 2, 3]);
    }, 3000);
});

render(
    <Permission hasPermission={promise} onLoad={<div>Loading...</div>}>
        <div permission="1">1</div>
        <div permission="2">2</div>
        <div permission="3">3</div>
    </Permission>,
    document.getElementById('app')
);

onDeny

Change denied element.

render(
    <Permission hasPermission={[1]} onDeny={el => React.cloneElement(el, { style: { color: 'red' } })}>
        <div permission="1">1</div>
        <MyComponent permission="2">2</MyComponent>
    </Permission>,
    document.getElementById('app')
);

Replace denied element.

render(
    <Permission hasPermission={[1]} onDeny={<h3>Permission denied</h3>}>
        <div permission="1">1</div>
        <MyComponent permission="2">2</MyComponent>
    </Permission>,
    document.getElementById('app')
);

Handle deny to specific element.

render(
    <Permission hasPermission={[1]}>
        // DOM Elements can not use 'onxxx' custom attributes, so use 'deny' in place of it.
        <div permission="1" deny={<h3>Permission denied</h3>}>1</div>
        <MyComponent permission="2" onDeny={<h3>Not Allow</h3>}>2</MyComponent>
    </Permission>,
    document.getElementById('app')
);

Use Context Provider

Set global Permission.

import Permission, { PermissionContext } from '@easytool/react-permission';

render(
    <PermissionContext.Provider value={{ hasPermission: [1, 2, 3] }}>
        <Permission>
            <div permission="1">1</div>
            <div permission="2">2</div>
        </Permission>
        <Permission>
            <div permission="3">3</div>
            <MyComponent permission="4" />
        </Permission>
    </PermissionContext.Provider>,
    document.getElementById('app')
);

Asynchronous setting permission.

import Permission, { PermissionContext } from '@easytool/react-permission';

var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve([1, 2, 3]);
    }, 3000);
});

render(
    <PermissionContext.Provider value={{ hasPermission: promise, onDeny: <h3>Permission denied</h3> }}>
        <Permission>
            <div permission="1">1</div>
            <div permission="2">2</div>
        </Permission>
        <Permission>
            <div permission="3">3</div>
            <MyComponent permission="4" />
        </Permission>
    </PermissionContext.Provider>,
    document.getElementById('app')
);

Updating permission from a nested component.

class Home extends React.Component {
    static contextType = PermissionContext;

    componentDidMount() {
        setTimeout(() => {
            this.context.togglePermission([1, 2, 3]);
        }, 2000);
    }

    render() {
        return (
            <Permission>
                <h1 permission="1">Home</h1>
                <p permission="2">permission 2</p>
                <p permission="3">permission 3</p>
            </Permission>
        );
    }
}

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            hasPermission: [1, 2],
            togglePermission: (permissions) => {
                this.setState({
                    hasPermission: permissions
                });
            }
        };
    }

    render() {
        return (
            <PermissionContext.Provider value={this.state}>
                <Home />
            </PermissionContext.Provider>
        );
    }
}

render(
    <App />,
    document.getElementById('app')
);

Work with React Router

react-router@4-5

import Permission, { PermissionContext } from '@easytool/react-permission';

function Deny() {
    return <p>Permission denied</p>;
}

let res, rej;
const context = { 
    hasPermission: new Promise((resolve, reject) => {
        res = resolve;
        rej = reject;
    }),
    onDeny: (el, index) => React.cloneElement(el, { component: Deny })
};

class App extends Component {
    constructor(props) {
        super(props);
    }

    componentDidMount() {
        // request permission
        setTimeout(() => {
            res([1, 2]);
        }, 2000);
    }

    render() {
        return (
            {/* using global setting */}
            <PermissionContext.Provider value={context}>
                <Permission>
                    <HashRouter>
                        <Switch>
                            <Route path="/home" component={Home} permission="2" />
                            {/* this route will be denied  */}
                            <Route path="/list" component={List} permission="3" />                            
                            <Route path="/" component={App} permission="1" />
                        </Switch>
                    </HashRouter>
                </Permission>
            </PermissionContext.Provider>
        );
    }
}

render(
    <App />,
    document.getElementById('app')
);

react-router@3

function Deny() {
    return <p>Permission denied</p>;
}

render(
    <Permission hasPermission={[1, 2]} onDeny={(el, index) => React.cloneElement(el, { key: index, component: Deny })}>
        <Router history={hashHistory} >
            <Route path="/" permission="1">
                <Route path="/home" component={Home} permission="2" />
                <Route path="/detail" component={Detail} permission="3" />
            </Route>
        </Router>
    </Permission>,
    document.getElementById('app')
);

onLoad props is required when use Promise for react-router@3.

var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve([1, 2]);
    }, 3000);
});

render(
    <Permission hasPermission={promise} onLoad={<h1>Loading...</h1>}>
        <Router history={hashHistory} >
            <Route path="/" permission="1">
                <Route path="/home" component={Home} permission="2" />
                <Route path="/detail" component={Detail} permission="3" />
            </Route>
        </Router>
    </Permission>,
    document.getElementById('app')
);

Work with AntD Table

import { Table } from 'antd';
import Permission, { PermissionContext } from '@easytool/react-permission';

var dataSource = [{
    key: '1',
    permission: 1,
    name: 'Stephen'
}, {
    key: '2',
    permission: 2,
    name: 'Ricky'
}, {
    key: '3',
    permission: 3,
    name: 'Ray'
}];

render(
    <PermissionContext.Provider value={{ hasPermission: [1, 2] }}>
        <Table dataSource={dataSource}>
            <Column
                title="Name"
                dataIndex="name"
                key="name"
                render={(text, record, index) => {
                    return (
                        <Permission onDeny={<span>Permission denied</span>}>
                            <span permission={record.permission}>{text}</span>
                        </Permission>
                    );
                }}
            />
        </Table>
    </PermissionContext.Provider>,
    document.getElementById('app')
);

API

Permission

Param Type Description
hasPermission string|number|array|promise set user's permission.
comparePermission function custom compare function, receive(elementPermission, hasPermission). return true means authorized, false means denied.
onLoad react element when the hasPermission prop is promise type and state is pending then will use this element to render.
onDeny react element|function this method will be invoked when permission denied occur, function receive denied element and element index in parent children, return a replace element or nothing.
onError function when hasPermission is promise and throw error, it will be invoked.

PermissionContext.Provider

You can specify Context Provider that will be applied to every <Permission>.

value

Param Type Description
hasPermission string|number|array|promise as above.
comparePermission function as above.
onLoad react element as above.
onDeny react element|function as above.
onError function as above.

TODO

  1. 用户自己选择查找的子元素, 默认是children
  2. 对比方法用户自定义
  3. 返回时添加装饰器
  4. filterChildren 增加用户自定义判断

About

Use for react element permission.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages