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
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 trying to push data to my database and I want to check if the pushed data's owner id is the same as the uid of the person pushing it. I get permission denied . I don't know how to write security rules for pushing data, and I can't find anything about it. The data structure looks like this:
Shops{
"Shop1PushId" : {
"ShopCredentials" : {
"Owner" : "ownerUID"
}
}
"Shop2PushId" : {
...
}
This is the object I am pushing.
{
"ShopCredentials" : {
"Owner" : "owner_id",
"Another" : "another thing"
}
}
This is my firebase rule:
"Shops" : {
".read" : true,
".write" : "newData.child('ShopCredentials').child('Owner').val() === auth.uid"
}
Code in android studio:
DatabaseReference shopsRef = database.getReference("Shops");
shopsRef.push().child("ShopCredentials").child("Owner").setValue(shopData.getShopOwner());
Right now you're enforcing the rules on /Shops itself. But that is a list of shops. You're looking to enforce the rules on a specific shop, not on the list. To do that you add a so-called $ variable to the rules, which indicates that the rules below it apply to each child node:
"Shops" : {
".read" : true,
"$shopid": {
".write" : "newData.child('ShopCredentials').child('Owner').val() === auth.uid"
}
}
Now anyone can read all of the shops (even when they don't know the specific show ID), but someone can only write the shop if they know its specific ID and specify themselves as the owner of the new shop.
I'm not sure what you're exactly trying to secure here. If you are looking to bootstrap the process, so that people can only create new shops that have themselves as the owner, realize that with these rules anyone can still claim ownership of any shop they know the ID of. If you want to prevent that, and only want to allow claiming of ownership when the shop is created, use something like this:
"Shops" : {
".read" : true,
"$shopid": {
"ShopCredentials": {
"Owner": {
".write" : "!data.exists() && newData.val() === auth.uid"
}
}
}
}
I have database json structure as:
{
"notifications" : {
"approved" : {
"notification_1" : {..},
"notification_2" : {..},
"notification_4" : {..},
"notification_6" : {..}
},
"pending" : {
"notification_3" : {..},
"notification_5" : {..},
"notification_7" : {..},
"notification_8" : {..}
}
},
"users" : {
"some_user" : {
"sent_notifications" : {
"notification_1" : "notification_1",
"notification_2" : "notification_2",
"notification_4" : "notification_4",
"notification_6" : "notification_6"
}
}
}
Security rules are as:
{
"rules": {
"notifications": {
"approved": {
".read" : true,
".write" : "auth.uid === 'admin'"
},
"pending": {
".write" : "auth != null && (newData.child('by_user').val() === auth.uid || auth.uid === 'admin')",
"$id" : {
".read" : "data.child('by_user').val() == auth.uid || auth.uid == 'admin'"
}
}
},
"users" : {
"$user_id":{
".read" : "auth.uid === $user_id",
".write": "auth.uid === $user_id"
}
}
}
}
Here, 'sent_notifications' stores notification id's which were added by user. On client side(Android), I wish to get list of those objects from notifications/approved, and notifications/pending, whose keys are in 'sent_notifications'. When a user sends a notification, that notification data goes in 'pending' and the key of that notification is stored in 'sent_notification'. After moderation admin would then move the data from pending to approved node. With any method I find myself doing a lot of queries on server to get all the nodes one by one. I need a better way to do this.
I am a newbie to firebase database. This may not be the best way to implement the database structure. I needed notifications/approved to be visible to general public and notifications/pending/$id to be visible only to user who is sending notification. This is the reference for above structure. If there is better way to implement it, please help me with that as well.
One option would be as follows:
Have the master list of all notifications (all users, pending and approved) under /notifications/ and grant read access only to the individual notifications (/notifications/$id) so that you must know the ID in order to read the notification.
Have an /approved_notifications/ list that just contains the notification IDs of approved notifications (just use the ID as the key and set the value to true or similar).
Have a /users/$user_id/sent_notifications/ list that again just contains the notification IDs of approved notifications.
If necessary have a /pending_notifications/ list as well, that again just contains IDs of notifications.
Basically you have one master list of notifications and then several "light" lists that "point" into that master list. Since the master list requires you to know the ID in order to read an individual post, users can't just read the list directly (you could also redundantly store a pending / approved flag inside the notification and have further security rules based on that if you wanted).
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.