I was able to read data from the firestore emulator but cannot add any data to it throught the client which is an android app.
This is the error:
W/Firestore: (24.0.0) [Firestore]: Write failed at Users/vBLloPGsMJrXGDZdZcVO: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
My firestore.rules file in local environment
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
This is the code used to write to firestore
FirebaseFirestore.getInstance().collection("Users")
.document(userId)
.set(newUser)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Log.d(TAG, "new user has been added");
}else {
Log.d(TAG, "Failed to add new user"+Objects.requireNonNull(task.getException()).getMessage());
}
}
});
Looks like you're trying to update a document (different from writing one). Try to add "update" in your firestore security rules like so:
allow read, get, update: if true;
Related
I'm a bit lost, I'm writing an android app that will give new users who are not yet signed-in to read some data from firestore, so I set up anonymous login and I want to authenticate the anonymous user using firebase-auth, once the user is authenticated I want to use his uid/cred to get access to the firestore database.
Firebase auth:
mAuth = FirebaseAuth.getInstance();
mAuth.signInAnonymously()
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
printWithDash("INSIDE onComplete");
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
printWithDash("SIGN IN SUCCESSFULL");
FirebaseUser user = mAuth.getCurrentUser();
printWithDash(user.toString()); // address
} else {
// If sign in fails, display a message to the user.
printWithDash("SIGN IN FAIL!!!");
}
}
});
And here's how I write to firestore:
db.collection("answers")
.add(jsonAnswers)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
System.out.println("-----------------------------------------------------------------------------------------");
System.out.println("DocumentSnapshot added with ID: " + documentReference.getId());
System.out.println("-----------------------------------------------------------------------------------------");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
System.out.println("Error adding document " + e);
}
});
here are my firetore rules
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if request.auth.uid != null && request.auth.token.firebase.sign_in_provider == 'anonymous';
allow write: if request.auth.uid != null && request.auth.token.firebase.sign_in_provider == 'anonymous';
}
}
}
I'm new to android development, how does authentication works on android apps?. And how can I use my anonymous user to write to firestore db?
Put only the request.auth.uid != null; to able read and write the signed in anonymous users:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
A users who sign in anonymously are also authenticated.
I've learned that signing anonymously will save your user cred on the phone itself, look at the device file explorer under apps/ your app. so once we did the anonymous login , the user is considered authenticated until you will do mAuth.signOut();
Performing the get() function in security rules is not working.
It returns permission denied on the client, but passes in simulation.
The config/permissions layout is an array structure:
config/permissions-->
---------------------------> CollectionName1 :
----------------------------------------------------> 0 : UID1
----------------------------------------------------> 1 : UID2
---------------------------> CollectionName2 :
----------------------------------------------------> 0 : UID3
----------------------------------------------------> 1 : UID4
I also tried to use single key/value fields in the config/permissions as so
config/permissions-->
---------------------------> CollectionName1 : UID1
---------------------------> CollectionName2 : UID3
with the rule
allow read: if request.auth.uid == get(/config/permissions).data[c] and this passed simulation and failed on the app. If I hardcode the UID instead of request.auth.uid it gives the same result.
UID is definitely correct on the app. This was tested by using the following rule, where it passed in simulation AND the app.
allow read: if request.auth.uid == 'USER_ID_HERE'
and by comparing the logcat output of the UID to the one above.
Please help. This is the Nth day of trying to find a suitable way to structure and query Firestore. I'm certain this is an issue with either the get() call or the way I am writing the call.
Android Code:
FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setTimestampsInSnapshotsEnabled(true)
.build();
db.setFirestoreSettings(settings);
Log.d("UID", FirebaseAuth.getInstance().getCurrentUser().getUid());
DocumentReference docRef = db.collection(collection).document("X153#111");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d("FIREBASE", "DocumentSnapshot data: " + document.getData());
} else {
Log.d("FIREBASE", "No such document");
}
} else {
Log.d("FIREBASE", "get failed with ", task.getException());
}
}
});
I have a rule which executes correctly in Firestore Rules simulation as seen below.
The /config/permissions document is many arrays named X153, X154, X155, etc., which contain UIDs:
When I attempt this access in Android, I get a PERMISSION_DENIED response.
Code:
DocumentReference docRef = db.collection("arcs").document("X153");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d("FIREBASE", "DocumentSnapshot data: " + document.getData());
} else {
Log.d("FIREBASE", "No such document");
}
} else {
Log.d("FIREBASE", "get failed with ", task.getException());
}
}
});
The UID used in simulation is the same as in Android:
If I set the rule to authenticate access of the UID directly
Android permission accepted, returns document.
If I flatten out the config/permissions structure to just key/values, like X153 : '9iXQBaG3Ycaey4cFUj8tZjhKMaB3', and change the rule to
match /arcs/{x} {
allow read: if request.auth.uid == get(/config/permissions).data[x];
}
Android returns PERMISSION DENIED.
Why am I receiving this PERMISSION DENIED response using the rule pictured?
I'm a newbie in firebase.
How do I get through this below rule?
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
I've tried to change the rule to below,
{
"rules":
{
".read": true,
".write": true,
}
}
but there's an error of
mismatched input '{' expecting {'function', 'service', 'syntax'}
Below is the db structure.
Currently, this is my code (which keeps returning Permission-denied):
// [START initialize_database_ref]
mDatabase = FirebaseDatabase.getInstance().reference
// [END initialize_database_ref]
val result = HashMap<String, Any> ()
result.put("timestamp", getCurrentTime())
result.put("user_id", USER_ID)
result.put("x_position", -1)
result.put("y_position", -1)
mDatabase!!.ref.child("raw data").child("Z9QD79lDzP7MpD6feWeJ").setValue(result).addOnFailureListener(object : OnFailureListener {
override fun onFailure(#NonNull e: Exception) {
Log.d("firebase", e.localizedMessage)
}
})
Any help would be appreciated! Thanks :)
I was able to solve the problem by switching from Cloud Firestore to Realtime Database, and then changing the rule. (After I've changed this, there was no more error showing!)
For others struggling with this problem, the proper solution is to change the false in
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
To true while testing. Don't forget to add additional security when going live with your project!
You should check in your Angular NgModule and components if you are using "Realtime Database" or "Cloud Firestore". See diferences using "angularfire2":
REALTIME DATABASE
#NgModule({
...
imports: [
AngularFireDatabaseModule,
...
],
providers: [
AngularFireDatabase,
...
]
})
#Component({...})
export class FirestoreComponent{
constructor(private realtimeDb:AngularFireDatabase, ...) {
this.locations = realtimeDb.list('locations').valueChanges();
}
...
}
CLOUD FIRESTORE
#NgModule({
...
imports: [
AngularFirestoreModule,
...
]
})
#Component({...})
export class FirestoreComponent{
constructor(private firestore:AngularFirestore, ...) {
this.locations = firestore.collection('locations').valueChanges();
}
...
}
Because your method query the Firebase not Cloud Firestore
so you should use this method :
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("YourCollectionName").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.w(TAG, "Error getting documents.", task.getException());
}
}
});
dont forget this :
implementation 'com.google.firebase:firebase-firestore:17.0.1'
I am using both Firebase Authentification and Firestore for my Android app. What I am trying to do is the following:
the user signs in
if it's the first time the user signs in a document named by his uid is created
if the user has already signed in before (hence document named by uid already exists) then I load some further data.
Here's my logic to solve this:
get the FirebaseUser from FirebaseAuth instance
from the FirebaseUser I get the uid
build a DocumentReference with this uid
use get() query on the DocumentReference
if DocumentSnapshot is != null then user already exists in firestore
if DocumentSnapshot == null the user doesn't exist and I create it in firestore
I was testing the code below:
FirebaseUser user = mAuth.getCurrentUser();
if(user != null) {
// get uid from user
String uid = user.getUid();
// make a query to firestore db for uid
DocumentReference userDoc = db.collection("users").document(uid);
userDoc.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
Log.d(LOG_TAG, "DocumentSnapshot data: " + task.getResult().getData());
} else {
Log.d(LOG_TAG, "No such document");
}
} else {
Log.d(LOG_TAG, "get failed with ", task.getException());
}
}
});
}
When uid exists in firestore I get the log message with appropriate data but when it doesn't I get the following exception and I can't find a way to get to use DocumentSnapshot.exists():
java.lang.IllegalStateException: This document doesn't exist. Use DocumentSnapshot.exists() to check whether the document exists before accessing its fields.
Can anyone help me understand what I am doing wrong ?
Thanks a million ! :)
The object returned by get() is a DocumentSnapshot not the document itself. The DocumentSnapshot is never null. Use the exists() method to determine if the snapshot contains a document. If exists() is true, you can
safely use one of the getXXX() methods (in your case, getData() for a map) to obtain the value of the document.
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot snapshot = task.getResult();
if (snapshot.exists()) {
Log.d(LOG_TAG, "DocumentSnapshot data: " + snapshot.getData());
} else {
Log.d(LOG_TAG, "No such document");
}
} else {
Log.d(LOG_TAG, "get failed with ", task.getException());
}
}