简体   繁体   中英

Firebase delete account along with Database and Storage on iOS

I am trying to implement a function to delete current user's account on iOS. Account deletion works properly but the problem is that I cannot delete the account's data from Database and Storage when deleting an account.

"currentUser.delete" deletes the account but I think there is no authentication to delete its data from Database and Storage. Permission denied message shows up in the log. After running this function, I get to see the account is gone in Firebase Console Authentication page but data from Database and Storage persists.

Is this the correct way to delete an account?

I tried to delete data from Database and Storage before deleting the account. However, Firebase asks for re-authentication if session is more than 5 minutes old. Re-login shows empty data to the user before performing account deletion again so this is misleading and very confusing.

Please let me know how to remove data when deleting an account.

private func deleteAccount() {
  guard let currentUser = Auth.auth().currentUser else {
    return print("user not logged in")
  }

  currentUser.delete { error in
    if error == nil {
      // 1. Delete currentUser's data from Database. Permission denied
      // 2. Delete currentUser's data from Storage. Permission denied
      // present login screen (welcome page)
      self.presentLoginScreen()
    } else {
      guard let errorCode = AuthErrorCode(rawValue: error!._code) else { return }

      if errorCode == AuthErrorCode.requiresRecentLogin {
        self.showMessage("Please re-authenticate to delete your account.", type: .error)

        do {
          try Auth.auth().signOut()
          self.presentLoginScreen()
        } catch {
          print("There was a problem logging out")
        }
      }
    }
  }
}

you can first make your specific user deleted and and its value through its UID then you can deleted user and take him to root view controller or login screen after deleting it.

// removing user data from firebase and its specific user id 
         let user = Auth.auth().currentUser
        user?.delete { error in
          if let error = error {
            // An error happened.
            print(error.localizedDescription)
          } else {
            Database.database().reference().child("users").child(user?.uid ?? "").removeValue()
            self.navigationController?.popToRootViewController(animated: true)
            // Account deleted and logout user
//            do {
//                try Auth.auth().signOut()
                // take you to root
//                self.navigationController?.popToRootViewController(animated: true)


        }

Swift 5 | Firebase 8.11.0

To solve the problems that you've mentioned (delete the data before deleting the actual user and potentially get the AuthErrorCode.requiresRecentLogin error), you may use DispatchGroup and check the lastSignInDate , like this (just call deleteUserProcess() ):

let deleteDataGroup = DispatchGroup()

func deleteUserProcess() {
    guard let currentUser = Auth.auth().currentUser else { return }
    deleteUserData(user: currentUser)
    // Call deleteUser only when all data has been deleted
    deleteDataGroup.notify(queue: .main) {
        self.deleteUser(user: currentUser)
    }
}
/// Remove data from Database & Storage
func deleteUserData(user currentUser: User) {
    // Check if `currentUser.delete()` won't require re-authentication
    if let lastSignInDate = currentUser.metadata.lastSignInDate,
        lastSignInDate.minutes(from: Date()) >= -5 {
        deleteDataGroup.enter()
        Database.database().reference().child(userId).removeValue { error, _ in
            if let error = error { print(error) }
            self.deleteDataGroup.leave()
        }
        // Delete folders from Storage isn't possible,
        // so list and run over all files to delete each one independently
        deleteDataGroup.enter()
        Storage.storage().reference().child(userId).listAll { list, error in
            if let error = error { print(error) }
            list.items.forEach({ file in
                self.deleteDataGroup.enter()
                file.delete { error in
                    if let error = error { print(error) }
                    self.deleteDataGroup.leave()
                }
            })
            deleteDataGroup.leave()
        }
    }
}

/// Delete user
func deleteUser(user currentUser: User) {
    currentUser.delete { error in
        if let error = error {
            if AuthErrorCode(rawValue: error._code) == .requiresRecentLogin {
                reauthenticate()
            } else {
                // Another error occurred
            }
            return
        }

        // Logout properly
        try? Auth.auth().signOut()
        GIDSignIn.sharedInstance.signOut()
        LoginManager().logOut()

        // The user has been deleted successfully
        // TODO: Redirect to the login UI
    }
}

func reauthenticate() {
    // TODO: Display some UI to get credential from the user
    let credential = ... // Complete from https://stackoverflow.com/a/38253448/8157190
    Auth.auth().currentUser?.reauthenticate(with: credential) { _, error in
        if let error = error {
            print(error)
            return
        }

        // Reload user (to update metadata.lastSignInDate)
        Auth.auth().currentUser?.reload { error in
            if let error = error {
                print(error)
                return
            }
            // TODO: Dismiss UI
            // Call `deleteUserProcess()` again, this time it will delete the user
            deleteUserProcess()
        }
    }
}

The minuets function can be added in an extension to Date (thanks to Leo Dabus ):

extension Date {
    /// Returns the amount of minutes from another date
    func minutes(from date: Date) -> Int {
        return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM