Dart - FirebaseFirestore exception handling - firebase

The documentation is very poor about exception handling when using firebase firestore. I'm about to assume there is no such thing to handle specific errors.
I'm currently using the latest dependencies:
firebase_core: ^0.5.0
firebase_auth: ^0.18.0+1
cloud_firestore: ^0.14.0+2
On firebase_auth it is well documented and straight forward how to handle exceptions. There is an exception class named FirebaseAuthException which has a code field that contains the specific error code (unfortunately as a String, but at least it provides something) such as invalid-email, user-disabled, weak-password and so on. It is a nice to have because I can notify the user what went wrong and the program can act accordingly based on these error codes.
On the other hand, unfortunately there is no such thing as FirebaseFirestoreException and the documentation is not much of a help. It shows nothing more than a .catchError() to handle possible exceptions with an error variable with dynamic type so it basically can be anything.
Future<void> addUser() {
// Call the user's CollectionReference to add a new user
return users
.add({
'full_name': fullName,
'company': company,
'age': age
})
.then((value) => print("User Added"))
.catchError((error) => print("Failed to add user: $error"));
}
So my question is if there anything or similar to handle specific exception cases like in FirebaseAuthException with some error codes and stuff. And furthermore how can I identify if it is a FirebaseFirestore exception? Why it does not provide exceptions to make things more comfortable for developers? Or am I missing the point? Please let me know.
Documentation about firebase firestore with flutter: https://firebase.flutter.dev/docs/firestore/usage

Related

Flutter: info: 'await' applied to 'RemoteConfig', which is not a 'Future'

I am getting an info message after upgrading my Firebase packages. The documentation wasn't helpful. The line below is triggering the info compiler alert.
RemoteConfig remoteConfig = await RemoteConfig.instance;
The info message is:
info: 'await' applied to 'RemoteConfig', which is not a 'Future'. (await_only_futures at lib/splash.dart:72)
While this is just an 'info' message and doesn't prevent compilation, I want to make sure that I am not doing anything wrong. Please help.
As the FlutterFire documentation on using Remote Config shows, the call to RemoteConfig.instance is not asynchronous and is:
RemoteConfig remoteConfig = RemoteConfig.instance;
Where you will need to deal with asynchronous behavior is when fetching the remote config, which can be done with:
bool updated = await remoteConfig.fetchAndActivate();
if (updated) {
// the config has been updated, new parameter values are available.
} else {
// the config values were previously updated.
}
both snippets are from the linked documentation, so I recommend keeping that page handy.

How to link phone number to already logged in firebase gmail user

How to use firebase linkWithCredential? I'm trying to link the phone number to the current firebase user. My problem is linkWithCredentials has an error of The method 'linkWithCredential' isn't defined for the type 'Function' Is this because of my version of firebase_auth: ^0.15.5+3? Or I am doing it wrong.
FirebaseAuth.instance.currentUser.linkWithCredential(phoneCredential);
The error is because of the version.
.currentUser is a method in version 0.15.5+3. Link
You need to call the method to get the FirebaseUser instance.
So your code becomes as shown below:
await (await FirebaseAuth.instance.currentUser()).linkWithCredential(phoneCredential);

Where i can find all the error codes for [ firebase_auth: ^1.0.1 ]

Is there any documentation available, which provides all the error codes related to firebase_auth.
I am using firebase with flutter, i have done my research and cannot find any good source where i can find all the error codes for flutter.
For eg:
On password error the code is wrong-password
} on FirebaseAuthException catch (e) {
//i am talking specifically about this code
return e.code;
} catch (e) {
debugPrint(e.toString());
return 0;
}
Though, i have found this file where all the errors are present inside comment. https://github.com/FirebaseExtended/flutterfire/blob/6bd6cd84a624a533857105e30f85650c5c68a2f7/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart#L426
But cannot find any rigid documentation available for firebase_auth: ^1.0.1 which states all the errors.
Thanks
Flutter introduces its own layer on top of firebase Auth and simply routes Firebase Errors through it. You can find a list of error codes below.
Unfortunately, Flutter currently does not maintain a list of active error codes but rather attempting to catch all errors with the same handler.
Here is a list of error codes I could find
https://firebase.flutter.dev/docs/auth/error-handling
https://firebase.google.com/docs/reference/swift/firebaseauth/api/reference/Enums/AuthErrorCode
https://firebase.google.com/docs/auth/admin/errors
https://www.techotopia.com/index.php/Handling_Firebase_Authentication_Errors_and_Failures#FirebaseAuth_Error_Codes
If you are experiencing specific errors, feel free to ask in another question.

Flutter: firebase_auth seems not to work, how do I authorize?

