![](/img/trans.png)
[英]Firestore security rules how to check if document was created by user (is owner)
[英]Firestore security rules document id causing Null value error
我正在努力保护我的 Firestore 数据库,但在使用集合通配符时遇到了问题。 我有一个名为study
的根级集合,我只想在status
字段设置为“已发布”时才允许读取。
我目前的安全规则如下
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
...
function isStudyPublished(studyId) {
return get(/databases/$(database)/documents/study/$(studyId)).data.status == "published";
}
...
// Match for participant permissioning
match /study/{studyId}/{document=**} {
// Deny all requests to create, update, or delete the study
allow create, update, delete: if false
// Allow the requestor to read the study if it is published
allow read: if isStudyPublished(studyId)
}
...
}
}
此安全规则在请求单个文档时非常有效,但在执行集合级别查询时则无效。 我收到错误消息: Null value error. for 'list'
Null value error. for 'list'
。 我知道 Firestore 规则不能充当过滤器,但是,我相信我的查询应该只请求status
字段等于“已发布”的文档。
这是我的两个查询:
// successfully retrieves a single document
export const getStudy: GetStudy = (studyId) => {
return new Promise((resolve, reject) => {
getDoc(doc(firestore, COLLECTION_KEYS.STUDY, studyId))
.then((doc) => {
resolve(dataToStudy(doc.id, doc.data()));
})
.catch((error) => reject(error));
});
};
// fails to retrieve multiple documents
export const getStudies: GetStudies = (cursor) => {
const studies: StudyDoc[] = [];
return new Promise((resolve, reject) => {
let q = query(collection(firestore, COLLECTION_KEYS.STUDY), where("status", "==", "published"), orderBy(FIELD_KEYS.UPDATED));
if (cursor) q = query(q, startAfter(cursor));
getDocs(q)
.then((snapshot) => {
snapshot.forEach((doc) => {
studies.push(dataToStudy(doc.id, doc.data()));
});
return resolve([studies, snapshot.docs[snapshot.docs.length - 1]]);
})
.catch((error) => {
return reject(error);
});
});
};
我最初的想法是我的集合查询正在请求不符合安全规则的文档,但在盯着查询之后,我认为这不是真的......
作为测试,我更改了我的安全规则以测试使用调试功能的帮助会通过什么。 我最终意识到每次引用studyId
变量时检查都会失败。 例如,以下 match 语句失败。
match /study/{studyId}/{document=**} {
// Deny all requests to create, update, or delete the study
allow create, update, delete: if false
// Allow the requestor to read the study if it is published
allow read: if debug(debug(true) && (debug(studyId) != null));
}
查看firestore-debug.log
时,如果我运行请求单个文档的查询,我会看到以下记录:
bool_value: true
string_value: "rMxuVTJ0O15qPjMbpEU1"
bool_value: true
但是,在运行收集查询时会记录以下内容:
bool_value: true
我从来没有遇到过文档 id 通配符抛出这样的错误。 我无法确定这是否是我的匹配语句或查询的错误,但感谢您提供任何帮助。
我不确定您的用例到底是什么,但是在尝试从正在访问或读取的文档中读取数据时,您不必使用get()
。 您应该改用resource.data
。 请参阅下面的 Firestore 规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isStudyPublished() {
return resource.data.status == "published";
}
// Match for participant permissioning
match /study/{studyId}/{document=**} {
// Deny all requests to create, update, or delete the study
allow create, update, delete: if false
// Allow the requestor to read the study if it is published
allow read: if isStudyPublished();
}
}
}
更新:
当访问您的子集合时,您的查询应该与您的安全规则相匹配。 您应该拥有根集合的文档 ID 才能访问您的子集合。 例如:
// Document-ID refers to study's document
let q = query(collection(db, "study", <DOCUMENT-ID>, <SUBCOLLECTION-NAME>), where(<FIELDNAME>, "==", <STRING>));
安全规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /study/{studyId} {
// Deny all requests to create, update, or delete the study
allow create, update, delete: if false
// Do all restrictions here for the study collection.
function isStudyPublished() {
return get(/databases/$(database)/documents/study/$(studyId)).data.status == "published";
}
// Rules for accessing subcollection of study collection.
match /subcollection-name/{docId} {
// Allow read if the document referenced from the study collection is published.
allow read: if isStudyPublished();
// Do all restrictions here for study's subcollection.
}
}
}
}
如果study
集合中的引用文档标记为已发布,则上述示例规则将仅允许读取子集合文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.