Couldn't read firebase child - firebase

Users can able to data when they login in. But I want everyone can able to this child.No matter logged in.
Child is "gunluksifreler"
Here are my rules
{
"rules": {
"Homeland": {
".indexOn": ["username","email","bakiyetl","yarismada","yarismadabb","splashmesaj","uygulama1tut","uygulama2tut","uygulama3tut","uygulama4tut","uygulama5tut","uygulama6tut","uygulama7tut","uygulama8tut","uygulama9tut","uygulama10tut"]
},
"Odultalepleri": {
".indexOn": ["username","odul1"]
},
"Yardim": {
".indexOn": ["id"]
},
"gunluksifreler": {
".read": true, // <-- allows every person
".write": true
},
"Devices": {
".read": true, // <-- allows every person
".write": true
},
".read": "auth !== null", // <-- allows read if logged in
".write": "auth !== null" // <-- allows write if logged in
}
}
It can be read for everyone when I set true last read line
".read": true, // <-- allows read everbody
".write": "auth !== null" // <-- allows write if logged in
But this time everyone can read every child. What I'm missing?
Code
var kullanici = firebase.database().ref();
kullanici.on('value' ,function(datasnapshot) {
if(datasnapshot.hasChild("gunluksifreler")){
alert("yes");
}});
But it's not about the code it's about the rules.

