firebase - Firestore 规则和使用电子邮件 key 查询文档映射以与用户共享数据

标签 firebase google-cloud-firestore firebase-security

用例总结

  1. 用户 A 创建了一个故事
  2. 用户 A 通过电子邮件(通过云功能发送)与未知(向应用程序)用户 B 分享故事
  3. 用户 B 收到有关该故事的电子邮件
  4. 用户 B 访问应用并创建一个新帐户
  5. 用户 B 查看/阅读用户 A 创建的故事

注意故事只能被分享或创建的人看到

我正在构建一个基于角色的访问系统。我一直在看 role based access firestore documentation我少了一件。

考虑一个故事,该故事只能由已为其共享该故事的用户阅读。包括 firestore 示例在内的大多数示例都使用 UID 具有识别共享用户的 key 。但是,该用户目前可能不是 firebase 应用程序的用户,此外,用户如何分配该 UID。

故事数据

{
  title: "A Great Story",
  roles: {
    aliceUID: {
      hasRole: true,
      type: "owner",
    },
    bobUID: {
      hasRole: true,
      type: "reader",
    }
  }
}

故事查询

firebase.firestore().collection('stories').where(`roles.${user.uid}.hasRole`, '==', true)

第二部分可能会通过维护一个单独的用户集合来解决,然后您可以从他们的电子邮件地址中找到用户,但这并不能解决从未登录过的用户。

想要分享故事的用户可以添加带有电子邮件地址的用户。然后使用 firebase 函数,我们可以发送一封电子邮件来通知用户共享的故事,用户可以登录到应用程序并阅读该故事。

如果我们继续使用此方法,那么您将没有 UID,而只有电子邮件地址作为 key 。

故事数据

{
  title: "A Great Story",
  roles: {
    alice@yahoo.com: {
      hasRole: true,
      type: "owner",
    },
    bob@gmail.com: {
      hasRole: true,
      type: "reader",
    }
  }
}

故事查询

firebase.firestore().collection('stories').where(`roles.${user.email}.hasRole`, '==', true)

更新的 Firestore 规则 - 来自 documentation

function getRole(rsc) {
  // Read from the "roles" map in the story document.
  return rsc.data.roles[request.auth.uid] || rsc.data.roles[request.auth.token.email];
}

我无法使电子邮件查询正常工作。这SO issue提到

Unfortunately dots are not allowed as a map key. So email addresses won't work.

我不明白为什么这会在规则方面产生冲突。它确实导致了一个可能无效的 where 子句

例如

.where(`roles.${user.email}.hasRole`, '==', true) -> .where(`roles.bob@gmail.com.hasRole`, '==', true)

这看起来像无效的 JS,不幸的是 [] 是无效的字符,所以我们不能这样做

.where(`roles[${user.email}]hasRole`, '==', true)

我看到的最后一件事是使用这个 Firebase talk是使用类似的东西转义电子邮件地址

function encodeAsFirebaseKey(string) {
  return string.replace(/\%/g, '%25')
    .replace(/\./g, '%2E')
    .replace(/\#/g, '%23')
    .replace(/\$/g, '%24')
    .replace(/\//g, '%2F')
    .replace(/\[/g, '%5B')
    .replace(/\]/g, '%5D');
};

这似乎修复了查询 where 子句,它是一个有效的数据结构,但它不是 valid Firestore rule这意味着它没有真正的安全实现。

关于如何实现这个的任何想法?请包含有效的数据结构、Firestore 规则和查询。我已经展示并看到了很多示例,这三个示例中有两个都是无效的解决方案。

谢谢!

最佳答案

基本问题是我不知道如何正确地制定有效的查询。事实证明,您不需要在一行中创建查询。

您可以使用 FieldPath构造您的查询参数。

var path = new firebase.firestore.FieldPath('roles', email ,'hasRole');
firebase.firestore().collection('stories').where(path, '==', true)

这解决了原来丢失的部分。

关于firebase - Firestore 规则和使用电子邮件 key 查询文档映射以与用户共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49265907/

相关文章:

java - 如何更新 Firebase 数据库中的子节点数据?

firebase 功能 - `firebase deploy` - 该服务当前不可用

javascript - Firebase Cloud Firestore错误+Vue+Vuex(firebase.firestore.QuerySnapshot)

javascript - 在 Cloud Firestore 中查找具有特定引用的所有文档

flutter - 使用StreamBuilder来获取Firestore文档,该文档包含Flutter中的 map 列表

android - Android/Firebase 调试签名证书 SHA-1 的用途

android - 将firebase数据库url(字符串)分配给数据库引用变量?

javascript - Firestore规则: fetch message thread by threadId in secure way

swift - 使用 Firebase 安全规则,如何在不公开整个节点的情况下检查可用的用户名?

firebase - 我可以访问在 Firebase 通知中注册的所有用户的注册 token 吗?