I have an Events collection and a Users collection. My Event page increments a counter (in Users collection) when an event is uploaded. I want to limit the number of events per user to 10.
This what I have so far and it doesn't seem to work as expected:
rules_version = '2';
service cloud.firestore {
match /databases/collection/Events{
allow read;
allow write: if 50 >
get(/databases/collection/Users/$(request.auth.uid)).data.numberOfEvents;
}
}
//Tried this:
rules_version = '2';
service cloud.firestore {
// Do not change this
match /databases/{database}/documents {
// Path to your document
match /Users/{doc=**} {
allow read;
allow write;
}
match /Events/{doc=**} {
allow read;
allow write: if get(/databases/$(database)/documents/Users/$(request.auth.uid)).data.numberOfEvents < 50;
}
}
}
Actually the last one seems to work, let me test some more, thanks for all help!
It seems to work! Thanks!
You are not specifying the document path correct. Assuming events and users are both root level collections. Try the following rules:
rules_version = '2';
service cloud.firestore {
// Do not change this
match /databases/{database}/documents {
// Path to your document - collection names are case sensitive
match /events/{eventId} {
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.numberOfEvents < 10;
}
}
}
You should however not allow users to write to numberOfEvents directly from client as they can reduce the number and try to add more events. Firestore triggers for Cloud functions might be useful here to increment/decrement the value securely from backend.
Related
I played around with my Security Rules a little bit today and now I cannot create any more (chat)rooms when cliking the corresponding button in my app. I even put the security rules back to allowing all read and write requests, but still it does not work anymore. Any advice?
> rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
// every user can only read his own data
allow write: if request.auth != null && userId.matches(request.auth.uid);
allow read;
// add part to allow access if uid equals admiin uid
}
match /rooms/{roomId=**} {
allow write, read;
}
}
}
If my firestore looks like this:
/domain path (eg. xyz.com)/users and other data/ecc
which rule can I set to allow user to access only the domain path they are in? Something like:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} { <-- what here
allow read, write: if request.auth <-- what here ;
}
}
}
edit: actual firestore screenshot
It seems you have user's domain as collection name so you can use a wildcard as shown below:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{colName}/{docId} {
allow read, write: if colName == request.auth.token.email.split("#")[1];
}
}
}
This rule will check if the collection name is equal to requesting user's domain in their email.
However, this above rule will be applied for all the collections in your database so I'll recommend creating a single collection "users" and storing the domain name as a field as shown below if possible:
users -> { userId }
(col) (doc)
// document in users collection
{
email: "user#domain.tld",
domain: "domain.tld",
...otherFields
}
You can then easily access the domain name in the security rules from document data.
So I am trying to only allow a client to create a file it it has a certain name, but failing completely doing so.
// This is what I have tried so far:
https://firebase.google.com/docs/reference/rules/rules.List#hasAny
request.resource.__name__.split('/').hasAny('someDocument')
https://firebase.google.com/docs/reference/rules/rules.String#matches
request.resource.__name__.matches('.*someDocument')
And trying to compare the exact string from the rules-playground
request.resource.__name__="/databases/%28default%29/documents/someCollection/someDocument/someOtherCollection/thisDocument"
But all of them returned false for me.
service cloud.firestore
{
match /databases/{database}/documents
{
match /{document=**}
{
allow read: if true;
allow write: if {insert correct condition here};
}
}
}
You just need a wildcard to get the value of a document ID. Try the following:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /collectionName/{docId} {
allow read, write: if docId.size() > 5; // example
}
}
}
If you want to match collection name as well then you can add another wildcard like this:
match /{colId}/{docId} { ... }
Checkout the documentation for more information.
This is what I have in my rules setup but it does not allow me to view fetched data from firestore unless I'm logged in.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Photos/{PhotoID}/{document=**} {
allow read, write: if request.auth.uid != null
}
}
}
The request.auth.uid != null will return false if a user requesting data is not logged in with Firebase Authentication. If you want anyone to to fetch data then the rule should be allow read: if true;.
I'm not sure about your use case here but it's best to allow users to read/write their own data only. For that you'll need to store their UID somewhere in the document.
Then rules in your questions apply for Photos collection and all of it's sub-collection as you are using a recursive wildcard.
You may visit there docs here
Basics of firebase security rules
In addition to #Dharmaraj answer:
The code you provided above helps you check if user is logged in, if logged in then it allows both read and write operation else disallows/denies the operation.
Then if you want a free access to your database such that it will not check whether logged in or not , remove the if condition and only end the command with semicolon[;],
But be careful because if you allow both read and write access without checking if user is authenticated or not, then you endanger your data to the entire world.
To allow only read access:
rules_version = '2';
service cloud.firestore {match /databases/{database}/documents
{
match/Photos/{PhotoID}/{document=**} {
allow read:if true;
allow write: if false;
}
}
}
To allow only write access:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match
/Photos/{PhotoID}/{document=**} {
allow read: if false;
allow write:if true;
}
}
}
What would be the best Firestore rules when users should only be able to read and write their own collections, i.e. the collection name is the same as the userId? Currently I have the following which works, but is it secure enough?
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{userId}/{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
I also tried the following which didn't work.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{userId}/{document=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
The first rule is indeed not sufficient, since there is no check on the collection name: any authenticated user can read all the collections named with any users' uid.
The second one should work for your requirements ("Users should only be able to read and write their own collections, i.e. the collection name is the same as the userId"). You are probably having an error somewhere else, e.g. with the code for writing or reading or for authenticating the user. You should share this code in order we double check it