Home > other >  Authorize read if uid matches write uid - Realtime Database
Authorize read if uid matches write uid - Realtime Database

Time:09-04

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.

CodePudding user response:

You should also save the unique id of users in there respective documents.

Then you can query the document which contain the uid same as the requesting user. The query should look like.

root.whereEqualTo("uid", auth.currentUser?.uid).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) {

            }
        });

CodePudding user response:

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
  }
}
  • Related