I am trying to figure out best practices for a Firebase Realtime database structure when securing data. I have read about how to secure the database using Firebase Realtime Database Rules.
For example: A user adds "notes" and shares those "notes" with other users (members) who can then edit and comment those "notes". Lets consider a storage structure like the one below:
-categories
-uuid-cat1
-data
title: "my category 1"
-members
author: "uuid-user1"
-notes
-uuid-note1
-data
title: "Hello World!"
categoryId: "uuid-cat1"
-comments
-uuid-comment1
title: "Can you explain?"
author: "uuid-user2"
-uuid-comment2
title: "Certainly!"
author: "uuid-user1"
-members
author: "uuid-user1"
uuid-user2: "uuid-user2" //UPDATE 2 - This is another user with access to the note
-uuid-note2
-data
title: "Hello Universe!"
-categoryIds
uuid-2: "uuid-cat2"
-members
author: "uuid-user2"
-users
-uuid-user1
name: "Jane"
-uuid-user2
name: "Jane"
Users only have access to notes or categories if they are listed as "members/author" or "members/user-id". This is enforced by Firebase Realtime database Rules.
Would this work in on a larger scale? Let's say we store 200 000 notes.
When requesting to read all "notes" from the database, would this structure cause a performance issue in Firebase - since Firebase will have to loop thru all "notes" to determine access before returning the list?
Is there a better way (best practice) to structure the data?
UPDATE
My rules would look something along the lines of:
{
"rules": {
"notes" : {
//indexes
".indexOn": ["data/title", "members/author"],
//access
".read": "
auth.uid != null &&
query.orderByChild == 'members/author' && query.equalTo == auth.uid
",
".write": "
auth.uid != null &&
query.orderByChild == 'members/author' && query.equalTo == auth.uid
",
"$noteid": {
"data": {
"title": {
".validate": "newData.isString() && newData.val().length > 0"
}
},
"members" : {
".read" : true,
".write": true,
//validation
".validate": "newData.hasChildren([
'author'
])",
"author" :{
".validate": "newData.isString()"
}
}
}
},
"categories": {
//The same type of rules as for "notes"
},
"users": {
"$userid": {
".read": "$userid === auth.uid",
".write": "$userid === auth.uid"
}
}
}
}
My code would look somethin along the lines of:
const myUid = firebase.auth().currentUser.uid;
const ref = firebase.database().ref('notes');
ref.orderByChild('members/author').equalTo(myUid).on('value', (snapshot) => {
console.log(snapshot.key)
const notesArray = []
snapshot.forEach( (childSnapshot) => {
notesArray.push({
id: childSnapshot.key,
data: childSnapshot.val()
});
});
console.log(notesArray);
}