0

I've made an AuthService that should help me take care of all authentication matters like logging in, registering, getting user data from server etc.

I am looking for a solution that runs only on login, on page refresh and when triggered to refresh get the user data from the service and make it available on the controllers that i include the service to. I would like to have something like vm.user = AuthService.getUserData() and this returns the session variable from the service. Something like this:

function getUserData(){
    if (session) {
        return session.user;
    }
    return null;
}

On $rootScope.$on('$stateChangeStart' i have :

AuthService.loadSessionData();

Which translates to:

function loadSessionData() {
    $http({
            url: API.URL+'auth/session-data',
            method: 'GET'
        })
    .success(function(response)
    {
        session = response;
    })
    .error(function(err){
        console.log(err);
    });
};

One of the issues here are that i have to set a timeout on AuthService.getUserData() because when this executes, the call that retrieves the session data from the server is not finished yet, but this is a bad practice.

Here is the complete service code http://pastebin.com/QpHrKJmb

2 Answers 2

2

How about using resolve? If I understood correctly you wish to have this data in your controller anyway.

You can add this to your state definitions:

.state('bla', {
    template: '...'
    controller: 'BlaCtrl',
    resolve: {
        user: ['AuthService', function(AuthService) {
            return AuthService.loadSessionData();
        }
    }
}

also, alter your loadSessionData function: (make sure to inject $q to AuthService)

function loadSessionData() {

    return $q(function(resolve, reject) {
        $http({
            url: API.URL + 'auth/session-data',
            method: 'GET'
        })
        .success(function(response)
        {
            if (response) {
                resolve(response);            
            } else {
                reject();
            }
        })
        .error(function(err){
            reject(err);
        });
    })
}

Lastly, add the user object from the resolve function to you controller:

    app.contoller('BlaCtrl', ['$scope', 'user', function($scope, user) {
        $scope.user = user;
    }]);

What does this accomplish?

  1. In case the user does not have a valid session or an error occurs, the state change is rejected and the event $stateChangeError is thrown. You can listen (like you did for $stateChangeStart for that event and respond with a modal, redirect to an error page, or whatever.

  2. You only pull the session for states that needs it - not for every state change.

  3. The state is not resolved until the user data is resolved as well (either by resolve or reject).

Sign up to request clarification or add additional context in comments.

3 Comments

thanks that did the trick. I would add that i've made an abstract state with resolve : { Session: ...} so i will have the session available on every state that derivates from app. Also another good tweak is that on loadSessionData at the beginning i check if the session variable exists so it doesn't fetch the data again.
I actually wanted to mention you can alter what I wrote to use a cache :) When using a root state if you switch between the children state you only resolve the child state, not the parent. Keep that in mind so you won't have a single root state which resolves the session only once and assumes it is valid from that point onwards. However, this depends on your how you wan't to use sessions in your app
This session is not actually the session is the user data on this session. This stays the same, until for example a user changes something in his profile and then i force-update it. The session is kept with JWT tokens so it's separated.
0

You should call loadSessionData() in getUserData()

function getUserData(){
   loadSessionData()
   .success(function(response)
    {
       if (response) {
         return response.user;
       }
    })
    return null;
 }

and

function loadSessionData() {
   return $http.get(API.URL+'auth/session-data');
};

1 Comment

my approach was kinda the same because vm.user = AuthService.getUserData() doesn't wait for the call to terminate, is async and the final value of vm.user is undefined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.