Правило get () Firestore работает в симуляторе, но не в приложении - PullRequest
1 голос
/ 17 июня 2020


Я пытаюсь создать правило firestore, которое будет проверять, является ли пользователь владельцем «родительской» коллекции.

У меня такая структура:


   collection of -> [Diets]
        document -> (owner : "owner")
                      |
   subCollection -> [Food]
        document -> (name : "Carrot")

Я хотел бы иметь возможность читать и писать документы в подколлекции [Food], используя свойства do c документа [Diet].


Эта версия работает, но она проверяет только запрошенный источник, он не всегда проверяет [Diet].

rules_version = '2';
service cloud.firestore {
    match /databases/{database}/documents{
        match /diets/{id}/{id2=**} {
            allow read, write: if resource.data.owner == request.auth.uid;
        }
    }
}


Эта версия не будет работать, даже если родитель (сама Diet do c) является запрошенный источник. Разве это решение не должно быть таким же, как и предыдущее при проверке DO C внутри диет?

rules_version = '2';
service cloud.firestore {
    match /databases/{database}/documents{
        match /diets/{id}/{id2=**} {
            allow read, write: if get(/databases/$(database)/documents/diets/$(id)).data.owner == request.auth.uid;
        }
    }
}

Разве это решение не должно работать так же, как предыдущее, при проверке Документ диеты?

Он работает в симуляторе, и все выглядит нормально, даже при запросе документов субколлекций, но я получил «FirebaseError: Отсутствуют или недостаточные разрешения» ошибка в моем app.


Это код моего приложения.

firebase.firestore().collection("diets").where("owner", "==", this.userID).get()
.then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        console.log(doc);
        console.log(doc.id, " => ", doc.data());    
    });
})
.catch(function(error) {
    console.log("Error getting documents: ", error);
});

1 Ответ

0 голосов
/ 17 июня 2020

Симулятор консоли может моделировать только отдельные документы. В настоящее время он не может имитировать запросы на сбор, которые обрабатываются по-разному.

Проблема, с которой вы столкнулись, заключается в том, что правила безопасности не являются фильтрами . Я настоятельно рекомендую прочитать эту документацию и эту статью . Причина, по которой ваше первое правило работает, заключается в том, что правило может очень легко проверить, соответствует ли фильтр вашего запроса этим ограничениям в правиле для всех возможных возвращаемых документов. Запрос не может когда-либо требовать чего-либо большего, чем четко разрешает правило. Однако, когда вы задействуете get(), правило не будет оценивать это get() для каждого документа в коллекции, так как это будет очень медленно с большими коллекциями. Он не будет пытаться фильтровать документы, проверяя результат get() для каждого из них.

Правило работает для отдельных документов, получаемых, потому что фильтрация не задействована - только один проверка документов - что вполне соответствует возможностям правила в массовом масштабе.

И снова уловка состоит в том, чтобы увидеть это с точки зрения правил в массовом масштабе. Если у вас есть миллиарды документов в коллекции, проверка каждого из них по отдельности будет просто неэффективной, поэтому правило просто отклоняет ее. Правило может только проверять соответствие фильтров запроса заданным c ограничениям правила без проверки каждого документа.

...