Правила безопасности Firestore не работают должным образом - PullRequest
0 голосов
/ 09 июля 2020

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

match /UserData/{uid}/DAILY_USAGES/{day} {
  allow create: if !exists(/databases/$(database)/documents/UserData/$(request.auth.uid)/DAILY_USAGES/$(day));
  allow read, update: if request.auth.uid == uid;
}

Я смоделировал эти правила в консоли с этим путем к документу и учетными данными пользователя

/UserData/UoeJtUhPpJTi78HouKLIqhcRpfs48/DAILY_USAGES/09-07-2020

Если я создам документ с идентификатором 09-07- 2020 и смоделировать с указанным выше путем, это не удается. Когда я удаляю документ 09-07-2020, то симуляция выше работает. Так что это хорошо работает в симуляторе правил.

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

Вот код, который я использовал в android studio для создания этого документа только один раз

DailyUsage usage = new DailyUsage();
        usage.setUsage(0);
        usage.setTime(formatDate(date));
        FirebaseFirestore.getInstance().collection(Constants.USER_DATA_ROOT).document(uid)
                .collection(Constants.FIRESTORE_CHILD_DAILY_USAGES).document(today).set(usage);

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

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Метод set() имеет два поведения в зависимости от того, существует документ или нет:

Если документ не существует, он будет создан. Если документ действительно существует, его содержимое будет перезаписано вновь предоставленными данными, если вы не укажете, что данные должны быть объединены в существующий документ

Это означает, что когда документ уже существует, правило, что будет запущено правило update, поэтому вам придется изменить свое правило:

allow read, update: if request.auth.uid == uid;

, чтобы включить лог c, необходимый, когда вы вызываете set и документ существует.

Возможно, вы захотите взглянуть на этот ответ , касающийся использования set и update. Упоминается метод create , который может удовлетворить ваши потребности, но не является частью веб-API, не знаю, доступен ли он в используемом вами API.

0 голосов
/ 10 июля 2020

Благодаря @DougStevenson и @Emmanuel я четко понял ситуацию. Я думал, что set() всегда запускает правило безопасности allow create, потому что мы используем set() для создания документов и update() для обновления документов. Однако это не совсем так, set() запускает правило allow update, если ранее существовал документ с таким же идентификатором. set() также используется для обновления с параметрами слияния, и я этого не знал.

Мой вопрос касался создания документа firestore только один раз и предотвращения его воссоздания. Однако, с одной стороны, я также обновляю этот документ в некоторых ситуациях. Я хотел предотвратить перезапись документа со значением по умолчанию, равным 0. Поэтому я обновляю правила и знаю, что блокирую обновления, если значение равно 0.

match /UserData/{uid}/DAILY_USAGES/{day} {
      allow create: if !exists(/databases/$(database)/documents/UserData/$(request.auth.uid)/DAILY_USAGES/$(day));
                allow read: if request.auth.uid == uid; 
        allow update: if request.auth.uid == uid && request.resource.data.usage != 0;
    }

В приложении, которое я не делал. Ничего не менять и использовать вот так:

DailyUsage usage = new DailyUsage();
        usage.setUsage(0);
        usage.setTime(formatDate(date));
        FirebaseFirestore.getInstance().collection(Constants.USER_DATA_ROOT).document(uid)
                .collection(Constants.FIRESTORE_CHILD_DAILY_USAGES).document(today).set(usage);

Этот код срабатывает при запуске приложения, если нет документа с тем же идентификатором allow create правило безопасности срабатывает и создает документ. Но если есть документ allow update правило безопасности запускает и проверяет поступающие данные ресурса и блокирует обновление, если используется значение 0. В кодовом блоке приложения он отправляет значение 0 при запуске приложения, поэтому он не позволяет ничего обновлять. в документе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...