Правило Firestore работает на детской площадке, но не по внешнему запросу - PullRequest
1 голос
/ 17 апреля 2020

У меня есть приложение Android (Kotlin) (min SDK версия 26), которое использует Google Firebase. В частности, я использую Firestore. У меня есть правило, которое работает на игровой площадке, но не из моего приложения, и я не могу понять, почему.

Вот правило, о котором идет речь:

match /events/{eventId}
    allow delete, update: if get(/databases/$(database)/documents/organisations/$(resource.data.organisationId)).data.access[request.auth.uid] == 'admin'
}

А вот код вызова:

db.collection("events").document(event.id)
    .delete()
    .addOnSuccessListener { _ ->

    }
    .addOnFailureListener { deleteResult ->
        println("-----> FAIL DELETE EVENT: $deleteResult")
    }

Как вы можете сказать из правила, разрешения для события определяются ролью пользователя в родительской организации события. В этом случае я использую одного и того же пользователя на игровой площадке правил и внутри приложения, поэтому проблем с разрешениями определенно не существует. У меня такое ощущение, что эта проблема как-то связана с "правила не являются фильтрами" , но я не совсем уверен, что изменить ...

Спасибо

ОБНОВЛЕНО, чтобы включить скриншоты базы данных и UID ниже:

Ниже показано, как я извлекаю все события для указанных c organisationId и l oop поверх тех, которые нужно удалить. Перед удалением я печатаю пользовательские auth.uid, eventId и organisationId.

db.collection("events")
    .whereEqualTo("organisationId", selectedOrganisationId)
    .get()
    .addOnSuccessListener { result ->
        for (event in result) {
            println("------ USER UID: ${currentUser?.uid}, EVENT ID: ${event.id} , ORG ID: ${event.get("organisationId")}")
            db.collection("events").document(event.id)
                .delete()
                .addOnSuccessListener { _ ->

                }
                .addOnFailureListener { deleteResult ->
                    println("-----> FAIL DELETE EVENT: $deleteResult")
                }
        }
    }
    .addOnFailureListener { result ->
        println("-----> FAIL GET EVENTS TO DELETE: $result")
    }

Ниже показан вывод println, содержащий идентификаторы:

I / System.out: ------ UID пользователя: lCagHz9IFSUoGp6eBhrr70HgUOp2, идентификатор события: gkf7FRq0gP0wHiCqhTVE, идентификатор ORG: Wh1YkTmWptuDtaMKb2k6

10: 10 * *1029* 1030 1030

I / System.out: -----> СОБЫТИЕ УДАЛИТЬ СБОЙ: com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: отсутствуют или отсутствуют разрешения.

Вот некоторые скриншоты базы данных Firestore, в которых показаны существующие идентификаторы и структура: Organisations Event

Еще одно обновление: просто быстро отметим, что если я изменю правило на allow delete, update: if true, правильные события будут удалены. Поэтому я абсолютно точно пытаюсь удалить правильные документы.

Ответы [ 2 ]

2 голосов
/ 18 апреля 2020

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

  1. Мой root - /61272476, просто потому, что я использую тот же проект для многих других тестов.
  2. Правила, которые я создал для него:
    match /61272476/{doc=**} {
        match /events/{eventId} {
            allow read: if get(/databases/$(database)/documents/61272476/README/organisations/$(resource.data.organisationId)).data.access[request.auth.uid] == 'admin'
        }
    }
    
    Вы заметите, что я сделал это read правилом, просто чтобы его было проще тестировать.
  3. Документ организации выглядит следующим образом:

    enter image description here

  4. Документ мероприятия, который я тестировал:

    enter image description here

  5. И наконец: код, который я тестировал:

    firebase.auth().onAuthStateChanged(function(user) {
      if (!user) {
        console.log("Signing in...");
        firebase.auth().signInAnonymously();
      }
      else {
        console.log("Signed in user "+user.uid);
        var db = firebase.firestore();
        var ref = db.doc("61272476/README/events/event1").get().then(function(doc) {
          console.log("Got document", doc.data());
        }).catch(function(error) {
          console.error(error);
        });
      }
    });
    

Вы также можете найти код в рабочей форме здесь: https://jsbin.com/rotefez/edit?js, консоль

Когда я удаляю UID из поля access в организации, чтение отклоняется. Когда я добавляю его обратно, чтение снова разрешается.

На данный момент я понятия не имею, чем отличается ваш случай. Я проверил событие, смог ли я удалить документ при предоставлении разрешения delete, и это тоже сработало, как и ожидалось.

На данный момент лучшее, что я могу порекомендовать, это попытаться воспроизвести это в другом проекте. аналогично тому, что я сделал здесь.

0 голосов
/ 20 апреля 2020

Итак, мне удалось выяснить это. Я думаю, что это было бы быстрым решением для @FrankvanPuffelen, если бы я включил код, который запускается сразу после удаления событий.

API-интерфейс Firestore Kotlin является асинхронным. Сразу после удаления всех событий, связанных с организацией, но код вызывает удаление самой организации; это так, что при удалении организации мы удаляем все документы, которые будут ссылаться на организацию.

То, что происходило, это то, что события удаления и , которые удаляли организации, вызывались практически одновременно. Удаление организаций завершится, по-видимому, даже до первого удаления событий (вероятно, потому что правила событий содержат дополнительные запросы к коллекции организаций). Это будет означать, что к тому времени, когда будет выполнен запрос на разрешения организации из правила событий, организация больше не будет существовать, поэтому запрос не будет выполнен, и у нас больше нет разрешения на удаление события.

...