I have a family, A, b, c, d, and A is the leader. We have an intruder, E. We only want b, c, d to read/write A's data.
ALL OF THESE letters (b, c d,...) will be the UID's
Here is what I have so far:
Everyone is authenticated with email. People send requests to A to be allowed in his group. If he accepts, they can read/write to his.
Design for database Firebase
{
"Leaders" : {
"A" : {
"ALLOWED" : {
"b" : 0,
"c" : 0,
"d" : 0
},
"DATA" : {
"blah blah1" : "content writable by bcd",
"blah blah2" : "content writable by bcd"
},
"REQUESTS" : {
"E" : 0
}
}
}
}
I can use CRUD to move the b, c, d but how do I make the rules so that it follows that only people in the ALLOWED can read/write data for each leader?
{
"rules": {
".read": "auth != null",
".write": "auth != null"
"Leaders":{
".write": "$uid == ????"
}
}
}
Thanks for helping!
Should be a matter of checking if the node exists under the current leader:
{
"rules": {
"Leaders":{
"$leaderuid": {
".write": "$leaderuid == auth.uid",
"DATA": {
".write": "data.parent().child('ALLOWED').child(auth.uid).exists()"
}
}
}
}
}
Things I changed:
Remove the top-level read/write rules. Otherwise any authenticated user can read/write all data and you can never take that permission away at a lower level anymore.
The leader can write their entire node. I use auth.uid here as described in the documentation on securing user data.
A user can only write under DATA if their uid exists in the ALLOWED node.
Related
My rules look like this:
{
"rules": {
"userShaders": {
"$uid": {
"shaders": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid || data.child('public').val() == true"
}
}
}
}
}
My data looks like this:
userShaders
8v4N3yLlXAU1cpRiaDj5kkDQaKn1
shaders
myShaderName
attr_1: ""
attr_2: ""
public: false
I am not logged in as this user and am attempting to query their data. I expect to succesfully get back 0 records because they have none marked as public.
However, I'm getting a permission denied error.
My query looks like this:
val shaderRef = db
.getReference("userShaders/${uid}/shaders")
.orderByChild("public")
.equalTo(true);
shaderRef.get().addOnSuccessListener {
// do something with the data
}
To summarize, I am trying to query for only public data, while simultaneously making a rule that non-public data is impossible to fetch by other users. I want to write a query such that I may receive 0 or many records back, but never a permission denied error.
The most important thing to realize is that Firebase security rules don't filer data. Instead they merely check that you're only requesting data you are authorized for.
Your code already queries only for the public data, so you need to validate that query in your rules with something like:
"shaders": {
".read": "query.orderByChild === 'public' &&
query.equalTo === true"
}
Even with that you will still need separate read operations for the shared that this user created and all public shaders, as there's no way to express that OR condition in a single query.
Well, I ended up just separating my data into separate public and private sections in Firebase like this:
"userShaders": {
"$uid": {
"shaders": {
"public": {
".write": "auth.uid === $uid",
".read": "true"
},
"private": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
},
}
}
}
It's more work, because when I update the isPrivate boolean I have to make sure to delete it from the other section, but it does get the job done.
Open to other answers if there's another way to do this.
I'm the Android app developer, and I'm using Firebase Realtime Database. I want to make an app that when users who want to use my app can save something like the text in their repository. But when I save the text in my app, other users who download my app can see my unique saved text. Firebase Realtime Database rules like this. But they didn't work. Please tell me how to use private node in Realtime Database.
{
"rules": {
"messages": {
"$user" : {
".read" : "$user === auth.uid",
".write" : "$user === auth.uid"
}
}
}
}
enter image description here
You also need to check if the auth rules are null. If yes, then not allow anyone to access the information. Also, you need to use a wildcard, instead of a static $uid value. So, put this inside the messages node. So, as you want people to write in the messages node, but only those who are owners to see the message, this is the code for it:
{
"rules": {
"messages": {
"${uid}": {
".read": "auth.uid != null",
".write": "auth.uid != null && auth.uid == uid"
}
}
}
}
I think the rules below do the trick. The codes snippet:auth.uid == $uid makes sure that only the owner of the node has writing rights while auth != null makes sure that only users logged in to your app can read from it.
{
"rules": {
"messages": {
"$uid" : {
".read" : "auth != null",
".write" : "auth.uid == $uid"
}
}
}
}
Another StackOverflow Question may also be useful for you if the situation becomes a little more complex.
I am developing a rudimentary delivery app using android studio and I am using Firebase as the database. I need to save the user info and also products that all the users can select from.
So basically each user has access to only their details but each user can access details from all the Products.
Here are my rules for the database:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "auth != null"
}
},"Products": {
"$uid": {
".read": true,
".write": true
}
}
}
}
And the database structure:
pat-2017-42536
Products
1
Description: "Product description"
Name: "Name of product"
Price: "Price of product"
2
Description: "Product description"
Name: "Name of product"
Price: "Price of product"
etc...
I tried changing the permissions to true as some previous questions suggested but it still keeps giving me this error:
W/SyncTree: Listen at /Products failed: DatabaseError: Permission denied
This is in my onCreate in Andoid Studio:
databaseProducts = FirebaseDatabase.getInstance().getReference("Products");
databaseProducts.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
showData(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here is the method that is supposed to fetch the product details:
private void showData(DataSnapshot dataSnapshot) {
for(DataSnapshot productSnapShot: dataSnapshot.getChildren()){
Product product = productSnapShot.getValue(Product.class);
product.setName(productSnapShot.child("item").getValue(Product.class).getName());
product.setDescription(productSnapShot.child("item").getValue(Product.class).getDescription());
product.setPrice(productSnapShot.child("item").getValue(Product.class).getPrice());
ArrayList<String> array = new ArrayList<>();
array.add(product.getName());
array.add(product.getDescription());
array.add("R" + product.getPrice() + ".00");
Log.d(TAG,"showData: name " + product.getName());
Log.d(TAG,"showData: description " + product.getDescription());
Log.d(TAG,"showData: price " + product.getPrice());
ArrayAdapter adapter = new ArrayAdapter(CustomerActivity.this,android.R.layout.simple_expandable_list_item_1,array);
listViewProducts.setAdapter(adapter);
}
}
It is probably a simple error but I can't seem to find it. Any help?
The problem is that you try to read at /Products while you allow read at /Products/Something. Enable read at Products node.
Your rules should be something like
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "auth != null"
}
},
"Products": {
".read": true,
".write": true
}
}
}
I don't think the above answer Birendra provided will do what you want it to. I believe that that will allow any authenticated user to read and write in any other specific users id. This is the same as the default rules, but just specific to the users id. He is right about the fact that you have it set up so that it is looking for /Products/$uid and so if you want anyone at all (whether authenticated or not) to both read and write to your products list then that would be the rules--but I can't imagine that you want your products list to be modifiable by everyone. From what I understand you want users to be able to read and write their own account info, but everybody can access the products. I'm not sure if you only want authenticated users to be able to view the products or not, so I'll include the rules for both. Remember, your read and write rules do NOT have to be the same for a particular node. So if you wanted to have every authenticated user be able to see the information of other users but only that particular user can write to their own profile, and if you want your "products" to be viewable by the general public (authentication not required), but you obviously don't want the public messing with your products you could have rules like this:
{
"rules": {
"users": {
".read": "auth != null", //all authenticated users can read the information from the "users" node.
"$uid": {
".write": "$uid === auth.uid" //only a user with an authenticated uid that matches the uid of the child node will be able to write to their node--no need for a read rules because it is already covered in the parent node
}
},
"Products": {
".read": true,
".write": false //you don't want just anybody to write to this node--probably even better since this wouldn't allow anyone to modify the products is to set it up with an admin access where a specific uid is the only one that has access--such as ".write": "auth.uid === 'dJrGShfgfd2'"
}
}
}
If you want only authenticated users to be able read the products, but not modify the products, then you would want:
{
"rules": {
"users": {
".read": "auth != null",
"$uid": {
".write": "$uid === auth.uid"
}
},
"Products": {
".read": "auth != null",
".write": false
}
}
}
Finally, if authenticated users can add or modify products, then you would want:
{
"rules": {
"users": {
".read": "auth != null",
"$uid": {
".write": "$uid === auth.uid"
}
},
"Products": {
".read": "auth != null",
".write": "auth != null"
}
}
}
Make the rules to be as shown below
Make sure that you have chosen REALTIMEDATABASE.
{
security rules. */
"rules": {
".read": true,
".write": true
}
}
There will be two DATA bases
1) cloud firestore
2) Real Time data Base
Choose the real time database and change the rules as the above mentioned one.
The above rule makes it visible to all the people.
I have a problem with the Firebase rules.
I want to grant write access to the books node (add new books) only to authenticated users. Also, I want that a single book can be modified only by the owner of the book. This is my DB and my rules:
o- books
o- book1
o- owner : user1
o- name : nice book
o- pages { ... }
o- users { ... }
o- book2
o- owner : user2
o- name : other book
o- pages { ... }
o- users { ... }
And here the rules
{
"rules": {
"books": {
".write": "auth != null",
"$bookId": {
".read": "data.child('users').hasChild(auth.uid)",
"pages" : {
".write": "data.child('owner').val() == auth.uid"
}
}
}
}
}
The problem is that is granting the write operation in /books/book1 with the authenticated user2 because the first write (auth != null) is true...
I appreciate any help,
Thank you very much.
When you set the write access right under the books branch you will give write access for the users to write on whatever data under it. So I guess you are looking for something like the following:
{
"rules": {
"books": {
"$bookId": {
".write": "newData.child('owner').val() == auth.uid && (!data.exists() || data.child('owner').val() == auth.uid)",
".read": "data.child('users').hasChild(auth.uid)"
}
}
}
}
This will ensure that whatever change the user make it will have his uid on it. And also, if is not a new book it is a book owned by him.
I am Developing an App where you live in a flat and have roommates, now I'm trying to disable access for all users that don't live in that flat.
Here are my Rules:
{
"rules": {
// no access
".read": "false",
".write": "false",
"Users" : {
"$userID" : {
//read on User Folder for all Users
".read" : "auth != null",
//write only for the user itself
".write" : "$userID === auth.uid"
}
},
"Flat" : {
"$flatID" : {
//Flat (identified through flatID) can only be accessed, if you are a roommate
".read" : "$flatID === root.child('Users').child(auth.uid).child('flatID').val()",
".write" : "$flatID === root.child('Users').child(auth.uid).child('flatID').val()"
}
}
}
}
My Database looks somewhat like this:
root
.Users
..uID
...(data)
...flatID : number
.Flat
..flatID
...(data)
So the flatID of that User is stored in his "folder" at root/Users/uID/flatID, which I try to get here: root.child('Users').child(auth.uid).child('flatID').val() and then I check it with the "folder" flatID.
Now if I try to write any Data into the flat, I don't have the right permission, and I cannot find my error.
The Users/userID rule is working fine
Thanks in advance :)
Edit:
The Data looks like this:
root
_Flat
__1
___name : "asdf"
__2
___(more Flats, for the Problem we only need one)
_Users
__F8XpTmxfIzYzrEY92alBOnx5eTO2 (Auth ID)
___flatID : 1
__nextUserID
___NextUserData
My Java Code to edit the flatname is:
fref.child("Flat").child(flatID).child("name").setValue(flatNameInput.getText().toString())
The flatID is a variable with the flatID for that user