0

What i'am attempting to do is create new users with Firebase authentication and create their own document entry within Firestore. So far everything went well until i wanted to create unique usersnames. What is the most optimal way of going about doing this? should i create an array of all the users to cross-reference upon each sign up, or perhaps create a collection dedicated to Usernames with their email attached (which you can see i did in the second call to Firebase)

Firebase auth takes in email and passwords only so thats out of the question, or at least from what i gather.

export const signInUser = async ({ name, email, password }) => {
  try {
    await firebase
      .auth()
      .createUserWithEmailAndPassword(email, password)
      .then(cred => {
        return firebase
          .firestore()
          .collection("users")
          .doc(cred.user.uid)
          .set({
            name: name,
            email: email,
            friends: []
          });
      });
    await firebase
      .firestore()
      .collection("usernames")
      .doc(name)
      .set({ username: name, email: email });
    firebase.auth().currentUser.updateProfile({
      displayName: name
    });

    return {};
  } catch (error) {
    switch (error.code) {
      case "auth/email-already-in-use":
        return {
          error: "E-mail already in use."
        };
      case "auth/invalid-email":
        return {
          error: "Invalid e-mail address format."
        };
      case "auth/weak-password":
        return {
          error: "Password is too weak."
        };
      case "auth/too-many-requests":
        return {
          error: "Too many request. Try again in a minute."
        };
      default:
        return {
          error: "Check your internet connection."
        };
    }
  }
};

Soni Sol
  • 2,367
  • 3
  • 12
  • 23
Ahmed Ali
  • 105
  • 2
  • 10
  • 1
    "I want to create unique user names. What is the most optimal way of doing this?" What did you already try? And what's the problem you encountered with that? – Frank van Puffelen Dec 23 '19 at 21:25
  • 1
    Also see many of the questions already asked about the topic, such as https://stackoverflow.com/q/47405774, https://stackoverflow.com/q/51363730, and probably more from here: https://www.google.com/search?q=firestore+unique+username – Frank van Puffelen Dec 23 '19 at 21:28
  • @FrankvanPuffelen I was about to use the snapshot.empty method to achieve my result but since you mentioned that it could be abused by a malicious user as you've previously stated i chose not too. Thanks, ill be going with the reverse mapping method linked by Peter O. – Ahmed Ali Dec 24 '19 at 00:03

1 Answers1

2

I'd skip the "usernames" collection here, as you're basically creating an index, which fireStore already does for you. To check whether a name is unique, you can do:

const snapshot = await firestore.collection("users").where("name", "==", name).get();
// The name is taken if snapshot.empty is false.
bigblind
  • 12,539
  • 14
  • 68
  • 123
  • 1
    To ensure that only one user can claim a name, you'd need a transaction. And even then, a malicious user can bypass that code and do whatever they want, since you can't prevent duplicate *values* using security rules. That's why the other answers use the name as the *key* to identify documents. Since keys are by definition unique, this automatically prevents duplicate user names, and *can* be secured using security rules. – Frank van Puffelen Dec 23 '19 at 22:14