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