Home > OS >  How to check if a user already exists in a Firestore collection after signing in with Firebase Auth
How to check if a user already exists in a Firestore collection after signing in with Firebase Auth

Time:01-13

@Published var isNewUser: Bool?

init() {
  self.isNewUser = false
}

func checkIfTheUserExistsInDataBase(
  userID: String?, completion: @escaping (_ isNewuser: Bool) -> Void
) {
  let docRef = db.collection("users").whereField("user_id", isEqualTo: userID!).limit(to: 1)
  docRef.getDocuments { querySnapshot, error in
    if error != nil {
      print(error?.localizedDescription)
    } else {
      if let doc = querySnapshot?.documents, doc.isEmpty {
        completion(true)
      } else {
        completion(false)
      }
    }
  }
}

func login(
  email: String, password: String,
  completion: @escaping (_ error: Error?, _ isEmailVerified: Bool) -> Void
) {
  Auth.auth().signIn(withEmail: email, password: password) { authDataResult, error in
    if error == nil {
      if authDataResult!.user.isEmailVerified {
        DispatchQueue.main.async {
          self.checkIfTheUserExistsInDataBase(userID: authDataResult?.user.uid) { isNewUser in
            self.isNewUser = isNewUser
          }
        }
        UserDefaults.standard.set(authDataResult?.user.uid, forKey: CurrentUserDefaults.userID)
        completion(error, true)
      } else {
        print("Email not verified")
        completion(error, false)
      }
    } else {
      completion(error, false)
    }
  }
}

I tried to use DispatchSemaphore to let a longer running function execute first which is checkIfTheUserExistsInDataBase, but it froze my app. Is there a better way to do this?

CodePudding user response:

Firebase supports async/await (see this short, this video, and this blog post I created to explain this in detail.

To answer your question: you should use async/await to call signing in the user, waiting for the result, checking if the user exists in your Firestore collection, and the updating the UI.

The following code snippet (which is based on this sample app) uses the new COUNT feature in Firestore to count the number of documents in the users collection to determine if there is at least one user with the ID of the user that has just signed in.

func isNewUser(_ user: User) async -> Bool {
  let userId = user.uid
  let db = Firestore.firestore()
  let collection = db.collection("users")
  let query = collection.whereField("userId", isEqualTo: userId)
  let countQuery = query.count
  do {
    let snapshot = try await countQuery.getAggregation(source: .server)
    return snapshot.count.intValue >= 0
  }
  catch {
    print(error)
    return false
  }
}

func signInWithEmailPassword() async -> Bool {
  authenticationState = .authenticating
  do {
    let authResult = try await Auth.auth().signIn(withEmail: self.email, password: self.password)
    if await isNewUser(authResult.user) {

    }
    return true
  }
  catch  {
    print(error)
    errorMessage = error.localizedDescription
    authenticationState = .unauthenticated
    return false
  }
}

See this video for more details about how to implement Firebase Authentication in SwiftUI apps.

  • Related