Firebase indexOn a logged in user to the application - firebase

Does Firebase allow for dynamic indexes for searches!?
I have the following structure:
PlayerInPool: {
12345: <- PoolId
DUmwewIfzAbfWZN4NjS8mhX82 : true <- UserId
LpWgezRkC6EWS0sjXEWxhFl2 : true
etc...
}
}
I put an observer as such:
ref.queryOrdered(byChild: (Auth.auth().currentUser?.uid)!).queryEqual(toValue: true).observe(.value, with: { snapshot in ...
When I run the app I get the following warning:
[Firebase/Database][I-RDB034028] Using an unspecified index.
Consider adding ".indexOn": "DUmwewIfzAbfWZN4NjS8mhX82" at
/PlayerInPool to your security rules for better performance
I am trying to do the following in the 'Rules' in Firebase
"PlayerInPool": {
".indexOn" : "auth.uid"
}
but it wont allow it stating that :
Error saving rules - Line 45: Invalid key: auth.uid. Index must be
either .value or declared on a valid path
How can I get this to work!?
Updated Comment
If I invert the structure as suggested I would get this:
PlayerInPool: {
DUmwewIfzAbfWZN4NjS8mhX82: <- UserId
12345 : true <- PoolId
98765 : true
LpWgezRkC6EWS0sjXEWxhFl2:
12345 : true
}
}
I'm not entirely sure how this changes anything!?

Related

Firebase rules, deny edits after initial write, write depend on value

I got an "object" on my realtime database.
-MHHP5ZSmLKG_xeA9SLJ
0NThxhcHIPgOJGZC1MyE3Fg0NUc2
XCEI5dQxP8YxaChrF5O061eyFv32
creatorID: "7Pao7pDRaFUVWM9c234Qq44UwoE3"
message: "I wish I knew, why the world is is getting craz..."
messageID: "-MHHP5ZSmLKG_xeA9SLJ"
timestamp: 1600184270739
timestampReverse: 998399815846742
Two questions.
Is there a way for me to make it, such that creatorID: can't be written to after the original initialization.
"creatorID" : {
.write : "false"
}
Does this work, or would it also block initial write? Essentially I'm looking to make it unable to be edited.
And is there a way to writea rule such that only if auth.uid and creatorID.value is equal, can you edit the message:
"message" : {
.write : "auth.uid == creatorID.value"
}
Best regards,
Sam
If you want the creatorID field to only be writeable upon creation, you can do:
"creatorID" : {
.write : "!data.exists()"
}
If you want the message field to only be writeable by its original author, that'd be:
"message" : {
.write : "auth.uid == data.child('creatorID').val()"
}

basic functionnalities doesn't work for firestore security

I want to secure my Firestore database with the integrated code editor in the firebase website. My aim is to check before reading document called "moyenne", if:
numr == request.auth.token.phone_number || numr in get(/databases/$(database)/documents/Profil/$(request.auth.token.phone_number).resource.data.numbers
I tried this:
//first try
match /Note/{numr}/moyenne/moyenne {
allow read:
if (numr == request.auth.token.phone_number || numr in get(/databases/$(database)/documents/Profil/$(request.auth.token.phone_number)).resource.data.numbers);
}
//second try
match /Note/{numr}/moyenne/moyenne {
allow read:
if (numr == request.auth.token.phone_number ||
numr in get(/databases/$(database)/documents/Profil/$(path(request.auth.token.phone_number))).resource.data.numbers);
}
But unfortunately, it doesn't work.
Error for the first try (the test number is +91909090909):
Call the [get] function with a path to a non-existing resource: / databases /% 28default% 29 / documents / Profile /% 2B33651177261
Error for the second try:
Error: simulator.rules line [14], column [17]. Property resource is undefined on object.
PS: structure of the profil document:

Firebase security rule with read and write at separate locations

I have my Realtime database schema designed like this.
"roles" : {
"uid-1" : "user",
"uid-2" : "moderator",
"uid-3" : "user" // ... and so on
}
"photos" : {
"uid-1" : {
"photo" : "..."
"date" : "..."
}
// ... and so on
}
And my security rules are defined like this. Only relevant part is shown.
"photos" : {
"$key" : {
".read" : "auth.uid == $key || root.child('roles/'+auth.uid).val() == 'moderator'",
".write" : "auth.uid == $key"
}
}
As it is clear from the above snippet I want the users to be able to read or write to their own key under photos node. As for the moderators I want them to be able to read any users data.
At first it seems to work as expected but there is a small catch. According to fire-base if no rule is specified at a node it will be considered as false. That means moderator can now read every users data but only if he explicitly asks for certain UID. In other words reading photos/<uid> is allowed but photos/ as a whole is not allowed.
A potential solution was to move read statement to make it direct child of photos node. But there I cant enforce $key for other users.
One might try to split the rule and define at both locations but that would not work because according to firebase docs shallow rules will override the deeper rules.
You seem to have two requirements:
Each user can read and write their own photos.
A moderator can read photos of all users.
That can be enforced in server-side security rules like this:
"photos" : {
".read" : "root.child('roles/'+auth.uid).val() == 'moderator'",
"$key" : {
".read" : "auth.uid == $key",
".write" : "auth.uid == $key"
}
}
The permission that an moderator gets from /photos carries down onto each user's photos. This permission cannot be revoked at a lower level. But you can definitely give users *additional** permission at a lower level, which is what these rules do.

Firebase database rules: Use variable before it is declared in the database path

I am working on a Firebase app where users ("students") just have access to some courses (these courses are declared in the users parts of the database).
Every user needs to have access to "courses" in the database, but I cannot give general read rules to this path, because it will overwrite any deeper path security rules as well.
I tried to just use the Firebase rule I used at "courses/$course_id" for "courses", but it does not work because the variable "$course_id" is not declared at this point.
My Firebase database structure for "courses" is as following:
"courses" : {
"76g" : {
"questions" : {
"123h9014bsd" : true,
"56a" : {
"firstWrongAnswer" : "B",
"question" : "A",
"rightAnswer" : "A",
"secondWrongAnswer" : "C"
}
},
"title" : "Course1"
}
These are the Firebase rules I wrote to achieve what I described above:
"courses": {
//error for the following line: Error saving rules - Line 9: Unknown variable '$course_id'.
".read": "root.child('students').child(auth.uid).child('courses').hasChild($course_id)",
"$course_id": {
".read": "root.child('students').child(auth.uid).child('courses').hasChild($course_id)
}
}
Can this problem even be changed by just using Firebase database rules or do I need to change my database structure?

How do I give read/write access to all nodes with Firebase rules?

Default setting gives full access:
{
"rules": {
".read": true,
".write": true
}
}
For the sake of testing my understanding of rule-writing from the Firebase guide and documentation, I'm (now retreating to) trying to achieve the same results by writing rules for the 4 parent nodes.
If it makes a difference, the first two nodes only have values, no children. **Sidequest: are they still called nodes?
The rules below cause the same behavior as when the rules above are changed to false read and write.
{
"rules": {
"myNode1": {
".read" : true,
".write" : true
},
"myNode2" : {
".read" : true,
".write" : true
},
"myNode3" : {
".read" : true,
".write" : true
},
"myNode4" : {
".read" : true,
".write" : true
}
}
}
What is wrong with my rules?
UPDATE/context:
I have an authDataCallback that stops running here (within the if (authData) { clause):
var ref = new Firebase("https://<my>.firebaseio.com")
ref.once("value", function(snapshot){
Found that if I change the ref var to something more specific: var ref = new Firebase("https://<my>.firebaseio.com/myNode1"), the authDataCallback runs in entirety.
Surely it won't be necessary to produce snapshots of the entire database; this was a confused way of getting the data I need. I've updated, but I'm still confused about why the rules held up the callback considering I gave read and write to the whole database.
I think this is the answer based on the info provided:
The two sets of rules you posted are different. The first set
{
"rules": {
".read": true,
".write": true
}
}
allows everyone read and write access to every node, including the parent node, within your firebase at
https://<my>.firebaseio.com
The second set of rules allows everyone access to specific nodes within your firebase reference but blocks access to all other nodes including access to the parent node. In the update the code is trying to read the parent node which has no rules defined for it so by default read and write are false.
So say you have the following structure:
https://whirlygig.firebaseio.com
Whirlygig
someRandomData: "3.141"
otherRandomData: "6.02"
myNode1
firstName: "first"
lastName: "last"
myNode2
first: "first"
last: "last"
With your first set of rules, everyone can access someRandomData as well as the myNode1, myNode2 etc.
With the second set of rules, everyone can access ONLY myNode1 and myNode2 but cannot access someRandomData

Resources