Firestore security rules : searching for a user's id in array in a document

FirebaseGoogle Cloud-Firestore

Firebase Problem Overview


First, sorry for my terrible English, it is not my native language...

I am building a simple app in Firebase, using the Firestore database. In my app, users are members of small groups. They have access to other users' data. In order not to query too many documents (one per user, in a subcollection of the group's document), I have chosen to add the users' data in an array inside the group's document. Here is my group's document:

{
   "name":"fefefefe",
   "days":[false,false,false,false,true],
   "members":[
       {"email":"[email protected]","id":"aaaaaaaa","name":"Mavireck"}, 
       {"email":"[email protected]","id":"bbbbbbbb","name":"Mavireck2"}, 
   ],
}

How can I check with the security rules if a user is in a group ? Should I use an object instead ? I'd really prefer not use a subcollection for users, because I would reach the free quota's limits too quickly...

Thank you for your time !

EDIT: Thanks for the answer. I will change it to an object : "Members": { uid1 : {}, uid2 : {} }

Firebase Solutions


Solution 1 - Firebase

In general, you need to write a rule like the following:

service cloud.firestore {
  match /databases/{database}/documents {
    match /collection/{documentId} {
      // works if `members` = [uid1, uid2, uid3]
      // no way to iterate over a collection and check members
      allow read: if request.auth.uid in resource.data.members;
      // you could also have `members` = {uid1: {}, uid2: {}}
      allow read: if resource.data.members[request.auth.uid] != null;
    }
  }
}

You could also use subcollections:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow a user to read a message if the user is in the room
    match /rooms/{roomId} {
      match /documents/{documentId} {
        allow read: if exists(/databases/$(database)/documents/documents/$(documentId)/users/$(request.auth.uid));
      }
      match /users/{userId} {
        // rules to allow users to operate on a document
      }
    }
  }
}

Solution 2 - Firebase

I made it happen with this code

Allow some user to read/write some document of a collection if this same user is present into an array of another collection

service cloud.firestore {
  match /databases/{database}/documents {
    match /repositories/{accountId} {
      allow read, write: if request.auth.uid in get(/databases/$(database)/documents/accounts/$(accountId)).data.users
    }
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMavireckView Question on Stackoverflow
Solution 1 - FirebaseMike McDonaldView Answer on Stackoverflow
Solution 2 - FirebasecalebeairesView Answer on Stackoverflow