0

I'm trying to update the Email details of the currently logged in user in Firebase, it's working correctly, but I'm wondering if there's a better way for me to detect a duplicate email error.

I think I have two options:

  1. Run a check to see if the email the user inputs is already registered in Firebase, and if not, then proceed with the function to insert it.

or

  1. Attempt to insert the email first, and then handle the error if it detects that the email already exists.

I think the second method would be more efficient, as most users won't enter a duplicate email, so running this check every time seems pointless. But what is the correct way to handle the detection of a duplicate email in the second method?

This is my current code:

function submitEmail(){

    var requesteduseremail = "myemail@email.com";
    var currentuser = firebase.auth().currentUser;

    currentuser.updateEmail(requesteduseremail).then(function() {
        console.log("Email should now be entered into the Firebase console.");

    }, function(error) {

        console.log("Something went wrong: "+error);
        if(error == "Error: The email address is already in use by another account."){
            console.log("That email is already registered... so handle it here.");
        }
    });
}

This code is working correctly, I can show a message to the user informing them that the email is already registered. But since I'm using the Firebase error text "Error: The email address is already in use by another account." to detect this error, it will break if Firebase ever change the error message. Is there perhaps a numerical error code I could use instead? Something that would be less prone to being changed by Firebase into the future?

Thank you for your help.

UPDATE

Current attempt to check if the email already exists:

var useremail = testemail1@email.com;

    firebase.database().ref().child("active_emails").orderByChild("email").equalTo(useremail).once("value", function(snapshot) {
     var emailSnapshot = snapshot.val();
     if (emailSnapshot){

     console.log("Sorry, that email already exists");

     }else{

     console.log("Email doesn't already exist, can now run function to create the account.");

     }
});

This keeps saying that the email doesn't exist, even when I try an email that is already registered with the Firebase app. I think I may be referencing the data incorrectly.

This is the layout of my database:

MYAPP
|_______chat
|
|_______users
|       |_____userA
|       |     |______email
|       |     |______first_name
|       |     |______last_name
|       |
|       |_____userB
|
|_______active_emails      
        |_______"email":"testemail1@email.com"
        |_______"email":"testemail2@email.com"  

So I'm trying to check to see if the var useremail is contained inside active_emails

I take it the error is in the line firebase.database().ref().child("active_emails").orderByChild("email").equalTo(useremail).once("value", function(snapshot){ but I haven't been able to figure it out.

Any help with this would be really appreciated, thanks again!

UPDATE 2

My current attempt:

            firebase.database().ref('/active_emails/').equalTo(useremail).once("value", function(snapshot) {
                var emailSnapshot = snapshot.val(); 
                if(emailSnapshot){
                console.log("Email exists.");
                }else{
                console.log("Email doesn't exist.");
                }
Emily
  • 1,151
  • 4
  • 21
  • 42

1 Answers1

2

In your first option you check for existence of the email address first and then insert the new email address. This has a race condition:

 User A                    User B                   Server
   |                         |
   + does a@b.com exist?--------------------------->
   |                         |
   |                         + does a@b.com exist?->
   |                         |
   +<- no ------------------------------------------
   |                         |
   |                         +<- no ----------------
   |                         |
   + create a@b.com ------------------------------->
   |                         |
   |                         + create a@b.com ----->
   |                         |

In this at best you'll still get an error message for the second user, which is your second option.

That's why you must always handle the situation server-side and check for errors. If you have the time, you may also implement the initial client-side check to early alert your users to the duplicate.

For example, you could implement this early check while the user is typing and show a "this email address is already in use" as soon as you detect the situation. But you must always check for duplicates when the user submits their email address, and thus handle errors.

For handling the error you indeed shouldn't have to depend on the message string. The error returned is a JSON object:

{
  code: "auth/email-already-in-use", 
  message: "The email address is already in use by another account."
}

So you can check for the code. See the reference documentation for updateEmail for a list of possible error codes.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Hi @frank-van-puffelen thank you so much for your answer! I'm going to mark it as correct now, but was wondering if you could take a look at the update at the bottom of my question. I'm trying to check to see if the email already exists, but I can't seem to get it right, it keeps saying the email doesn't exist, I think I'm referencing the child node incorrectly? Thank you again for your help. – Emily Dec 03 '16 at 15:20
  • Hi again @frank-van-puffelen I've updated my answer with my latest attempt at checking for the presence of an email in the database. It still isn't working, but I'm wondering, do I need to return the entire contents of ``active_emails`` and then search for the email , or is it possible to specify the email inside the Firebase query as I'm attempting to above? Thanks again for your help with this. – Emily Dec 05 '16 at 16:40
  • At a quick glance that code looks correct. But it's hard to be certain with just a snippet. If you keep having problems, the best way to get help is to set up a minimal jsbin that reproduces the problem. – Frank van Puffelen Dec 06 '16 at 05:18
  • Hi again @frank-van-puffelen I was able to get it to work by adding ``orderByValue`` before ``equalTo`` :) Thanks again for your help! When I wrote this question I didn't realize how Firebase handles arrays, it appears that in order to run this check, all registered emails need to first be compiled into an array and then sent client-side? ... – Emily Dec 08 '16 at 13:15
  • ... I read your answer here: http://stackoverflow.com/questions/27124406/proper-way-to-store-values-array-like-in-firebase but was wondering if there was a simpler method, I wrote about it here: http://stackoverflow.com/questions/41039986/firebase-what-is-the-most-efficient-way-to-check-if-an-email-is-registered I'd be grateful if you could take a look and let me know what you think. Thank you again! – Emily Dec 08 '16 at 13:15