我有关于Firestore规则的问题。
我有一个保存文档的集合...并且这些文档也有子集合....并且这些文档也有子集合。
例如
"Collection" -> "Document" -> "Sub-collection-1" -> "Document1" -> "Sub-collection-2" -> "Document2"
(i have changed the names to make it simpler to understand)
我在“文档”中存储了2个时间戳,用于控制用户何时可以阅读文档……例如它必须在“ startTimestamp”之后但在“ endTimestamp”之前。
我对此的规则如下。
allow read: if request.auth.uid != null
&& int(resource.data.startReadTimestamp) < request.time.toMillis()
&& int(resource.data.endReadTimestamp) > request.time.toMillis()
我的问题是,如果用户尝试读取子集合文档,例如基于父文档收集规则,“ Document1”或“ Document2”及其请求的时间基于“ Document”中的时间戳无效吗?
如果没有,我看到您可以将get和功能结合使用来访问其他文档,但这似乎很浪费,因为这将使我无法自拔。
例如这样做
function getTopLevelDocData() {
return get(/databases/$(database)/documents/Collection/$(documentWildcard)).data
}
我唯一想到的另一种方法是将时间戳记写入子集合中的每个文档...但这可能很难跟踪。
感谢您的帮助:)
---更新
我刚刚尝试过,它确实允许读取“ Document1”如果我不调用“ Document1”规则中的检查“ Document”时间戳的函数,则需要澄清的是将读取“ Document1”或“ Document2”只能读取1篇,因为它必须检查“文档”时间戳?
---第二次更新
想象一下上面示例中的“文档”实际上具有文档名称“ 2020-08-29”。
如果我尝试读取“ Document1”或“ Document2”,那么有一条存储规则,该规则不会引起任何文档读取,但仍会在请求时间戳(转换后)与父“文档”名称不匹配的情况下阻止读取,例如“ 2020-08-29”
例如,这样的工作可行吗?
match /collection/{document}{
match /Sub-collection-1/{document1}{
function transfomRequestTimestampToDate(){
return request.time.year() + "-" + request.time.month() + request.time.day();
}
allow read if request.auth.uid != null && transfomRequestTimestampToDate() == {document}
}
}
答案 0 :(得分:2)
我只是试过了,如果我不调用该函数,它确实允许读取...
您没有显示将问题中显示的read
安全规则应用于哪个集合,但是请注意,resource.data
指向您要阅读的resource
,因此,如果您在子集合文档中没有相应的字段,则这些文档将不适用于这些文档。
读取“ Document1”或“ Document2”只会多读1条 将必须检查“文档”时间戳?
是的,它将在每次评估安全规则时继续读取一个文档。
是的,通过使用通配符语法,您可以使用父级的文档ID来为子级编写规则,例如,如下所示:
service cloud.firestore {
match /databases/{database}/documents {
match /Collection/{parentDocId} {
allow read: if parentDocId == '2020-08-29';
match /Subcollection1/{SubcollectionDoc} {
allow read: if parentDocId == '2020-08-29';
}
}
}
}
,如果要使其动态化,可以执行以下操作:
service cloud.firestore {
match /databases/{database}/documents {
match /a/{a} {
allow read: if a == string(request.time.year()) + "-" + string(request.time.month()) + "-" + string(request.time.day());
match /b/{b} {
allow read: if a == string(request.time.year()) + "-" + string(request.time.month()) + "-" + string(request.time.day());
}
}
}
}
不过,请注意,string(request.time.day())
和string(request.time.month())
将在10月之前的几个月内返回一个字符的字符串,例如8月8日或10日之前的8天。您可以通过使用YYYY-M-D或微调安全规则来解决此问题。