Правила базы данных Firebase - разрешать неаутентифицированным пользователям только отфильтрованные запросы - PullRequest
1 голос
/ 10 ноября 2019

У меня есть база данных Google Firestore в реальном времени, которая содержит флаг isPublic. Если установлено значение true, дочерний узел details может быть прочитан неаутентифицированными пользователями. Если установлено значение false, доступ к записи может получить только один (на данный момент) авторизованный и авторизованный пользователь.

Только авторизованный пользователь имеет разрешение на запись.

Кроме того,дочерний узел private всегда предоставляет доступ только одному авторизованному пользователю.

Решение, которое я изучил, основано на правилах, основанных на запросах https://firebase.google.com/docs/database/security/securing-data#query-based_rules К сожалению, я получаю ответ permission_denied,даже как авторизованный пользователь.

Информация в стороне: это в проекте Vue JS, использующем Firebase SDK.

Вот пример моей базы данных.

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

Второй вообще не должен показываться неаутентифицированным пользователям, заставляя ихчтобы выполнить запрос dbRef.orderByChild('isPublic').equalTo(true)

"products": {
  "-pushIdxyz1" : {
    "isPublic" : true,

    "private" : {
      "notes" : "lorem ipsum always private",
      "soldDate" : ""
    },

    "details" : {
      "imageURL" : "https://firebasestorage.imagexyz",
      "keywords" : "this, that",
      "title" : "Public product title",
      "workCategory" : "hardware",
    },
  },
  "-pushIdxyz2" : {
    "isPublic" : false,

    "private" : {
      "notes" : "lorem ipsum always private",
      "soldDate" : ""
    },

    "details" : {
      "imageURL" : "https://firebasestorage.imagexyz",
      "keywords" : "this, that",
      "title" : "Secret product title",
      "workCategory" : "hardware",
    },
  }
}

И мои неработающие правила

"rules": {
  "products": {
    "$product_id": {
      ".indexOn": "isPublic",
      ".read": "query.equalTo == true || auth.uid == '[admin user id]'"
      // alternative attempt
      // ".read": "(query.orderByChild == 'isPublic' && query.equalTo == true) || auth.uid == '[admin user id]'",
      ,
      ".write": "auth.uid == '[admin user id]'",

      "details": {
        ".read": true,
      },
      "private": {
        ".read": "auth.uid == '[admin user id]'",
      }
    }
  }
}

Этот запрос для неавторизованных пользователей должен предоставить доступ на чтение к дочернему узлу сведений:

firebase.database().ref('products').orderByChild('isPublic').equalTo(true).once('value')
  .then(...)

Этот запрос, только для авторизованного пользователя, должен предоставить доступ на чтение ко всем данным

firebase.database().ref('products').once('value')
  .then(...)

При текущей настройке я получаю «разрешение запрещено» для любого запроса, зарегистрированного какавторизованный пользователь или нет.

1 Ответ

0 голосов
/ 10 ноября 2019

Если вы хотите, чтобы пользователь мог читать с узла products, вам необходимо иметь правило .read на этом узле. И поскольку вы хотите разрешить чтение только в том случае, если это запрос для общедоступных продуктов, вам следует проверить этот конкретный запрос.

Примерно так:

"rules": {
  "products": {
    ".indexOn": "isPublic",
    ".read": "(query.orderBy == 'isPublic' && query.equalTo == true)
              || auth.uid == '[admin user id]'"
  }
}

Итак:

  1. Вы определили правило на один уровень слишком низко, что означает, что все чтения на /products были отклонены.
  2. Ваше правило не проверяло поле orderBy.

Обратите внимание, что дополнительное правило .read, которое вы объявили для private, здесь не имеет смысла, так как тот же пользователь уже получил разрешение на чтение на всем узле `products.

...