I store my data on Firebase with the format
{
"list": [
"id created by Firebase": {
"foo": "bar"
},
"another id created by Firebase": {
"foo": "bar"
},
...
]
}
I would like to create an index on foo, using Firebase Rules.
However, according to Firebase doc, I need to know the specific ID created by Firebase to put in the rules specification.
Does anyone know of a way to get around this?
You don't need to know the specific ID, that wouldn't be possible. You simply need to have an .indexOn rule on the parent node. https://www.firebase.com/docs/security/guide/indexing-data.html
{
"rules": {
"list": {
".indexOn": ["foo"]
}
}
}
If you need to add additional rules for the children, then you add those normally like so:
{
"rules": {
"list": {
".indexOn": ["foo"],
"$item": {
"foo": {
".validate": "newData.isString()"
}
}
}
}
}
Related
Using Firestore Security rules, I was wondering if there is anyway to directly view a parent document using path? For example, for any path in a subcollection, I would want to do the following:
match /myRootCollection/{myRootDoc=**} {
allow write: if request.path.split('/')[0] === "myRootDoc1":
}
I understand I can also just have the reference of myRootDoc1 in the subcollection's documents as so:
{
myRootCollection: {
{myRootDoc1}: {
mySubCollection: {
{mySubCollectionDoc1}: {
name: "someUser0",
parent: "myRootDoc1",
},
{mySubCollectionDoc2}: {
name: "someUser1",
parent: "myRootDoc1",
},
{mySubCollectionDoc3}: {
name: "someUser2",
parent: "myRootDoc1",
},
}
{myRootDoc2}: {
mySubCollection: {
{mySubCollectionDoc1}: {
name: "someUser3",
parent: "myRootDoc2",
},
{mySubCollectionDoc2}: {
name: "someUser4",
parent: "myRootDoc2",
},
{mySubCollectionDoc3}: {
name: "someUser5",
parent: "myRootDoc2",
},
}
}
}
}
Here, I would be able to read the mySubCollectionDocs if they are under a specific parent. The above works because I have the field directly in each doc, but is it possible to just read a mySubCollectionDoc and get its parent using path from Firestore Security without the specified field?
If I am able to, how would I able to query using node.js (as Firebase protects against any potential leaky queries)?
Thanks in advance.
Try this:
match /myRootCollection/{myRootDoc}/mySubCollection/{id} {
allow write: if myRootDoc == "xxx";
}
In firebase, my app will be creating nested data all the time. My question is do I first have to check if a key exists before i can reference it, or can i just...
const ref = firebase.database().ref("dataTree/" + childVar1 + "/" + childVar2);
ref.push({data: "this is data"});
and it will create the nested structure for me? i.e. :
{
"dataTree": {
"notChildVar1": {
"someChildName": {
"data": "test"
}
}
"alsoNotChildVar1": {
"someChildName": {
"data": "test"
}
}
}
}
Should Become...
{
"dataTree": {
"notChildVar1": {
"someChildName": {
"data": "test"
}
}
"alsoNotChildVar1": {
"someChildName": {
"data": "test"
}
}
"childVar1": {
"childVar2": {
"data": "test"
}
}
}
}
And if the above code will return an error, what can i do to test if a key exists, add it if it does not exist, and then push something in that?
Maybe you can try something like create the full content of childVar1 and insert directly in your database including the childVar2: {data: test} (I supposed that you're using RealtimeDatabase).
const ref = firebase.database().ref("dataTree/" + childVar1);
ref.push(
"childVar2": {
"data": "this is data"
}
);
You can write to any arbitrary location in the database, and any required nodes that do not exist will be created for you automatically. You don't have to create each child node individually.
Similarly, if all children of a node are deleted, the node itself will be deleted automatically (there is no such thing as an "empty" child node).
I´m learning FireBase and now at Using $ Variables to Capture Path Segments
' I read about the wildcard usage. I see they use this $othervariable.
Where is a list documentation of all variables that FireBase uses in the RealTime Databas Rules?
There is no $other variable. It's a placeholder and could be any string like $someOtherPath, or $dudesPath or $coolPath
From the docs:
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}
The 'title' and 'color' paths are accounted for and have rules set.
$other is any path other than title or color. It could easily be
"$anyPathOtherThanTitleOrColor": { ".validate": false }
I'm working on setting up validaton rules for a Firebase data structure, created using the Bolt compiler.
I'm currently having the Bolt statement below:
path /sharedEvents/{share} is Boolean[] {
read() { isMailOfCurrentUser( share ) }
create() { isOwnerOfEvent( ...) } //NOT YET CORRECT!
delete() { isOwnerOfEvent( prior(...) } //NOT YET CORRECT!
}
With this, I'm trying to achieve that:
Only users having a mail corresponding to the key of 'share' are allowed to read the data (they use this date to retrieve the key of events shared with them.
Only the owner of an event is able to add/remove the key for his event to the list of shared events.
This second point is where I'm running into trouble -I'm not able to create the create/delete rules- since I have no idea how to reference the keys of the boolean values in the validation rule...
Example data in Firebase for the above bolt statement:
sharedEvents
ZW5kc3dhc0BldmVyeW1hMWwuYml6
-BDKBEvy-hssDhKqVF5w: true
-FDKBEvy-hsDsgsdsf5w: true
-ADBEvy-hfsdsdKqVF5w: true
aXQnc251bWJlcnNAbWExbDJ1LnVz
-KBEvy-hsDhH6OKqVF5w: true
To clarify the needs on this example:
Only user with mail 'ZW5kc3dhc0BldmVyeW1hMWwuYml6' is able to read the three nested childs.
Only the owner of event '-BDKBEvy-hssDhKqVF5w' should be able to create/delete this value. (the same for the other event key/boolean pairs).
My question: is this setup going to work (and how to setup the create/delete rules)? Or is this not going to work and should I rethink/structure the data?
Any help is appreciated!
-----------------OUTPUT JSON FILE------------------------------------------
The question above has been answered, this section is showing the resulting json
"sharedEvents": {
"$share": {
".read": "<removed for readability>",
"$event": {
".validate": "newData.isBoolean()",
".write": "<removed for readability>"
}
}
},
Thanks again for your quick support!
You'll need a nested path statement to handle the restriction on the events (the nodes under /sharedEvents/$mail/$eventid). I quickly prototyped with this JSON structure:
{
"events": {
"-ADBEvy-hfsdsdKqVF5w": {
"name": "Event 1",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-BDKBEvy-hssDhKqVF5w": {
"name": "Event 2",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-FDKBEvy-hsDsgsdsf5w": {
"name": "Event 3",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-KBEvy-hsDhH6OKqVF5w": {
"name": "Event 3",
"ownerMail": "ZW5kc3dhc0BldmVyeW1hMWwuYml6"
}
},
"sharedEvents": {
"ZW5kc3dhc0BldmVyeW1hMWwuYml6": {
"-ADBEvy-hfsdsdKqVF5w": true,
"-BDKBEvy-hssDhKqVF5w": true,
"-FDKBEvy-hsDsgsdsf5w": true
},
"aXQnc251bWJlcnNAbWExbDJ1LnVz": {
"-KBEvy-hsDhH6OKqVF5w": true
}
},
"userMails": {
"peter": "aXQnc251bWJlcnNAbWExbDJ1LnVz",
"puf": "ZW5kc3dhc0BldmVyeW1hMWwuYml6"
}
}
And came up with these rules:
path /sharedEvents/{share} {
read() { isMailOfCurrentUser(share) }
}
path /sharedEvents/{share}/{event} is Boolean {
create() { isOwnerOfEvent(event) }
delete() { isOwnerOfEvent(prior(event)) }
}
isMailOfCurrentUser(share) { true }
getMailOfCurrentUser(uid) { root.ownerMails.uid }
getEventOwnerMail(event) { root.events.event.ownerMail }
isOwnerOfEvent(event) { getMailOfCurrentUser(auth.uid) == getEventOwnerMail(event) }
Ignoring any mistakes on my end, this should be the basics of the authorization structure you're looking for.
Given the two JTokens:
{ "Users": { "Name": "Carl" } }
and
{ "Users": [ { "Name": "Carl" }, {"Name": "Peter"} ] }
How can I tell if Users is a JProperty or JObject/JArray?
I need loop Users with
foreach (JObject User in myjobject["Users"]) { ... }
Solution
It was as simple as myjobject["Users"].GetType(). However, that didn't work in the Watch debugger window, but it worked at runtime. Hrmpff.
The Type property will tell you the type of the token you have.
switch(token.Type)
{
case JTokenType.Array:
break;
case JTokenType.String:
break;
}