Reputation: 17397
I'm trying to cleanly implement a way to redirect the user to a login route if they're not logged in. I'm basing my solution off of another SO answer here that doesn't work out of the box. Here's my solution.
angular.module('myApp', ['ngResource', 'ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
var requireAuthentication = function () {
return {
load: function ($q) {
console.log('Can user access route?');
if (g_isloggedIn === true) { // fire $routeChangeSuccess
var deferred = $q.defer();
deferred.resolve();
console.log('Yes they can!');
return deferred.promise;
} else { // fire $routeChangeError
console.log('No they cant!');
return $q.reject("'/login'");
}
}
};
};
$routeProvider
.when('/some_page_that_requires_authentication', {
templateUrl: '/views/secret.html',
controller: 'secretCtrl',
resolve: requireAuthentication()
})
.when('/anybody_can_see_me', {
templateUrl: '/views/public.html',
controller: 'publicCtrl',
});
}]);
My question is, where can I listen on the $routeChangeError
event so that I can redirect the route? I tried doing it in a directive, but could never get the event to fire. I can't put it into a controller, because it won't load if the promise is rejected. Any thoughts?
Upvotes: 5
Views: 10246
Reputation: 5860
I'm sure you're well past this issue, but for those looking for answers now, here's my two cents.
The only thing you are missing here is what happens when the promise is rejected. You'll want to do this with HTTP interception. You put a listener on routeChangeError, and redirect there. https://docs.angularjs.org/api/ng/service/$http (scroll down to interceptors section)
Upvotes: 0
Reputation: 1923
Is there a reason why you shouldn't redirect the user from inside the function? This works fine for me, it doesn't load the controller / view if the promise is not resolved.
I modified the function like this:
var requireAuthentication = function () {
return {
load: function ($q, $location) {
console.log('Can user access route?');
var deferred = $q.defer();
deferred.resolve();
if (g_isloggedIn === true) { // fire $routeChangeSuccess
console.log('Yes they can!');
return deferred.promise;
} else { // fire $routeChangeError
console.log('No they cant!');
$location.path('/login');
// I don't think this is still necessary:
return $q.reject("'/login'");
}
}
};
};
Upvotes: 3
Reputation: 3412
You might find some help in this question: AngularJS: Understanding $rootScope.$on('$routeChangeSuccess
Generally I feel that using "resolve" for ensuring authentication is a bit odd, but there are not much better ways, I would suggest adding some services etc. Which is besides the point.
Finally, other routing solutions like https://github.com/dotJEM/angular-routing may provide you with a better degree of control.
Upvotes: 0