【问题标题】:Firestore Invalid Permissions: request.auth.uid inFirestore 无效权限:request.auth.uid in
【发布时间】:2018-01-29 07:23:54
【问题描述】:

我正在使用 Cloud Firestore,但我似乎无法让“IN”运算符使用安全规则。我尝试过使用数组和地图,但都不起作用。当然,当我将其设置为 allow read, write; 时,它工作正常。我做错了什么?

规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /rooms/{roomId=**} { 
      allow read, write: if request.auth.uid in resource.data.users;
      allow read, write: if request.auth.uid in resource.data.users2;
      allow create: if request.auth != null;
    }
    match /user-rooms/{userId} { 
      allow read, write: if userId == request.auth.uid;
    }
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
      allow get, create: if request.auth != null;
    }
  }
}

客户:

db.collection("rooms")
  .document(self.room.getRoomId())
  .collection("messages")
  .addSnapshotListener { .....

//Room is: d6l946swspNSouANzVdZ
//Username is: eX8gkxJNDREv

【问题讨论】:

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


    【解决方案1】:

    data 将返回它的直接子级而不是子级(用户和用户2)所以你应该使用getexists 而不是in

    match /rooms/{roomId=**} { 
      allow read, write: if request.auth.uid in get(/databases/$(database)/documents/rooms/$(roomId)/users/$(request.auth.uid)).data;
      allow read, write: if exists(/databases/$(database)/documents/rooms/$(roomId)/users2/$(request.auth.uid));
      allow create: if request.auth != null;
    }
    

    查看doc

    【讨论】:

    • 你是说users和users2的数组值是子子项吗?与原始字符串相反?因此,如果我只有两个可能的用户进行身份验证,我可以只做resource.data.fromUser == request.auth.uid || resource.data.toUser == request.auth.uid(无需通过使用get() 来读取数据库)?
    • 对于我之前的评论,没有。似乎唯一有效的方法是使用get() 获取resource.data。我不明白 Firestore 的这个限制......
    【解决方案2】:

    您正在尝试访问 resource.data 中不存在的名为“users”的变量。 resource 变量包含来自当前正在写入数据库的对象的数据。

    您可能想要做的是检查此用户是否存在于usersusers2 字段中,这可以通过规则来实现:

    match /rooms/{roomId=**}{
        allow read, write:  if (exists(/databases/$(database)/documents/rooms/$(roomId)/users2/$(request.auth.uid)) || 
                             request.auth.uid in get(/databases/$(database)/documents/rooms/$(roomId)).data.users);
        allow create: if request.auth!=null;
    }
    

    【讨论】:

    • 好的,但我很抱歉这对我来说仍然没有意义。 “该资源代表一个 Cloud Firestore 文档。它包含 存储resource.data 的文档中的字段和值的映射。”文档看起来好像 request.resource.data 是正在写入的数据,而 resource.data 是已经存储在 firestore 数据库中的数据。至少我是这样解释文档的。为什么我必须 get() Firestore db 应该已经拥有的资源(来自它的内部查询)是没有意义的。
    • 你的理解是正确的。 resource.data 是已经存储的内容(如果您正在更新数据)。如果您不更新现有数据,它将不存在。
    • 看我的截图,数据已经有了! ...除非您说写入不会先执行读取,因此 resource.data 是空的?编辑:不,实际上不可能这样。我正在尝试读取测试中的数据。 EDIT2:那么您是说resource.data 在任何读取操作中都为空?
    • 假设您的数据库中有一个名为 user 的文档。使用名称字段(假设其值为“Ryan”)。然后你想更新这个字段成为“Rosario”。 request.resource.data 将包含“Rosario”,resource.data 将包含“Ryan”。它仅包含有关正在更新/写入的字段的数据,并且在此字段之外没有其他任何内容。
    • 那么你是说resource.data 在任何读操作中都是空的吗?因为我正在查看docsallow read: if resource.data.keys().hasAll(['name', 'age']) 显然意味着读取操作确实填充了resource.data,我应该能够对数据进行一些验证,而不必使用get() 获取资源。还是没有?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多