Firestore安全规则:在文档中的数组中搜索用户的id

Mav*_*eck 23 firebase google-cloud-firestore

首先,对不起我可怕的英语,这不是我的母语......

我正在使用Firestore数据库在Firebase中构建一个简单的应用程序.在我的应用中,用户是小组的成员.他们可以访问其他用户的数据.为了不查询太多文档(每个用户一个,在组文档的子集合中),我选择将用户的数据添加到组文档中的数组中.这是我小组的文件:

{
   "name":"fefefefe",
   "days":[false,false,false,false,true],
   "members":[
       {"email":"eee@ff.com","id":"aaaaaaaa","name":"Mavireck"}, 
       {"email":"eee2@ff.com","id":"bbbbbbbb","name":"Mavireck2"}, 
   ],
}
Run Code Online (Sandbox Code Playgroud)

如果用户在组中,如何检查安全规则?我应该使用对象吗?我真的不想为用户使用子集合,因为我会很快达到免费配额限制...

感谢您的时间 !

编辑:谢谢你的回答.我将其更改为一个对象:"成员":{uid1:{},uid2:{}}

Mik*_*ald 25

通常,您需要编写如下规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /collection/{documentId} {
      // works if `members` = [uid1, uid2, uid3]
      // no way to iterate over a collection and check members
      allow read: if request.auth.uid in resource.data.members;
      // you could also have `members` = {uid1: {}, uid2: {}}
      allow read: if resource.data.members[request.auth.uid] != null;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用子集:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow a user to read a message if the user is in the room
    match /rooms/{roomId} {
      match /documents/{documentId} {
        allow read: if exists(/databases/$(database)/documents/documents/$(documentId)/users/$(request.auth.uid));
      }
      match /users/{userId} {
        // rules to allow users to operate on a document
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


cal*_*res 16

我用这段代码实现了它

如果同一用户存在于另一个集合的数组中,则允许某些用户读取/写入集合的某些文档

service cloud.firestore {
  match /databases/{database}/documents {
    match /repositories/{accountId} {
      allow read, write: if request.auth.uid in get(/databases/$(database)/documents/accounts/$(accountId)).data.users
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 您在规则中使用了 `get()` 函数,这将导致额外读取定价。这意味着即使您的规则拒绝请求,您也会为 **阅读文档** 付费。https://firebase.google.com/docs/firestore/security/rules-conditions#access_other_documents (4认同)
  • 这对我来说是新的!很高兴知道。 (2认同)
  • @Mikes 下面的答案无需额外阅读即可完成此操作,但仅在您访问该特定资源时才有效。这个答案适用于访问的任何资源。 (2认同)

小智 6

只是提供替代解决方案。就我而言,我存储两个单独的字段。在你的情况下,它将是:

"membersSummary":[
  {"email":"eee@ff.com","id":"aaaaaaaa","name":"Mavireck"}, 
  {"email":"eee2@ff.com","id":"bbbbbbbb","name":"Mavireck2"}, 
],
"members": ["aaaaaaaa", "bbbbbbbb"]
Run Code Online (Sandbox Code Playgroud)

我知道这不一定是最佳的,但由于我们使用的是 firebase,我认为我们可以在文档中使用非规范化数据。

我将使用该members字段进行集合查询和 firestore 规则(allow read: if request.auth.uid in resource.data.members;按照上面 Mike 的回答),并使用该字段membersSummary在 UI 中呈现信息或使用其他字段进行其他类型的处理。

如果您使用 uid 作为键,那么如果您想查询一个集合并列出该用户所属的所有文档,并按名称对它们进行排序,那么 firebase 将需要为每个 uid 一个单独的复合索引,除非您有一个固定的用户组(极不可能)基本上会导致您的应用程序崩溃。

我真的不喜欢仅仅为了访问控制而读取额外文档的想法,但如果您更喜欢这种方法来跟踪两个单独的相关字段,那么就这样做。没有完美的解决方案——只是提供另一种可能性,有其优点和缺点。