In my Firestore, I want a Donors collection. Here are my security rules for it:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Donors/{donor} {
allow read: if true;
allow create: if request.auth != null;
allow update, delete: if request.auth != null && request.auth.uid == resource.data.userId;
}
}
}
As can be seen from the rules, I want anybody to read any of the documents in the collection, I only want authenticated users to be able to create documents, and I want only the creators of the document to be able to change the document (see my Donor class below).
public class Donor {
private String Email;
private String Name;
private String City;
private String Country;
private String ImageURL;
private int Balance;
private String userId;
public Donor(String email, String name, String city, String country, String userId) {
this.Email = email;
this.Name = name;
this.City = city;
this.Country = country;
this.Balance = 0;
this.userId = userId;
}
}
I use the following code to create the document.
if (firebaseAuth.getCurrentUser() != null) {
Log.d("cs50", firebaseAuth.getCurrentUser().getEmail() + " signed in");
} else {
Log.d("cs50","signed out");
}
if (radioDonor.isChecked()) {
database.collection("Donor").document(email).set(new Donor(email,
getIntent().getStringExtra("name"),
getIntent().getStringExtra("city"),
getIntent().getStringExtra("country"),
firebaseAuth.getCurrentUser().getUid()))
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e("cs50", "Error creating donor", e);
}
});
}
I get a message in my logcat "[email] signed in", which means that the user is authenticated using Firebase authentication. But the document is not created with the following error message:
2020-09-20 18:24:47.298 15566-15566/com.example.treeapp D/cs50: [email protected] signed in
2020-09-20 18:24:48.651 15566-15566/com.example.treeapp E/cs50: Error creating donor
com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:117)
at com.google.firebase.firestore.core.SyncEngine.notifyUser(SyncEngine.java:521)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(SyncEngine.java:451)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedWrite(MemoryComponentProvider.java:109)
at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(RemoteStore.java:714)
at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(RemoteStore.java:670)
at com.google.firebase.firestore.remote.RemoteStore.access$600(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore$2.onClose(RemoteStore.java:206)
at com.google.firebase.firestore.remote.AbstractStream.close(AbstractStream.java:344)
at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(AbstractStream.java:398)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3(AbstractStream.java:151)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$Lambda$4.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(AbstractStream.java:137)
at com.google.firebase.firestore.remote.FirestoreChannel$1.onClose(FirestoreChannel.java:135)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:426)
at io.grpc.internal.ClientCallImpl.access$500(ClientCallImpl.java:66)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:689)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$900(ClientCallImpl.java:577)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:751)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:740)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:229)
at java.lang.Thread.run(Thread.java:764)
Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
at io.grpc.Status.asException(Status.java:541)
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:115)
at com.google.firebase.firestore.core.SyncEngine.notifyUser(SyncEngine.java:521)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(SyncEngine.java:451)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedWrite(MemoryComponentProvider.java:109)
at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(RemoteStore.java:714)
at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(RemoteStore.java:670)
at com.google.firebase.firestore.remote.RemoteStore.access$600(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore$2.onClose(RemoteStore.java:206)
at com.google.firebase.firestore.remote.AbstractStream.close(AbstractStream.java:344)
at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(AbstractStream.java:398)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3(AbstractStream.java:151)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$Lambda$4.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(AbstractStream.java:137)
at com.google.firebase.firestore.remote.FirestoreChannel$1.onClose(FirestoreChannel.java:135)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:426)
at io.grpc.internal.ClientCallImpl.access$500(ClientCallImpl.java:66)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:689)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$900(ClientCallImpl.java:577)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:751)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:740)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:229)
at java.lang.Thread.run(Thread.java:764)
When I allow anyone to read and write using the following rules, the document gets created without any problem.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
I can't figure out exactly what I'm doing wrong. I am confirming that the user is authenticated in my code, but the Firestore database does not recognize the user as authenticated.
Please help me out.
PropertyNameon the Java class. - Frank van Puffelen