In the Firestore security rules, is it possible to check certain document fields when using a list
query?
Using Angular, I want to retrieve a single document from the userprofiles
collection using its username
property as follows:
let userprofile = this.afs.collection( 'userprofiles', ref =>
ref.where('username', '==', username ).limit(1);
I want this query to be allowed by the Firestore security rules, if either:
Here are my Firestore security rules:
match /userprofiles/{userprofileId} {
allow list: if( resource.data.published==true || (
resource.data.published==false &&
resource.data.uid==request.auth.uid )
);
}
}
For context, I am using the exact same rule to allow get
request, which works fine. However, the query in the above example causes a list
request, not a get
. And in that case, these rules do not permit the query. I am getting Error: Missing or insufficient permissions.
I remember reading something along the lines of that for list queries, the rules must allow either all or no documents, which in my case doesn't apply. So I sort of understand why it doesn't work.
My question is, can I change something to make it work for my query? Or is this not possible? Any ideas for workarounds? (apart from the obvious "query by document-id" or "make username the document-id")
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.
Cloud Firestore Security Rules allow you to control access to documents and collections in your database. The flexible rules syntax allows you to create rules that match anything, from all writes to the entire database to operations on a specific document.
rules // is a file used to define the security rules for your Firestore database. firestore. indexes. json // is a file used to define indexes for you Firestore queries.
Firestore offers robust access management and authentication through two different methods, depending on the client libraries you use. For mobile and web client libraries, use Firebase Authentication and Firestore Security Rules to handle serverless authentication, authorization, and data validation.
In order to allow "list" for queries, the query parameters must match the security rules. Please refer to the documentation.
Your query would need to include the published==true statement:
let userprofile = this.afs.collection( 'userprofiles', ref =>
ref.where('published', '==', true).where('username', '==', username ).limit(1);
And your rules could be simplified to:
match /userprofiles/{userprofileId} {
allow list: if resource.data.published==true ||
resource.data.uid==request.auth.uid;
}
Note that the query would only list the published userprofiles. I don't think it would be possible to query for "published==true" OR matching the uid condition at once, your code would need to query twice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With