-1

I know that generally you don't want to do this, but I've found a use case where I can't seem to find any other solution and want to have my function which contains a promise wait until the promise resolves before returning anything.

I'm modifying the authentication mechanism for an application and have the following code set up to double check that the user is authorized whenever the $state changes, and redirect them back to the login screen if they are not authorized:

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

    // double check that the user is logged in
    if (toState && toState.name.indexOf('auth')<0) {
        if (!user.isAuthorized()) {
            event.preventDefault(); // do not continue to the non-auth state
            user.logout();
            $state.go("auth.login");
        }
    }
});

Currently, the user.isAuthorized() function simply returns a true or false value from an internal boolean that is set/unset when the user logs in or out, and everything works fine.

However, we need to make that function call out to the server (if the local boolean is set to false) to check if the user already has an active session and then set the boolean and return true. We don't want the application to do anything at all until that server call returns, since it is checking to see if the user should be able to see the UI at all.

I have attempted to utilize a promise to handle this case, but it has unexpected results because the event.preventDefault() call doesn't get called immediately (only after the promise resolves), at which point the $state has already changed. At a minimum this causes the UI to flash briefly before being sent to the login screen, and in some cases those other $states make their own server calls when loaded which fail and/or cause the browser to prompt the user for basic authorization (username/password).

This does not work:

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

    // double check that the user is logged in
    if (toState && toState.name.indexOf('auth')<0) {
        user.isAuthorized().then(function(isAuthorized) {
            if (!isAuthorized()) {
                event.preventDefault(); // this does not prevent state change any more
                user.logout();
                $state.go("auth.login");
            }
        });
    }
});

I think we need to have the user.isAuthorized() function look something like this:

user.isAuthorized = function() {
    if(user.isAuthorizedBoolean) {
        return true;
    } else {
        var returnValue = false;

        // make server side call that returns promise
        user.isAuthorizedServerCheck().then(function(result) {
            if (result === true) {
                returnValue = true;
            }
        });

        // pause execution until promise resolves???

        return returnValue;
    }
};

But I'm not sure how to accomplish that.

Brian Medendorp
  • 289
  • 2
  • 5

1 Answers1

0

It looks like the solution posted here: Confusing $locationChangeSuccess and $stateChangeStart by @RadimKöhler is what I'm looking for.

Community
  • 1
  • 1
Brian Medendorp
  • 289
  • 2
  • 5