[英]Firestore security rules document id causing Null value error
I am working on securing my Firestore database and am having trouble with a collection wildcard.我正在努力保护我的 Firestore 数据库,但在使用集合通配符时遇到了问题。 I have a root-level collection called
study
, I want to allow reads only if the status
field is set to "published".我有一个名为
study
的根级集合,我只想在status
字段设置为“已发布”时才允许读取。
My current security rules are as follows我目前的安全规则如下
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)
}
...
}
}
This security rule works great when requesting a single document, but not when doing a collection-level query.此安全规则在请求单个文档时非常有效,但在执行集合级别查询时则无效。 I get the error message:
Null value error. for 'list'
我收到错误消息:
Null value error. for 'list'
Null value error. for 'list'
. Null value error. for 'list'
。 I understand that Firestore rules do not act as a filter, however, I believe my query should only be requesting documents where the status
field equals "published".我知道 Firestore 规则不能充当过滤器,但是,我相信我的查询应该只请求
status
字段等于“已发布”的文档。
Here are my two queries:这是我的两个查询:
// 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);
});
});
};
My initial thought is that my collection query was requesting documents that would fail the security rules, but after staring at the query I don't think that's true...我最初的想法是我的集合查询正在请求不符合安全规则的文档,但在盯着查询之后,我认为这不是真的......
As a test, I changed up my security rules to test what would pass using the help of the debug function .作为测试,我更改了我的安全规则以测试使用调试功能的帮助会通过什么。 I ended up realizing that the check fails every time I reference the
studyId
variable.我最终意识到每次引用
studyId
变量时检查都会失败。 As an example the following match statement fails.例如,以下 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));
}
When looking at the firestore-debug.log
, if I run the query that requests a single document I see the following logged:查看
firestore-debug.log
时,如果我运行请求单个文档的查询,我会看到以下记录:
bool_value: true
string_value: "rMxuVTJ0O15qPjMbpEU1"
bool_value: true
however, when running the collection query the following is logged:但是,在运行收集查询时会记录以下内容:
bool_value: true
I've never run into the document id wildcard throwing an error like this.我从来没有遇到过文档 id 通配符抛出这样的错误。 I can't determine if this is an error with my match statement or my query, but any help is appreciated.
我无法确定这是否是我的匹配语句或查询的错误,但感谢您提供任何帮助。
I'm not sure what your use-case really is but you don't have to use get()
when trying to read data from the document being accessed or read.我不确定您的用例到底是什么,但是在尝试从正在访问或读取的文档中读取数据时,您不必使用
get()
。 You should use resource.data
instead.您应该改用
resource.data
。 See Firestore Rule below:请参阅下面的 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();
}
}
}
UPDATE:更新:
When accessing your subcollection, your query should be matched with your security rules.当访问您的子集合时,您的查询应该与您的安全规则相匹配。 You should have the document ID of the root collection to access your subcollection.
您应该拥有根集合的文档 ID 才能访问您的子集合。 Eg:
例如:
// Document-ID refers to study's document
let q = query(collection(db, "study", <DOCUMENT-ID>, <SUBCOLLECTION-NAME>), where(<FIELDNAME>, "==", <STRING>));
Security rules:安全规则:
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.
}
}
}
}
The sample rule above will only allow reads to the subcollection documents if the referenced document from the study
collection is tagged as published.如果
study
集合中的引用文档标记为已发布,则上述示例规则将仅允许读取子集合文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.