IT:AD:Durandal.JS:HowTo:Navigation/Security
Summary
Dynamic Menu Bars already mentioned that just because the user can't see a link doesn't mean they can't cut/paste the url manually.
Somewhere early – in main, shell, or in the menu view model, you need to also provide a replacement router.guardRoute, which OTB/ always allows access.
//override the router's method:
router.guardRoute = function(routeInfo, params, instance){
//Notice that response is flipped compared to visibleValidRoutes:
if (!routeInfo.settings.authenticated){
return true;
}
//or user is in role
if (user.isAuthenticated()){
//If no roles defined, considered open to authorised users:
if ((!routeInfo.settings.roles)||(routeInfo.settings.roles.length==0)) {
return true;
}
//iterate through requested roles, looking for presence in user's defined roles.
var userRoles = user.roles();
for (var i=0;i<routeInfo.settings.roles.length;i++){
var x = routeInfo.settings.roles[i];
var r = $.inArray(x, userRoles);
if (r>-1){
alert ("Found!");
return true;
}
}
}
return false;
}
Catching those that get through
router.guardRoute works when the app generates the jump to the new view (eg, like after submitting a search, and invoking router.navigateTo("#/search/results")).
But if the user refreshes the page while on the #/search/results page, Durandal will happily refresh and rebuild the page without checking.
It's either a bug, or the guardRoute method is not being assigned early enough.
If it's a bug, you'll have to add the following to all protected views:
model.prototype.activate = function (view) {
//Hack: Because sammy.js can handle an entered route
//before Durandal's router can process it and guardRoute,
//have to check and redirect manually:
// alert (router.activeRoute().url);
var valid = !router.guardRoute(router.activeRoute());
if (valid){
router.navigateTo("#/");
}