在 DaftMonk/generator-angular-fullstack 中未定义 getCurrentUser().role [英] getCurrentUser().role undefined in DaftMonk/generator-angular-fullstack

查看:28
本文介绍了在 DaftMonk/generator-angular-fullstack 中未定义 getCurrentUser().role的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在为一个项目使用 DaftMonk/AngularJS 全栈生成器.生成的代码包含管理用户(注册、登录、角色等)的逻辑,非常棒.但是,使用代码时会出现问题,有时会未定义当前用户的角色.

我们遇到了这个问题,因为我们想要实现一个简单的功能:登录/注册后,用户应该被重定向到一个取决于他的角色的 URL.例如,'teacher' 用户应该被重定向到 /teacherHome'student' 用户应该被重定向到 /studentHome.由于 Auth.getCurrentUser().role 未定义,逻辑不起作用.

如何重现问题

要重现该问题,请编辑 client/app/account/login/login.controller.js 文件并添加语句以记录 Auth.getCurrentUser().role 的值,如下所示:

<预><代码>...if(form.$valid) {验证登录({电子邮件:$scope.user.email,密码:$scope.user.password}).then( 函数() {//登录,重定向到首页console.log("当前用户角色:" + Auth.getCurrentUser().role);$location.path('/');}).catch(函数(错误){$scope.errors.other = err.message;});}};...

测试这段代码的时候,你会发现这个阶段的用户角色是未定义的.然而,稍后,它被分配了一个值.这表明该问题可能与异步 REST 调用有关.

解决方案

实际上有几个相关的问题和解决方法.

方案一:使用提供的Auth.isLoggedInAsync函数

Auth 模块是生成代码的一部分,它提供了一种方法来检查登录过程是否已完成(并在这种情况下调用回调函数).因此,解决此问题的一种方法是在客户端代码中使用此函数,如下所示:

 if(form.$valid) {验证登录({电子邮件:$scope.user.email,密码:$scope.user.password}).then( 函数() {//登录,重定向到首页console.log("当前用户角色:" + Auth.getCurrentUser().role);Auth.isLoggedInAsync(功能(成功){console.log("当前用户角色:" + Auth.getCurrentUser().role);});$location.path('/');}).catch(函数(错误){$scope.errors.other = err.message;});}};

在这种情况下,您将在控制台中看到两条语句.第一个将显示 Auth.getCurrentUser().role 仍未定义.第二个将显示它现在有一个值.因此,如果您想在登录时执行逻辑并且这取决于用户角色(或其他用户属性),请将此逻辑放在您传递给 Auth.isLoggedInAsync().

解决方案 2:修复 auth.service.js

中的根本原因

如果您查看client/components/auth/auth.service.js 中的代码,您会发现异步代码存在问题.问题是 currentUser = User.get(); 触发了一个异步 HTTP 调用,并且 currentUser 没有立即设置(它是一个非阻塞调用).由于承诺会立即得到解决,因此客户会认为登录过程已经完成并且所有用户数据都可用,而实际上它仍在进行中.

在提议的修复中,promise 在传递给 User.get() 的回调函数中解析.

/*** 验证用户并保存令牌** @param {Object} 用户 - 登录信息* @param {Function} 回调 - 可选* @return {承诺}*/登录:函数(用户,回调){var cb = 回调 ||angular.noop;var deferred = $q.defer();$http.post('/auth/local', {电子邮件:user.email,密码:user.password})./* 原始代码——承诺过早解决成功(功能(数据){$cookieStore.put('token', data.token);currentUser = User.get();deferred.resolve(data);返回 cb();}).*//* PROPOSED FIX -- 一旦 HTTP 调用返回,promise 就会得到解决 */成功(功能(数据){$cookieStore.put('token', data.token);currentUser = User.get(function() {deferred.resolve(data);返回 cb();});}).错误(功能(错误){this.logout();deferred.reject(err);返回 cb(err);}.bind(this));返回 deferred.promise;},

相关问题和修复

提议的代码解决了一个问题.现在可以在成功登录后将用户重定向到特定页面.但是,在注册过程之后会出现类似的问题.在这种情况下,Auth.getCurrentUser().role 暂时未定义(足够长的时间会导致重定向逻辑失败).

在这种情况下,代码修正如下:

/*** 创建一个新用户** @param {Object} user - 用户信息* @param {Function} 回调 - 可选* @return {承诺}*/createUser:函数(用户,回调){var cb = 回调 ||angular.noop;/* 原始代码 ---------------------返回 User.save(user,功能(数据){$cookieStore.put('token', data.token);currentUser = User.get();返回 cb(用户);},功能(错误){this.logout();返回 cb(err);}.bind(this)).$promise;--------------------- *//* 建议修复 --------------------- */var deferred = $q.defer();用户.保存(用户,功能(数据){$cookieStore.put('token', data.token);currentUser = User.get(function () {console.log('User.save(), 用户角色:' + currentUser.role);deferred.resolve(data);返回 cb(currentUser);});},功能(错误){this.logout();返回 cb(err);deferred.reject(err);});返回 deferred.promise;},

We are using the DaftMonk/AngularJS Full-Stack generator for a projet. The generated code contains the logic to manage users (registration, login, roles, etc.), which is great. However, there is an issue when using the code and the role of the current user is sometimes undefined.

We encountered the issue as we wanted to implement a simple feature: after login/signup, the user should be redirected to a URL that depends on his role. For instance, 'teacher' users should be redirected to /teacherHome and 'student' users should be redirected to /studentHome. Because Auth.getCurrentUser().role is undefined, the logic does not work.

How to reproduce the issue

To reproduce the issue, edit the client/app/account/login/login.controller.js file and add statements to log the value of Auth.getCurrentUser().role, like so:

...
  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 the user role is undefined at this stage. Later on, however, it is assigned a value. This suggests that the issue might be related to an asynchronous REST call.

解决方案

There are actually a couple of related issues and ways to fix them.

Solution 1: use the provided Auth.isLoggedInAsync function

The Auth module, part of the generated code, provides a method to check if the login process has been completed (and to invoke a callback function when this is the case). So, one way to fix the issue is to use this function in the client code, like so:

  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 statements in the console. The first one will show that Auth.getCurrentUser().role is still undefined. The second one will show that it now has a value. So, if you have logic that you want to execute at login time and that depends on the user role (or other user attributes), put this logic in a callback function that you pass to Auth.isLoggedInAsync().

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

If you look at the code in client/components/auth/auth.service.js, you will see that there is an issue with asynchronous code. The problem is that currentUser = User.get(); triggers an asynchronous HTTP call, and that currentUser is not immediately set (it is a non-blocking call). Since the promise is resolved immediately, clients are lead to believe that the login process has completed and that all user data is available, whereas it is in fact still in flight.

In the proposed fix, the promise is resolved in a 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 proposed code fixes one issue. It is now possible to redirect the user to a specific page upon successful login. However, a similar problem arises after the signup procedure. In this case also, Auth.getCurrentUser().role is undefined for a while (long enough for the redirection 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;

  },

这篇关于在 DaftMonk/generator-angular-fullstack 中未定义 getCurrentUser().role的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