Reputation: 67
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
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
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.
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)
When removing the user "8Zvq1fpWl2S0h1t7bIxNoxDcucn1" from BlockList and use Simulator again, i get:
Summary: to me it looks working quite well.
Upvotes: 3
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