skip to Main Content

I’m using Flutter and Firebase for my app and the following is the code for my register function:

Future registerWithEmailAndPassword(String email, String name, String password) async {
try{

  // Creates user account with Firebase Auth:
  UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);

  User user = result.user!;

  // Creates a new document in Firestore with the uid:
  await DatabaseService(uid: user.uid).createUserData(
    name: name,
    email: email,
  );

  return _userObjectFromUser(user);
} on FirebaseAuthException catch(e) {
  return e;
}

}

It works well. However, I keep wondering if this is the best way to do this… What if the connection gets interrupted after creating the account but before creating the documents in Firestore? What if the creation of the document fails for some reason? Then the user would be in a weird situation where they have an account but no data saved in the database, meaning the app would probably load forever.

So, I wonder: is there a way to create something similar to a batch write that would somehow create an account at the same time as the documents are created?

2

Answers


  1. Since you tagged with google-cloud-functions, doing the create-user-and-write-profile-document would reduce the chances of having the type of interruption that you talk about.

    But my approach is typically to either write the profile document each time the onAuthState changed listener for a user gets a value, or to check for the existence of a document at that time and create it if needed.

    Login or Signup to reply.
  2. I guess you shouldn’t be concerned about this since the two methods will run on each other, they’re in a really small chance of this happening, either both will succeed or both will fail together, however, I can recommend for those cases to listen to the authStateChanges() stream and take an action based on it, combined with using the isNew like this :

      // At first, we were not sure that the document exists
      bool areWeSureThatTheuserHaveDocument = false;
    
      // we listen to auth changes of new user
      FirebaseAuth.instance.authStateChanges().listen((user) {
    
         // we want this method to get triggered only when the user authenticates, we don't want it to get executed when the user signs out
         if(user != null && !areWeSureThatTheuserHaveDocument) {
    
         // here we create the document
           await DatabaseService(uid: user.uid).createUserData(
             name: name,
             email: email,
           );
    
         // now if the document does exists, it will return true, for future checks on this method it will not be executed
            areWeSureThatTheuserHaveDocument = await doesUserDocumentExists(user.uid);
         }
       });
    
        // this is the check document existence
         Future<bool> doesUserDocumentExists(String id) async {
           final collection = await FirebaseFirestore.instance.collection("users").get();
           return collection.docs.map((doc) => doc.id).contains(id);
          }
    

    Actually, if you’re willing to implement this code or something similar to it, you might want to know that by this you can make sure 100% of the user has a document in the database, but it will cost you one additional read to check that existence od document.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search