0
votes

i am new to firebase. i have set up a firebase realtime database and can read from and write to it if the read and write rules are set to true.

i have a problem with authentication.i have set up authentication for google and email plus password.

my goal is to allow any user to read the data but only one user (myself) can write data after logging in using a single email address and password.

i can successfully read from and write to the database if i login with google (with rules set to: auth != null.)

i can also read from and write to the database using the same rules (auth != null) if i log in with the email address and password.

i don't know how to set it up to only allow write access for the single user logging in with an email address and password.

i have tried including a user node in the rules but i can't get access when using the simulator (see below) and i don't know how to include the uid (which i can get after logging in) when building the reference - this is the reference i currently use (which works with the read and write rules set to true):

DatabaseReference databaseReference = mRootReference.child("Action_helper/1/Action_table_of_contents");

i have not included a users node in my database as i am assuming that is taken care of by firebase authentication.

here is the layout of my data:

enter image description here

i have tried the simulator using various rules options. testing access using these settings in simulator (choosing the Custom provider option):

Auth {"provider" : "firebase", "uid" : "Rp3OgoaABMN3hqTv0aF29ECQRCQ2"}

note: i get the provider and uid from Firebase object after logging in with an email address and password which i have set up in Firebase authentication:

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    if (user != null) {
        // User is signed in
        userId = user.getUid();
        String provider = user.getProviderId();

enter image description here

enter image description here

i would appreciate some help in 1) formulating my rules, 2) if and how i should change my data structure, and finally 3) how to include the uid in the database reference which i'll use to write data to the database.

thanks

2

2 Answers

1
votes

There is no users node so, defining in rules would not help. I think the rule that may work would be something like below (assuming 0 and 1 are uid):

   {
      "rules": {

         "Action_helper":{

           "$uid":{

               //user-based security
               ".read": "auth != null && $uid === auth.uid",
               ".write": "auth != null", 

           }//$uid

        }//Action_helper

   }// rules
}

Examining above rules by default if we do not define rules then it is false i.e. at Action_helper it is false for both read and write. When it comes to the node uid (where $ denotes wild card) then, we check if the user id of logged in user is same to uid of this node and define rules accordingly.

I highly recommend to go through the link The key to Firebase security - Google I/O 2016 , it is very helpful, easy to follow, and best explanation I found so far with demo example.

The data layout will depend on your requirement and screens. Although Firebase allows 32 level of nesting it is highly recommended to nest nodes as less as possible. And other important thing to think about the data layout is to keep data as denormalize as possible even if we have to make copies of fields across the nodes.

To include uid in database reference you can keep on appending each child:

DatabaseReference databaseReference = mRootReference.child("Action_helper).child(uid).child("Action_table_of_contents");

So, here we are referring from root node to child "Action_helper" and going further down to it's child that matches uid and of that uid we are referencing to the child "Action_table_of_contents".

0
votes

thanks for the help. i managed to get it working (partly) but am not sure that i am doing it correctly. here is my data structure (i have changed the names)- there is one user node (using the authentication uid), and two child nodes which contain the data:

enter image description here

and here are my rules:

enter image description here

essentially it works in the simulator but in code, i am able to log in and read and write. BUT i now have a problem, if i don't log in then the uid passed in the query reference is null, if i put a dummy value as the uid then i can't access the data at all (as the data is under users/the_valid_uid node and the dummy uid does not match the_valid_uid).

so how do i build a database reference without hard coding the valid user's uid? so that i can access the data in the Addiction_items and table_of_contents_items nodes (my aim is to allow anyone to read data in both nodes but to only allow one user (myself) to be able to write to both nodes after logging in with my email address and password?

thanks