0
votes

I have a problem with creating rules in firestore.

This is my example: collection "users" -> many docs -> not every doc has inside, the subcollection with name "recipes". If subcollection "recipes" exists then it has docs with some data. One of them is "public" with type of boolean.

My problem: I want to get all recipes from all users, if condition of "public" is true.

Im stack at rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow write: if request.auth != null && request.auth.uid == userId;
      match /recipes/{recipeId} {
            allow read: if resource.data.public == "true";
        }
    }
  }
}

enter image description here

And it shows me: Error: simulator.rules line [9], column [21]. Null value error.

In this case, how should I get/call this data with clean javascript? If i just get some scripts like firebase.firestore() or firebase.auth().

2
The problem description is not very clear to me. It would be more helpful if you showed actual document contents, as well as the query in the client code that should be allowed or rejected by the rule in specific situations. - Doug Stevenson
I edited post. You can check foto and code - Nienormalny_
I want to show every recipe with public true. And it doesn't matter if user/viewer is logged-in/authenticated or not. - Nienormalny_
You can put a filter on the query using a where clause. That's pretty straightforward according to the documentation on queries. Rules will not filter the results for you. - Doug Stevenson
@Doug could you share the mentioned documentation please? - Soni Sol

2 Answers

2
votes

for those they are searching for solution. I found one! let me explain:

  1. I found https://firebase.google.com/docs/firestore/security/rules-query document about query rules.
  2. Then i decide to use firebase.firestore().collectionGroup('recipes').get().then(...)...
  3. My security code it looks like:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{path=**}/recipes/{document} {
      allow read: if resource.data.public == true;
    }
  }
}
  1. My javascript call, looks like:
firebase.firestore().collectionGroup('recipes').where('public', '==', true).get().then(recipes => {
  recipes.forEach(doc => {
    console.log(doc.data());
  })
});
  1. After that i could see error in my console.log: AILED_PRECONDITION: The query requires an index. You can create it here or something familiar with link!
  2. I clicked the link and then accepted indexing settings for collectionGroup.
  3. You can find it here as well: enter image description here

Sorry for my bad english and Polski język, but i think i got this right! So it helped me to get onlz public recipes!

1
votes

You can't filter result with security rules. Security rules will block your request if there is one or more document violating the rules. What you need is collection group queries. For example:

const querySnapshot = await db.collectionGroup('recipes').where('public', '==', true).get();
    querySnapshot.forEach((doc) => {
        console.log(doc.id, ' => ', doc.data());
});