Roman Samoilenko
Roman Samoilenko

Reputation: 936

Custom security rules for Cloud Firestore

I want to create a Cloud Firestore realtime database containing groups which users can join and share information to other members of their group. I want to preserve users anonymity so the way I see it to be implemented is:

So basically the data structure is something like this:

/groups/ : [
    //groups as documents
    "ABCD-0000-0000-0001" : { /*group data model*/ }
    "ABCD-0000-0000-0002" : { /*group data model*/ }
    "ABCD-0000-0000-0003" : { /*group data model*/ }
]

The question is, what security rules should I write to permit users to read, create and update data ONLY in the group they belong to (have its group key)? At the same time, how to forbid users from finding out other groups' keys?

Upvotes: 0

Views: 571

Answers (2)

Jason Berryman
Jason Berryman

Reputation: 4908

You can save the group ID in the user's profile. Then create a rule which only allows CRU permissions if that group ID exists.

db.collection.('users').doc({userId}.update({
  ABCD-0000-0000-0001: true
})

match /groups/{groupId} {
  allow read, create, update: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.$(groupId) == true;
}

Upvotes: 1

AsifM
AsifM

Reputation: 699

Your group structure can remain as is-

groups (Collection) : [
    //groups as documents
    "ABCD-0000-0000-0001" : { /*group data model*/ }
    "ABCD-0000-0000-0002" : { /*group data model*/ }
    "ABCD-0000-0000-0003" : { /*group data model*/ } ]

And to maintain the access, you can have another separate collection named group_users as-

group_users(Collection)/ <group_id>(Document)/ members(Collection)/ :
       uid_1 (document)
       uid_2 (document)    
       ...

Now the rule to allow can be like-

service cloud.firestore {
  match /databases/{database}/documents { 
    match /groups/{group_id} {
        allow read, create, update: if exists(/databases/$(database)/documents/group_users/$(group_id)/members/$(request.auth.uid));
    }
  }
}

When a member joins the group, you will have to add the user's uid to that new collection-

group_users/<group_id>/members

For admins, you can have a similar collection, and uid will be added when the admin creates the group-

group_users/<group_id>/admins

Instead of having a separate collection outside of groups collection, you could have a collection within group itself as an alternative solition, then you will have to modify the group data model to some more extent.

Also FYI, each exists () call in security rules is billed (probably as one read operation).

And here is a detailed documentation explaining almost every possible aspect of firestore security rules.

Upvotes: 2

Related Questions