Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore rules for document field

I'm struggling within Firestore to set security rules for a document. With the RTDB is was possible to set rules for a specific object property and I'm trying to do the same with Firestore.

RTDB Code:

"users": {
    ".read": true,
    ".indexOn": ["profile/name"],
    "$uid": {
        ".read": "auth != null",
        ".write":
            "$uid === auth.uid && !data.exists()",
        "profile": {
            "birthday": {
                ".write": "$uid === auth.uid"
            },
            "name": {
                ".write": "$uid === auth.uid"
            },
            "banned": {
                ".write": "root.child('admins').child(auth.uid).exists()"
            }
        }
    }
}

Below the same code in Firestore:

service cloud.firestore {
    match /databases/{database}/documents {
        match /users/ {
            allow read
            match /{$user} {
                allow read: if request.auth.uid != null
                allow write: if request.auth.uid == request.resource.id &&  exists(/databases/$(database)/documents/users/$(request.resource.id)) === false

                match /birthday {
                    allow write: if request.auth.uid == request.resource.id
                }
                match /name {
                    allow write: if request.auth.uid == request.resource.id
                }
                match /banned  {
                    allow write: get(/databases/$(database)/documents/users/$(request.auth.uid)).data.userType > 3
                }

            }
        }
    }
}

When I'm writing security rules for a subcollection it's working fine. But for a document field it's not working. Is this not possible or is there a special path segment in the match reference? The documentation doesn't state anything about this.

like image 801
Edblocker Avatar asked Apr 19 '18 11:04

Edblocker


People also ask

How do you set rules on firestore?

Cloud Firestore provides a rules simulator that you can use to test your ruleset. You can access the simulator from the Rules tab in the Cloud Firestore section of the Firebase console. The rules simulator lets you simulate authenticated and unauthenticated reads, writes, and deletes.

What file should be used for firestore rules?

firestore. indexes. json // is a file used to define indexes for you Firestore queries.

How many fields can a document have firestore?

Because each field appears in 2 indexes (ascending and descending), the maximum number of fields is 20,000.

What language are firestore rules written?

Cloud Firestore and Cloud Storage rules use a language based on the Common Expression Language (CEL), that builds on CEL with match and allow statements that support conditionally granted access.


2 Answers

You can do this by checking the request.resource.data property. As shown in this section of the documentation. You only need to match the document level. You check the field rules with an if condition.

However, you are unable to control read access to individual fields. A user can either read a whole document or not. If you need to store private data, consider adding this to a sub-collection of the user document.

Here is an example

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}
like image 187
Jason Berryman Avatar answered Oct 23 '22 16:10

Jason Berryman


Looks like this is now supported:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

The resource variable refers to the requested document, and resource.data is a map of all of the fields and values stored in the document.


To give a concrete example, in my case I needed to provide read access to a group only if the requesting user is in the members field (which is an array) of the groups collection. So I did this:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    function isMember(userId) {
      return (userId in resource.data.members);
    }
    match /groups/{group} {
      allow read: if request.auth != null && isMember(request.auth.uid);
    }
    //...
  }
}
like image 26
Alaa M. Avatar answered Oct 23 '22 16:10

Alaa M.