Search code examples
python-3.xgoogle-cloud-firestorefirebase-security

Firestore Security Rules is allowing updates without an update rule


It's possible I'm not understanding proper use of firestore sdk set() method. My understanding is that if a document id does not exist it will perform a "create". If it does it will perform an "update" to the existing document and overwrite unless merge=True is included. That's not what I'm seeing however.

I have the following firestore db structure:

Investment (collection)
  News (subcollection)

These are my current rules:

rules_version = '2';
service cloud.firestore {
  
  function isUpdateToActivityField() {
    return request.resource.data.diff(resource.data).affectedKeys().hasOnly(['activity']);
  }

  match /databases/{database}/documents {
    match /Investment/{iid} {
      allow read: if request.auth != null;
      allow update: if request.auth != null && isUpdateToActivityField();
      allow create: if request.auth != null;
      
      match /News/{nid} {
        allow read: if request.auth != null;
        allow create: if request.auth != null;
      }
    }
  }
}

If I manually modify fields in news items and then perform an update it will overwrite my records reverting the text.

enter image description here

This is how I'm using the set() method.

        product_ref = client.collection("Investment").document(self.symbol)
        batch = client.batch()
        for n in news:
            ndict = n.to_dict()
            new_news_ref = product_ref.collection("News").document(ndict.pop("uuid"))
            batch.set(new_news_ref, ndict, merge=True)
        batch.commit()

My goal is just to have the rules prevent a create or update if the record is already there without having to check in code. I've even tried changing the create rule to:

allow create: if request.auth != null && !exists(/databases/$(database)/documents/Investment/$(iid)/News/$(nid))

No luck however.

Am I going about this incorrectly?


Solution

  • The Python SDK for Cloud Firestore is considered a server-side SDK, which means it bypasses the security rules you set for the project. From the documentation:

    Server client libraries create a privileged Firebase environment with full access to your database. In this environment, requests are not evaluated against your Firebase security rules. Privileged Firebase servers are secured using Identity and Access Management (IAM), see Security for server client libraries.

    You should only use server-side SDKs in trusted environments, where you can ensure the code accessing the project is code that you control.

    To enforce the security rules, use client-side SDKs for Firestore which are available for Web, Android, iOS, C++, Unity, and Flutter.