Issue
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.
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.
Solution
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
}
}
Answered By - Alex Mamo
Answer Checked By - Mary Flores (JavaFixing Volunteer)