【问题标题】:Firestore can read through collection('users') but not doc('users/{id}')Firestore 可以读取 collection('users') 但不能读取 doc('users/{id}')
【发布时间】:2020-04-01 20:24:59
【问题描述】:

我正在使用@react-native-firebase/firestore

我必须以错误的方式思考集合或文档,但如果直接通过doc 获取文档时被拒绝,我希望以下安全规则阻止我通过onSnapshot 获取文档,但事实并非如此案例

// I get permission denied when doing this
firestore().doc('users/KRImYj0Lrmv00P9KRAuJ').get()

// I do not get permission denied when doing this and can access the document I can't get above
firestore().collection('users').onSnapshot() 

安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read: if resource.data.is_deleted == false
      allow write: if false;
    }
  }
}

更新完整代码

// FIRST
try {
  await firestore()
    .collection('users')
    .where('is_deleted', '==', true)
    .onSnapshot((snapshot) => {
      if (snapshot) {
        snapshot.forEach((s) => {
          console.log('User', s.data())
        })
      }
    })
}
catch (error) {
  console.log(error)
}
// SECOND
try {
  const docs = await firestore()
    .collection('users')
    .where('is_deleted', '==', true)
    .get()

  console.log(docs)
}
catch (error) {
  console.log(error)
}

第一个返回快照,我可以记录文档

FIRST LOGS

User {"fname": "Steve", "is_deleted": true, "lname": "Kaspar", "name": "Steven Kaspar", "name_change_count": 2}
User {"fname": "Brian", "is_deleted": true, "lname": "Fitz"}


SECOND LOGS

[Error: [firestore/permission-denied] The caller does not have permission to execute the specified operation.]

【问题讨论】:

  • 我很困惑 - 你是说 get() 是不允许的,但 onSnapshot() 是允许的?请编辑问题以明确什么是有效的。
  • @DougStevenson - 抱歉,恰恰相反。我不能get() 但我可以通过onSnapshot() 得到它
  • 我根本不希望第二个查询起作用,因为它缺少 is_deleted==false 的过滤器。请确保您的规则已保存并且您的查询是正确的。另外,如果您有其他规则,请务必在此处显示。
  • @DougStevenson - 这就是我所期待的。这是整个规则集,所以我不知道接下来要尝试什么。继续打破并重试,直到它起作用我猜哈哈
  • 同意 Doug 的观点:这看起来很奇怪。一些帮助调试的步骤: 1) 你可以尝试在集合上做一个get() 而不是onSnapshot() 吗? 2) 你能编辑显示你如何处理onSnapshot()吗?我特别好奇您是否/如何处理错误。

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


【解决方案1】:

我怀疑在onSnapshot 的情况下,结果来自本地缓存,在您禁止读取操作之前已填充。

这是onSnapshot 的正常行为:如果请求的文档在缓存中,它会立即触发,如果服务器上的文档不同,则可能会再次触发。而且由于安全规则只在服务器上执行,如果缓存中有数据,第一次回调总是会发生。

另一方面,get() 调用 立即 尝试从服务器获取文档。在您的情况下,这会拒绝读取操作。您可以通过执行get({ source: 'cache' }) 来验证这一点,这将从缓存中读取文档,并且很可能会成功,原因与onSnapshot 所做的相同。

我建议通过卸载并重新安装应用程序来清除本地缓存,这样它就不会包含用户(现在)不再有权访问的文档。

【讨论】:

  • 我昨天尝试擦除模拟器的内容,以为可能是这种情况,但它似乎没有做任何事情。我今天将尝试再次重置设备并再次运行以查看更改是否生效。我支持你——我认为缓存在某种程度上是个问题
  • 好的,所以我重置了设备并在 react-native 缓存上做了 --reset-cache。现在,onSnapshot 永远不会返回任何结果(快照为空)。我想这是预期的行为?我希望它会以同样的方式失败,我猜会出现权限错误,但也许它悄悄失败是有原因的?
  • 很高兴听到您摆脱了缓存。 Internet 连接的间歇性丢失是预期行为,因此不会将其视为onSnapshot 的错误情况。您可以检查您的侦听器获取的任何快照是否来自服务器(或至少保证与服务器同步),这通常是您用来向用户显示一些关于他们的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-17
  • 2022-11-28
  • 2022-11-10
  • 1970-01-01
相关资源
最近更新 更多