I have a locations-orders table that looks like this:
{
"0BW3H9T3R7HJB" : {
"orders" : {
"01750ea0-4980-4bc4-58b2-988c02324e671478636582396" : {
"created_at" : 1478636560000,
},
"01750ea0-4980-4bc4-58b2-988c02324e671478636582483" : {
"created_at" : 1478636560000,
}
}
}
Each location-orders node has an orders node with multiple keys/objects. Those objects have a created_at field on it.
I added this to my database Rules:
{
"rules": {
".read": true,
".write": true,
"users": {
".indexOn": "merchantId"
},
"merchants": {
".indexOn": "locations"
},
"locations-orders": {
".indexOn": ["orders/created_at"]
}
}
}
However, Firebase is still complaining that I'm missing an index:
Using an unspecified index. Consider adding ".indexOn": "created_at" at /locations-orders/1JS53G0TT5ZQD/orders to your security rules for better performance
Am I supposed to run something to create the index? Or is it written incorrectly?
=== UPDATE ===
I changed my file to look into:
{
"rules": {
".read": true,
".write": true,
"users": {
".indexOn": "merchantId"
},
"merchants": {
".indexOn": "locations"
},
"locations-orders": {
"$location_id": {
".indexOn": ["orders/created_at", "orders/status_updated_at"]
}
}
}
}
but I still get the same warning:
Using an unspecified index. Consider adding ".indexOn": "created_at" at /locations-orders/1JS53G0TT5ZQD/orders to your security rules for better performance
If you look at your data structure, there is no orders/created_at under /location-order/$orderId.
{
"rules": {
".read": true,
".write": true,
"users": {
".indexOn": "merchantId"
},
"merchants": {
".indexOn": "locations"
},
"locations-orders": {
"$someid": {
".indexOn": ["orders/created_at"]
}
}
}
}
Try this:
{
"rules": {
".read": true,
".write": true,
"users": {
".indexOn": "merchantId"
},
"merchants": {
".indexOn": "locations"
},
"locations-orders": {
"orders": {
"$orderid": {
".indexOn": "created_at"
}
}
}
}
}
Related
How to set security rules for Firebase realtime database structure as below:
users: {
...
...
...
},
books: {
...
...
...
},
sales: {
...
...
...
}
Condition: Firebase auth is set to email/password and only user logged-in with emails ending with domain [mydomain.co.in] must be able to read or write to parent node. Without using custom claims.
Adding below security rules is applied/working only for the the first parent node [users] and not to all, what is a miss here?
{
"rules": {
".read": false,
".write": false,
"users": {
".read": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".write": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".indexOn": "name"
},
"books": {
".read": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".write": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".indexOn": "title"
},
"sales": {
".read": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".write": "auth.token.email.matches(/.*#mydomain.co.in$/)",
".indexOn": "price"
},
}
}
Try below enclosed within uid field?
Reference https://firebase.google.com/docs/reference/security/database
same code works with auth.token.email.matches(/.*#mydomain.co.in$/)
{
"rules":{
".read": "false",
".write": "false",
"users":{
"$uid":{
".read":" auth.token.email.endsWith('#mydomain.co.in')",
".write":" auth.token.email.endsWith('#mydomain.co.in')",
".indexOn":"name"
}
},
"books":{
"$uid":{
".read":" auth.token.email.endsWith('#mydomain.co.in')",
".write":" auth.token.email.endsWith('#mydomain.co.in')",
".indexOn":"title"
}
},
"sales":{
"$uid":{
".read":" auth.token.email.endsWith('#mydomain.co.in')",
".write":" auth.token.email.endsWith('#mydomain.co.in')",
".indexOn":"price"
}
}
}
}
Auth Token payload
{
"token":{
"email": "test#mydomain.co.in"
}
}
I have a firebase real-time database structured like this:
{
"USERS": {
"user-1": { ... },
"user-2": { ... }
}
"GROUPS": {
"group-1": {
"id": "group-1",
"AUTH": {
"user-1": true,
}
},
"group-2": {
"id": "group-2",
"AUTH": {
"user-2": true
}
},
"group-3": {
"id": "group-3",
"AUTH": {
"user-1": true,
"user-2": true
}
}
}
}
I know that I can give read permissions that would give read access to users that only belong to a specific group, like this:
{
"rules": {
"GROUPS": {
"$groupId": {
".write": false,
".read": "auth != null && data.child('AUTH').child(auth.uid).exists()"
}
}
}
}
I'm trying to find a query + rules combination that would return me all the groups that the logged in user belongs to.
For example:
A query and firebase rule change that for logged in 'user-1' returns a snapshot of:
{
"group-1": {
"id": "group-1",
"AUTH": {
"user-1": true,
}
},
"group-3": {
"id": "group-3",
"AUTH": {
"user-1": true,
"user-2": true
}
}
}
OR
[
{
"id": "group-1",
"AUTH": {
"user-1": true,
}
},
{
"id": "group-3",
"AUTH": {
"user-1": true,
"user-2": true
}
}
]
querying for the "GROUPS" reference now give me a 'permissions denied' error.
adding '.read=true' to the GROUPS:
{
"rules": {
"GROUPS": {
".read": true,
"$groupId": {
".write": false,
".read": "auth != null && data.child('AUTH').child(auth.uid).exists()"
}
}
}
}
or any combination for '.read' that passes the condition, gives everyone access to all the data.
Is there a way (in the current structure) to query the database and get from the "GROUPS" branch all the groups that I belong to by adding some restriction to the rules?
or do I need to maintain under each user the list of the group that he belongs to?
Here is my data.
"users" : {
"user1": {
"1234": {
"role": "admin"
},
"1235": {
"role": "normal"
}
},
"user2": {
"1236": {
"role": "admin"
},
"1237": {
"role": "normal"
}
}
}
And here is rules for that.
"rules" {
"users": {
".read": "root.child('users').child('user1').child(auth.uid).child('role') === 'admin'"
}
}
But the rule doesn't work. I seem the auth.uid isn't gotten correctly.
Try this :-
{
"rules": {
"users": {
"user1": {
"$user_id": {
".read": "$user_id === auth.uid && root.child('users/user1/' + $user_id + '/role/').val() === 'admin' "
}
}
}
}
}
Here is the database schema:
Here are the rules:
"notifications": {
"$year": {
".read": "false",
".write": "!data.exists()",
"$month": {
".read": "false",
".write": "!data.exists()",
"$day": {
".read": "false",
".write": "!data.exists()",
"$hour": {
".read": "false",
".write": "!data.exists()",
"$minute": {
".read": "false",
".write": "!data.exists()",
"$data": {
".read": "false",
".write": "!data.exists()"
}
}
}
}
}
}
How can I validate (using ".validate" or ".write" rules) that the users can enter only integers into that tree? Or is there some workaround?
What I am trying to achieve is to create write only (no deletes, or updates) log that has some structure and will be processed later. I can change the structure for example to something like 2015-10-6-17-30 for the key, or something else. I just can't believe that Firebase does not have something for this situation.
Update:
This is not duplicate, I am searching for a workaround, or something else that will help me achieve what I am after.
To validate that a key is a number:
{
"$key": {
".validate": "$key.matches(/^[0-9]+$/)"
}
}
But please read about array-like behaviors in Firebase. Hint: probably use a prefix like "y2015", "m12", etc. to avoid some unexpected results with using numbers.
If using push IDs works for you, here's a security rule structure you could use.
{
"notifications": {
"$notification_id": {
".write": "!data.exists()",
".read": "false",
".validate": "newData.hasChildren(['time', 'state', 'message'])",
"time": {
".validate": "newData.val().matches(/YOUR REGEX/)"
},
"state": {
".validate": ""
},
"message": {
".validate": ""
}
}
}
}
Obviously you'll need to fill in the blanks. The main thing here is that you can use a regex to match the time field.
The actual data would look like:
{
"notifications": {
"-K-z5koYf8mYZu5OfSGR": {
"time": "2015-10-06-17-30",
"state": 1,
"message": "foo"
},
"-K-z5koYf8mYZwgwsfGx": {
"time": "2015-10-06-17-30",
"state": 1,
"message": "bar"
}
}
}
My firebase data looks like this-
My security rules are-
{
"rules": {
"users": {
"fred": {
".read": true,
".write": true
},
"wilma": {
".read": "auth.id == '1'",
".write":true
},
"$other": {
"name": {
".read": true,
".write": true
}
}
}
}
}
First click on Authenticate button.
Path you should enter is /users/wilma