我有两个集合-租约和用户。
租户文档的字段名为“ landlordID”,类型为REFERENCE(不是String)。
现在,在我的Firestore安全规则中,仅当租约的landlordID字段与发出请求的用户的uid(即request.auth.uid
)匹配时,我才希望允许更新租约。
将其读取为“如果使用户身份经过认证的租户文档得以更新,则request.auth.uid!= null,并且landlordID字段的ID应与request.auth.uid的ID相等。
因此代码应该是这样的:
service cloud.firestore {
match /databases/{database}/documents {
match /tenancies/{tenancyID}{
allow update: if request.auth.uid != null &&
request.auth.uid == get(resource.data.landlordID).id
}
}
我也尝试过get(/databases/$(database)/documents/users/$(resource.data.landlordID)).data.id
支持我的数据库的屏幕截图
这应该非常简单,但是get()根本不起作用。 Firebase Docs, scroll to "Access other documents"对我的情况完全没有帮助,我不确定如何使它正常工作。
如果引用不能像文档的任何其他字段那样使用,将是一种耻辱。
答案 0 :(得分:3)
我在这里看到几个问题。第一个问题是get()函数需要一个完整指定的文件路径,例如:
get(/databases/$(database)/documents/users/$(resource.data.landlordID)).data.id
第二个问题是您正在尝试在规则中使用引用类型,不幸的是,我认为这不可能。
Firestore中的引用类型不是非常有用(还),我认为您应该将地主ID存储为字符串,然后可以简单地执行以下操作:
service cloud.firestore {
match /databases/{database}/documents {
match /tenancies/{tenancyID}{
allow update: if request.auth.uid != resource.data.landlordID;
}
}
答案 1 :(得分:2)
可能为时已晚,但是我能够拼凑(尽管缺少文档)文档引用只是一条路径,并且可以使用以下方式创建完整的路径
/databases/$(database)/documents/users/$(request.auth.uid)
然后我在引用的存储区中有一个数组/列表,称为reads
,可以用来抓取:
get(/databases/$(database)/documents/users/$(userId)/userinfo/granted_users).data.reads
让我能够创建布尔值和规则:
/databases/$(database)/documents/users/$(request.auth.uid) in get(/databases/$(database)/documents/users/$(userId)/userinfo/granted_users).data.reads
显然,您的数据结构会有所不同,但是了解ref是路径是这里的重要部分。
答案 2 :(得分:1)
我有一个同样的问题,我需要一个答案。参见this Google-thread以及Google某人的回答。引用它:
您可以使用“ index”运算符从路径中获取ID:
some_document_ref
应该看起来像/databases/(default)/documents/foo/bar
有5个细分:
["databases", "(default)", ...]
some_document_ref[4]
应该是“栏” 允许创建:if request.resource.data.some_document_ref [4] ==“ bar”;您还可以在其上使用常规的
get
和exists
函数。您可能会遇到的一些困难方面:
目前无法检索路径中的段数(我们即将添加),因此您需要提前了解有关参考的一些信息
< / li>对于在Firebase控制台中使用模拟器编写参考的支持不大。我使用Firestore模拟器测试了此行为(gist1,gist2)
答案 3 :(得分:1)
我必须做一些尝试才能使它正常工作。这对我有用的功能
function isUserRef(database, userId) {
return 'user' in resource.data
&& resource.data.user == /databases/$(database)/documents/users/$(userId);
}
我这样称呼它:
match /answers/{answer} {
allow read:
if isUserRef(database, request.auth.uid);
}
答案 4 :(得分:0)
这是我创建的对我有用的功能。我猜您有一个用户集合,这些用户的id
与他们的auth.uid
function isUserRef(field) {
return field in resource.data
&& resource.data[field] == /databases/$(database)/documents/users/$(request.auth.uid)
}
根据用例进行调整,可以这样调用该函数:isUserRef('landlordID')
,尽管其末尾的ID有点误导,因为该字段实际上是参考。
答案 5 :(得分:0)
正如其他一些答案所提到的,引用有一个 path
属性,它只是一个看起来像 users/randomuserid123
的字符串。您可以将其拆分为一个数组,并将其与发出更新请求的用户进行匹配。
...
match /tenancies/{tenancyID}{
allow update: if request.auth.uid != null &&
resource.data.landlordID.path.split('/') == ['users', request.auth.uid]
}
...