angularjs ui-router generates infinite loop

2019-06-21 05:26发布

问题:

I am aware this question was discussed multiple times but the solutions didnt fit into my requirement. The quest is simple. If the user is not logged in the user should be redirected to login page. When i do it in $on, it generates infinite loop. Let me know what is the best solution.

    var adminpanel = angular.module('administrator', ['ngMessages','ui.router','ui.bootstrap','ngCookies']);
    adminpanel.config(function ($stateProvider, $urlRouterProvider) {
    //    $urlRouterProvider.otherwise("/login");
        $urlRouterProvider.otherwise( function($injector, $location) {
                var $state = $injector.get("$state");
                $state.go("login");
            });
                $stateProvider
                .state('login', {
                                url: "/login",
                                controller:"userCtrl",
                                templateUrl: "views/login.tpl.html",
                                permissions:{except:['admin']}
                                }
                      )
                  .state('menu', {
                                templateUrl: "views/menu.tpl.html",
                                controller:'adminCtrl',
                                permissions:{allow : ['admin']}
                                }
                      )
                  .state('menu.dashboard', {
                                url: "/dashboard",
                                templateUrl: "views/dashboard.tpl.html",
                                permissions:{allow : ['admin']}
                                }
                      )

});


adminpanel.run([ '$rootScope', '$state', '$stateParams','$cookieStore',function ($rootScope, $state, $stateParams,$cookieStore) {
 $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
        $rootScope.$on('$stateChangeStart',function(event, toState, fromState){

            if($rootScope.session == undefined && $cookieStore.get('name') == undefined){$rootScope.session={}}
            else if($rootScope.session == undefined && $cookieStore.get('name') != undefined){
                    $rootScope.session={set:true, name : $cookieStore.get('name'), userid :$cookieStore.get('userid'), role:$cookieStore.get('role')};
            };
        //Added below lines as update    
             if(toState.name === "login"){
              return;
            }
        //Added above lines as update
        var authorized = true;
         if(Object.keys($rootScope.session).length === 0){
              event.preventDefault();
            $state.go('login');
         }
        else if(Object.keys(toState.permissions).length !=0){
                    console.log($rootScope.session.role);
                    angular.forEach(toState.permissions, function(value,key){
                     angular.forEach(value,function(role){
                        if(key === 'except' && role === $rootScope.session.role)
                        {authorized = false;}
                        else if(key === 'allow' && role !== $rootScope.session.role)
                        {authorized = false;};
                    });
                });
}
if(!authorized){
                        event.preventDefault();
                        $state.go('menu.dashboard');
                };

        });

}]);

Thanks in advance for help.

Update 1 :

The solution works fine. But if the user is logged in, the user shall not access the login page if he tries to hit it through address bar. So i created a permission parameter with except key.

But if the user hits login page through address bar, the login page is generated, which should not and it should be redirected to menu.dashboard.

Hope i am clear.

回答1:

The point here, is to avoid redirection, if it already happened, if already redirected:

...
// never redirect to state, if already going there
if(toState.name === "login"){
  return;
}

// evaluate some IF here only if we go to other state then login
if(Object.keys($rootScope.session).length === 0) {
  event.preventDefault();
  $state.go('login');
  return;

}


回答2:

Changed the if loop and it worked as required. Below is the working code.

if(Object.keys($rootScope.session).length === 0){
             if(toState.name === "login"){
              return;
            }
             else{
              event.preventDefault();
            $state.go('login');
             }
         }
        else if(Object.keys(toState.permissions).length !=0){

                    angular.forEach(toState.permissions, function(value,key){
                     angular.forEach(value,function(role){
                        if(key === 'except' && role === $rootScope.session.role)
                        {authorized = false;}
                        else if(key === 'allow' && role !== $rootScope.session.role)
                        {authorized = false;};
                    });
                });
           };
        if(!authorized){
                    event.preventDefault();
                    $state.go('menu.dashboard');
            };