Skip to content
Advertisement

Authorize read if uid matches write uid – Realtime Database

I have a functioning app where users can signup/login, upload images, and view images that have already been uploaded by themselves, they can’t see other’s images and vice versa. My rules are therefore UID of requesting user = uid of user who uploaded the image.

Here is the code:

package com.example.auth;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;

public class ShowActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ArrayList<Model> list;

    private MyAdapter adapter;

    private DatabaseReference root = FirebaseDatabase.getInstance().getReference("Image");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show);

        recyclerView = findViewById(R.id.recyclerview);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        list = new ArrayList<>();
        adapter = new MyAdapter(this , list);
        recyclerView.setAdapter(adapter);


        root.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                for (DataSnapshot dataSnapshot : snapshot.getChildren()){
                    Model model = dataSnapshot.getValue(Model.class);
                    list.add(model);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });
    }
}

Here are the corresponding realtime database rules.

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid",
        ".read": "$uid === auth.uid"
      }
    }
  }
}

It should be a fairly simple fix to check the user’s UID against the user who uploaded the image’s UID, however I have not been successful with my attempts. Any help is appreciated.

Advertisement

Answer

When you’re adding Model objects under the following reference:

DatabaseReference root = FirebaseDatabase.getInstance().getReference("Image");

Then indeed you need a query to get the objects that correspond to a particular user. If don’t want that, then you can restructure your database a little bit, so you can point exactly to the user images:

Firebase-root
  |
  --- images
       |
       --- $uid
             |
             --- $modelId
                   |
                   --- //data

This means that you’ll be able to get the data really fast because when you don’t use a query, there is nothing that you need to compare against.

Now, to read that objects that correspond to a particular user, you only need to use the following reference:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = db.child("images").child(uid);
uidRef.addValueEventListener(/* .../*);

Besides that, the rules you have added, only allow a user to read and write data under users/$uid, and will indeed reject any operation that you perform under images. So if you want to allow a user to read and write data only its own data, then you should also add another rule to allow that:

{
  "rules": {
    "images": {
      "$uid": {
        ".write": "$uid === auth.uid",
        ".read": "$uid === auth.uid"
      }
    },
    //Other rules
  }
}
4 People found this is helpful
Advertisement