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.
Related
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', ...
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)
I'm new to Firebase and really struggling with the security rules.
I'm trying to store data for anonymous user sessions that can only be accessed by that user but as soon as I tighten up the security rules I get permission denied and can't work out why.
The structure I have is:
/userSessions/$user/user_id
The application pushes to user sessions and writes the user_id as returned by the anonymous login.
I have the following security rules:
{
"rules": {
".read": true,
"userSessions": {
"$user": {
".write": "newData.child('user_id').val() == auth.id",
"user_id": {
".validate": "newData.isString()"
}
}
}
}
}
I'm sure I'm doing something silly, but can't work out how to use the security simulator either so don't know how to go about troubleshooting this
Any help greatly appreciated
EDIT -
Problem occurs when trying to create a new entry under userSessions after authenticating anonymously.
Code:
var userSessionsRef = new Firebase('https://xxxxxx.firebaseio.com/userSessions');
var userSession;
var auth = new FirebaseSimpleLogin( userSessionsRef, function(error,user) {
if (error) {
console.log(error);
} else if (user) {
userSessionsRef.child(user.id).set({
user_id: user.id,
provider: user.provider,
created: Firebase.ServerValue.TIMESTAMP
});
userSession = new Firebase('https://xxxxx.firebaseio.com/userSessions/'+user.id);
userSession.onDisconnect().remove();
}
The set() operation you've provided runs great; no errors; there must be another issue at play here that you haven't captured in your repro (did you enable anonymous auth in Forge?). Here's a fiddle running on your security rules, copied line-for-line (just moved down one child path): http://jsfiddle.net/katowulf/wxn5J/
On a related note, your current security rules will not allow the userSession.onDisconnect().remove(); op, since records can only be written if newData() contains a user_id value (i.e. it can't be null). A better way to structure these security rules would be as follows:
{
"rules": {
".read": true,
"userSessions": {
"$user": {
".write": "$user === auth.id", // delete allowed
"user_id": {
".validate": "newData.isString() && newData.val() === $user"
}
}
}
}
}
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())",
}
},