firebase - Firestore 安全规则:如何确保文档中值的唯一性?
问题描述
在配置文件集合中创建文档之前,以下安全规则能否确保名字、姓氏、用户名和电子邮件的唯一性?
match /profiles/{document=**} {
allow create: if request.auth.uid != null
&& (request.resource.data.firstName is string && resource.data.firstName != request.resource.data.firstName)
&& (request.resource.data.lastName is string && resource.data.firstName != request.resource.data.firstName)
&& (request.resource.data.username is string && resource.data.username != request.resource.data.username)
&& (request.resource.data.email is string && resource.data.email != request.resource.data.email)
}
例如,以下是 Firestore 收集配置文件中的数据
{
"document1":{
"firstName":"Jek",
"lastName":"Choo",
"email":"jeksomething@gmail.com",
"username":"jek"
},
"document2":{
"firstName":"Cara",
"lastName":"Choo",
"email":"babycara@gmail.com",
"username":"cara"
}
}
我想创建下面的新文档,应该拒绝这个创建访问
{
"document3":{
"firstName":"Jek",
"lastName":"Choo",
"email":"jeksomething@gmail.com",
"username":"jek"
}
}
我想创建下面的新文档,这应该是允许的。
{
"document4":{
"firstName":"example",
"lastName":"com",
"email":"test@example.com",
"username":"example"
}
}
总之,上述firestore安全规则是否有助于在允许创建文档之前确保字段值的唯一性?
解决方案
了解resource
创建新文档的规则的作用很重要,这是您在此处显示的唯一规则。
resource
指“正在编写的(现有)文档”。request.resource
如果写入成功,这与描述尚不存在的文档形成对比,即即将存在的文档。
换句话说,在本节中:
resource 变量引用请求的文档,resource.data 是存储在文档中的所有字段和值的映射。
在创建的情况下,没有正在写入的现有文档。因此,您可以假设任何匹配resource
失败。因此,这将无法确保唯一性。
实际上,您无法确保创建时任何给定文档字段的唯一性,因为在安全规则中不可能查询集合中的所有文档是否存在该字段。
Firestore 观察到的唯一形式是集合中文档的 id。该文档的所有字段不能被安全规则限制为唯一,并且 Firestore 中没有确保唯一性的索引。
如果您需要一个字段唯一,您应该在创建文档后使用 Cloud Function 触发器进行检查,如果不满足要求则删除该文档。
推荐阅读
- javascript - 卡在 NullPointer 异常
- deployment - Wildfly : ClassNotFoundException: org.apache.xerces.parsers.SAXParser 部署时
- c++ - 在 C++ 中使用 RegSetValueEx() 附加到用户环境变量
- python - 连接 Google BigQuery 时遇到问题
- android - 如何在 android Studio 中将 Postgresql 与 Android 应用程序连接,然后将应用程序数据插入数据库表?
- python - 未找到带有参数“(”,)”的“后详细信息”的反向。尝试了 1 种模式:['post/(?P
[0-9]+)/$'] - azure - CosmoDB 序列生成器
- c++ - 此代码来自 Geeks for Geeks 网站关于 BFS
- javascript - 无法在手机中使用网络摄像头,但在 PC 中可以正常使用
- django - ReactJS API 调用 Django REST - 使用 IP 还是 localhost?