2

I am trying to prevent the user from going straight to bookmarked URL when not logged in (maybe I should figure out how to only display one URL, no matter what the state ?).

If the user has logged in, then $scope.serverToken will be set.

If not, I want to change state to index.login - BUT the login dialog is not being displayed - perhaps because of the first check in the function??

What am I doing wrong?

 $rootScope.$on('$stateChangeStart', 
      function(event, toState, toParams, fromState, fromParams)
        {
            if (toState == fromState)
                return;

            if (fromState.name == "")
            {
                $scope.serverToken = "";
                event.preventDefault();
                $scope.SetLoginDialog('login');
                $state.go("index.login");
                return;
            }

          // Take the user to the login page if server token expired only if user is not already transitioning to the
          // login page
          if (($scope.serverToken == "") && (toState.name !== 'index.login'))
          {
              console.warn('Attempt to go directly to URL without logging in');
              event.preventDefault();
              $scope.SetLoginDialog('login');
              $state.go("index.login");
              return;
          }

            var url = HOST + 'api/is_user_logged_in.php?token=' + $scope.serverToken;
            console.log('Check if user is logged in at ' + url);

            $http.get(url)
                .success(function(data, status, headers, config) 
                    {

State changes are via a menu who's entries look like this

<li ui-sref-active="active">                
   <a ui-sref="index.events"><i class="fa fa-desktop"></i> <div class="nav-label">Events</div></a>
</li>     

This might also help you to help me ...

$stateProvider

    .state('index', {
        abstract: true,
        url: "/index",
        templateUrl: "views/common/content.html",
    })

    .state('index.login', {
        url: "/login",
        templateUrl: "views/login.html",
        data: { pageTitle: 'Login' }
    })

    .state('index.overview', {
        url: "/overview",
        templateUrl: "views/overview.html",
        data: { pageTitle: 'Overview' }
    })

    .state('index.events', {
        url: "/events",
        templateUrl: "views/events.html",
        data: { pageTitle: 'Events' },
    })

Here's some of my controller, in case it helps ...

angular
    .module('MyApp')
    .controller('MainCtrl', MainCtrl)

function MainCtrl($rootScope, $scope, $http, $interval, $state, $location)
{
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • 1
    I assume you have one controller for multiple states? can you show it? It's possible you're initializing the controller in each state change, thus "destroying" the dialog – AranS Aug 07 '16 at 11:55
  • Yes, I have one mega controller for multiple states, 2k+ lines and far to large to post :-( Which part would show "initializing the controller in each state change"? I am using a framework, which has menu buttons & handles state change, so it is unlikely to be wrong. – Mawg says reinstate Monica Aug 07 '16 at 12:03
  • 1
    can you display your routing code? the state declaration? maybe we can find a solution by resolving the specific state (when routing to this state the controller will show the dialog) – AranS Aug 07 '16 at 12:20
  • I hope you will excuse me if I misunderstood. Are you looking for the code that I have added at the end of the question? Or something else? Sorry to be so dumb :-( – Mawg says reinstate Monica Aug 07 '16 at 12:37
  • 1
    probably the first 40 lines of yoru controller will work. – nycynik Aug 07 '16 at 12:38
  • 1
    don't feel bad my friend! do you have the location of declaring states, like this: `$stateProvider.state("index.login")...` – AranS Aug 07 '16 at 12:40
  • @nycynik I will add the first lines of my controller. Arans, thank you for your patience!! I have posted it now – Mawg says reinstate Monica Aug 07 '16 at 12:55
  • 1
    Are you using some additional Frameworks like AngularMaterial or Ionic or just "plain" AngularJS? Do you get any error messages on your JS-Console in the browser? – albert Aug 08 '16 at 07:19
  • Just plain Angular and there are no console errors. EVen if there are errors int he code, is my approach correct? – Mawg says reinstate Monica Aug 08 '16 at 08:14
  • 1
    You can find several auth examples using ui-router like: http://stackoverflow.com/questions/22537311/angular-ui-router-login-authentication, https://solidfoundationwebdev.com/blog/posts/require-authentication-for-certain-routes-with-ui-router-in-angularjs, https://www.npmjs.com/package/ui-router.login, https://medium.com/@petehouston/protect-authentication-routes-in-angular-ui-router-and-satellizer-7745257a7e6#.6wbq30874 – albert Aug 08 '16 at 08:55
  • @Mawg Just a shot in the dark, but what happens if you try to open the modal once the user has been transitioned to `"index.login"`? – Cosmin Ababei Aug 12 '16 at 09:07
  • What modal? I don't udnerstand. I don't have any modal dialogs – Mawg says reinstate Monica Aug 12 '16 at 10:14
  • @Mawg The login dialog, the one which you one with `$scope.SetLoginDialog('login');`. – Cosmin Ababei Aug 12 '16 at 11:30
  • Maybe this SO thread helps: http://stackoverflow.com/questions/27212182/angularjs-ui-router-how-to-redirect-to-login-page – Sebastian Sebald Aug 12 '16 at 11:32
  • 1
    `if (toState.name == 'index.login')return;` Don't you prevent the transition to login with this statement? – Herr Derb Aug 12 '16 at 12:04
  • @CosminAbabei that's not a modal dialog. It's just a variable to tell me whether we are at login, resigstration or lost password receovery. I use it no `ng-sho/hide` parts of the page – Mawg says reinstate Monica Aug 12 '16 at 12:04
  • @HerrDerb Yes, that is be the answer. Feel free to post it as an answer and claim the bonus points. I cannot understand why I ever put that comment `return; // else we loop forever back to here when we set the state below` - when I remove that check, everything works as expected. – Mawg says reinstate Monica Aug 12 '16 at 12:17
  • 1
    before trigerring a new transition and go to home.login state you should cancel the current transition using `event.preventDefault()` – Walfrat Aug 12 '16 at 13:14
  • I tried that (I have updated the question) - but it is still looping infintely :-( – Mawg says reinstate Monica Aug 13 '16 at 11:41

2 Answers2

1

I guess, this is simple. Just modify your function like this:

function (event, toState, toParams, fromState, fromParams) {
    // Take the user to the login page if server token expired only if user is not already transitioning to the
    // login page
    if (!$scope.serverToken && toState.name !== 'index.login') {
        console.warn('Attempt to go directly to URL without logging in');
        $scope.SetLoginDialog('login');
        $state.go("index.login");
        return;
    }
}
Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121
0

if (toState.name == 'index.login')return; is preventing any state change to index.login.

if (fromState.name == 'index.login')return; will do the transition once if not already in login state

Update:

I think you created another endless loop. If you enter the app with an initial "" state, it will always be true here and will interrupt every transition.

if (fromState.name == "")
     {
                $scope.serverToken = "";
                event.preventDefault();
                $scope.SetLoginDialog('login');
                $state.go("index.login");
                return;
     }

Try

if (fromState.name == "" && toState.name!=="index.login")
Herr Derb
  • 4,977
  • 5
  • 34
  • 62
  • Sorry, I was sure that would do it, but it seems like my comment **was** correct after all. When I remove the `if (toState.name == 'index.login')return;`, I get an infinite loop of `Attempt to go directly to URL without logging in`, so I still have a problem. Sorry for being so quick (and so wrong) to say that you had the answer :-( – Mawg says reinstate Monica Aug 12 '16 at 12:27
  • 1
    try it like this then: `if (fromState.name == 'index.login')return;` using the fromState allows you to do the transition once, if not already in the login state – Herr Derb Aug 12 '16 at 12:55
  • I have updated the question. Could you plaase have another look? – Mawg says reinstate Monica Aug 13 '16 at 11:42