Firestore匹配规则,用于在另一个集合中的文档中查找数据

时间:2019-05-19 18:35:50

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

当权限存储在另一个集合的另一个文档中时,Firestore规则出现问题。我还没有找到任何这样的例子,但是我已经读到可以做到的。

我想这样做是为了避免当一个学生与许多其他学生共享作业列表时不得不进行大量写操作。是的,我知道这算作另一读。

我有3个集合,用户,权限和家庭作业以及一些示例数据。

用户

{
    id:  fK3ddutEpD2qQqRMXNW,
    name: "Steven Smith"
},

{
    id:  YI2Fx656kkkk25,
    name: "Becky Kinsley"
},

{
    id:  CAFDSDFR244bb,
    name: "Tonya Benz"
}

权限

{
    id:  fK3ddutEpD2qQqRMXNW,
    followers: [YI2Fx656kkkk25,CAFDSDFR244bb]  
}

家庭作业

{
    id:  adfsajkfsk4444,
    owner:  fK3ddutEpD2qQqRMXNW,
    name: "Math Homework",
    isDone: false
}

我的Firestore规则的开始:

 service cloud.firestore {

//lock down the entire firestore then open rules up.
  match /databases/{database}/documents {

    match /{document=**} {
      allow read, write: if false;
    }

match /homework/{      } {
      allow get: if isSignedIn()

    }

// helper functions
    function isSignedIn() {
      return request.auth != null;
    }

    function isUser(userId) {
      return request.auth.uid == userId;
    }

    function isOwner(userId) {
        return request.auth.uid == resource.data.uid;
    }

  }
}

用例:

史蒂芬·史密斯(Steven Smith)与托尼亚·本茨(Tonya Benz)分享了他的作业清单。

Tonya Benz登录到该应用程序以查看她的朋友Steven的作业。该应用程序运行此查询以获取史蒂文·史密斯的作业列表。

var homeworkRef = db.collection("homework");
var query = homeworkRef.where("owner", "==", "fK3ddutEpD2qQqRMXNW");

问题:
正确的Firestore匹配规则是什么,当用户Tonya Benz登录后,该数据会从作业集合中的“所有者”字段中作为权限集合中的id查找,以便可以运行此查询。

1 个答案:

答案 0 :(得分:1)

使用当前的查询和数据库结构,您将无法使用安全规则实现目标。

首先,听起来您希望能够根据另一个文档的内容过滤查询结果。安全规则不能充当查询过滤器。 所有必须通过安全规则授予与查询匹配的文档的读取访问权限,否则整个查询将被拒绝。您将需要提出一个查询,该查询具体说明应允许访问哪些文档。不幸的是,没有单个查询可以对您当前的结构执行此操作,因为这将需要在权限和作业之间进行某种“联接”。但是Firestore(像所有NoSQL数据库一样)不支持联接。

您将需要以与规则兼容的方式对数据建模。您可以想到一种选择。

您可以将应该阅读的列表用户存储在作业中的特定文档中,该文档位于同一文档内,并以列表字段表示。该查询可以基于该列表字段中用户的uid存在来指定过滤器。并且该规则可以指定仅向ID出现在该列表中的用户授予读取访问权限。

{
    id:  adfsajkfsk4444,
    owner:  fK3ddutEpD2qQqRMXNW,
    name: "Math Homework",
    isDone: false,
    readers: [ 'list', 'of', 'userids' ]  // filter against this list field
}

这里的底线是您需要满足以下两个要求:

  1. 您的查询需要具体说明确切哪些文档希望可读。您不能使用规则来过滤结果。
  2. 您的规则需要一种方法来确定对当前uid的访问权限,而无需使用比文档本身或其他已知文档上的get()更复杂的字段。