在 User.login() 和 User.getCurrent() Angular SDK 中包含角色

Include roles in User.login() and User.getCurrent() Angular SDK

我目前正在使用 Loopback Angular SDK 编写管理界面。在仔细研究了文档和代码之后,我仍然不知道如何在响应中包含用户的角色。这让我在前端感到非常头疼,因为我对 Angular 还没有足够的经验来弄清楚如何对我的每个状态执行角色检查(我正在使用 UI-Router)。

客户端:/auth.js

        // Log the user in
        $scope.doAuth = function() {

            $scope.hasError = false;
            $scope.busy = true;

            $scope.loginResult = User.login({include: 'roles'}, $scope.credentials,

                function wasSuccessfulAuth(authResponse) {

                    $scope.busy = true;

                    $rootScope.isAuthenticated = true;
                    $rootScope.user = authResponse.user;

                    $location.path('dashboard');

                },

                function wasFailedAuth(authResponse) {

                    $timeout(function() {

                        $scope.hasError = true;
                        $scope.authError = authResponse.data.error.message || 'Unknown error';
                        $scope.busy = false;

                    }, 1000);

                }

            )
        }

服务器:/common/models/user.json

{
  "name": "user",
  "plural": "Users",
  "base": "User",
  "properties": {

  },
  "relations": {
    "roles": {
      "type": "belongsTo",
      "model": "RoleMapping",
      "foreignKey": "principalId"
    }
  },
  "acls": [],
  "methods": []
}

所以这在 API 资源管理器中有效,我有我期望的路线与一个有关系的对象,但我似乎无法比那更进一步......所有这些返回的是标准用户登录内容(id、accessToken、电子邮件等)当我走到这一步时,文档似乎 运行 很冷,但我认为这将是一个常见的用例?

这对我来说有点阻碍。

User.login returns AccessToken 实例。要获取用户角色,您应该单独请求获取用户,包括角色。

使用 LoopBack 解决这个问题实际上非常容易:这就是“model scopes”派上用场的地方——包括默认范围,我发现它对这种情况非常有用。

首先简单说明模型作用域:

模型范围类似于保存的查询或 "view",它允许您为该范围的任何查询指定内置 filter。例如,如果您将默认范围设置为有效过滤器,则针对您的模型的每个查询(任何类型)都将应用此过滤器!

这会给你带来一大堆麻烦,但有一个用例非常安全(所有其他条件相同)并且实际上完美地解决了你的问题:当我说范围让你给出有效的 filter,事实证明过滤器不仅仅是 where 子句,还有 includelimit

因此,要解决您的问题,您只需要在 User 模型上有一个默认范围,include 就是您需要包含的任何内容。例如:

只需将 scope 对象添加到您的 common/models/user。json:

{
  "name": "user",
  "plural": "Users",
  "base": "User",
  "scope": {
    "include": [
      "roles"
    ]
  },
  "properties": {

  },
  "relations": {
    "roles": {
      "type": "belongsTo",
      "model": "RoleMapping",
      "foreignKey": "principalId"
    }
  },
  "acls": [],
  "methods": []
}

通过添加带有 "include" 的默认作用域,LoopBack 将根据命名关系自动嵌入相关模型的对象(就像您将其添加到查询中一样——讨论,在这种情况下是不可能的,或者至少不容易。

一个警告:由于 RoleRoleMapping 是内置模型并且肯定被标记为非 public,我实际上不确定您是否可以直接包含它们(但出于与上述不同的原因)。我对 ACL 的研究还不够多(但),但大概在访问控制方面存在更多的复杂性,尤其是在相关模型中。

因此,虽然我上面的示例代码解释了执行 include 机制 ,但政策问题可能会减慢您的速度(我很想知道如果他们这样做了)。

也就是说,但是,我猜你可以添加一个你制作的派生模型(来自 RoleMapping)public(就像你为用户所做的那样),然后在任何地方使用它(包括在关系 to/from user) 中——希望这很清楚(如果不清楚请告诉我)。

结论:如果您将 default scope 添加到派生的 user 模型,为您执行 include,AngularJS 服务包装器(由 lb-ng 构建)将 none 更明智(include 全部发生在后端):

$scope.loginResult = User.login($scope.credentials,
  function wasSuccessfulAuth(authResponse) {
    console.log('Related models are here: ', authResponse.roles,
                authResponse.user);
    ...

换句话说,生成的模型将包含一个数组,.roles[],其中包含与该用户相关的角色(基于您的关系定义),以及 .user 和整个 [=24] =] 模型就在那里!

后一点尚不清楚,但我对此很有信心,因为我完全按照上面的方法做了,但使用了我知道有效的不同相关模型。令我惊讶的是,user 也被包括在内,因为这是 LoopBack $resource 包装器(由 lb-ng 创建的包装器)明确要求的。所以,实际上,您不必执行单独的查询来获取 user——它已经存在了!在使用 $service 包装器时,我没有看到 API 来获取内置的 include 并进行更改;我想这就是上面评论中发布的内容。

希望这对您有所帮助。

史蒂夫