环回3:检查模型是否存在以及属于我的模型

时间:2018-12-04 00:22:09

标签: javascript loopbackjs

使用回送ACL来设置模型访问规则,以便只有所有者才能检查或修改模型详细信息:

{
  "accessType": "*",
  "principalType": "ROLE",
  "principalId": "$owner",
  "permission": "ALLOW"
},
{
  "accessType": "*",
  "principalType": "ROLE",
  "principalId": "$everyone",
  "permission": "DENY"
},

但是,我的一个项目中有一个模型,其逻辑并不是那么简单。流程类似于:

  • 我从物联网设备获取ID
  • 我将该ID发送到API
    • 如果该设备未在API中注册,我可以声明该设备为我的
    • 如果它已注册并且不是我的,那么应该告诉我我不能与该设备进行交互
    • 如果它已经注册并且是我的,那么我会得到一个回复​​,让我知道我已经声明了这个。

我似乎无法仅凭状态码来做到这一点。

*尝试一项:使用*存在**

如果我允许任何经过身份验证的用户检查模型是否存在:

{
  "accessType": "EXECUTE",
  "principalType": "ROLE",
  "principalId": "$authenticated",
  "permission": "ALLOW",
  "property": "exists"
}

然后,如果模型存在,它将返回状态码200,如果不存在,则返回状态码404。因此,我需要执行第二次查询(例如,使用findById)来知道它是否属于我(在这种情况下,我会得到403状态代码)

尝试两个:使用findById

由于只有所有者可以与模型进行交互,因此查询存在的模型(不是我的模型)将返回403。足够好。

但是,查询不存在的模型也会返回状态码403 。我猜这是由于不存在的模型没有所有者,因此不允许查询其详细信息。

尝试三个:为其他经过身份验证的用户启用findById

设备所属的每个模型都有适当的ACL,因此我认为如果启用findById,它将不会显示相关实体。原来我错了。如果启用它:

{
  "accessType": "READ",
  "principalType": "ROLE",
  "principalId": "$authenticated",
  "permission": "ALLOW",
  "property": "findById"
}

如果模型不存在,则返回404;如果存在,则返回其他相关实体的每个细节,即使它属于另一个用户。

就这样。看来我不打算使用一种特殊的远程方法来处理这种情况,但是我很困惑,这听起来像是一个相当普遍的情况,我只想获取404/403/200以允许前端相应地执行操作。 / p>

1 个答案:

答案 0 :(得分:0)

好吧,万一有人遇到这个问题,我终于用远程方法做到了。

它将上下文作为请求中的参数,因此在模型json文件中将其定义为:

 "methods": {
    "hasclaimed": {
        "accepts": [{
                "arg": "deviceId",
                "type": "number",
                "required": true
            },
            {
                "arg": "res",
                "type": "object",
                "http": {
                    "source": "res"
                }
            },
            {
                "arg": "options",
                "type": "object",
                "http": "optionsFromRequest"
            }
        ],
        "returns": {
            "arg": "data",
            "type": "object",
            "root": true
        },
        "http": {
            "verb": "GET",
            "path": "/hasclaimed/:deviceId"
        }
    }
}

在javascript文件中为:

Customer.hasclaimed = function(deviceId, res, options) {
    const Device = this.app.models.Device;
    return Device.findById(deviceId, null, options).then(device => {
      const token = options && options.accessToken;
      const userId = token && token.userId;
      if (!userId) {
        res.status(401);
        return {};
      }
      if (!device) {
        res.status(204);
        return {};
      }

      console.log('(%s) %j', userId, device.idCustomer);

      if (device.idCustomer !== userId) {
        res.status(403);
        return {};
      }
      res.status(200);
      return device;
    });
  };

所以基本上:

  • 我正在传递要查找的deviceId
  • 响应对象,因此我可以设置自定义标头
  • 获取当前登录用户的上下文。

使用客户端点,我致电GET customer/hasclaimed/:deviceId

如果用户未登录,将收到401。 到那时,可用设备将返回204(我不想返回404,因为端点是正确的,只是没有设备可显示) 一个存在的设备将向所有者返回200(及其属​​性),如果存在则返回403,但不是他的。