【问题标题】:Unique field in Firestore database + FlutterFirestore 数据库中的唯一字段 + Flutter
【发布时间】:2021-11-14 06:07:24
【问题描述】:

我正在尝试在我的应用程序中实现一个正常的身份验证系统,但我想为每个用户创建一个新字段,即“uniqueName”,以便用户可以在他们的朋友列表中搜索和添加彼此。我正在考虑在 uniqueName 的注册表单中添加一个 textField 并更新我的 User 类,以这种方式添加一个新字符串:

class User {
  String email;
  String name;
  String uniqueName;
  String userID;
  String profilePictureURL;
  String appIdentifier;

  ...
}

现在,因为我有这个方法来注册电子邮件和密码:

static firebaseSignUpWithEmailAndPassword(String emailAddress,String password,File? image,String name,) async {
try {
  auth.UserCredential result = await auth.FirebaseAuth.instance
      .createUserWithEmailAndPassword(
          email: emailAddress, password: password);
  String profilePicUrl = '';
  if (image != null) {
    await updateProgress('Uploading image, Please wait...');
    profilePicUrl =
        await uploadUserImageToFireStorage(image, result.user?.uid ?? '');
  }
  User user = User(
      email: emailAddress,
      name: name,
      userID: result.user?.uid ?? '',
      profilePictureURL: profilePicUrl);
  String? errorMessage = await firebaseCreateNewUser(user);
  if (errorMessage == null) {
    return user;
  } else {
    return 'Couldn\'t sign up for firebase, Please try again.';
  }
}

我必须如何修改它才能在注册中添加这个新字段?由于在数据库中创建新用户之前,我必须检查用户插入的 uniqueName 是否有效,我该怎么办?

此外,我认为如果在填写表格的同时进行此检查会很酷,我该怎么做? (这不是必须的)

谢谢大家的回答

【问题讨论】:

  • Firebase 实时数据库和 Cloud Firestore 是两个独立的数据库。请仅使用相关标签标记您的问题,不要同时使用两者。

标签: firebase flutter google-cloud-firestore firebase-authentication


【解决方案1】:

我建议执行以下步骤:

  1. 在 Firestore 中创建您自己的用户集合(例如 users),您可能已经这样做了。 (我不认为User 是一个好的类名,因为Firebase 身份验证使用相同的名称。试试MyUser 或其他东西。)

  2. 添加 authentication triggers 将确保无论何时添加或删除 Firebase 用户,它也会被添加到 users 集合中或从 users 集合中删除,使用 Firebase uid 作为标识符。

  3. 创建一个解决方案来检查uniqueName 是否已存在于users 集合中。您可以使用 Firestore 查询,但在这种情况下,您必须允许未经身份验证的访问以读取 users,至少是 uniqueName 字段。 (因为此时用户尚未经过身份验证。)Firebase Cloud Function 是另一种选择。

  4. 当用户输入他们想要的uniqueName 时,在创建 Firebase 用户之前运行检查。您可以在用户输入此内容或开始注册过程时执行此操作。

  5. 如果uniqueName 是唯一的,您可以尝试创建 Firebase 用户。请注意,此步骤也可能失败(例如,电子邮件名称被占用等)。您的 users 文档将由您在第 2 步中设置的身份验证触发器创建。

  6. 最后,您必须将此uniqueName 存储在users 集合中。此时您将拥有新创建的 Firebase 用户的 uid,因此您可以使用 Firestore set 命令并将 merge 选项设置为 true,这样您就不会覆盖其他数据。

请务必注意,当您到达第 6 点时,您不能保证 Firebase 触发器已经在 users 中创建了新文档,很可能触发器仍在工作甚至没有启动然而。这就是为什么您必须在身份验证触发器和设置uniqueName的您自己的代码中都使用set:它首先“到达”,将创建文档,第二个将更新它。

此外,出于同样的原因,您必须允许使用 Firestore 规则对 users 集合进行插入和更新。这听起来可能有点吓人,但请记住,这只是您自己的用户列表,用于跟踪uniqueName,并且身份验证不是基于此,而是基于 Firebase Authentication 的用户管理,该用户管理受到很好的保护。

最后评论:这不是 100% 的解决方案。在您检查它是否唯一和实际创建用户之间,其他人保留uniqueName 的可能性很小,但理论上可能会发生。为了缓解这种情况,最好在创建 Firebase 用户之前进行检查。即使在这种情况下,重复的可能性仍然很小。

【讨论】:

  • 谢谢,我真的需要这个完整的解释。你和对方完全满足了我的要求
  • 不客气,我最近刚花了一些时间解决像你这样的问题。
【解决方案2】:

您必须将您的用户保存在一个集合中,然后检查该集合中是否已经存在 uniqueName。如果存在,则返回错误。

然后在创建新用户帐户时,保存 uniqueName。

// this function checks if uniqueName already exists
Future<bool> isDuplicateUniqueName(String uniqueName) async {
  QuerySnapshot query = await FirebaseFirestore.instance
      .collection('PATH_TO_USERS_COLLECTION')
      .where('uniqueName', isEqualTo: uniqueName)
      .get();
  return query.docs.isNotEmpty;
}

// call the above function inside here.
static firebaseSignUpWithEmailAndPassword(String emailAddress, String password, File? image, String name,) async {
  if (await isDuplicateUniqueName(name)) {
    // UniqueName is duplicate
    // return 'Unique name already exists';
  }
  // ... the rest of your code. Go ahead and create an account.
  // remember to save the uniqueName to users collection.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 2020-08-09
    • 2021-02-09
    • 1970-01-01
    • 2022-12-08
    相关资源
    最近更新 更多