是否可以只允许推入数组字段(在文档中),但阻止写入该数组中的任何现有值?
myDocument: {
myArray: [
"value1",
"value2"
]
}
我想在
"value3"
中添加myArray
。我打算使用 firestore 文档中提出的这种方法
但我想阻止除上述之外的
myArray
字段的任何其他更新,并且我没有找到一种优雅的方法来使用云 Firestore 安全规则来执行此操作。
是否有办法接受
myArray
字段的更新(如果使用 arrayUnion
进行更新)并阻止所有其他更新请求?
因为永远不会太晚!
这是我的解决方案!为了仅允许使用 arrayUnion 更新字段,我使用了两件事:
.size()
检查用户是否正在更新数组仅添加一个元素,因此我检查新数组的大小是否等于旧数组的大小 + 1 👌request.resource.data.offers.size() == resource.data.offers.size() + 1
.hasAll
确保用户仅添加新值而不编辑现有值(非常重要的一点⚠️)request.resource.data.offers.hasAll(resource.data.offers)
提供的最终版本是我的数组,他们只接受
arrayUnion
作为更新👇
match /swaps/{swapId} {
allow create: if request.auth != null;
allow read: if request.auth != null;
allow update: if (
request.resource.data.offers.size() == resource.data.offers.size() + 1
&& request.resource.data.offers.hasAll(resource.data.offers)
);
allow delete: if false;
}
这是最全面的解决方案,可以确保以下几点:
只添加了一项
该项目已添加到数组的末尾
现有数组项尚未更改或重新排列
match /winners/{gameId} {
// Not really important stuff:
allow create: if false; // I'm creating documents with a cloud function, don't want users to create them with random data.
allow delete: if false;
allow read: if request.auth != null;
// THE IMPORTANT STUFF:
allow update: if
request.auth != null // Not really important to the question, but I always make sure users are authenticated.
&&
(
request.resource.data.winners.size() == resource.data.winners.size() + 1 // Ensure only one item was added.
&&
resource.data.winners == request.resource.data.winners[0:resource.data.winners.size()] // This is the most important part - make sure the original array is contained in the first part of the new array. See notes below for more info how it works.
);
}
关键是从新列表创建一个子列表并将其与原始列表进行比较(数组在安全规则中称为列表)。子列表需要与原始列表的长度相同,因此我们使用 range 运算符
[i:j]
从新列表创建子列表,从索引 0
开始,与原始列表具有相同的长度。请注意,文档当前是错误的,称范围运算符需要两个索引。根据我的测试,它确实需要一个起始索引和许多元素来包含。
这是我基于@Trev14 答案的解决方案。
let stored = resource.data.myArray;
let incoming = request.resource.data.myArray;
return incoming is list
&& incoming.size() == stored.size() + 1
&& (stored.size() == 0 || incoming[0:stored.size()] == stored)
在
stored.size() == 0
时允许更新对我来说很重要,因为列表可能为空。由于某种原因,incoming[0:0]
不能等于 stored
。