Bon Echo
Bon Echo

Reputation: 67

Firestore Blocked users rule

I've been searching for an answer for this for a time now,

Simply I have an Android app, this app allows users to write or read to/from the database which is Firestore

I have a collection named BlockList which meant to hold the users uid as the document name and a field value named userUid, the purpose of this collection is to deny any write "only" request for users who misbehave in the application. In other words, I am looking for firestore rule to allow the users in BlockList to read only what's shared in the application and deny all the write operations they try to make.

I've already tested these rules but it doesn't work, it doesn't allow any read or write operation even if the user is not on the BlockList

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
   function isBlackListed() {
      return exists(/databases/$(database)/BlockList/$(request.auth.uid))
    }
    match /{document=**} {
      allow read, write: if request.auth != null && !isBlackListed();
    }
  }
}


----------


rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
         allow write: if !exists(/databases/$(database)/documents/BlockList/$(request.auth.uid))

  }
}

Update

Thanks to Marc's answer I managed to get everything right Working rule

 match /Posts/{document=**}{
      allow write :if !exists(/databases/$(database)/documents/BlockList/$(request.auth.uid))
      allow read :if request.auth.uid != null;
}

Upvotes: 4

Views: 2266

Answers (3)

Zorayr
Zorayr

Reputation: 24942

If the number of people in the blocked list is low, you can use the following solution of manually blocking off people in the rules.

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
        function isBanned(uid) {
                return uid in [
        // List of banned naughty peope!
        "uid-1....DLZV2",
        "uid-2....OB0w2"
        ];
        }
        allow read, write: if request.auth != null && !isBanned(request.auth.uid);
    }
  }
}

Upvotes: 0

Logemann
Logemann

Reputation: 2973

dont know if i get your problem right and it would have been helpful to have seen your rules which you tried so far, but i think this should work:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      // Make sure a write to all documents is only allowed when
      // the current user has no document in BlockList collection
      allow write: if !exists(/databases/$(database)/documents/BlockList/$(request.auth.uid))
    }
  }
}

I have tested this with my firestore instance and it looks ok to me. Of course you most likely will need to specify the documents better instead of the wildcard match.

It doesnt matter what data you have in the BlockList documents as long there is a document with the userUid as doc name in the BlockList collection.

I have created two documents (which represent users) in the BlockList collection.

two users in BlockList

Now i try to write to my tournaments table which has the mentioned security.rule via Simulator "Update" method (with auth credentials supplied of course)

blocked by rule because user is in BlockList

When removing the user "8Zvq1fpWl2S0h1t7bIxNoxDcucn1" from BlockList and use Simulator again, i get:

allowed by second rule

Summary: to me it looks working quite well.

Upvotes: 3

Flignats
Flignats

Reputation: 1274

There are a few ways to solve this issue, here is a strategy based off of what you have already (collection of user documents that include uids of users that you want to block from write access).

Frontend Solution

When a user authenticates with your app, send a request to see if that uid is also in the BlockList collection. If it does exist, set a boolean flag in your app that all db calls reference before allowing the call to execute.

Backend Solution

Since nothing is secure in the frontend, you'll want to couple the frontend validation with backend security.

The changes the user is attempting to make can be staged in a 'trigger document' that a cloud function in the backend then executes onWrite.

Your cloud function can then query the BlockList collection to see if the uid is indeed among the collection, and if so then send back an error (or not) to the client while preventing any writes.

Upvotes: 1

Related Questions