0
votes

I have an onUpdate triger on my users collection that updates the corresponding user profile.

exports.onUpdateUser = functions.firestore.document('/users/{uid}')
.onUpdate((change, context) => {
    const { uid } = context.params;
    const { email, displayName, photoURL } = change.after.data();

    return admin.auth().updateUser(uid, {
        email,
        displayName,
        photoURL
    });
});

The trigger may throw an error if the email provided already exists. In this case, I want to discard the changes made to the user document and then let the client know about that error.

With the above implementation, the document would be updated successfully and the trigger would throw an error silently, without the client knowing this.

Can I change this behavior or my only option is implementing a separate HTTP cloud function for handling user updates?

1

1 Answers

2
votes

What you can do, in case of error, is to write, with the Cloud Function, to a specific sub-node under the /users/{uid} node and have your client front-end listening to this sub-node.

The Cloud Function code would look like:

exports.onUpdateUser = functions.firestore.document('/users/{uid}')
.onUpdate((change, context) => {
    const { uid } = context.params;
    const { email, displayName, photoURL } = change.after.data();

    return admin.auth().updateUser(uid, {
        email,
        displayName,
        photoURL
    })  
    .catch(error => {
        if (error == "auth/email-already-exists") {

           return admin.database().ref('/users/' + uid).set({updateError: true})
           .catch(error => {
                console.log("Error reporting email error");
                return false;
           });

        } else {
            console.log("Error updating user:", error);
            return false;
        }
    });

});

In your front end listen to the /users/{uid}/updateError node and in case a new value is written, show an alert/message. The exact listener syntax depends on your front end technology (web app? Android app? iOS app?).

Note that, in the Cloud Function, you take advantage of the error management of the admin.auth().updateUser() method and the fact that it return a specific code.

see https://firebase.google.com/docs/auth/admin/errors

and https://firebase.google.com/docs/auth/admin/manage-users#update_a_user, which states that:

If the provided uid does not correspond to an existing user, the provided email or phone number is already in use by an existing user, or the user cannot be updated for any other reason, the above method fails with an error.