I have a working flutter app which uses the cloud_firestore package, it's going well with Android and iOS. But my database is "allow read,write: if true", and so Google keeps reminding me to fix this unsecurity. This I did:
including firebase_auth
changing my rules on firebase
creating a mail/password account
implementing the login procedure
changing the rules to "allow write: if request.auth != null;"
I think I made everything ok. In the app, it seems so:
print("User ${(await FirebaseAuth.instance.currentUser()).email})");
This gives me the mail of my account. Also I have a onAuthStageChanged listener and I get what I would expect. So I guess the login did work.
But if I try to make a database access e.g. with .setData(), I get an error
W/Firestore( 4411): (19.0.0) [Firestore]: Write failed at...: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
It looked for me as if the auth package is not informing the firestore package correctly. In the logs, I see
D/FirebaseAuth( 5698): Notifying id token listeners about user (...).
I would expect something like "Firestore: received token...", but this does not come.
Do I have to be careful with the initialization order? Mine is
_app = await Firebase.App.configure...
_firestore = Firestore(app: _app);
await FirebaseAuth.instance.signInWithEmailAndPassword...
I tried it on some Samsung and OnePlus devices with Android 8 and 9.
Any hints someone?
I got it running!! Used a hint from Flutter & Firebase - using firebase_storage along with firebase_auth
When accessing the database, I used a pointer to the firestore which I created like
static Firestore _firestore;
...
_firestore = Firestore(app: ...);
And later I used
await _firestore.collection(...)...setData(...);
But the Firestore seems to change after a login. It works when I write:
await Firestore.instance.collection...setData
Interesting!!

request.auth.uid seems to always be null in Cloud Firestore rules

I must be missing something really basic here... but any time I make a call to my Cloud Firestore db and I try to institute any kind of rules for security, they always fail.
Doing something like
match /users/{userId} {
allow create, read, update: if true;
}
works, but it obviously defeats the point. However, if I do any kind of additional scrutiny, such as the go-to example in all the docs like
match /users/{userId} {
allow create, read, update: if request.auth.uid != null;
}
it fails every time. Am I missing something obvious in how I'm wiring together my client side code?
Here's my client side code that logs the user in, and then makes a call to the db to grab a user.
(Note that in my db the keys for the users are by email, not by uid)
// this is a snippet from the code where I log the user in
firebase.auth().signInWithEmailAndPassword(email, FIREBASE_USER_PASSWORD)
.then(user => {
// the user comes back successfully logged in,
// I grab its uid and add it to a preparedUser object that I've been building,
// then pass this user to my getFirestoreUserObject function
preparedUser.uid = user.uid;
getFirestoreUserObject({dispatch, user: preparedUser, navigate});
})
// then the getFirestoreUserObject function:
// note that all the code below works fine when there are no security rules in place
const getFirestoreUserObject = ({dispatch, user, navigate}) => {
const {name, email, imageUrl} = user;
// if I ask for currentUser here, I get back my logged in user
const currentUser = firebase.auth().currentUser;
// email is defined correctly here as the user's email
firebase.firestore().collection('users').doc(`${email}`)
.get() // the request fails here due to insufficient permissions
.then(doc => {
if (doc.exists) {
const currentUser = doc.data();
getUserFavorites({dispatch, currentUser, navigate});
} else {
createUserInFirestore({dispatch, user, navigate});
}
})
};
Is there something obvious that I'm missing? If I log a user in via firebase.auth(), and then immediately after call firebase.firestore(), shouldn't that have the context of the auth'd user? If not, how do I pass it to the firestore call?
Thanks!
After weeks of searching, and firestore and auth both working independently but not together... it was the most simple thing.
I was on firebase 4.x, which was the latest available when I started my project. Then, when I came around to adding auth rules, the latest published documentation on firebase for how to do the db rules (which I hadn't even looked at when I started, but came back to months later when I was ready to implement them) were listed using firebase 5.y. Updated my package.json, npm install, and everything magically worked :(
Hope this can help someone else... make sure you're on at least version 5!
Update emulators using: npm install -g firebase-tools
June 2021
Still have the issue with firebase cli 9.12.1.
Had to downgrade firebase JS to 8.3.1 to make it work but with that version it tries to verify the user online and not with the emulator
See this post
I had the same problem but what ended up working for me is updating the firebase cli by running npm install -g firebase-tools which in turn updated the cloud firestore emulator
NB: There might be a different way of updating your firebase cli depending on the method of installation that you used. The above solution will work if you used npm to install the firebase cli. For other ways of updating the firebase cli, see the firebase docs.
You should use firebase.firestore().collection('users').doc(`${currentUser.uid}`).get() instead of firebase.firestore().collection('users').doc(`${email}`).get().
This is because your security rules
match /users/{userId} {
allow create, read, update: if request.auth.uid != null;
}
check for the uid of the user when determining whether or not to provide access to the data to the user, not the user's email.
Hope that helped.

Resources