Firestore: Security Rules for Querying Collection Group?

Viewed 55

Here is my structured data:

Users
 - w34rj3d9d2383
   - name
   - email
   - items (sub-collection)
     - dj23jd23wkjdkl
       - name
       - notes
       - createdBy
     - 4ru328rjwiodj2309
       - name
       - notes
       - createdBy

Using the rules below, I am able to specify the userId and itemId to successfully subscribe to an individual item in the items subcollection for the authenticated user. I am also able to fetch all the items for the specified user if I don't apply a predicate.

The problem is that when I attempt to apply a predicate to the collection (see below), it doesn't return anything.

let path = "users/w34rj3d9d2383/items"
let predicate = NSPredicate(format: "SELF.name CONTAINS %@", name)
let collectionReference = Firestore.firestore().collection(path).filter(using: predicate)
collectionReference.addSnapshotListener(includeMetadataChanges: false) { querySnapshot, error in
    //...
}

Here are my security rules. How can I query over my sub collection?

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

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

Update 1: I tried the following, but it still shows permission issues:

  1. Updating my reference to collection group:
let collectionReference = Firestore.firestore().collectionGroup("items").filter(using: predicate)
  1. Adding this to my rules
match /{path=**}/items/{itemId} {
    allow list: if request.auth.uid == resource.data.createdBy;
    allow get: if request.auth.uid == resource.data.createdBy;
}

Update 2: I got a query going, and the following rule working:

match /{path=**}/items/{itemId} {
    allow read, write: if request.auth != null;
}

This means I can fetch all items anytime I do a collection group query without a predicate. However, I want to only return items where the resource.data.createdBy value matches request.auth.uid. However, when I add this check it says resource is null.

0 Answers
Related