Reputation: 9264
Naturally the users in my database have information that can be publicly accessible and other information only they should see. I'm considering two different ways to implement this.
Option 1: Have /users/$uid
readable only by that user and have /users/$uid/profile
be readable by anyone.
Option 2: Keep /users/$uid
readable only by that user and have a /profiles/$uid
that is public. This follows the recommendation for a flatter data structure, but I don't see how it is better in this case.
Upvotes: 12
Views: 5350
Reputation: 598728
The easiest way to see why the "flatter" structure is better is to look at how you'd secure it and how you'd then implement functionality.
Your first structure is:
users: {
uidOfJacob: {
stackId: 884522,
ssn: "999-99-9999",
profile: {
displayName: "Jacob Philips"
}
},
uidOfPuf: {
stackId: 209103,
ssn: "999-99-9999",
profile: {
displayName: "Frank van Puffelen"
}
}
}
You'd secure it with:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid == $uid",
".write": "auth.uid == $uid"
"profile": {
".read": true
}
}
}
}
}
One of the main reasons for having public information is to be able to show a list of that information. In JavaScript:
ref.child('users').child(???).child('profile').on('child_added'...
This won't work, because what do we put in ???
. Firebase operations need to be able to read the entire list from one location, and the user needs to have read permission on that entire location (not just to the individual child nodes).
If we structure the data to separate the public information from the private information, we get:
users: {
uidOfJacob: {
stackId: 884522,
ssn: "999-99-9999",
profile: {
displayName: "Jacob Philips"
}
},
uidOfPuf: {
stackId: 209103,
ssn: "999-99-9999",
profile: {
displayName: "Frank van Puffelen"
}
}
},
"profile": {
uidOfJacob: {
displayName: "Jacob Philips"
},
uidOfPuf: {
displayName: "Frank van Puffelen"
}
}
You'd secure it with:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid == $uid",
".write": "auth.uid == $uid"
}
},
"profiles": {
".read": true,
"$uid": {
".write": "auth.uid == $uid"
}
}
}
}
Now to get a list of the public user profiles, you'd do:
ref.child('profiles').on('child_added'...
This will work, because everyone has read permission on profiles
.
Upvotes: 27