I want allow users to create their account only if they have a token(invitation).
In my firebase Security i have:
{
"rules": {
".read": false,
".write": false,
"users": {
// allow to write if in the invitations there is child equal to token from newData()
".write":"root.child('invitations').hasChild(newData.child('token').val())",
},
"invitations":{
"$invitation":{
".read": "true"
}
}
}
}
as is in the comment i want allow to write if in the invitations there is child equal to token from newData().
From Simulator:
Attempt to write {"token":"evl6yky3vi0pmn29","name":"John"} to /users/99 with auth=null
/:.write: "false"
=> false
/users:.write: "root.child('invitations').hasChild(newData.child('token').val())"
6:52: hasChild() expects a string argument.
=> false
/users/99:<no rules>
how should I do this?
You've almost got it perfect. The only flaw here is that you're trying to write to users/99, but you've put the rule on users/.
Presumably, you meant this:
"users": {
"$user_id": {
// allow to write if in the invitations there is child equal to token from newData()
".write":"root.child('invitations').hasChild(newData.child('token').val())",
}
},
Related
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.
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', ...
Is there a way to let only the creator of the room (by uid) change the value of ready? Maybe in rules? I've no clue.
room
-L55EIcL2HfaGCKpKN9o
creatorUid: "GCKpKjFHUccihC0ikxmXjnqO82"
ready: false
user
-L55FCzXGL7IbPyNJXhI
uid: "GCKpKjFHUccihC0ikxmXjnqO82"
-L55GK540811AQl0TDYt
uid: "KRVpMnjjFHUccihC0C0ikxmXjF"
I tried:
{
"rules": {
".read": true,
".write": true,
"room": {
"$ready": {
".write": "$creatorUid == auth.uid"
}
}
}
}
But I get the error:
Line 10: Unknown variable '$creatorUid'.
Creating a room with following JS code:
let user = firebase.auth().currentUser
let room = dbRoomRef.push()
room.set({
creatorUid: user.uid,
creatorName: user.displayName,
ingame: false,
timestamp: firebase.database.ServerValue.TIMESTAMP
})
According to the documentation:
Shallower security rules override rules at deeper paths. Child rules
can only grant additional privileges to what parent nodes have already
declared. They cannot revoke a read or write privilege.
This means that the ".read":true and ".write":true will override any other rule you specify under the root node. So you might want to start by removing that ".write":true line.
The node under the "room" node is the roomID, not the ready child. The ready child is under the roomID, so you'll have to follow that structure:
{
"rules": {
".read": true,
"room": {
"$roomID": {
"ready":{
".write": "data.parent().child('creatorUid').val() == auth.uid"
}
}
}
}
}
Notice that I've used the parent() method in the rule to access the roomID node, then child() to access the creatorUid under that same node. Then I compare if it's value is equal to the auth.uid.
I tried to set some important write persmissions but I can't solve my problem. I got told that, if I add a write-rule to room, then I overwrite my room/$roomID/ingame rule.
What I'm trying to do is
Creating a room by auth users.
Set/update ingame of a room only by the creator of the room. (That works)
Rules:
{
"rules": {
".read": true,
"user": {
".indexOn": "displayname"
},
"room": {
"$roomID": {
"ingame":{
".write": "data.parent().child('creatorUid').val() == auth.uid"
}
}
}
}
}
How I call to create a new room:
let user = firebase.auth().currentUser
dbRoomRef.push().then((room) => {
room.set({
creatorUid: user.uid,
ingame: false,
})
}).catch(function(err) {
console.log(err.message)
}
)
Error message (as expected):
FIREBASE WARNING: set at /room/-L572bnuRv0_vntko-Bd failed: permission_denied
Thank you.
The error messages says that you're trying to write /room/-L572bnuRv0_vntko-Bd and have no permission to write there. That is correct, since your rules only give permission to write to /room/-L572bnuRv0_vntko-Bd/ingame.
If creatorUid is already set when you create the room, you don't have to include it in your write statement and can just do:
room.child("ingame").set(false);
If you're trying to allow everyone to create a new room (or write to an existing room) as long as they are the owner, you need to set your rules one level higher:
"room": {
"$roomID": {
".write": "newData.child('creatorUid').val() == auth.uid"
}
}
So I've set up a simple db/web form to collect some user data. Rn I am trying to figure out the rules thing but I am running into this problem - if my read flag is set to true then I can simply run this in the console
var ref = firebase.database().ref();
ref.on("value", function(snapshot) {
console.log(snapshot.val());
}, function (error) {
console.log("Error: " + error.code);
});
and expose the users which should not be the possibility. If I set read to false then I cant access the DB upfront to validate if email address is unique or not. I guess I need to achieve 2 things:
Prevent db snooping through the dev tools running any snippets
Make sure email address is unique.
p.s. My currents rules (prevent delete, prevent read, make sure POST request has certain fields):
{
"rules": {
"users": {
".read": false,
"$uid": {
".write": "!data.exists()",
".validate": "newData.hasChildren(['first_name', 'last_name', 'email', 'country', 'amount'])"
}
}
}
}
To avoid duplicates you will want a validation check in the DB rather than reading data from the client and checking (you can't trust the client).
Since there is no easy way to check for duplicate child values in a firebase base collection, you will need a separate collection to track emails and then validate your emails against that, i.e.:
{
"rules": {
"users": {
".read": false,
"$uid": {
".write": "!data.exists()",
".validate": "newData.hasChildren(['first_name', 'last_name', 'email', 'country', 'amount'])",
"email": {
".validate": "!root.child('emails').child(newData.val()).exists()"
}
}
},
"emails": {
".read": false,
".write": "!data.exists()"
}
}
}
You will then need to write the users' emails to the email collection as the users are added, e.g.:
var ref = firebase.database().ref('emails/'+email);
ref.set(uid)