Loop problem with $stateChangeStart

Asked

Viewed 87 times

0

Hello person I am creating an authentication system and check levels with Angularjs, I am using stateChangeStart to validate permissions in view.

Only when I use $state.go('app.home'); it goes into infinite loop.

My code is this::

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams)
   {      
      if (typeof(toState) !== undefined){
        $templateCache.remove(toState.templateUrl);
      }

      if($rootScope.session == undefined && $cookieStore.get('user') == undefined) 
      {
        $rootScope.session =  {};
      }else if($rootScope.session == undefined && $cookieStore.get('user') != undefined) 
      {   

          $rootScope.session = {
            set:true, 
            name : $cookieStore.get('user')['name'], 
            userid : $cookieStore.get('user')['id'], 
            role: $cookieStore.get('user')['nivel'],
            email: $cookieStore.get('user')['email']
          };          
      }

      if(toState.name === "page.login" || toState.name === "page.register")
      {
        return;
      }

      var authorized = true;

      if(Object.keys($rootScope.session).length === 0) 
      {
          event.preventDefault();
          $state.go('page.login');
          return;
      }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('app.home');
        return;
      }; 

   }); // Start View

I tried too:

var array = toState.permissions['except'];

if(array.indexOf($rootScope.session.role) > 0)
{
  authorized = false;
}

Thank you.

  • What is your problem? It’s good that you indicate exactly where the problem is and what the desired result is so that users don’t have to read your entire code and guess what might be wrong.

  • That’s right, I’m sorry

1 answer

1


First, there is nothing really stopping the continuation of the code, IE, it will read your code and independent of having a session or not, the var authorized will be validated as true and it will pass.

You need to do your checking within the same block and ensure that the var authorized is only validated as true if it is actually logged in.

Another observation, before making any check of session, check first if the user is trying to access a restricted area. If it is a public area, there is no need to check if the user is logged in. That is, the logic of its verification must be something like this:

The state requires login?
if not -> continues
if yes -> checks..

The user is logged in?
if yes -> continues
if no -> returns to login

The user has permission?
if yes -> continues
if no -> returns to permission page

I would need to do some tests to identify if it will actually work, but I believe the structure of your code should follow something +- like this:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
  if(toState.name === "page.login" || toState.name === "page.register") {
    return;
  } else {

    if (typeof(toState) !== undefined) {
      $templateCache.remove(toState.templateUrl);
    } else {

      if($rootScope.session == undefined && $cookieStore.get('user') == undefined) {
        $rootScope.session =  {};
        event.preventDefault();
        return $state.go('page.login');

      } else if($rootScope.session == undefined && $cookieStore.get('user') != undefined) {
        $rootScope.session = {
          set:true, 
          name : $cookieStore.get('user')['name'], 
          userid : $cookieStore.get('user')['id'], 
          role: $cookieStore.get('user')['nivel'],
          email: $cookieStore.get('user')['email']
        };

        var authorized = true;

        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();
          return $state.go('app.home');
        };
      }
    }
  }
});

I hope this helps you better understand how to organize checks.

  • I forgot to put my problem, sorry to rush. Next. My problem is that at the time you put $state.go('app.home'); it goes into infinite loop. I used the Location window and it was good. looks like the $state runs $stateChangeStart every time it’s called, generating an infinite loop.

  • But execution always happens. That is why I recommended the use of checking the login need before checking if the user is really authenticated. That should solve your problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.