1
\$\begingroup\$

Firebase v3 Offers Authentication via 3rd party oAuth providers, facebook, github,google, and twitter. They also offer password pased authentication.

Authenticated users have a firebase.User object with 4 key properties - displayName, email, photoURL. A password is required to sign in and to register.

In oAuth, the email, displayName, and photoUrl are gotten from the oAuth provider. Developers must enter this in the Firebase v3 Auth system via an .updateProfile method for Password based users.

So, for registering new users, I collect the 4 values from <inputs> and call the below homemade function to register the new user with all the values in one go. Promise chaining was used. Any missing arguments must be null (not undefined prior to invoking the firebase methods).

Is there a cleaner way to chain these or does this look fairly solid. I know it works. I'm just seeing if it can be smartened up a bit.

createUserWithEmailAndPassword

createUserWithEmailAndPassword(email, password) returns firebase.Promise containing non-null firebase.User. Creates a new user account associated with the specified email address and password.

updateProfile

var profile = {displayName: nullable string, photoURL: nullable string}; updateProfile(profile) returns firebase.Promise containing void. Updates a user's profile data.

function registerPasswordUser(email,displayName,password,photoURL){
  var user = null;
  //nullify empty arguments
  for (var i = 0; i < arguments.length; i++) {
    arguments[i] = arguments[i] ? arguments[i] : null;
  }

  firebase.auth().createUserWithEmailAndPassword(email, password)
  .then(function () {
    user = firebase.auth().currentUser;
    user.sendEmailVerification();
  })
  .then(function () {
    user.updateProfile({
      displayName: displayName,
      photoURL: photoURL
    });
  })
  .catch(function(error) {
    console.log(error.message);
  });
  console.log('Validation link was sent to ' + email + '.');
}
\$\endgroup\$
1
\$\begingroup\$

registerPasswordUser is a weird name. It's sort of like "register a user with a password" which all of registered users should have anyways. registerUser might be just fine.

One thing you can do instead of "nullifying" is to accept a user object that has the 4 fields. Then to "nullify", use Object.assign.

const userDefaults = {email: ..., displayName: ..., password: ..., photoURL: ... };

function registerUser(user){
  const finalUserConfig = Object.assign({}, defaults, user);
  ...
}

There is no way for the caller to actually know if the procedure succeeded or failed. This function is a one-off, and the only way to know is a visual console.log. Consider returning the promise, that way the caller knows it succeeded or failed.

function registerUser(user){
  ...
  return firebase.auth()
    .createUserWithEmailAndPassword(email, password)
    .then(...)
    .then(...)
    .catch(error => {
      console.log(error.message);

      // promise.catch recovers the chain.
      // We want to preserve the error for the caller.
      return Promise.reject(error);
    })
}

The two thens you have appear to have one-off calls, sendEmailVerification and updateProfile. They first then doesn't return a promise, which means next one doesn't appear to be waiting for it. They both will fire when createUserWithEmailAndPassword resolves and they may both be merged in one then.

However, since they don't return promises, the chain will not know about their presence. Should they fail, your catch will not capture.

Promise.resolve('test')
.then(function(v){
  Promise.reject('error')
})
.then(function(v){
  console.log('this gets called');
})
.catch(function(error){
  console.log('this never gets called');
});

Consider using Promise.all to handle both calls that return promises. This way, you know if they fail.

Here's how I would do it:

function registerPasswordUser(config){
  const defaults = {email: null,displayName: null,password: null,photoURL: null };
  const userConfig = Object.assign({}, defaults, userConfig);

  firebase.auth()
    .createUserWithEmailAndPassword(userConfig.email, userConfig.password)
    .then(() => {
      const user = firebase.auth().currentUser;

      // Do both in parallel while being able to capture errors in promise
      return Promise.all([
        user.sendEmailVerification(),
        user.updateProfile({ displayName, photoURL });
      ]);
    })
    .catch(error => {
      console.log(error.message);
    });
}
\$\endgroup\$
  • \$\begingroup\$ Thanks Joseph. I will try it this way. The reason for the naming of registerPasswordUser is that Firebase also has oAuth type users. Password is one of the auth provider names they use. Thanks for looking at this for me. \$\endgroup\$ – Ron Royston Jul 28 '16 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.