AngularJS (Restangular): Making a promise block? Need to use it for validating a token
Asked Answered
C

3

6

I have stumbled upon Restangular for making calls to a rest service. It works great and returns a promise. I need to be able to have the call block. The reason for this is on a fresh page reload I am technically not loggged in but I may have a token stored in a cookie. i would like to validate this token against a rest service. Problem is that I need it to block.

If a timeout occurs or if its not valid that i can treat teh user as not authenticated.

This is the reason for wanting to block is that i would like to redirect them using $location.path to a new URL it not a valid token.

This doesn't happen on a specific route so i can't use resolve which is blocking. It technically happens on every route - I use the $on.$routeChangeStart and check an internal variable got LoggedIn or not, if not logged in i check for the stored token.

This happens on each Page refresh but not while navigating inside the application.

The affect I am trying to get is how Gmail works.

Look forward to any insight anyone has on this

Thanks

Cown answered 7/8, 2013 at 13:42 Comment(0)
P
8

Basically you need to ensure that some asynchronous action occurs prior to any route change occurring, and in this case the action is authenticating a user.

What you can do is use the $routeChangeStart event that's emitted in order to add a property to the resolve object on the route like so:

function authenticate() {
    if ( user.isAuthenticated ) {
        return;
    }
    // Just fake it, but in a real app this might be an ajax call or something
    return $timeout(function() {
        user.isAuthenticated = true;
    }, 3000);
}

$rootScope.$on( "$routeChangeStart", function( e, next ) {
    console.log( "$routeChangeStart" );
    next.resolve = angular.extend( next.resolve || {}, {
        __authenticating__: authenticate
    });
});

Since angular will wait for any promises in the resolve object to be fulfilled before proceeding, you can just use a pseudo dependency as in the example. Using something like that, you should be able to guarantee that your user is authenticating prior to any routes successfully executing.

Example: http://jsfiddle.net/hLddM/

Primatology answered 15/8, 2013 at 2:24 Comment(1)
Nice!, this was what i was looking for.Cown
M
0

I think the best way to do this might be to push the user around with $location.path, You can use .then() to effectively force a wait by leaving the user on a loading page.

var currentPath = $location.path();

$location.path(loadingScreen);

//Assuming you have some sort of login function for ease.
Restangular.login(token).then(
    function(result) {
        $location.path(currentPath)
    },
    function(error) {
        $location.path(logInScreen)
    }
);
Mullen answered 7/8, 2013 at 14:40 Comment(1)
Thanks Matt, that sounded like what I needed but the $location.path(loadingScreen) would change the address bar of the browser. Anyway round this ?Cown
S
0

If you're using ui-router, you could move to another state with the same URL, where you'd use that Restangular.login with the then, and in case of success go back to the "logged in" state, otherwise, go to the "log in" state where the user must enter his username and password.

If you're not using ui-router, you could implement something like that with some ng-switch.

So, upon arrival to the screen, you do that Restangular.login and by default you show loading page by setting some boolean to true. Then, if it doesn't succedd, you send him to the login, otherwise, you set loading to false and show page.

Anyway, I'd strongly recommend using ui-router, it rocks :)

Hope this works!

Spelaean answered 11/8, 2013 at 3:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.