Я получаю свои документы на основе списка идентификаторов.
db.collection("fruits").where(db.FieldPath.documentId(), "in", fruitIds).get()
Как мне написать свои правила безопасности, чтобы разрешить вышеуказанный вызов и отклонить приведенный ниже вызов
db.collection("fruits").get()
Это невозможно именно так, как вы требуете. Что вы можете сделать, так это установить свои правила следующим образом:
match /fruits/{id} {
allow get: true;
allow list: false;
}
Это позволяет клиентам получить документ, если им известен идентификатор, но делает невозможным массовый запрос документов.
Затем вам нужно будет закодировать запрос клиентского приложения для каждого документа отдельно с помощью DocumentReference get()
(вместо запроса с предложением where). Снижение производительности при этом незначительно (нет, нет никакого заметного прироста производительности при использовании запроса "in" так, как вы здесь показываете, и в любом случае вы ограничены 10 документами в пакете).
@sleepystar96 Нет, это не сработает. request.data
нет. См. определение Объект запроса. Кроме того, нет никакого способа сделать то, что вы предлагаете.
А, ты прав, спасибо @Doug
Поскольку @Дуг описан в их ответ, в настоящее время он не поддерживается должным образом.
Однако, глядя на Справка, вы можете, по крайней мере, ограничить операции list
(запрос), наложив условия на orderBy
и limit
, используемые любыми запросами, чтобы усложнить их, а не полностью блокировать.
Считайте этот ответ образовательным, вместо этого просто извлекайте элементы один за другим и отключите доступ к списку/запросу в своих правилах безопасности. Он включен сюда для тех, кто просто хочет запутать, а не напрямую блокировать такие запросы.
Это будет означать изменение вашего запроса на:
db.collection("fruits")
.where(db.FieldPath.documentId(), "in", fruitIds)
.orderBy(db.FieldPath.documentId()) // probably implicitly added by the where() above, but put here for good measure
.limit(10) // this limit applies to `in` operations anyway, but for this to work needs to be added
.get()
service cloud.firestore {
match /databases/{database}/documents {
// Matches any document in the cities collection as well as any document
// in a subcollection.
match /fruits/{fruit} {
allow read: if <condition>
// Limit documents per request to 10 and only if they provide an orderBy clause
allow list: if <condition>
&& request.query.limit <= 10
&& request.query.orderBy = "__name asc" // __name is FieldPath.documentId()
allow write: if <condition>;
}
}
}
Используя эти ограничения, это больше не должно работать:
db.collection("fruits").get()
Но вы все равно можете очистить все более мелкими фрагментами, используя:
const fruits = [];
const baseQuery = db.collection("fruits")
.orderBy(db.FieldPath.documentId())
.limit(10);
while (true) {
const snapshot = await (fruits.length > 0
? baseQuery.startAt(fruits[fruits.length-1]).get()
: baseQuery.get())
Array.prototype.push.apply(fruits, snapshot.docs);
if (snapshot.empty) {
break;
}
}
// here, fruits now contains all snapshots in the collection
Это хорошее решение, но не могли бы они также сделать
allow read: if request.data.id != null
?