GetCurrentUser (). undefined role in DaftMonk / generator- angular-full stock

We use the DaftMonk / AngularJS Full-Stack generator for the project. The generated code contains user management logic (registration, login, roles, etc.), which is excellent. However, there is a problem when using the code, and the role of the current user is sometimes undefined.

We ran into a problem because we wanted to implement a simple function: after logging in / registering, the user should be redirected to a URL that depends on its role. For example, users 'teacher' should be redirected to /teacherHome and 'student' , users should be redirected to /studentHome . Because the role is Auth.getCurrentUser (). undefined, the logic does not work.

How to reproduce the problem

To reproduce the problem, edit the client/app/account/login/login.controller.js and add operators to register the value of the Auth.getCurrentUser () role. For instance:

 ... if(form.$valid) { Auth.login({ email: $scope.user.email, password: $scope.user.password }) .then( function() { // Logged in, redirect to home console.log("Current user role: " + Auth.getCurrentUser().role); $location.path('/'); }) .catch( function(err) { $scope.errors.other = err.message; }); } }; ... 

When testing this code, you will find out that at this stage the user role is undefined. Later, however, it is assigned a value. This suggests that the problem may be related to an asynchronous REST call.

+5
source share
1 answer

In fact, there are a couple of related problems and ways to fix them.

Solution 1: use the function provided by Auth.isLoggedInAsync

The Auth module, which is part of the generated code, provides a method for verifying the completion of the login process (and for calling the callback function when this is the case). So, one way to fix the problem is to use this function in client code, for example:

  if(form.$valid) { Auth.login({ email: $scope.user.email, password: $scope.user.password }) .then( function() { // Logged in, redirect to home console.log("Current user role: " + Auth.getCurrentUser().role); Auth.isLoggedInAsync(function(success) { console.log("Current user role: " + Auth.getCurrentUser().role); }); $location.path('/'); }) .catch( function(err) { $scope.errors.other = err.message; }); } }; 

In this case, you will see two operators in the console. The first will show that Auth.getCurrentUser (). The role is still undefined. The second shows that now it matters. So, if you have logic that you want to execute during login and that depends on the role of the user (or other user attributes), put that logic in the callback function that you pass to Auth.isLoggedInAsync() .

Solution 2: fix the root cause in auth.service.js

If you look at the code in client/components/auth/auth.service.js , you will see that there is a problem with asynchronous code. The problem is that currentUser = User.get(); starts an asynchronous HTTP call and that currentUser not installed immediately (this is a non-blocking call). Since the promise is immediately resolved, customers are forced to believe that the login process is complete and that all user data is available, while it is actually in flight.

In the proposed fix, the promise is resolved in the callback function passed to User.get() .

  /** * Authenticate user and save token * * @param {Object} user - login info * @param {Function} callback - optional * @return {Promise} */ login: function (user, callback) { var cb = callback || angular.noop; var deferred = $q.defer(); $http.post('/auth/local', { email: user.email, password: user.password }). /* ORIGINAL CODE -- promise is resolved too early success(function (data) { $cookieStore.put('token', data.token); currentUser = User.get(); deferred.resolve(data); return cb(); }). */ /* PROPOSED FIX -- promise is resolved once HTTP call has returned */ success(function (data) { $cookieStore.put('token', data.token); currentUser = User.get(function() { deferred.resolve(data); return cb(); }); }). error(function (err) { this.logout(); deferred.reject(err); return cb(err); }.bind(this)); return deferred.promise; }, 

Related issue and fix

The suggested code fixes one problem. Now, upon successful login, you can redirect the user to a specific page. However, a similar problem occurs after the registration procedure. In this case, also Auth.getCurrentUser().role is undefined for some time (long enough for the redirect logic to fail).

In this case, the code was fixed as follows:

  /** * Create a new user * * @param {Object} user - user info * @param {Function} callback - optional * @return {Promise} */ createUser: function (user, callback) { var cb = callback || angular.noop; /* ORIGINAL CODE --------------------- return User.save(user, function(data) { $cookieStore.put('token', data.token); currentUser = User.get(); return cb(user); }, function(err) { this.logout(); return cb(err); }.bind(this)).$promise; --------------------- */ /* PROPOSED FIX --------------------- */ var deferred = $q.defer(); User.save(user, function (data) { $cookieStore.put('token', data.token); currentUser = User.get(function () { console.log('User.save(), user role: ' + currentUser.role); deferred.resolve(data); return cb(currentUser); }); }, function (err) { this.logout(); return cb(err); deferred.reject(err); }); return deferred.promise; }, 
+10
source

Source: https://habr.com/ru/post/1210409/


All Articles