Firestore: правило userId - PullRequest
       7

Firestore: правило userId

0 голосов
/ 09 апреля 2019

Я не могу заставить работать это правило пожарного депо.

Я хочу написать / прочитать user-read-only/USER-ID-HERE/business/settings

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

    match /user-read-only/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;

      match /{document=**} {
        allow read, update, delete: if request.auth.uid == userId;
        allow create: if request.auth.uid != null;
      }
    }
  }
}

Я продолжаю получать сообщение

FirebaseError: отсутствуют или недостаточные разрешения.

Я пробовал много разных подходов с симулятором, и все они успешны, но я не могу воспроизвести из своего приложения.


  • Выше что-то выглядит неправильно?
  • Можно ли упростить вышесказанное?Я бы хотел, чтобы пользователь мог контролировать все, кроме {userId}
  • Как узнать, правильно ли заполнены request.auth.uid и userId?

Этоработает

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

    match /{userId}/{document=**} {
      allow read, write;
    }
  }
}

не работает

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

    match /{userId}/{document=**} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Применяли ли вы правила безопасности?

См .: https://firebase.google.com/docs/firestore/security/get-started#deploying_rules

Прежде чем вы сможете начать использовать Cloud Firestore из своего мобильного приложения, вам нужно будет развернуть правила безопасности. Вы можете развернуть правила в консоли Firebase или с помощью интерфейса командной строки Firebase.

Вы вошли в систему, используя Firebase Authentication?

См .: https://firebase.google.com/docs/firestore/security/rules-conditions

Если ваше приложение использует Firebase Authentication, переменная request.auth содержит информацию об аутентификации для клиента, запрашивающего данные. Для получения дополнительной информации о request.auth см. Справочную документацию.

Как вы вызываете метод Firestore?

См:

Как это?

var userId = firebase.auth().currentUser.uid
var docRef = db.doc(`user-read-only/${userId}/business/settings`);

docRef.get().then(function(doc) {
    if (doc.exists) {
        console.log("Document data:", doc.data());
    } else {
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});

Я думаю, вам следует изменить данные структуры.

Данные структуры должны иметь вид db.collection('coll').doc('doc').collection('subcoll').doc('subdoc').

(Collections->doc->SubCollections->SubDoc->SubSubCollections->SubSubDoc)

Так что {userId} должен быть docId. Не коллекции.

Правила безопасности должны быть такими.

  match /databases/{database}/documents {

    match /users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;

      match /settings/{setting} {
        allow read, update, delete: if request.auth.uid == userId;
        allow create: if request.auth.uid != null;
      }
  }
}

Код коллекции настроек: db.collection('users').doc(userId).collection('settings').

Если не работает, вам следует попробовать базовые наборы правил.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}
1 голос
/ 09 апреля 2019

Обновление после вашего комментария «Намерение состоит в том, чтобы расширить правило, чтобы пользователь мог управлять чем-либо, кроме {userId}»:

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

    match /user-read-only/{userId}/{document=**} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;

    }
  }
}

Просто обратите внимание, что правило create ( скопировано из вашего вопроса ) позволяет любому аутентифицированному пользователю писать в любую папку {userId}.


(Напротив, если вы просто хотите объявить правило для business/settings sub-collection и doc), нужно выполнить следующее:

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

    match /user-read-only/{userId}/business/settings {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;

    }
  }
}

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

allow create: if request.auth.uid != null && request.auth.uid == request.resource.data.userId;

С другой стороны, Firebase Auth автоматически гарантирует, что request.auth.uid заполнен правильно.

Наконец, вы можете посмотреть это очень хорошее видео от команды Firebase о правилах безопасности: https://www.youtube.com/watch?v=eW5MdE3ZcAw


Вот HTML-страница, используемая для тестирования. Просто измените значение userId с другим идентификатором пользователя.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <script src="https://www.gstatic.com/firebasejs/5.9.3/firebase.js"></script>

    <script>
      // Initialize Firebase
      var config = {
        apiKey: 'xxxxx',
        authDomain: 'xxxxx',
        databaseURL: 'xxxxx',
        projectId: 'xxxxx'
      };
      firebase.initializeApp(config);

      firebase
        .auth()
        .signInWithEmailAndPassword('xxxxxx@gmail.com', 'yyyyyyy')
        .then(userCredential => {

          const userId = userCredential.user.uid;
          // Replace with another userId to test
          //e.g. const userId = 'l5Wk7UQGRCkdu1OILxHG6MksUUn2';

          firebase
            .firestore()
            .doc('user-read-only/' + userId + '/business/settings4')
            .set({ tempo: 'aaaaaaa' })
            .then(() => {
              return firebase
                .firestore()
                .doc(
                  'user-read-only/' + userId + '/testC/1/collec/2'
                )
                .get();
            })
            .then(function(doc) {
              if (doc.exists) {
                console.log('Document data:', doc.data());
              } else {
                // doc.data() will be undefined in this case
                console.log('No such document!');
              }
            })
            .catch(function(error) {
              console.log('Error getting document:', error);
            });
        });
    </script>
  </head>

  <body>
  </body>
</html>
...