Правила безопасности Firebase для ограничения доступа по всем путям, кроме одного?

Вопрос:

Как ограничить доступ ко всем, кроме одного, путям для различных коллекций топок верхнего уровня, представленных ниже?

Мы создаем схему данных в Firestore для поддержки приложения чата для учителей из нескольких школ.

Коллекции верхнего уровня включают:

  • /siteAdminUsers
  • /schools
  • /schools/{schoolId}/teachers
  • /schools/{schoolId}/chats

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

  1. действительный идентификатор пользователя
  2. ожидаемое значение существует в переменной userClaim request.auth.token.chatFlatList

Тем не менее, читатель для чтения /messages блокируется.

Сообщение об ошибке:

FirebaseError: [code= access-denied]: отсутствует или недостаточно разрешений


service cloud.firestore {
  match /databases/{database}/documents {

    match /{document=**} {
      allow read, write: if false;
    }

    match /schools/{schoolId}/chats/{discussionId}/messages {
      allow write: if false;
      allow read: if request.auth != null
                  && request.auth.token != null
                  && request.auth.token.chatFlatList.val().contains($discussionId);
    }
}

подробности

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

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

Примечания суб-коллекции:

В школе проводятся дискуссионные сессии для школьного персонала (учителей, администраторов и т. Д.).

/schools/{schoolId}/chats/{discussionId}

Где каждый дискуссионный документ содержит:

  1. список учителей участников
  2. Подколлекция для фактических сообщений, где каждый документ является отдельным опубликованным сообщением:

/schools/{schoolId}/chats/{discussionId}/messages

Код заявки пользователя из облачной функции

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

return firebaseAdmin
    .auth()
    .setCustomUserClaims(
        uid, {
            chatFlatList: 'id1 id2 id3'
        }
    );

ОБНОВЛЕНИЕ № 1

Попробовал следующий вариант, где правила пропускают / опускают проверку userClaim и auth.token.

Тем не менее, все еще та же ошибка разрешения.

service cloud.firestore {
  match /databases/{database}/documents {

        match /{document=**} {
          allow read, write: if false;
        }

        match /schools/{schoolId}/chats/{discussionId}/messages {
          allow write: if false;
          allow read: if request.auth != null;
        }

    }
}

1 ответ

Решение

Я думаю, что проблема в том, что вы пишете правило для коллекции, называемой сообщениями.

Все заявления о совпадении должны указывать на документы, а не на коллекции. https://firebase.google.com/docs/firestore/security/rules-structure

Вы должны попытаться добавить /{document=**} после вашего пути к сообщениям, что-то вроде:

    match /schools/{schoolId}/chats/{discussionId}/messages/{document=**} {
      allow write: if false;
      allow read: if request.auth != null;
    }

Это сработало для меня, если я хотел прочитать и записать всю коллекцию, но не одну коллекцию с именем "backStage";

rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{collection}/{document} {
          allow read: if true
          allow write: if (collection != "backStage");
        }
      }
    }

Вот решение (кажется, работает), которое включает в себя проверку на chatFlatList переменная заявки пользователя (из исходного вопроса) для подстроки:

        match /schools/{schoolId}/chats/{discussionId}/messages {
          allow write: if false;
          allow read: if request.auth != null
          && request.auth.token.chatFlatList.matches(discussionId);
        }

Понял это благодаря:

  1. Правила хранения Firebase на основе пользовательских параметров

    • Здесь пост показывает, что нет никакого $ запись для доступа к пути вар. Я помню, как видел это в примере кода с правилами безопасности - может быть, это относится к уровням базы данных?
  2. https://firebase.google.com/docs/reference/security/storage/

  3. https://regex-golang.appspot.com/assets/html/index.html

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