Правила безопасности Firestore: не могу понять, почему некоторые правила работают/не работают


Моя база данных firestore структурирована таким образом, что" лиги " являются верхней коллекцией, и каждая лига содержит поле, названное после каждого утвержденного идентификатора пользователя (с числовым значением).

Каждая лига также имеет подколлекцию "пользователи" документов, названных после каждого утвержденного идентификатора пользователя.

Вот пример запроса firestore:

FirebaseAuth mAuth = FirebaseAuth.getInstance();

// userId = ABCDEF123 for this example
String userId = mAuth.getCurrentUser().getUid();

FirebaseFirestore firestore = FirebaseFirestore.getInstance();
firestore.collection("leagues").whereLessThan(userId, 99).get();

Может кто-нибудь объяснить мне, почему это правило работает:

match /leagues/{league} {
    allow read, write: if resource.data.ABCDEF123 != null;

Но не это:

match /leagues/{league} {
    allow read, write: if resource.data.request.auth.uid != null;

Также, почему делает это правило работает:

//"ZYXWV987" is an example of a league the user is in
match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$('ZYXWV987')/users/$(request.auth.uid));

Но не это:

match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));

Ошибка, которую я получаю, - " com.гугл.опорному пункту.пожарный магазин.FirebaseFirestoreException: PERMISSION_DENIED: отсутствуют или недостаточны разрешения "

Я хочу понять, как работают эти правила, и, следовательно, как реализовать правильные правила для моей базы данных!

Редактировать:

Теперь я понимаю, что это работает (все еще НЗП):

match /leagues/{league} { 
    allow read, create, update: if request.auth.uid != null; 

    //only ever deleting a single league at a time 
    allow delete: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));

    match /{docs = **} { 
        allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid))} 
}

И я вроде как понимаю, что происходит (я не могу использовать подстановочный знак {league} при чтении/записи потенциально более одной лиги в запросе?), но я все еще не совсем уверен, почему?

1 2

1 ответ:

Может кто-нибудь объяснить мне, почему это правило работает:

match /leagues/{league} {
    allow read, write: if resource.data.ABCDEF123 != null;

Но не это:

match /leagues/{league} {
    allow read, write: if resource.data.request.auth.uid != null;

Я думаю, что в resource.data нет поля с именем request. Как синтаксис точки должен знать, что вы хотите оценить последнюю часть (запрос.автор.uid) сначала и использовать результат в качестве следующего ключа? Я не уверен, но вы могли бы попробовать resource.data[request.auth.uid] вместо этого.

Также, почему это правило работает:

// "ZYXWV987" is an example of a league the user is in 
match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$('ZYXWV987')/users/$(request.auth.uid));

Но не это:

match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));

Из документов по безопасности правила :

Каждый запрос базы данных от мобильного/веб-клиента Cloud Firestore библиотека оценивается в соответствии с вашими правилами безопасностираньше чтение или запись любых данных.

Оценивается первое правило, и в зависимости от результата пользователю разрешается читать все или ни одного документа Лиги. Второе правило должно быть оценено для каждого отдельного документа В зависимости от содержания. Это невозможно до их прочтения все.

Вы должны определить свои правила безопасности таким образом, чтобы Firestore мог оценивать их только на основе определения вашего запроса, независимо от возможного результата.