This is the error I receive:
"error" : "Index not defined, add \".indexOn\": \"release/date\", for path \"/north_america\", to the rules"
And this is the structure of my firebase data:
And my added rules don't seem to work, any help?
Try updating your database rules again with the index another level down.
"likes": {
"north_america": {
"$someid": {
"release": {
".indexOn": ["date"]
}
}
}
Also you should be able to wildcard out north_america so it works globally.
Related
I'm playing around with a simple web app that uses JS to interact with a Firebase Realtime Database that looks something like this:
{
"some-collection": {
"some-obscure-long-uuid": {
"name": {
"info_1": "foo",
"info_2": "bar"
}
},
"some-other-obscure-long-uuid": {
"name": {
"info_1": "foo",
"info_2": "bar"
}
}
}
}
The idea is not to use any form of authentication but to allow users to get a random shareable link, say www.myapp.com/some-obscure-long-uuid/index.html, so that other people can see and perform changes in real-time. With this in mind, I'm trying to find a set of rules that:
Don't expose the children of "some-collection" publicly
Give read and write access to the "some-obscure-long-uuid" child to anyone with the secret URL www.myapp.com/some-obscure-long-uuid/index.html
I've read the docs and suspect this can be achieved using the newData variable, but cannot get my head round to how to use it. Hope this makes sense and thanks a lot!
I'm not sure if I understood correctly but below should give read-write access to anyone who is attempting to read or write to path some-collection/[some-obscure-long-uuid] and your some-collection parent would be safe from getting queried without anyone specifying the full path.
{
"rules": {
"some-collection": {
".read": "false",
".write": "false",
"$some-obscure-long-uuid": {
".read": "true",
".write": "true",
}
}
}
}
I am struggling with what seems to be a very trivial task. I am receiving the following warning from Firebase when doing a simple query:
Query:
admin.database().ref('/dispatch/')
.orderByChild('shipmentKey')
.equalTo(shipmentKey)
.once('value')
.then(
Warning:
FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "shipmentKey" at /dispatch to your security rules for better performance
My database looks like the following:
And my database.rules.json looks like this:
{
"rules": {
"dispatch": {
".indexOn": "shipmentKey"
}
}
}
and have also tried:
{
"rules": {
"dispatch": {
".indexOn": ["shipmentKey"]
}
}
}
I have already read all the other stackoverflow questions on this topic and cannot seem to rid our project of this warning, any help would be greatly appreciated.
UPDATE 06/22/2017
I have solved the problem, and it was very simple. It turns out that firebase deploy wasn't actually deploying the database rules so the database.rules.json was not being uploaded. I simply ran the following command:
firebase deploy --only database
And everything works great now! Thanks to Bob Snyder for helping point this out. Hope this helps someone else out there!
You need to put all the indexes in square brackets, separated by a comma if you have more than one.
{
"rules": {
"dispatch": {
".indexOn": ["shipmentKey"]
}
}
}
I have firebase security something like this
{
"rules":{
"item":{
"$items":{
".write": "root.child('user').child('is').val() === true"
}
},
"user":{
"$is": "....."
}
}
}
But root file is only getting "item" section not main "rules" section How can I solve this issue?
Thank you
You can’t do that. The root variable is the root of your dataset, not the rules. As far as I know, there’s no methods to traverse the rule set - only the data.
I have created a database in Firebase which looks like:
Now I go into a REST client and issue this query:
https://movielens3.firebaseio.com/movieLens/users.json?orderBy="age"&startAt=25&print=pretty
It gives me an error:
"error": "Index not defined, add ".indexOn": "age", for path "/movieLens/users", to the rules"
So I go in the rule section and define this rule:
{
"rules": {
"users" : {
".indexOn": ["age", "gender", "occupation", "zipCode"]
},
".read": true,
".write": true
}
}
But I still get the same error.
You're defining indexes for /users. There is no child node users straight under the root of your tree, so those indexes will be empty.
Since you query /movieLens/users, that's exactly where the index has to be defined:
{
"rules": {
"movieLens": {
"users" : {
".indexOn": ["age", "gender", "occupation", "zipCode"]
},
".read": true,
".write": true
}
}
}
Update for problem in the comments:
You're storing the user's age as a string, so cannot filter them as a number. The solution is to fix your data and store it as a number.
But in the meantime this query somewhat works:
https://movielens3.firebaseio.com/movieLens/users.json?orderBy="age"&equalTo="35"
In JavaScript:
ref
.orderByChild('age')
.startAt('35')
.limitToFirst(3)
.once('value', function(s) {
console.log(JSON.stringify(s.val(), null, ' '));
}, function(error) {
if(error) console.error(error);
})
The "somewhat" being that it does a lexical sort, not a numerical one. Fix the data for a real solution.
Note that you're also ignoring Firebase guidance on structuring data by storing the data as an array. This was already causing problems for me in the REST API, which is why I dropped the print=pretty. I highly recommend that you read the Firebase programming guide for JavaScript developers from start to finish and follow the advice in there. The few hours that takes now, will prevent many hours of problems down the line.
For the past few weeks i've been exploring Firebase and its features to build a web app, but I've kind of ran into a wall when it comes to security rules.
I've build a data structure on Firebase but I'm not sure if it follows best practices (if it doesn't, feel free to suggest anything different about it):
{
"groups" : {
<GROUP_KEY>
"name": "",
"rels": {
"users": {
<RELS_USERS_KEY>
"key":"" (USER_KEY)
},
"notes": {
<RELS_NOTES_KEY>
"key":"" (NOTE_KEY)
}
},
"isPrivate": true
},
"users": {
<USER_KEY>
"email": "",
"rels": {
"friends": {
<RELS_FRIENDS_KEY>
"key":"" (USER_KEY)
}
},
},
"notes": {
<NOTE_KEY>
"title": "",
"description": "",
"rels": {
"files": {
<RELS_FILES_KEY>
"key":"" (FILE_KEY)
}
}
},
"files": {
<FILE_KEY>
"mode": "",
"url": ""
}
}
The application flow is as follows:
The user signs up: a key is created on "users";
Is redirected to "Groups" view, where he should be shown only
groups that have his ID in RELS > USERS, or that has
"isPrivate":"false";
As the user creates a Group, a new group is added with his ID in RELS > USERS;
Entering the Group view, he should only see notes that are in RELS > NOTES for that group.
The rest of the logic follows the same principle, and I believe that if I can get through the first hurdle of understanding the Firebase security rules and applying them to this case, I can get through the rest.
I've tried a couple of rules, but I can't seem to get any feedback at all from the web application, debugging this has been a trial-and-error process, and its not really working.
Could someone help me at least understanding the logic behind it ? I've read all of their tutorials but they all seem very shallow with no deeper examples on complex structures.
Thanks for the help.
EDIT
I've added the debug:true flag to the login (thanks #Kato), but I'm still getting no feedback on the rules. With the rules as below, I still enter the "Groups" view, but get no feedback on the console, and the logged-in user sees groups he shouldn't:
{
"rules": {
"groups": {
".read": "data.child('rels').child('users/' + auth.user).exists()",
".write": "data.child('rels').child('users/' + auth.user).exists()"
}
}
}
As for the rules I've tried, they were countless, but this is the most recent one (still no feedback).
Maybe I'm missing something ?
Thanks again.
Rules cascade. That is, if any rule allows read, then you cannot revoke it later in a nested child. In this way, you can write rules like the following:
"$record": {
// I can write the entire record if I own it
".write": "data.child('owner').val() === auth.uid",
"foo": {
// anybody in my friends list can write to foo, but not anything else in $record
".write": "data.parent().child('friends/'+auth.uid).exists()"
},
"bar": {
// this is superfluous as permissions are only "granted" and never "revoked" by a child
".write": false
}
}
Note how, because I am the owner, I can also write to foo and to bar, even though bar has tried to revoke my read privilege.
So in your case above, your rules declaration lists read: true which allows full read access to the entire repo. Change that to false and you'll see better results.