0

I'm starting to use the MEAN Stack taking advantage of the angular-fullstack generator. It comes with an Authentication service which has a method that returns the current user object.

I'm successfully retrieving the Authenticated User object from my Controller this way:

angular.module('myApp')
   .controller('CompanyOwnerCtrl', function ($scope, $http, Auth) {
       $scope.user = Auth.currentUser();

});

$scope.user actually holds the user object since I'm able to display all its attributes in my view:

{{user}} //prints successfully all user data

My problem is that I'm unable to use the _id attribute in my controller to make a call to the backend and retrieve data from another collection

angular.module('myApp')
   .controller('CompanyOwnerCtrl', function ($scope, $http, Auth) {
       var u = Auth.currentUser();
       $scope.user = u;

       //retrieve additional data
       $http.get('/api/companies/' + $scope.user._id) 
         .then(function(result) {
            $scope.company = result.data; 
       }); 

});

If I try the code above to retrieve the company information it says the $scope.user._id is undefined BUT if I write in my view

{{user._id}}

It displays the user ID properly. I may not be using the best approach since this project is just to learn the stack, but, does anyone know why I can't use the user id the way I'm doing it in my controller?

Edit: Here's the Authentication Service

'use strict';

angular.module('myApp')
.factory('Auth', function Auth($location, $rootScope, Session, User, $cookieStore) {

// Get currentUser from cookie
$rootScope.currentUser = $cookieStore.get('user') || null;
$cookieStore.remove('user');

return {

  /**
   * Authenticate user
   * 
   * @param  {Object}   user     - login info
   * @param  {Function} callback - optional
   * @return {Promise}            
   */
  login: function(user, callback) {
    var cb = callback || angular.noop;

    return Session.save({
      email: user.email,
      password: user.password
    }, function(user) {
      $rootScope.currentUser = user;
      return cb();
    }, function(err) {
      return cb(err);
    }).$promise;
  },

  /**
   * Unauthenticate user
   * 
   * @param  {Function} callback - optional
   * @return {Promise}           
   */
  logout: function(callback) {
    var cb = callback || angular.noop;

    return Session.delete(function() {
        $rootScope.currentUser = null;
        return cb();
      },
      function(err) {
        return cb(err);
      }).$promise;
  },

  /**
   * Create a new user
   * 
   * @param  {Object}   user     - user info
   * @param  {Function} callback - optional
   * @return {Promise}            
   */
  createUser: function(user, callback) {
    var cb = callback || angular.noop;

    return User.save(user,
      function(user) {
        $rootScope.currentUser = user;
        return cb(user);
      },
      function(err) {
        return cb(err);
      }).$promise;
  },

  /**
   * Change password
   * 
   * @param  {String}   oldPassword 
   * @param  {String}   newPassword 
   * @param  {Function} callback    - optional
   * @return {Promise}              
   */
  changePassword: function(oldPassword, newPassword, callback) {
    var cb = callback || angular.noop;

    return User.update({
      oldPassword: oldPassword,
      newPassword: newPassword
    }, function(user) {
      return cb(user);
    }, function(err) {
      return cb(err);
    }).$promise;
  },

  /**
   * Gets all available info on authenticated user
   * 
   * @return {Object} user
   */
  currentUser: function() {
    return User.get();
  },


  /**
   * Simple check to see if a user is logged in
   * 
   * @return {Boolean}
   */
  isLoggedIn: function() {
    var user = $rootScope.currentUser;
    return !!user;
  },
};

});

2
  • 1
    What does the currentUser() method in Auth look like? Commented May 9, 2014 at 6:16
  • /** * Gets all available info on authenticated user * * @return {Object} user */ currentUser: function() { return User.get(); }, Commented May 9, 2014 at 6:22

2 Answers 2

2

Here's one possible and working solution for this problem. Keep in mind that this particular solution works for the angular-fullstack generator and I have no idea if there is a similar implementation in the backend for other generators

Instead of using the Auth.currentUser() method I ended up calling the /api/users/me end point which is connected to the current user session and therefore returns all the current user information.

$http.get('/api/users/me') 
  .then(function(result) {
    $scope.userId = result.data._id;
    // Do whatever you need to do with the userId here.

});

It is better to call the /api/users/me in every page instead of storing the userId in a session for security reasons. Remember to add the authenticate: true in your route to make sure there will always be a logged in user.

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

Comments

1

My guess would be that by the time the line of code making the $http call is reached the user object on the $scope is not populated, but after a little while it is and hence why you can check for the _id in your view, maybe due to some async operation? How about watching the user object and only making the call once it exists?

$scope.$watch(Auth.currentUser,function(user){
       if(user){
          $scope.user=user;
          $scope.GetCompanyDetails(user._id);
       }
},true);

$scope.GetCompanyDetails=function(userId){
       $http.get('/api/companies/' + userId) 
         .then(function(result) {
            $scope.company = result.data; 
       }); 
}

3 Comments

It didn't work this way. the $watch wouldn't register a change but you gave me some pointers on how to solve it. I ended up using an AJAX call to retrieve the current user information based on the session created and made a second in the callback of the initial to retrieve the company info. Thank you
You're welcome, if the User.get() method is making an async call, that would explain why it wan't working.
@MarceloC. Hi Marcelo, I'm having the exact same issue as you did on this piece of code. I was just wondering, is it okay if you post your answer or how you got your answer? It would be very helpful for me. Thanks!!

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.