React-router: Setting up a route policies

Created on 29 Jun 2015  Â·  9Comments  Â·  Source: ReactTraining/react-router

Hi guys,
I think that could be great if React-Router give the possibility to set up the policies for each route.

As policy, I mean that there be a function (or maybe an object or a Singleton) that has the responsibility to let user enter on a route by checking a certain condition.

I.e.: logged user must be an Administrator; this could be a policy to enter into the administrative Area. Normal or Guest users can't. The policy could be AdminLoggedUserPolicy.

A policy could be used in more than one route.

If there are several approvals, I'll submit a pull request.

Thank you all

Most helpful comment

Actually you could easily implement a policy with that method above using something like:

function Policy(name, policyFunc) {
    return React.createClass({
       displayName: name,
        statics: {
            willTransitionTo() {
                policyFunc.call(this, arguments);
            }
        },
        render() { return <RouteHandler/> }
    });
}
<Route handler={RootView}>
    <Route handler={Policy('AdminsOnly', function(transition, params, query) {
            if(!isAdmin()) {
                transition.redirect('unauthorized', params, query);
            }
        }>
        <Route name='admin' handler={AdminView} path='/admin' />
    </Route>
</Route>

maybe? I wrote that fast and dirty, I'm not sure if that would actually work, but I think the idea there would work. Anyways, maybe someone else will have some ideas on this.

All 9 comments

You can handle this logic using willTransitionTo static method on your Route Handler component.

something like this:

var isAdmin = function() { return whether user is admin or not }

var AdminView = React.createClass({
    statics: {
        willTransitionTo(transition, params, query) {
            if(!isAdmin()) {
                transition.redirect('user-view', params, query);
            }
        }
    },
    render() {
        ...
    }
});

Thanks @BradHarris .
But, with that method I have to delegate the responsibility to check permissions at Components.

Doing so, I can't use that component when I need using it with different or without permissions.

The policies must be separated, this is normal separation of concern, as saw in Law of Demeter!
Don't you think?

That is a fair point, however if you are routing to generic components that you need to use elsewhere without the same permissions you could easily just have a permissions routing wrapper. That would adequately satisfy separation of concern in my mind.

<Route handler={RootView}>
    <Route handler={AdminsOnlyPolicy}>
        <Route name='admin' handler={AdminView} path='/admin' />
    </Route>
</Route>
var AdminsOnlyPolicy = React.createClass({
    statics: {
        willTransitionTo(transition, params, query) {
            if(!isAdmin()) {
                transition.redirect('unauthorized', params, query);
            }
        }
    },
    render() { return <RouteHandler/> }
});

This does create extra boilerplate though, but not much more than you would create with policies.

Actually you could easily implement a policy with that method above using something like:

function Policy(name, policyFunc) {
    return React.createClass({
       displayName: name,
        statics: {
            willTransitionTo() {
                policyFunc.call(this, arguments);
            }
        },
        render() { return <RouteHandler/> }
    });
}
<Route handler={RootView}>
    <Route handler={Policy('AdminsOnly', function(transition, params, query) {
            if(!isAdmin()) {
                transition.redirect('unauthorized', params, query);
            }
        }>
        <Route name='admin' handler={AdminView} path='/admin' />
    </Route>
</Route>

maybe? I wrote that fast and dirty, I'm not sure if that would actually work, but I think the idea there would work. Anyways, maybe someone else will have some ideas on this.

Both of them could be great solutions!
What do you think if this would be simplified by the Router itself?

Il martedì 30 giugno 2015, Brad Harris [email protected] ha
scritto:

Actually you could easily implement a policy with that method above using
something like:

function Policy(name, policyFunc) {
return React.createClass({
displayName: name,
statics: {
willTransitionTo() {
policyFunc.call(this, arguments);
}
},
render() { return }
});
}

if(!isAdmin()) {
transition.redirect('unauthorized', params, query);
}
}>


maybe? I wrote that fast and dirty, I'm not sure if that would actually
work, but I think the idea there would work. Anyways, maybe someone else
will have some ideas on this.

—
Reply to this email directly or view it on GitHub
https://github.com/rackt/react-router/issues/1443#issuecomment-117251367
.

Luca Colonnello
340 8707406
luca.[email protected]

I don't think it is necessary for the Router to simplify it, the Router doesn't need to know about this functionality at all, in fact I have just used this exact solution to implement route transitions. This is effectively just route middleware.

function Transition(name, isActive) {
    return React.createClass({
        displayName: name,
        mixins: [State],
        render() {
            return (
                <TimeoutTransitionGroup
                    transitionName='form-transition'
                    className='panel flex-no-shrink'
                    enterTimeout={300}
                    leaveTimeout={300}
                >
                    <RouteHandler key={isActive.call(this) ? 'active' : null} />
                </TimeoutTransitionGroup>
            );
        }
    });
}

somewhere deep in my routing table:

    <Route handler={SimpleView}>
        <Route handler={Transition('listTransition', function() { return this.isActive('list') } )}>
            <Route name='list' handler={ListView} path=':list?'>
                <Route handler={Transition('formTransition', function() { return this.isActive('form') } )}>
                    <Route name='form' handler={FormView} path=':id?' />
                </Route>
            </Route>
        </Route>
    </Route>

And this actually works, my list and my form animate in using react css transition group (well actually khan academy transition group)

Oh, thank you for your suggests.
Ok, I think you're right.

Thank you for posting your solutions!
Il giorno mar 30 giu 2015 alle 20:12 Brad Harris [email protected]
ha scritto:

And this actually works, my list and my form animate in using react css
transition group (well actually khan academy transition group)

—
Reply to this email directly or view it on GitHub
https://github.com/rackt/react-router/issues/1443#issuecomment-117288232
.

thanks for the great explanation on that issue @BradHarris

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nicolashery picture nicolashery  Â·  3Comments

wzup picture wzup  Â·  3Comments

misterwilliam picture misterwilliam  Â·  3Comments

alexyaseen picture alexyaseen  Â·  3Comments

ackvf picture ackvf  Â·  3Comments