Reputation: 127
My database structure is.
Homeland
+Ui4PSHU0kCPGpFJ6jWIJPOdLvEds
+service
+quta
+period
+55dwaSHU0kCPGpFJ6jWIJPOdLvEds
+service
+quta
+period
I want to make public "service" and "quta" childs, but only registered user can shown the "period" child.But there is an issue about able to my user directory.
First I want to test for able to my $uid.But I can't.It's work when I remove to $uid only use "Homeland".So it's didn't work
{
"rules": {
"Homeland": {
"$uid" : {
".read": true,
".write": "auth !== null"
},
},
".read": "auth !== null",
".write": "auth !== null"
}
}
This is work
{
"rules": {
"Homeland": {
".read": true,
".write": "auth !== null"
},
".read": "auth !== null",
".write": "auth !== null"
}
}
UPDATE
Change my security rules as samthecodingman mentioned.
{
"rules": {
"Homeland": {
"$uid" : {
"service": {
".read": true, // <-- publically readable
".write": "auth.uid === $uid" // <-- writable only by owner
},
"quta": {
".read": true, // <-- publically readable
".write": "auth.uid === $uid" // <-- writable only by owner
},
"period": {
".read": "auth !== null", // <-- readable by any logged in user
".write": "auth.uid === $uid" // <-- writable only by owner
}
},
},
"$other": { // <-- everywhere else not named above
".read": "auth !== null", // <-- allows read if logged in
".write": "auth !== null" // <-- allows write if logged in
}
}
}
Code
var kullanici = firebase.database().ref().child("Homeland").child(uservaluefrominput).child("service");
kullanici.on('value' ,function(datasnapshot) {
sifre = datasnapshot.val();
console.log(sifre);
});
But code and simulation both are denied the read value.
Catch the error.Note: This time I declared the user id clear.
try {
kullanici = firebase.database().ref().child("Homeland").child("Ui4PSHU0kCPGpFJ6jWIJPOdLvEO2").child("service");
kullanici.on('value' ,function(datasnapshot) {
sifre = datasnapshot.val();
console.log(sifre);
});
} catch (someError) {
console.log('got some error: ', someError);
}
Upvotes: 0
Views: 55
Reputation: 26171
It is important to note that database rules cascade. Even if you denied access to /users/$uid
to anyone other than $uid
but allowed access to /users/
to anyone, anyone would be able to modify the deeper location /users/$uid
.
In your rules above, even though you have configured rules for /Homeland/$uid
, you have allowed read/write access to the root database for any logged in user.
{
"rules": {
"Homeland": {
"$uid" : {
".read": true,
".write": "auth !== null"
},
},
".read": "auth !== null", // <-- allows read everywhere if logged in
".write": "auth !== null" // <-- allows write everywhere if logged in
}
}
To fix this, you can introduce the $others
key so that a logged in user can read/write anywhere in your database except underneath /Homeland
unless otherwise allowed.
{
"rules": {
"Homeland": {
"$uid" : {
".read": true,
".write": "auth !== null"
},
},
"$other": { // <-- everywhere else not named above
".read": "auth !== null", // <-- allows read if logged in
".write": "auth !== null" // <-- allows write if logged in
}
}
}
The next step is to restrict access to /service
, /quta
and /period
under the /Homeland/$uid
key.
{
"rules": {
"Homeland": {
"$uid" : {
"service": {
".read": true, // <-- publically readable
".write": "auth.uid === $uid" // <-- writable only by owner
},
"quta": {
".read": true, // <-- publically readable
".write": "auth.uid === $uid" // <-- writable only by owner
},
"period": {
".read": "auth !== null", // <-- readable by any logged in user
".write": "auth.uid === $uid" // <-- writable only by owner
}
},
},
"$other": { // <-- everywhere else not named above
".read": "auth !== null", // <-- allows read if logged in
".write": "auth !== null" // <-- allows write if logged in
}
}
}
However, because of the mixed permissions levels under /Homeland
, you are limited by what queries you can perform on this data. As an example, you can't just list off all the users under /Homeland
using a query because the read operation will be denied.
A query that wouldn't work would be:
firebase.database().ref('/Homeland').on('child_added', (snap) => { ... })`
To fix this in as simple a way as possible, you can split /Homeland
into /HomelandPublic
and /HomelandRegistered
based on who can access the data. The rules for this would be similar to:
{
"rules": {
"HomelandPublic": {
"$uid" : {
".write": "auth.uid === $uid" // <-- writable only by owner
},
".read": true // <-- publically readable
},
"HomelandRegistered": {
"$uid" : {
".write": "auth.uid === $uid" // <-- writable only by owner
},
".read": "auth !== null" // <-- readable by any logged in user
},
"$other": { // <-- everywhere else not named above
".read": "auth !== null", // <-- allows read if logged in
".write": "auth !== null" // <-- allows write if logged in
}
}
}
The query from before would now be changed to:
// get publicly accessible data
firebase.database().ref('/HomelandPublic').on('child_added', (snap) => { ... }) // alternatively: once('value', (snap) => {})
// get data accessible by registered users
if (firebase.auth().currentUser) {
firebase.database().ref('/HomelandRegistered').on('child_added', (snap) => { ... }) // alternatively: once('value', (snap) => {})
}
This should give you enough knowledge to adapt it to your situation and needs.
Upvotes: 1