Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep globally current user until logout with angular_devise?

Tags:

How to create own service accessible globally that will call server by currentUser() only once on page load, if User is logged in then keep it and provide data to controllers or states until logout? Now I'm resolving many times in many states or controllers currentUser(), I found in docs: authparseresponse that it is possibility to make own service, but I don't know how to handle this in right way.

e.g in ui-router I've two server calls, would be sufficient only when page is loaded:

.state('login', {
  url: '/login',
  templateUrl: 'auth/_login.html',
  controller: 'AuthCtrl',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function() {
        $state.go('home');
      });
    }
  ]
})
.state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function(user) {}, function(err) {
        $state.go('home');// user not logged in
      });
    }
  ]
})

or each time next server call in NavController:

app.controller('NavController', [
  '$state', '$scope', 'Auth', function($state, $scope, Auth) {
    $scope.signedIn = Auth.isAuthenticated;
    $scope.logout = Auth.logout; // logout function
    Auth.currentUser().then(function(user) {
      $scope.user = user;
    });
    $scope.$on('devise:login', function(e, user) {
      $scope.user = user;
    });
    $scope.$on('devise:logout', function(e, user) {
      $scope.user = {};
      $state.go("home");
    });
  }
]);

I found similar question without answer: stackoverflow

like image 484
luzny Avatar asked Apr 02 '15 22:04

luzny


2 Answers

As we know factory is a singleton object and basically it is used for data sharing. We can inject it to any controller and functions as an dependency .So this may be also solve your problem. inject this service to your state resolve block and check if user exists or not if not then call the fetch user function of factory

app.factory("User", function($http, $q, $rootScope) {
var user = null;
return {
    fetchUser: function() {
        /*your ajax call that return current user*/
        user = YOUR_SERVER_RESPONSE;
        return user;

    },
    getUser : function(){
        return user;
    },
    setUser : function(u){
        user = u;
    }
}

});

and your state config block is look like

  .state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  resolve : function(User){
    if(User.getUser()){
        return User.getUser();
    }else{
        return User.fetchUser();
    }
  }
})
like image 185
Bharat Bhushan Avatar answered Sep 19 '22 10:09

Bharat Bhushan


I've had to deal with user Authentication in a large Angular app and found this article very useful: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

Specific to 'how to make it happen only once':

  • you can call the init() of the Service in an app.run block
  • adding it as a resolve requirement of an outer state for the app (if you use nested states)

A UserService Service to represent user's logged in state works well for sharing state throughout the application. The login and logout functions can be exposed through this service and the user's details can be stored here too. Defining a UserApi that extends $resource will probably help too to separate the actual HTTP concerns from managing user state.

Other concerns that will catch you, both of which are covered in the article: persistent state across page refreshes, and having areas of the site that are only accessible when the user is logged in.

like image 23
zayquan Avatar answered Sep 23 '22 10:09

zayquan