In Cloud Firestore, I have a collection of documents with an array field containing all of the users that should have read permission on that document. My simplified security rules are:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /collection_name/{document=**} {
allow read: if request.auth.uid in request.resource.data.listOfIds.toSet();
}
}
}
A sample simplified document is:
{
listOfIds: ["uid1", "uid2"]
}
Using the rules simulator to perform a get, reads work as expected. However, executing a similar query using the Android API returns a permission denied error. I think I'm constraining my query in the same ways the rules are (which is a requirement of Firestore; it doesn't filter out documents that the user can't read for you).
firestoreClient.collection("collection_name")
.whereArrayContains("listOfIds", firebaseUid)
.get()
.addOnCompleteListener(...);
It turns out, Firestore thought the query wasn't properly constrained to the defined read permissions. It was the .toSet() that threw it off. Removing that resulted in the behavior I expected.
Why did I have .toSet() to begin with? I had erroneously thought that converting the array into a set was a requirement to use the in operator. That operator works with lists as well as sets.
Related
My app is user-based, and so each user has his data saved in the app's Firestore Database.
When the app is in debug mode (installed on my device by Android Studio), there's no problem reading and writing to Firestore.
The problem is, when the app is installed from the Play Store (So I guess this means it's in release mode), the app is no longer able to read and write to the Firebase Database.
All of the SHA1 and SHA256 are added to the Firebase app, including the debug keys, release keys, and update keys, while I got the last two from the Play Console (of the specific app), so probably the problem doesn't lie in these keys.
Here're my Firestore rules, if there's any chance that they're relevant:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}{
allow read, write: if request.auth.uid == uid;
}
match /{document=**} {
allow read, write: if true;
}
}
}
If any other code pieces are needed, say the word and I'll add them.
What's the problem, then?
And how can I fix it?
Help would be much appreciated!
I want to check if the user's username and phone number is unique. I have implemented it using
FirebaseFirestore.getInstance().collection("Users").whereEqualTo("phone",ph).get().addOnCompleteListener(...);
This is my firestore rule:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: true;
allow write: if request.auth.uid != null;
}
match /Users/{userID} {
allow update: if request.auth.uid == userID
&& (request.resource.data.username == resource.data.username
|| isUserNameAvailable(request.resource.data.username)
);
}
}
The code works fine with no issues. I am checking this before the signInWithCredential method and hence the request.auth.uid will always be null. To make the code work ill have to keep allow read: true;
But, now i am getting this warning
We've detected the following issue(s) with your security rules:
any user can read your entire database
Is there any workaround to prevent this?
This is a common mistake developers make when using usernames. You gave anyone permission to read your whole database. And even if you manage to put that to only read Users anyone could read all your users data.
I would recommend to remove the first allow read:true and write rules for each path as they should be. Also create a separated collection just for usernames and save all of them there like /usernames/${username} and /phones/${phone}. If the need to be saved together you can do that to.
That way you can very easy check without any query if a username or phone exists by just checking if that path exsists in your database.
You can very easy sync the users collection with those two and even write security rules that prevent creating users in the collection that have a username that already exists in the usernames collection.
I'm building an app with Kotlin. In the app, the user can sign up and log in. After the user log in, the user adds some text and pictures, and these data is successfully added to the firebase cloud store and displayed in the app as a list. However, this list can be accessed by anyone registered on the app.
What I want to do is how users can only see their own data. So I don't want users to see each other's data. I just want every user to see their own added data. I think that I need to change Cloud Firestore rules. How do I set permission to specific document?
I'm new to this field, Thank you !
My firebase Cloud Store rules;
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match/Notes/{noteId}{
allow read, write: if request.auth.uid != null ;
}
}
}
this is my firebase cloud store screen shot
it's done by settings up the rules. You can read more here: https://firebase.google.com/docs/database/security#section-overview
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I developed an app which is simple TO-DO list app. I create there my daily plan, my weekly plan and so on. TODO list is made offline. Now I would like to share my TODO list with different users of app. Like relationship MOM-KIDS (one to many) so mom can see what her kids are doing. So there is a question how to do this? I would like somehow to mark to who I would like to send my daily plan. Should I register in some cloud hosting? Probably there will be a problem with referencing to someones DB to insert other user data into someones DB (public rules are not acceptable). Allowing .read to true for "admin" (mom) users in my opinion is also bad solution cause other moms can not their kids plan. Should I send it through broadcasts or what's should be the solution in problems like this?
#Edit
I changed into Firestore DB but still I'm not sure how to get permission for users stored in array of receiverIds.
I was trying adjust Firestore security rules : searching for a user's id in array in a document into my case but I was getting always an errors. Can somebody tell me what I am doing wrong here?
service cloud.firestore {
match /databases/{database}/documents {
match /user_activity/{ids} {
allow read, write: if request.auth.uid in get(/databases/{database}/documents/user_activity/{ids}).data.receiverId
}
}
}
Greetings!
The best way would be using a database like Firebase Firestore database. It would be an easy and simple solution to implement.
For the data access rules, you can use Firebase security rules to enforce what you need.
For eg. in your case, the mom can read the data but not write to it which can easily be done.
Here are links to help you:
Firebase Firestore Introduction
Firebase security rules.
Firebase Firestore Codelab
Update:
Okay, so here is I quickly simulated, tried it and it worked absolutely fine!
This is the structure:
These are the rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /item/{items}{
allow write : if true;
allow read : if request.auth.uid in resource.data.uid;
}
}
}
NOTE: uid in resource.data.uid refers to the array uid in document.
And here are the screenshots of the results:
Here, the uid is the one entered in the array in database. Therefore, read allowed.
Here, the uid is not the one in the array in database. Therefore, read not allowed.
On the application I am developing, the user creates their account with e-mail and password but how can I make data specific to the user? For example, in my application a user can gain points by completing certain tasks. So when a user completes a task, I need to update their points and store it on the database so they can gain points overtime and use them to redeem awards. Here is what I think I am supposed to do, but I am unsure if I have to add anything to the rules or not.
Note: Every user's point amount is supposed to be unique to that specific user
If you want users to only be able to read/write their own data, you'll want to store that data under the user's UID. From the Firebase documentation on securely accessing user data:
Another common pattern is to make sure users can only read and write their own data:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}
👍 yup looks good, just be careful about who has access to write to that document.