Reputation: 4161
I'm trying to create basic validation whether user can access some route or not. I had progress in that, but there's one thing that I can't figure out.
I'm using $locationChangeStart to monitor route changes. Scenario is: 1. if user is logged in, then allow him to access all routes, except auth routes (login, register). I'm checking this by calling method isAuthenticated() from my AuthFactory 2. If user is not logged in, then he access only login and register routes. Any other route should be prevented, and user should be redirected to login in that case.
$rootScope.$on('$locationChangeStart', function(event, newUrl, oldUrl){
if(AuthFactory.isAuthenticated()){
if(AuthFactory.isAuthRoute(newUrl)){
event.preventDefault();
$location.path('/');
}
} else {
if(!AuthFactory.isAuthRoute(newUrl)){
event.preventDefault();
$location.path('/login');
}
}
});
Thing that troubles me, is the one with preventDefault(). If app reaches code with preventDefault(), location.path()
that comes after that, simply doesn't work.
However, if I remove event.preventDefault()
, location.path()
works. Problem with this, is that I need that prevent, in case non-logged tries to access some non-auth page.
Basically, I want to be able to prevent or redirect based on requested route. What is the proper way to do that?
Upvotes: 6
Views: 33405
Reputation: 1056
Ok, you need to do this:
var authPreventer = $rootScope.$on('$locationChangeStart', function(event, newUrl, oldUrl){
if(AuthFactory.isAuthenticated()){
if(AuthFactory.isAuthRoute(newUrl)){
event.preventDefault();
authPreventer(); //Stop listening for location changes
$location.path('/');
}
}
else {
if(!AuthFactory.isAuthRoute(newUrl)){
event.preventDefault();
authPreventer(); //Stop listening for location changes
$location.path('/login');
}
}
});
Upvotes: 4
Reputation: 1740
I recently had the same problem and I was finally able to solve it by listening to $routeChangeStart
instead of $locationChangeStart
(without needing to call $route.reload()
).
The documentation for both events is kinda vague... I suppose the $ruteChangeStart
event is called before the $locationChangeStart
(I'm going to read the source code to fully understand what's happening here).
Upvotes: 0
Reputation: 4161
Ok, I managed to do this using $routeChangeStart. The catch is in using $route.reload(). So above code, should look something like this:
$rootScope.$on('$routeChangeStart', function(event, next, current){
if(AuthFactory.isAuthenticated()){
if(AuthFactory.isAuthRoute(next.originalPath)){
$route.reload();
$location.path('/');
}
} else {
if(!AuthFactory.isAuthRoute(next.originalPath)){
$route.reload();
$location.path('/login');
}
}
});
I put this in my .run method, so all the request are handled here, and I don't need to think about every new route that I (or someone else adds). That's why this looks more clean to me.
If someone has different approach, please share.
Note: just in case, I do my check on backend part also :)
Upvotes: -2