我正在使用包含测验文档的Firestore应用程序数据库。每个文档可能都有一个名为peopleCanAccess的字符串数组字段。
我要在规则中做什么? 如果文档具有此字段(peopleCanAccess),则peopleCanAccess中仅存在人员可以读取该文档。如果此字段不存在,则所有经过身份验证的人员都可以访问它。
我尝试过:
function existingData() {
return resource.data;
}
function isAuthenticated() {
return request.auth != null;
}
function getUid() {
return request.auth.uid;
}
function fieldExists(data, field) {
return !isUndefined(data, field) && !isNull(data, field);
}
function isUndefined(data, field) {
return !data.keys().hasAll([field]);
}
function isNull(data, field) {
return data[field] == null;
}
match /quiz/{quizID}{
allow read : if
(isAuthenticated() && existingData().owner == getUid())
|| (isAuthenticated() && !('peopleCanAccess' in existingData().keys()))
|| (isAuthenticated() && getUid() in existingData().peopleCanAccess)
// !fieldExists(resource.data, 'peopleCanAccess');
...
}
这些规则无法正常工作。
示例: 身份为tcsFStMdplOJSyZsluJBLHeOuJs1的用户尽管未在peopleCanAccess字段中列出,但仍可以访问上图中提到的测验
查询:
db.collection("quiz")
.whereEqualTo("id", quizId)
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
if (queryDocumentSnapshots.isEmpty()){
}else {
QuizItem quizItem = queryDocumentSnapshots.getDocuments().get(0).toObject(QuizItem.class);
accessedQuiz.postValue(quizItem);
}
}
});
答案 0 :(得分:1)
最后,我找到了解决方案,
我在Rule Playground中检查了规则,但我的规则没有发现任何问题。它工作正常,问题出在我的客户查询中。 我在文档中找到了这一点:
在编写查询以检索文档时,请记住安全性 规则不是过滤器-查询全部或全部。为了节省您的时间, 资源,Cloud Firestore根据潜在查询评估查询 结果集,而不是所有您的实际字段值 文件。如果查询可能返回文档, 客户端没有读取权限,整个请求失败。
注意:您可以将读取规则分为get和list规则。获取规则 适用于单个文件的请求,而列表规则适用于 查询和索取要求。
我如何解决我的问题:
1-打破读写规则:
match /quiz/{quizID}{
allow get : if
(isAuthenticated() && getUid() in existingData().peopleCanAccess)
||
(isAuthenticated() && !checkIfExistsInKeys(existingData(), 'peopleCanAccess'))
allow list : if
(isAuthenticated() && getUid() == existingData().owner)
allow create : if (isAuthenticated() && getUid() == existingData().owner);
allow update : if (isAuthenticated() && getUid() == existingData().owner);
allow delete : if (isAuthenticated() && getUid() == existingData().owner);
}
2-更改我的客户查询以检索一个文档:
db.collection("quiz")
.document(quizId)
.get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (!documentSnapshot.exists()){
}else {
QuizItem quizItem = documentSnapshot.toObject(QuizItem.class);
accessedQuiz.postValue(quizItem);
}
}
});