管理用于注册 Firebase 的邀请码

Manage invite codes for registration with Firebase

我正在自学 AngularJS 和 Firebase,并且正在开发一个具有两个用户角色 A 和 B 的应用程序。角色 B 应该只有在拥有有效邀请码的情况下才能注册到网站。

我使用 Firebase 作为后端和 AngularFire 绑定。我已经使用 Yeoman 生成器 generator-angularfire 设置了我的项目。后者提供Firebase基本密码/简单登录认证方式。

我的注册表单的字段比 email/password 多。用户 ID、电子邮件、通行证由 Firebase 内部处理并成功存储。此外,我在成功注册后将这些其他字段保存在另一个名为 "accounts":

的 Firebase 文档中
"accounts": {
    "simplelogin:16" : {
      "company" : "foo corp",
      "firstName" : "lorem",
      "lastName" : "ipsum",
      "type" : "userRoleA"
    },
    "simplelogin:19" : {
      "company" : "bar corp",
      "firstName" : "dolor",
      "lastName" : "sit",
      "type" : "userRoleA"
    },
    "simplelogin:17" : {
      "city" : "new york",
      "firstName" : "asd",
      "lastName" : "asd",
      "type" : "userRoleB"
    },
    "simplelogin:18" : {
      "city" : "washington",
      "firstName" : "a",
      "lastName" : "a",
      "type" : "userRoleB"
    }
}

现在我正试图找到一种安全的方法来实现邀请码功能。我添加了一个名为 "inviteCodes":

的 Firebase 文档
"inviteCodes" : {
  "111" : {
    "generator" : "system"
  },
  "222" : {
    "generator" : "system"
  },
  "333" : {
    "generator" : "system"
  }
}

1 - 生成邀请代码:我不能简单地将它们直接放在 Firebase 中,因为在后面的步骤中我希望用户 A 能够生成这些代码。 但是我如何在不向前端公开方法的情况下在 Firebase 上生成代码? 我会通过添加一个 Firebase 规则来解决这个问题,该规则只授予类型为 "userRoleA" 的已验证用户"accounts" 文档对 "inviteCodes" 文档的写入权限。这是要走的路,还是有其他方法?因为在这种情况下,生成代码的方法仍然是暴露的。

2 - 假设 1) 已解决并且邀请码在 Firebase 文档中。注册后,在调用 $createUser 方法之前,我需要检查提供的邀请码是否有效。我会查询 Firebase 并检查提供的代码是否与任何已保存的邀请代码匹配。像这样的东西(用于说明的虚拟代码):

var firebaseCodes = firebaseRefInviteCodes;
var providedCode = registrationForm.providedCode;
var isCodeValid = false;

for (var i = 0; i < firebaseCodes.length; i++) {
  if (firebaseCodes[i] === providedCode) {
    isCodeValid = true;
  }
}

但同样,在此查询中,所有代码都会暴露给前端。 有没有办法在不暴露所有代码的情况下检查提供的代码是否有效?

感谢您的意见。

为了生成邀请,我认为前端这样做没有任何问题 - 除非它是一个安全的随机令牌生成器。您还可以让 Firebase 生成它:

var inviteCode = firebaseRef.push().key();

安全规则是保护 Firebase 中的应用程序数据的一种强大方式。但是,为了使它们正常工作,您必须以正确的方式设计数据结构。 'Relational' DB 方法在这种情况下不起作用。 问题是用户 A 仅与用户 B 共享邀请,其他任何人都不能 'see' 他们。因此,将所有访问代码存储在一个 'table' 中并不是一个好的选择。 我假设当 userA 创建邀请时,它知道该邀请是针对哪个用户的。在这种情况下,您可以设计类似这样的数据结构:

-inviteCodes
    -invitee
        -{$userB_email}
            -code: {codeValue}
            -inviterId: {userAId}
            -generator: "system"

有了这个结构,安全规则可以如下:

/inviteCodes/invitee - public, so userA can insert new invite code for userB

/inviteCodes/invitee/{userB_email} - write new data - public, read - private, can be accessed only by userB, e.g. data.exists() && newData.child('email').val() === $userB_email && newData.child('inviteCode').val() === data.child('code').val()

生成代码的 userA 还可以存储生成代码的用户的电子邮件,然后它也可以使用电子邮件及其 inviterId 访问此数据。

通过这种方式,您永远不必为其他用户检索邀请。