使用SwiftUI, Combine和Firebase,在将用户的帐户链接到电子邮件/密码之前,我如何验证用户是匿名登录



我有一个AuthService,函数如下:

func signInAnon() -> AnyPublisher<User, AuthError> {
return Future<User, AuthError> { promise in
Auth.auth().signInAnonymously { result, error in
if let error = error {
return promise(.failure(.signInAnon(description: error.localizedDescription)))
} else if let user = result?.user {
return promise(.success(user))
}
}
}.eraseToAnyPublisher()
}
func linkAccount(email: String, password: String) -> AnyPublisher<User, AuthError> {

let emailCredential = EmailAuthProvider.credential(withEmail: email, password: password)

return Future<User, AuthError> { promise in
Auth.auth().currentUser?.link(with: emailCredential) { result, error in
if let error = error {
return promise(.failure(.linkAccount(description: error.localizedDescription)))
} else if let user = result?.user {
Auth.auth().updateCurrentUser(user) { error in
if let error = error {
return promise(.failure(.updateCurrentUser(description: error.localizedDescription)))
} else {
return promise(.success((user)))
}
}
}
}
} .eraseToAnyPublisher()
}

在我的ViewModel中,我想将用户的匿名帐户与电子邮件/密码凭据链接起来。但是,在登录时,匿名登录还没有发生。

下面是我的ViewModel中的代码:

case .signUp:
isLoading = true
authService.signInAnon()
.timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError: { () -> AuthError in
return .signInAnon(description: self.error?.localizedDescription)})
.sink { completion in
switch completion {
case let .failure(error):
self.error = error
case .finished:
print("User signed in anonymously")
self.error = nil
}
} receiveValue: { user in
self.user = user
}
.store(in: &cancellables)
authService.linkAccount(email: email, password: password)
.timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError: { () -> AuthError in
return .linkAccount(description: self.error?.localizedDescription)})
.sink { completion in
self.isLoading = false
switch completion {
case let .failure(error):
self.error = error
self.alertIsPresented = true
print(error.localizedDescription)
case .finished:
print("Sign up successful")
}
} receiveValue: { user in
self.user = user
}
.store(in: &cancellables)

我遇到了问题,因为有时连接帐户的函数在匿名登录函数之前完成,呈现错误。

我怎么写这个条件,以便有一个检查,看看用户是否匿名登录?如果他们是,链接他们的帐户。如果不是,请匿名登录,然后链接他们的帐户。

以下是我对如何使用Firebase匿名认证的建议:

  1. 一旦你的应用程序启动,初始化Firebase并检查是否有用户登录。如果用户之前已经登录,Firebase认证将在调用此方法之前及时获取该用户。
  2. 如果没有用户,匿名登录
  3. 您可以开始使用所有受益于登录用户的Firebase服务(如Firestore)
  4. 一旦用户决定实际登录,使用任何Firebase身份验证提供者获得令牌,并将其链接到现有的匿名用户。顺便说一句,我建议使用比电子邮件/密码更安全的东西。

在应用程序启动时执行匿名登录的示例代码(取自本示例应用程序):

func signIn() {
if Auth.auth().currentUser == nil {
Auth.auth().signInAnonymously()
}
}

升级到Apple帐户Sign in的示例代码(取自同一示例应用程序):

case .link:
if let currentUser = Auth.auth().currentUser {
currentUser.link(with: credential) { (result, error) in
if let error = error, (error as NSError).code == AuthErrorCode.credentialAlreadyInUse.rawValue {
print("The user you're signing in with has already been linked, signing in to the new user and migrating the anonymous users [(currentUser.uid)] tasks.")

if let updatedCredential = (error as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as? OAuthCredential {
print("Signing in using the updated credentials")
Auth.auth().signIn(with: updatedCredential) { (result, error) in
if let user = result?.user {
currentUser.getIDToken { (token, error) in
if let idToken = token {
(self.taskRepository as? FirestoreTaskRepository)?.migrateTasks(from: idToken)
self.doSignIn(appleIDCredential: appleIDCredential, user: user)
}
}
}
}
}
}
else if let error = error {
print("Error trying to link user: (error.localizedDescription)")
}
else {
if let user = result?.user {
self.doSignIn(appleIDCredential: appleIDCredential, user: user)
}
}
}
}

如果你对合并的效果感兴趣,我们已经开始在Firebase中实现对合并的支持——查看我们的项目跟踪

相关内容

最新更新