新创建文档的子集合“权限不足或权限不足”

时间:2018-10-05 22:24:00

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

我开发了第一个Firestore应用程序,但实际上并没有意识到我没有构建权限模型,实际上我后来将它绑定了。 (如果这是问题的根源,我很乐意就权限最佳做法和/或如何更好地实施权限规则提供反馈)。

作为数据模型,我在事件下方的集合中有顶级的“事件”文档和“注释”文档,并且(事后)我创建了权限规则,以允许用户创建事件时编辑注释。 (请参见下文。)

现在,当在iOS上测试代码时,该应用程序将创建一个事件文档,然后不久便尝试将快照侦听器添加到notes子集合。它收到“缺少权限或权限不足”错误(当然,在未强制执行权限时并没有。)

此事件的创建是在列出所有事件的视图控制器中完成的,然后快照侦听器查询在推送的视图控制器中(在segue之后)发生。如果我弹出子视图控制器,然后再次对其进行推送,则可以正常工作。

令人困惑的是,它并非每次都发生,而是断断续续的。我想知道权限和新创建的事件文档之间是否发生了某些竞争情况。 (如果我在重试之前添加了一个简短的间隔,则在下一次尝试时它可以正常工作。)

Firebase Firestore版本0.13.4,Swift 4,Xcode 10.0

(编辑:实际上相同的代码在Android上不会失败,并且在脱机时也可以使用。)

相关权限在这里:

// Access granted... via ownership
function accessGranted() {
  return resource.data.userId == request.auth.uid;
}
function accessGrantedTo(container,rootId) {
  return get(/databases/$(database)/documents/$(container)/$(rootId)).data.userId == request.auth.uid;
}

// Events...
match /events/{event} {
  allow read, update, delete: if accessGranted();
  allow create: if request.auth.uid != null;
}
match /events/{event}/notes/{note} {
  allow read, update, delete: if accessGrantedTo("events",event);
  allow create: if accessGrantedTo("events",event);
}

1 个答案:

答案 0 :(得分:0)

上个月,我在Google Firebase Firestore支持[4-6103000026011]中探讨了此主题。经过多次关于“对象尚不存在,等待回调等”的反复讨论,最终将其提升为工程设计,最终解决方案是“按设计工作”。就我个人而言,我认为是非确定性行为(有时会工作,有时会失败)基于设备速度和竞争状况。也就是说,可能不支持我的情况,因此我在这里进行记录,以防它对其他人有帮助。

正如我所看到的……从存储的角度来看,方法调用返回后,Firestore可能在本地完成,但是其规则实现却没有。 在我添加权限规则之前一切正常,然后事情变得不确定。

在此客户端中创建/监听的每个对象都是由该客户端本地的同一客户端创建的,但由于权限原因而失败,但可以“在片刻/重试后”工作。

请记住,这可能是一个艰难的情况,我很可能是通过我的要求和规则选择而造成了这个问题。注意:

  • 我无法利用Firestore回调,因为它们仅在设备在线且数据已同步到服务器时才触发。在方法返回后,Firestore即已(本地)完成,即对象在方法返回后就存在,因此“无需等待回调”。 [恕我直言:回叫在现实世界(尤其是间歇性的移动设备在线世界)中价值不高,我出于好奇心仅将其用于故障排除。我在方法规范中看到了它们,未能深入了解它们的时机,并假设它们用于正常使用情况而使用它们,并在脱机时被咬住了……而他们没有被调用。我假设我不是唯一的开发人员。]注意:我也不确定回调是否仅通过花费一定的时间(而不是通过它们表示的内部操作)来“解决”问题。
  • 我认识到这些规则是“有趣的”(使用函数来遍历层次结构),但是我使用Firestore的文档和示例创建了这些规则。 (我选择不简化它们,如支持所建议的那样,将所有者属性放在较低的对象上,因为事实上,我希望进一步扩展它们以满足我的业务案例……允许团队处理数据,而不是只是创造者。)
  • 我确实知道该代码正在创建对象X,然后立即尝试侦听未创建的X子集合(即(我假设)为我创建)的更新。我确实询问支持人员,是否有办法创建该子集合以删除那里的任何竞争条件,但未作为解决方案提供。 (也就是说,当不涉及这些权限规则时,它可以正常工作,因此它“存在”。)

长话短说,我添加了一个严重的错误:“如果侦听刚创建的代码,并且遇到权限失败错误,请重试(有限次数)”…该代码似乎在第二次尝试中成功。 Bugly,我并不感到骄傲,而是“工作”。

顺便说一句:我确实创建了一个独立的示例来重现这一点。它是iOS(尽管Android也失败了,并且在Android提供的自动测试虚拟机上最可靠地失败了。)

代码:Standalone iOS code - Github Repository

规则:Rule Set - Github Gist