Firestore规则以批量验证多个创建

时间:2020-01-15 00:57:14

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

我正在编写一个应用程序,用户可以在其中将注释放入线程中。由于我为此使用Firestore的NoSQL后端,因此将每个注释存储在两个位置:

/threads/THREADID/comments/COMMENTID
/users/USERID/comments/COMMENTID

这样,我对线程中的所有注释以及用户已发布的所有注释进行了概述。为了确保始终同时创建这两个注释,我使用批处理写入。批处理写入是原子性的,因此它永远不会引起任何问题,但是我担心的是,恶意用户只能使用自定义代码在一个位置创建注释,而不能在两个位置都创建注释。我需要找到一条规则来验证是否创建了两个注释,或者都不应该创建两个注释。

  match /users/{userId}/comments/{commentId} {  
    allow create: if exists(/databases/$(database)/documents/threads/$(request.resource.data.threadId)/comments/$(commentId)
  }

  match /threads/{threadId}/comments/{commentId} {  
    allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/comments/$(commentId)
  }

commentId被重用,因此在两个集合中它应该相同,因此我可以在规则中重用它。前面的示例显然失败了,因为要插入一个位置,我要求它已经插入到另一位置,反之亦然。

谢谢!

1 个答案:

答案 0 :(得分:0)

编辑:

云功能将更适合解决此问题。使用onCreate触发器,可以在/ threads下创建/ users后自动创建该文档。话虽这么说,但我没有云功能的旧解决方案如下:

没有云功能的解决方案:

没有与getAfter()等效的existAfter()(存在于批处理或事务处理之后用于验证数据的函数)。因此,我的操作遵循以下规则:

  match /users/{userId}/comments/{commentId} {  
    allow create: if getAfter(/databases/$(database)/documents/threads/$(request.resource.data.threadId)/comments/$(commentId)).data.author == userId;
  }

  match /threads/{threadId}/comments/{commentId} {  
    allow create: if getAfter(/databases/$(database)/documents/users/$(request.auth.uid)/comments/$(commentId)).data.createdAt == request.time;
  }

getAfter()函数将在回写之后检查有效性,并将获取该字段的值。由于我只需要检查它们是否存在,因此该字段的值并不重要。