Firebase rule to avoid parent overwrite - firebase-realtime-database

In my db, I have a node like this on root:
-dbroot
--usernameuid
---user1:'someid'
---user2:'someid'
---user3:'someid'
...
for creating this I am using code below:
database().ref('usernameuid/' + that.state.username).set(auth().currentUser.uid).then(() => {
...
Recently, I am not sure how it happened but somebody managed to delete or overwrite all --usernameuid node.
As my investigation, I found out blank username passed despite i am checking username with regex.
Anyway, firebase got blank username (that.state.username) and overwrote like --usernameuid: 'someid' and all data gone.
For prevent this not to happen again in future, (app is live so cant modify code) what kind of firebase rule can i write for:
user can only add child to --usernameuid
can't overwrite all like --usernameuid: 'something'
can't delete anything under --usernameuid

I found solution like this:
{
"rules": {
".read": "auth.uid !== null",
...
"otherchild1": {
".write": "auth.uid !== null",
},
"otherchild2": {
".write": "auth.uid !== null",
},
...
"usernameuid": {
"$username" : {
".write": "auth.uid !== null",
}
},
Summary: No rule at parent, specify .write in child you want. But on root, you need to delete global .write rule and specify seperately for each child hence firebase does not support cascade rules.

Related

Firebase Write Rule for Item with nested approved users

I have a realtime database with users and teams. Each team has a list of approved users under settings.. I want to create a rule so only approved users can write to their team...
something like:
I would not recommend Custom Claims because they are very limited in space.
You can write the rule very easy using the exists clause:
"teams": {
"$team_id" : {
".read": "true",
".write": "auth != null && root.child('teams/'+$team_id+'/settings/approvedUsers/'+auth.uid).exists()"
}
}
This rule will also deny a creation if there is no user on that path. You can then create the team from the backend or mark some users as admins or if anyone can create a team you can add a clause that checks if there is any data before and if not the rule befor should not get used. Something like this:
"teams": {
"$team_id" : {
".read": "true",
".write": "!data.exists() || (auth != null && root.child('teams/'+$team_id+'/settings/approvedUsers/'+auth.uid).exists())"
}
}
Here we check if the team already exists and if not anyone can create it. If it exist only users under approvedUsers can change it. That way the first user creating the team can create it. But don't forget that he needs to add himself to approvedUsers.
If you are working with emails for users that are not already in the system you could use the email instead of an uid as key and just set the value of the key to true. Just make sure te remove all chars that are not allowed as key from the email withe something like:
email.replace('.','')
And also do the same in the rules like:
"teams": {
"$team_id" : {
".read": "true",
".write": "auth != null && root.child('teams/'+$team_id+'/settings/approvedUsers/'+auth.token.email.replace('.','')).exists()"
}
}
The databse would then look like:
teams
teamID1
approvedUsers
email1#test.com: true
email2#test.com: true
teamID2
approvedUsers
email1#test.com: true
email3#test.com: true

How to overcome the cascade in Firebase Realtime Database rules?

Given the following data structure:
items
categoryId1
itemId1
name
amount
dateAdded
itemId2
name
amount
dateAdded
categoryId2
itemId3
name
amount
dateAdded
I'd like to set the following rules:
If the user is logged-in using foo#gmail.com or bar#gmail.com, they should be able to add and update items.
Other logged-in users should be able to update only the item's amount.
I've tried the following Realtime Database rules:
{
"rules": {
"items": {
"$categoryId": {
"$itemId": {
".write": "auth !== null && auth.provider === 'password' && (auth.token.email === 'foo#gmail.com' || auth.token.email === 'bar#gmail.com')"
"amount": {
".write": "auth !== null && auth.provider === 'password'"
}
}
}
}
}
}
But, this doesn't allow someone_else#gmail.com to update the item's amount. The following promise gets rejected with "Permission Denied":
app
.database()
.ref(`items/${categoryId}`)
.push({
name,
amount,
dateAdded,
})
I know that with Realtime Database, rules work from top-down, with shallower rules overriding deeper rules.
So, what's the idiomatic way to overcome this? Is it possible to achieve the requirements above using this data structure, or do I need to restructure my data?
The problem was that the .write needed to be under $categoryId, not under $itemId. Thanks Frank!

confusing with firebase rules (read and write)

I'm using Firebase to make an IOS app but it seems i get a strange issue.
here's my current rules for the database:
{
"rules": {
".read": "auth == null",
".write": "auth != null"
}
}
In ma main app, I'm able to read and write as user or as non user to the database.
Im using a second app to edit my database by remote. they have the same firebase project so the same database.
Im registered on this second app but I'm not able to write and read on the database.
the consol say "permission denided".
If I simply change my database rules to :
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I'm able to read and write on it.
Please help me to understand it.
{
{
"rules": {
".read": "auth == null",
".write": "auth != null"
}
}
In this first rule case .read is set to auth == null, which means that you will only be able to read from your database when not authenticated/signed in.
Changing .read to auth != null means you are only able to read from your database when authenticated.
More information is available here in the Firebase documentation.
As #creativecreatorormaybenot answered ".read": "auth == null" will only allow reading of the data when the user is not logged in.
If you want to allow both authenticated and unauthenticated users to read the data you'll want to use:
".read": true

Unable to retrieve data from Firebase unless user is signed in

I am trying to retrieve some data from Firebase but it won't retrieve anything unless I am signed in first. I've already tried editing my database's rules and setting the values to true.
Here are the Rules
{
"rules": {
".read": true,
".write": true
}
}
In your Firebase console, you can click on Database --> Rules (Tab)
In there you can specify whether or not you need to be authenticated in order to retrieve your data.
"rules": {
".read": "auth == null",
".write": "auth == null"
}
I would only leave it this way for testing. It's pretty easy to setup the simple anonymous Auth through Firebase :) Best of luck!
In case if you don't want any security you can use the below rules
"rules": {
".read": "true",
".write": "true"
}

Firebase Rules settings

I decided to use Firebase in an old objectiv C iOS app.
I installed what I needed following the instructions given here:
Add Firebase to your iOS app right after login into Firebase.
Then I followed the instructions given here:
https://firebase.google.com/docs/database/
in order to work with a database.
At this point it basically works, I can write some data.
Nevertheless I have this issue about the Rules settings.
I followed the information given here:
https://firebase.google.com/docs/database/security/quickstart
But if I set my rules like this:
{
"rules": {
".read": true,
".write": true
}
}
it works as expected. On the other hand, if I set them like this:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
which is the default and should allow me to write data from my app, it does not work.
What is the problem?
If you don't want the user to login, you could automatically authenticate the user anonymously.
Authenticate with Firebase Anonymously on iOS
Then you could use:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
After reading your comment in reply to cartant,it is clear that you want to allow your app users to access your database for reading and writing , without need of signing in.
I would also like to do this without requesting the user to login. Is this possible?
YES
It is possible to allow your users to access your DB without any signing process.
Actually
{
"rules": {
".read": true,
".write": true
}
}
this rule says that you are providing read and write permission to your user without signing in.
On the other hand
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
in this rule you are mentioning that your authentication ("auth != null")has to be performed before granting the read , write permissions to your user.
So to accomplish your goal just use the default rule i.e rule without authentication.

Resources