firebase 云火:模范会员邀请

h7appiyu  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(111)

我正在使用Web Client SDK v9编写一个基于Cloud Firestore的应用程序(但这是数据库架构的一个更一般的问题,不一定与此特定的SDK相关)。
我想实现以下功能:

  • 用户可以创建组
  • 用户可以通过发送邀请码邀请其他用户加入他们的群组(应用程序创建一个邀请码,该邀请码将授予对相关群组的访问权限)
  • 其他用户可以使用此邀请代码加入组

这就是我希望在安全规则中对邀请/加入组的处理进行建模的方式:

  • 只有作为组成员的用户可以读取它
  • 只有属于组的用户才能写入它,但以下用户除外:
  • 具有有效邀请代码的用户可以将自己作为成员写入组

在Cloud Firestore中对此建模似乎是不可能的。
到目前为止,我有一个集合groups和另一个集合invites,invite的邀请代码为doc.id,字段groupId中有它将授予访问权限的组的id。
我发现一般有两种方法可以对组成员身份进行建模,但似乎这些方法都不允许对上述安全规则进行建模:
A)组具有子集合members,具有有效邀请码的用户可以将他们自己添加到该子集合。

match /groups/{groupID} {
  function hasValidInvite() {
    return exists(/databases/$(database)/documents/invites/$(request.resource.data.inviteCode));
  }

  match /members/{memberID} {
    allow write: if hasValidInvite();
  }
}

所以写成员资格是可行的,但是查询一个用户的所有成员资格似乎是不可能的,因为集合查询不能在子集合上执行where(documentId(), "==", getAuth().currentUser.uid)(这似乎是一些bug)。
鉴于此问题,建议采用第二种方法:
B)一个组有一个数组字段members,用户id被写入其中。我只需要检查当前的uid是否在组的members数组中。但是我发现没有办法编写安全规则来允许某人只在arrayUnion()字段上并且只对组执行arrayUnion()操作他们拥有的有效邀请。
所以我有两种非常不同的方法,每种方法都涵盖了解决方案的一半,但不兼容。
你知道我该怎么做吗?

p1iqtdky

p1iqtdky1#

事实证明,这两种解决方案可以在云函数的帮助下结合起来,该函数侦听对members集合中文档的更改,并将新创建文档的id写入相应groups文档中的members数组:

const functions = require("firebase-functions");

let isWriteMembershipToGroupInitialized = false;

exports.writeMembershipToGroup = functions.firestore
    .document("/groups/{groupId}/members/{memberId}")
    .onCreate((snapshot, context) => {
      const admin = require("firebase-admin");
      if (!isWriteMembershipToGroupInitialized) {
        admin.initializeApp();
        isWriteMembershipToGroupInitialized = true;
      }

      const docRef = admin.firestore().doc("groups/" + context.params.groupId);
      return docRef.update({
        members: admin.firestore
            .FieldValue
            .arrayUnion(context.params.memberId),
      }, {merge: true});
    });

缺点:

  • 引入了新的SDK(Firebase针对不同的用例提供了大量不同的SDK,每个SDK的作用略有不同)
  • 需要升级到付费计划(尽管仍有免费等级,但您必须提供计费信息)
  • 云函数可能需要几秒钟才能启动,因此用户可能无法立即看到更改!

相关问题