3 min read
Meteor and Mantra - Routing redirect
Recently I started using [Mantra]() to develop my Meteor apps. As with any other framework You’ll find a lot of answers to common questions in a related forum or any other resource. However I couldn’t get a good answer on how to implement routing logic properly. The Mantra specs also don’t tell much about how to approach it. So here’s my solution.
First I want to tell you about a little drawback, which is essential to understand the whole issue with routing in Mantra. The Flowrouter redirect statement can only work in the componentDidMount
directive of an React component.
componentDidMount(){
FlowRouter.go('/login');
}
As I don’t want load a component and then doing a redirect I had to make the redirect on a higher level of the Mantra architecture.
So where else could it be than in the route file? To give you a better understanding I’ll use the post module which is part of a blogging app.
client/modules/post/routes.jsx
...
FlowRouter.route('/posts', {
name: 'post.list',
triggersEnter: [function(context, redirect) {
actions.posts.access_route('post.list', redirect);
}],
action() {
mount(AppLayout, {
content: () => (<MainPage />)
});
}
});
...
As you can see I’ll use a trigger action, despite the Mantra specs tell me not do so. For now it’s the only practical approach.
Import the action in the route and call the access_route
function.
client/modules/post/actions/posts.js
import {cannot_access, redirect_login, redirect_verify} from '/lib/access_control';
...
access_route(routename, redirect) {
if(redirect_login(routename)){
redirect('/login');
} else if(redirect_verify()){
redirect('/email-verification');
} else if(cannot_access(routename)){
redirect('/');
}
}
...
This is done for every module. Then you get a custom routing logic for every module while still using the same function to verify f.g. a user can access a specific route.
/lib/access_control.js
// client side
export function redirect_login(routename){
var roles = _.findWhere(Meteor.settings.public.routes, {name: routename}).roles;
if(!_.contains(roles, "Public") && !Meteor.userId()){
console.log("redirect login");
return true;
}
return false;
};
// client side
export function redirect_verify(){
if(Meteor.userId() && !Meteor.user().emails[0].verified){
console.log("redirect verify");
return true;
}
return false;
};
// client side
export function cannot_access(routename){
var roles = _.findWhere(Meteor.settings.public.routes, {name: routename}).roles;
if(_.contains(roles, "Public") || Roles.userIsInRole(Meteor.user(), roles)){
console.log("allow route " + routename);
return false;
}
console.log("deny route " + routename);
return true;
};
Here I’ll bundle everything that is related in someway with permissions and access rights. The functions in this library are either used by the client or the server. I will use alanning roles to check role membership later on.
When assigning and checking for permissions with user, groups and rules I always use this schema:
Object <-> Access Group <-> Role <-> User
This schema is not a new invention, it’s a copy of Microsoft’s AGDLP idea.
Finally update the settings.json with access rules. Make sure to add it to the public part, otherwise the client can’t load the settings.
settings.json
...
{
"name": "post.list",
"roles": [
"Admin",
"Author",
"Manager"
]
},
...
Yay! you did it. So do you like my idea? Would like to hear from you in the comment section.
Categories: JavaScript developmentTags: architecture , mantra , meteor , redirect , routing
Edit this page
Show statistic for this page