在Firestore安全规则“列表”操作中使用变量

时间:2019-01-31 05:11:36

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

我正在尝试根据子集合中document字段的值设置允许访问集合的安全规则。

按ID检索单个文档(这是get操作)时,可以按预期工作。但是,在查询main_collectionlist操作)时,此操作失败,并显示“权限被拒绝”错误。由于集合中只有一个文档,因此在没有我对某些要查询的文档(例如在this question上)没有权限的情况下。

我的数据库结构如下所示。它包含列出的集合(main_collection),该集合具有一个文档(some_doc),该集合具有一个子集合(sub_collection),该子集合具有一个文档({{1} }。

another_doc

/main_collection/some_doc/sub_collection/another_doc有一个字符串字段another_doc

对于此示例,我的查询涉及整个集合,即单个文档。在我的实际应用程序中,它仅查询期望访问的文档,但是最终结果是相同的,因为我无法从客户端库中过滤文档的子集合。

someFieldValue

这些是我的安全规则。

firestore.collection('main_collection').get()

service cloud.firestore { match /databases/{database}/documents { match /main_collection/{mainColDoc} { // This operation works allow get: if subCollectionDocumentHasField('someFieldValue'); // This operation fails with permission denied allow list: if subCollectionDocumentHasField('someFieldValue'); // This checks for the existence of a field on the subcollection's document function subCollectionDocumentHasField(fieldName) { return get(/databases/$(database)/documents/main_collection/$(mainColDoc)/sub_collection/another_doc).data.keys().hasAny([fieldName]); //return get(/databases/$(database)/documents/main_collection/some_doc/sub_collection/another_doc).data.keys().hasAny([fieldName]); } } } } 函数检查文档subCollectionDocumentHasFieldsomeFieldValue字段是否存在。在此函数中,如果将another_doc变量替换为硬编码的文档ID $(mainColDoc),则some_doc操作成功。由于list路径变量可以在这种情况下使用,因此我希望其他变量也可以使用。

这是错误还是预期的行为?

3 个答案:

答案 0 :(得分:0)

This is actually the expected behavior, you can't use Firebase's rules to filter the results of your query.


A typical scenario would be to have collection of messages, where each message refers to its creator.

You can't simply add a rule where reading is only allowed on messages for which creator is the authenticated user, to filter automatically the messages of the current authenticated user.

The only way to go is to query with filter on the client side (or through a Cloud function).


The documentation is very clear about this :

When writing queries to retrieve documents, keep in mind that security rules are not filters—queries are all or nothing. To save you time and resources, Cloud Firestore evaluates a query against its potential result set instead of the actual field values for all of your documents. If a query could potentially return documents that the client does not have permission to read, the entire request fails.

From Firebase's documentation

答案 1 :(得分:0)

我向Google开了张罚单,并有效地确认了@José的使用情况,这是安全规则“每个查询仅检查一次”。

为澄清起见,尽管list操作上的安全规则通常查询文档的内容(以避免潜在的性能降低),但在以下情况下至少存在一种情况:它查询文档的内容。这是保证仅返回一个文档的安全规则。满足此保证条件后,将查询单个文档的内容,因为可以保持高性能。与get操作相同。

因此,在我的问题的链接示例中,list操作的规则正在引用父文档,因此可以满足此保证,并且将查询父文档的内容。

另外,在我的示例中,list操作的规则引用的是硬编码文档ID,则可以满足此保证,并且可以查询硬编码文档的内容。

出于明确说明的目的,对于list操作,在Firestore无法保证其规则仅查询单个文档的任何情况下,设计都会自动拒绝访问。

答案 2 :(得分:0)

重申其他答案所说的内容,但以略有不同的方式陈述:查询必须符合安全规则,在查看任何查询文档之前,否则将因许可而失败拒绝。

例如,如果子集合中的所有文档碰巧都匹配安全规则(例如,您的创建和列表规则都要求 owner 字段为“X” ),查询仍然必须符合安全规则(例如,查询还必须过滤 owner 是“X”),否则它将失败并出现权限被拒绝错误,与子集合的实际内容无关。