#google-cloud-firestore #firebase-security
#google-облако-firestore #firebase-безопасность
Вопрос:
Это должно быть довольно просто, но я столкнулся с проблемой чтения иерархических данных в Firestore. Взяв пример из официальной документации и немного адаптировав его, я…
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read: if resource.data.visible == true;
// Explicitly define rules for the 'landmarks' subcollection
match /landmarks/{landmark} {
allow read: if get(/databases/$(database)/documents/cities/$(city)/landmarks/$(landmark)).data.promoted == true;
}
}
}
}
Похоже, это способ выразить правило чтения на более низких уровнях, где условие основано на значении поля во вложенных данных, но, к сожалению, это не работает. Кто-нибудь знает правильный способ сделать это?
Ответ №1:
Firestore может следовать этому правилу в лучшем случае только для get
одного документа, а не list
для коллекции. «Правила безопасности — это не фильтры» — это мантра здесь: правила безопасности НЕ будут просто проходить через документы, которые соответствуют правилам, блокируя те, которые не соответствуют; если запрос может привести к блокировке файла, весь ЗАПРОС будет отклонен. Поскольку единственным документом, который может быть разрешен, будет один.get() документа
использование get() в правилах безопасности должно указывать один документ, даже если запрос предназначен для коллекции. Таким образом, единственным способом, которым могло бы работать подобное правило, было бы:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read: if resource.data.visible == true;
// Explicitly define rules for the 'landmarks' subcollection
match /landmarks/{landmark} {
allow read: if resource.data.promoted == true;
}
}
}
}
к нему можно получить доступ с помощью .get() одного documentRef, который, оказывается promoted
, установлен, или
collectionRef..where(field:'promoted', opStr:'==', value:'true')
таким образом, чтобы условие запроса соответствовало условию правила безопасности, то есть запрос фильтрует документы таким образом, чтобы все они соответствовали правилу безопасности.
Комментарии:
1. Спасибо. Я пробовал это с несколькими вариантами. Я использую Swift, но синтаксис запроса такой
ref.collection(cities).document("Paris").collection(landmarks).document("Eiffel Tower").whereField("promoted", isEqualTo: true).getDocuments() {...
. Нет проблем, когда правило нижеallow read: if true
. Устранение неполадок — сложная задача. Есть идеи, как действовать дальше?2. предложения .where() применяются только к операциям со СПИСКОМ (т. Е. К Коллекции), поэтому обычно мы рассматриваем
ref.collection(cities).document("Paris").collection(landmarks).whereField("promoted", isEqualTo: true).getDocuments() {...
.where() определяет подмножество документов, которые должны быть возвращены. Они не являются «более низким уровнем». В вашем примере будут возвращены все «знаковые» документы, помеченные как «повышенные». Вы пытаетесь получить все города , в которых есть повышенные ориентиры?3. Да, я понимаю, что a
where
делает в запросе. Цель запроса здесь — найти все продвигаемые достопримечательности в одном городе, например, в Париже. Затем запрос соответствуетif
инструкции в правиле безопасности.4. ОПЯТЬ ЖЕ — Правила безопасности не являются фильтрами — они НЕ будут выбирать одни документы, а не другие, либо разрешены ВСЕ записи в запросе, либо НЕТ. Ваш ЗАПРОС — это фильтр; правило безопасности — ваша защита.
5. «Нижнее правило» НЕ будет действовать как фильтр.