防止通过Firestore上的安全规则删除已使用的文档

时间:2018-03-08 15:52:46

标签: firebase google-cloud-firestore firebase-security-rules

背景:

假设Firestore上有产品和订单集合。

订单有很多产品,即(伪架构):

products {
  name: string
}

orders {
  items: [{
    product_id: (ref products)
    quantity: number
  }]
}

使用这些安全规则:

match /products/{document=**} {
  allow read, write: if request.auth != null;
}

match /orders/{document=**} {
  allow read, write: if request.auth != null;
}

情景:

现在,假设我们已经创建了产品A.

然后,我们为产品A创建了订单1.

接下来,假设我们从产品系列中删除了产品A(已在订单1中使用)。

这将使订单1仍然引用已删除的产品A.

问题:

有没有办法编写安全规则来阻止删除订单上使用的产品?

1 个答案:

答案 0 :(得分:0)

首先,如果目标只是一致性,您可以使用函数删除对A的引用,这样就没有断开的链接。

但是,如果你特意想要在链接时阻止删除,那么你需要一个不同的策略,因为目前无法在安全规则中查询另一条路径。

非规范化:保留产品中的参考列表

您的数据中包含以下内容:

  "{product_id}": {
      "name": "...",
      "orders": {
         "order_id": true 
      }
  }

允许你写这样的规则:

function isAuthenticated() {
   return auth != null;
}

function hasLinks(resource) {
   return !resource.data.links;
}

match /products/{pid} {
  allow delete: if isAuthenticated() && !hasLinks(request.resource);
}

其他想法

使用功能:我的第一直觉是队列方法(您将删除排队到服务器,服务器决定是否有产品链接,删除它或拒绝请求)。但这不适用于您当前的结构,因为您无法跨子集查询以在每个订单子集合中查找对产品的引用。您仍然需要一个非规范化的产品订单列表来使用此产品(这与我上面的解决方案非常相似)。

归档项目而不是删除项目:可能并不强烈需要实际删除项目,因此归档它们可以避免整个问题集。