我重新安排了Cloud Firestore的安全规则,以防止重新生成集合中的文档。这是我使用的规则:
match /UserData/{uid}/DAILY_USAGES/{day} {
allow create: if !exists(/databases/$(database)/documents/UserData/$(request.auth.uid)/DAILY_USAGES/$(day));
allow read, update: if request.auth.uid == uid;
}
我使用这些文档路径和用户凭据在控制台中模拟了此规则
/UserData/UoeJtUhPpJTi78HouKLIqhcRpfs48/DAILY_USAGES/09-07-2020
如果我创建一个ID为09-07-2020的文档并使用上述路径进行模拟,则它将失败。当我删除文档09-07-2020时,可以进行上述模拟。因此,它在规则模拟器中效果很好。
但是,当我在应用程序中尝试时,每次尝试时它都会再次创建文档。因此,如果文档内容以前有所不同,它将重置为用于创建文档的默认值。
这是我在android studio中仅用于一次创建此文档的代码
DailyUsage usage = new DailyUsage();
usage.setUsage(0);
usage.setTime(formatDate(date));
FirebaseFirestore.getInstance().collection(Constants.USER_DATA_ROOT).document(uid)
.collection(Constants.FIRESTORE_CHILD_DAILY_USAGES).document(today).set(usage);
我不想检查文档是否以前存在,因为它会使ui变慢,并且无法按我预期的那样工作。因此,我尝试使用安全规则来防止重新生成文档,但无法在应用程序上工作。有人可以帮忙吗?
答案 0 :(得分:1)
根据文档是否存在,set()
method有两种行为:
如果文档不存在,将创建该文档。如果文档确实存在,除非您指定将数据合并到现有文档中,否则其内容将被新提供的数据覆盖
这意味着当文档已经存在时,将要触发的规则将是update
规则,因此您将必须更改规则:
allow read, update: if request.auth.uid == uid;
包括在调用set且文档存在时必需的逻辑。
您可能想看一下answer,有关设置和更新的用法。提到create
method可能很适合您的需求,但它不是Web API的一部分,不知道您所使用的API是否可用。
答案 1 :(得分:0)
由于@DougStevenson和@Emmanuel,我清楚地了解了这种情况。我以为set()
总是触发allow create
安全规则,因为我们使用set()
创建文档,并使用update()
更新文档。但是,这并非完全正确,如果之前有相同ID的文档,则set()
会触发allow update
规则。 set()
还用于更新合并选项,我不知道。
我的问题是关于只创建一次Firestore文档并阻止其重新创建。但是,一方面,我还在某些情况下更新了此文档。我想防止使用默认值0覆盖文档。因此,我更新了规则,并且知道如果值是0,我将阻止更新。
match /UserData/{uid}/DAILY_USAGES/{day} {
allow create: if !exists(/databases/$(database)/documents/UserData/$(request.auth.uid)/DAILY_USAGES/$(day));
allow read: if request.auth.uid == uid;
allow update: if request.auth.uid == uid && request.resource.data.usage != 0;
}
在应用程序中,我没有进行任何更改,并使用了这样的方法:
DailyUsage usage = new DailyUsage();
usage.setUsage(0);
usage.setTime(formatDate(date));
FirebaseFirestore.getInstance().collection(Constants.USER_DATA_ROOT).document(uid)
.collection(Constants.FIRESTORE_CHILD_DAILY_USAGES).document(today).set(usage);
如果没有相同ID allow create
安全规则的文档触发,则此代码将在应用启动时触发并创建该文档。但是,如果有文档allow update
,安全规则将触发并检查即将到来的资源数据,并在使用率值为0时阻止更新。在应用程序的代码块中,当应用程序启动时,它将值发送为0,因此不允许更新文档中的所有内容。