英文:
Firebase limit update to a custom field
问题
以下是翻译好的内容:
在Firebase中,这是我的Firestore:
我正在使用此函数来更新“喜欢”:
const docRef = await doc(db, "databasetest", "explaura");
const Path = `${_Selected.Name}.Like`;
await updateDoc(docRef, {
[Path]: increment(1)
});
所以_Selected.Name是动态的(在截图上被引用为DynamicName)。
如何创建Firebase规则以仅允许“喜欢”更新?我找到了使用request.resource.data.keys().hasAll
的解决方案,但它不起作用。我可以更新DynamicName的所有子项或不更新任何子项,但无法仅更新“喜欢”。请问您能帮助我吗?
我也尝试了类似以下的内容:
match /databasetest/explaura/{id}{
allow read: if true;
allow update: if (request.resource.data.diff(resource.data).affectedKeys().hasOnly(['Like']));
}
英文:
In Firebase, here is my Firestore :
I am using this function to Update Like :
const docRef = await doc(db, "databasetest", "explaura");
const Path = `${_Selected.Name}.Like`;
await updateDoc(docRef, {
[Path]: increment(1)
});
So _Selected.Name is Dynamic (Reference as DynamicName on the screen Shot).
How can I create a Firebase rules to allow ONLY like Update ? Found solution with request.resource.data.keys().hasAll
but it's not Working. I can Update all child of DynamicName or none, but not Only "Like"
Can you help me please ?
I also Tried something like that :
match /databasetest/explaura/{id}{
allow read: if true;
allow update: if (request.resource.data.diff(resource.data).affectedKeys().hasOnly(['Like']));
}
答案1
得分: 2
所有rules.MapDiff
的方法返回一个不包含索引操作符的rules.Set
,就像rules.List
一样。这阻止了你用于你的目的(我大约两年前已经向Firebase提出了一个问题,希望他们将其添加到API中,但是至今没有任何消息,你可以自行创建一个)。
幸运的是,有一个已弃用的属性request.writeFields
,你可以使用它,它符合你的需求。它包含了所有已更改的字段(已更新、已创建、已删除):
match /databasetest/explaura/{id}{
allow read: if true;
allow update: if request.writeFields.size() == 1 // 只更新一个字段
&& validate_update();
function validate_update() {
let fields = request.writeFields[0].split('.'); // 在你的情况下,request.writeFields应该等于['DynamicName.like']
return fields.size() == 2 // ['DynamicName', 'like']
&& fields[0].size() <= 30 // 对DynamicName的某些条件
&& fields[1] == 'like' // 更新的字段只有'like'
&& request.resource.data.get(fields, 0) = 1 + resource.data.get(fields, 0) // 我们只接受增量,可以根据需要进行修改
}
}
在这里,我使用了接受数组作为参数的rules.Map.get版本来检索嵌套字段。
注意:
request.writeFields
已弃用,但仍在工作,使用时要小心。- 我猜测它已弃用,因为它在某些边缘情况下的行为可能有点奇怪,特别是对于嵌套字段。
- 尽管如此,我觉得在没有提供相同功能的新解决方案的情况下将其标记为弃用有点荒谬(向Firebase团队打招呼吧...)。
英文:
All methods of rules.MapDiff
return a rules.Set
which does not contain an index operator, like rules.List
does. This prevents using diff
for your purpose (I have created a ticket to Firebase like 2 years ago to have this added to the API but haven't got any news since, feel free to create one yourself).
Fortunatly there is a deprecated property request.writeFields
that you can use and that fits your need. It contains all the fields that have been changed (updated, created, deleted):
match /databasetest/explaura/{id}{
allow read: if true;
allow update: if request.writeFields.size() == 1 // Only one field is updated
&& validate_update();
function validate_update() {
let fields = request.writeFields[0].split('\\.'); // In your case request.writeFields should be equal to ['DynamicName.like']
return fields.size() == 2 // ['DynamicName','like']
&& fields[0].size() <= 30 // Some condition on DynamicName
&& fields[1] == 'like' // Only field updated is 'like'
&& request.resource.data.get(fields, 0) = 1 + resource.data.get(fields, 0) // We only accept increment, modify as you wish
}
}
Here I use the version of rules.Map.get accepting an array as parameter to retrieve nested fields.
Notes:
request.writeFields
is deprecated but still working, use at your own risk.- My guess is that it has been deprecated because its behavior can be a bit weird in some edge cases, especially for nested fields.
- Still, I find it crazy to mark something as deprecated when there is no new solution offering the same functionality (heads up to the firebaser here...)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论