Firebase DocumentSnapshot is always null - firebase

I am trying to get the data of a document in Firebase. I am using this function:
DocumentSnapshot docRef =
await Firestore.instance.collection("products").document("SF").get();
print(docRef.exists);
docRef.exists returns "false" even if the document is exisiting for sure.
I think it has something to do with the auth flow and the system does not recognize the logged in user.
print(FirebaseAuth.instance.currentUser());
results in Instance of 'Future < FirebaseUser>'.
Any idea how to solve the problem?
Best regards
EDIT:
Here are my rules from firebase:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}

The way you define the security rules is not correct. Change your security rules.
match /products/{document=**} {
allow read, write: if true;
}

Related

Check for username without login/user_credential

While a new user register I have to check if the desired username is already given. Therefor I check the username with the following query:
result = await FirebaseFirestore.instance
.collection('user')
.where('usernameName', isEqualTo: usernameEditController.text)
.get();
userNameExists = result.docs.isEmpty;
Code works fine and give back the right boolean if the username is already given.
Now there's a problem with the firebase rules. Because I ask for the username (code above) with being loged in I have to set the firebase firestore rules to:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
But with these rules everyone is allowed to read and write. Is there a possibility to check the username without changing the rules or with another query for the username?
You can allow all users to check the "users" collection even without authenticating. This is not an optimal solution because anyone will be able to read the user's collection.
Another thing you can do is to have another collection called "usernames", which you will add new users to, but the only data that will be there will be the username.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{collectionName}/{documentId} {
allow read : if (collectionName == "users" || request.auth != null);
allow write : if request.auth != null;
}
}
}

Firebase Firestore Database Rules: using arrays from another document

I am trying to make a web app that displays different elements based on what permissions I give to a user.
All the permissions are stored in the the Cloud Firestore database at /users/{userId} in the field "permissions", which is an array containing the permissionId's.
In /photo_libraries/{libraryId} I have a field called permissionId, which is a string.
I now want to give users that have the right permissionId to be able to read the document in /photo_libraries/{libraryId} that has that permissionId.
I've tried this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth.uid == userId;
}
match /photo_libraries/{libraryId} {
allow read: if get(/database/$(database)/documents/photo_libraries/$(libraryId)).data.permissionId in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.permissions;
}
}
}
But this doesn't seem to work, I'm quite new to the Firestore rules. Can anyone help me out?
P.S. This is how my database looks like:
This is the code I try to run:
const db = firebase.firestore(); const auth = firebase.auth();
auth.onAuthStateChanged(user => {
if (user) {
db.collection('photo_libraries').get().then(snapshot => {
// set up the UI
}, err => {
console.log(err.message);
});
} else {
// Logging out stuff
};
});
In the console I get the error message:
Missing or insufficient permissions.
Thank you,
Jonas
Try this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth.uid == userId;
}
match /photo_libraries/{libraryId} {
allow read: if resource.data.permissionId in get(/databases/$(database)/documents/users/$(request.auth.uid)).data.permissions;
}
}
}
But a better solution would be to add the persmissions array as a custom claim, then you dont need to call get.
When querying Firestore make sure you are only querying the documents you can actually access. Look for "rules are not filter" on google and you will get plenty of hits on SO and in the official Firebase documentation.

Authenticate with Firebase Anonymously

I am currently trying to let users achieve read access my Firestore database with anonymous authentication.
The reason I want to do this is because I keep getting emails saying "Your Cloud Firestore database has insecure rules" and I do not want to have the user to sign in.
To combat this problem I am making everyone an anonymous user when the application opens but I am having trouble with writing the rules that approve read access to anonymous users.
The function below is working:
func signInUser(){
let auth = Auth.auth()
auth.signInAnonymously{(result, err) in
if let err = err{
print(err.localizedDescription)
return
}
print("User Logged in anonymously")
}
}
How can I write a rule on the firebase console to allow read access only to the Firestore collections.
Also is this a bad idea?
Current Rule:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true
}
}
}
I suggest reading the documentation on security rules to understand how user authentication works with security rules.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Whether or not this is a good idea is entirely up to you. You'll have to decide if you want all users to be able to read all data.

Cloud Firestore - how to stop “any user can read your entire database” error email

I have these database security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: true;
allow write: if false;
}
}
}
all of our DB data is public by design, so we allow everyone to read it.
my question is how can I disable the error emails I keep getting from firebase?
Instead of match /{document=**} {... just create a simple rule for every collection:
match /users/{document} {
allow read: if true;
}
If the other answers don't help, are you using anonymous login? There are a few articles for iOS, Web, Android, etc... That show you how to do that.
Here is an example:
firebase.auth().signInAnonymously().catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
Keep in mind however that you may have to delete those users once in a while. For example, there is a discussion here on how to maintain this.

How can I setup rules so I can write documents to firestore protected by uid?

I want to make it so I can have authenticated users write to a collection that is only read/write/create-able to that user only. I'm struggling with the most basic Firestore setup. My firestore rules look like this:
service cloud.firestore {
match /databases/{database}/documents {
match /{userId} {
allow read, write, create: if request.auth.uid == userId;
}
}
}
I'm assuming this will prevent read/writes/creates to the database unless the initial part of the path matches the UID of the logged in user.
My JavaScript code looks like this:
function addSomeData(data) {
console.log( "Sending data with: ", user.uid, data );
db.collection(user.uid).add({ data })
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
}
I definitely have user.id set correctly after successful login.
Using things this way always gives me this error in the console:
Error adding document: Error: Missing or insufficient permissions.
If I revert to the original rules like this then the document is successfully created:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
What I'm trying to do is have each collection start with the UID of the logged in user. So, a sample shape of the data might be this:
/ax323/brty/data="Hello"
/ax323/98da/data="Goodbye"
/br981/ha31/data="No comment"
So, ax323 is a UID in Firebase, as is br981. ax323 has two documents in the collection, while br981 has one.
Is the "shape" of my data the problem?
I don't really understand what the {document=**} means in the original rules, and whether I need to convert my authentication rule to something similar.
In your database rules you have used match /users/{userId} {
This rule will apply only to the document mathching that particular path.
So if your document path is /ax323/brty/data then your rules should be like
service cloud.firestore {
match /databases/{database}/documents {
match /{userId}/{document=**} {
allow read, write, create: if request.auth.uid == userId;
}
}
}
Also looking at your question, I can't get what brty means when you mentioned
/ax323/brty/data="Hello" ?

Resources