If you don't want anonymous users to be able to read the entire database, you should not allow "read": true at the root level in your security rules.
Then if you want to allow everyone to read kullanici, you should allow "read": true on that node in your rules.
So this part of your original rules looks fine to me:
{
"rules": {
"gunluksifreler": {
".read": true
},
".read": "auth !== null"
}
}
I highly recommend focusing the rules/code in your question similarly in the future, as it ensures we're both looking at the same minimal-but-complete fragment.
The problem is not in the rules, but in your code:
var kullanici = firebase.database().ref();
kullanici.on('value', ...
This is trying to read the root of the database, which the rules explicitly disallow. So this read gets rejected.
A good way to remember this is that Firebase security rules don't on their own filter any data. They merely check whether the read you're trying to do is allows. So the read above tries to read the root, which is not allowed. Firebase doesn't check every child node of the root to only return allowed child data, as the performance of that would be hard to guarantee.
If you want read the kullanici node, you should attach your listener to only that node:
var kullanici = firebase.database().ref("kullanici");
kullanici.on('value', ...

Related

Allow write to one child in Realtime Firebase database

In a Realtime Firebase database there are a lot off Childs
And in those Childs the are some more.
What rule's do i add so Read = true
Butt only write to the child "Pupil" and everything in that child
"rules":
{
".read": true,
".write": false
}
"Pupil":
{
".read": true,
".write": true
}
}
I am missing a Expected ',' or '}'.
The security rules for the Firebase Realtime Database as in JSON format, and what you have is not valid JSON. In fact, it's not even close.
I highly recommend using a tool that can show you whether your code is valid JSON (a quick search can help you find one of these).
The closest valid JSON equivalent to what you have seems to be:
{
"rules": {
".read": true,
".write": false
},
"Pupil": {
".read": true,
".write": true
}
}
While this is now valid JSON, it is not a valid set of security rules, as you can only have one top-level event (names rules) in security rules, and the rest of your rules needs to be under that.
To make it into valid security rules, nest the Pupil node under the top-level rules:
{
"rules": {
".read": true,
".write": false,
"Pupil": {
".read": true,
".write": true
}
}
}
So you should be able to save the above in the Firebase console without an error.
You can simplify this a bit to:
{
"rules": {
".read": true,
"Pupil": {
".write": true
}
}
}
The top-level read permission is automatically inherited by all nodes under the root. And by default there is no permission, so the ".write": false on the root is implied here.

Can I set one child to be .write: true whilst others are restricted?

I have an object called 'Service' This can be read by anyone but changes can only be made by the owner. My firebase rule for this is:-
"Service": {
".read": true,
"$uid": {
".write": data.child('owner').val() == auth.uid"
}
}
Service has a child called 'owner' which is == to the users UI when logging in through firebase Auth.
I also have a User object which can make a Service as a favourite. I'm saving these in the user object as an array of [businessKey:true].
However, I've been asked to also save in the Service object the reverse relation of what users have favourited it. So an array However as a user isn't always the owner of a service I come into a permissions error. I'm trying to write rules that allow anyone to write to one child but not the others.
I have tried...
"Service": {
".read": true,
"$uid": {
".write": data.child('owner').val() == auth.uid" || data.child('users').val() != root.child('users').val()"
}
}
this is would allow a write if the user was the Service owner or just changing the child 'users' The effect was that any user was able to write to anything.
I've also tried
"Service": {
".read": true,
"$uid": {
"$users": {
".write" : true,
},
".write": "data.child('owner').val() == auth.uid"
}
}
thinking this would always allow a write to 'users' and any other child if user was owner.
I'm pretty new to firebase and this rules syntax in general so I'm probably making some glaring error! If what I want to achieve possible? what have I got wrong?

firebase realtime database security rules for non user data

So, I have an app where users can order the cakes and do other profile management, the rules looks like below:
{
"rules": {
"cakes" : {
".read": true,
".write": false
},
"users": {
"$user_id": {
".read": "auth != null && $user_id === auth.uid",
".write": "auth != null && $user_id === auth.uid"
}
}
}
}
Simply, they mean any one can read the cakes node (but no one can write). And an authenticated user can see or write to his on node.
This is good so far.
Now, my requirement is: When someone places an order through the app then i need to store it to firebase db in a top level node (lets say it orders). The question is what kind of security would be placed on orders node?
In functional definition: The app should be able to create new orders as user checks out, no one except seller should be able to read those orders, only seller should be able to have update access to a order.
If you want everybody to be able to write orders, and nobody able to read, the rules are simply the inverse of the ones for cakes:
"rules": {
"orders" : {
".read": false,
"$orderId": {
".write": true
}
},
With this anyone can push new data under /orders. And as long as you use push() to generate the new keys, you're guaranteed that they'll never conflict.
With these rules only a system-level admin can read the data. That is: you can read it in the Firebase Console, or someone can read it if they use the Admin SDK.
You might want to open it up for reading a bit more, e.g. by having the concept of an application-level administrator. Say that your UID is uidOfVik, you could model a list of admins in your database:
admins: {
uidOfVik: true
}
Now you can allow only admins to read the orders with:
"rules": {
"orders" : {
".read": "root.child('admins').child(auth.uid).exists()",
"$orderId": {
".write": true
}
},

Allow only read/write of one child

I've been messing around with my firebase database rules to try and allow users without authentication to only edit a certain child in my database, but I can't seem to figure it out.
Here is the database structure:
So I'm trying to allow users without authentication to edit the videoID, but not only that, I need the rule to ignore the room id (5555 in this example), meaning it only allows reading and editing of rooms/(roomid)/videoID
Thanks for all kinds of help!
The Firebase Database rules allow variables and can have different rules at different depths.
In your case, the below rules would allow any users (authenticated or not) to access /rooms/$roomid/videoID but only authenticated users to access the entire /rooms/ tree.
{
"rules": {
"rooms": {
".read": "auth != null",
".write": "auth != null",
"$roomid": {
"videoID": {
".read": "true",
".write": "true",
}
}
}
}
}
The Firebase rule simulator (accessible from the Rules tab of the Firebase Database console) is useful for testing rules before publishing:
Maybe something like this :
{
"rules": {
".read": true,
".write": "auth != null",
"rooms": {
"$roomId": {
"videoID": {
".write": true
}
}
}
}
}
It will allow user with authentification to edit another field beside videoID.
But if you want even authentificated user, also can only edit videoID, then the rule is :
{
"rules": {
".read": true,
".write": false,
"rooms": {
"$roomId": {
"videoID": {
".write": true
}
}
}
}
}
Remember, when the rule set true it will not traverse the child rule, But if it set false it will continue inspect the child rules.

Firebase: Cannot add user entry (`set` permission denied)

I want to ensure that a new user can be created (from the client), but only an authenticated user can read or write an existing object.
I have a simple rule set:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid === $uid",
".write": "!data.exists() || auth.uid === $uid"
}
}
}
}
I am calling createUser and then in the callback I'm trying to add an entry to my own users object:
const usersRef = ref.child('users');
const userEntry = {
[userData.uid]: {
created: new Date().getTime()
}
};
usersRef.set(userEntry)
I would have thought that even though the user is not yet logged in, they should have write permission because of !data.exists(). Yet I am getting a PERMISSION_DENIED error.
If I set ".write": true on the users level then it will cascade (and override?) my inner rules won't it?
Edit:
This fails even with:
"users": {
"$uid": {
".read": true,
".write": true
}
}
Thanks.
I think I initially misunderstood the problem. In your current callback, you are trying to overwrite the entire users level because of how set works.
You would really want to set only the thing that doesn't exist:
const userRef = ref.child('users').child(userData.uid);
const userEntry = {
created: new Date().getTime()
};
userRef.set(userEntry);
Then, I think that your existing rules would work.
I think this a confusing question because creating a user and writing to the database are completely different things. So i will just show how i do it in my app.
First step is creating the user
Next log the user in because creating doesn't automaticly log the user in (I do this in the callback function of create user)
Last step is writing the user data to firebase
I use the following rule to make sure each user can only write to his own node in firebase (documentation):
{
"rules": {
"users": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
And one thing to keep in mind is that set() will replace any existing data at that path. So make sure you use the uid of the user and not the users node.
Finally i want to point out a huge flaw in the rules you posted in your question:
".write": "!data.exists() || auth.uid === $uid"
This rule states you can write if there isn't any data yet OR you have the correct uid. The first part of this statement is the problem because ANYONE can write to this locaion when there isn't any data. Also because $uid is a dynamic path you can add anything there like:
"users": {
"WoWIjustMadeThisUp": {
"nice": "Some huge value making you go over your limit"
}
}
If you want users to only write an initial value and after that won't be able to edit it just use a validate rule to check if there is already data at that location.

Resources