Firebase数据库 - 反向索引

时间:2016-06-05 07:20:38

标签: json indexing firebase firebase-realtime-database firebase-security

在Firebase指南中,其中一个建议是维护反向索引以跟踪用户操作。以下是我所指的内容片段:

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
     "name": "Historical Tech Pioneers",
     "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

每个用户在反向索引中跟踪他/她的组 - 在这种情况下,密钥保持实际值,并且值无关紧要。

更新

我不确定如何在技术上更新索引但我在经过一些研究后得到了它:setValue可以采用所有变量,而不仅仅是键值对。这意味着更新索引非常简单:只需获取groups/$group_id/members/$member_id的引用并将其值设置为true

现在我的问题不同了:

让我们说所有团体都是私人的。意味着用户只能通过邀请加入组 - 当前组成员必须将另一个用户添加到成员列表。所以,如果我 ghopper 并且我想添加 alovelace 作为成员,我需要更新她的索引,这是她的用户对象的一部分 - 这意味着我必须知道她的用户ID在某种程度上具有对groups字段的写入权限 - 这似乎是一种安全风险。

关于如何在尽可能限制访问的同时管理此问题的任何想法?也许是另一个DB对象,它将用户已知的标识符(如电子邮件)映射到组列表?

1 个答案:

答案 0 :(得分:1)

解决方案1 ​​ - 客户端

一个解决方案是拥有一个单独的用户邀请对象,以便 ghopper 可以将 alovelace 添加到私人组,并让它显示 alovelace's 邀请而不是自动将她添加到组中。 alovelace 然后需要批准添加并更新她的群组成员资格。这样,只有用户才能保留对其用户记录的访问权限。这非常类似于在Facebook上添加朋友,或在linkedin上请求连接。

为了说明,架构看起来像这样

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         // Only Ada can write here
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "invitations": {
    "alovelace": {
      "name": "Ada Lovelace",
      "groups": {
         // the value here doesn't matter, just that the key exists
         // Anyone can write here
         "ghoppersfanclub": true, // Ada might accept this and move it to groups
         "explicitcontentgroup": true, // Ada might reject this and delete this entry
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
     "name": "Historical Tech Pioneers",
     "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

解决方案2 - 服务器端

尽管Firebase旨在支持在没有服务器代码的情况下构建应用程序,但有些情况下您应该将服务器混合在一起。在我看来,安全性和可信操作的执行,例如一个用户对另一个用户的记录进行更改(如果我们没有使用上面的'邀请'之类的单独对象),应由您的可信服务器使用admin API处理。当 ghopper alovelace 添加为成员时,一个可能的事件序列将是:

  • 检查 ghopper 是否属于该群组,并可以添加其他用户(客户端)
  • 向您的服务器发送请求,其中包含有效负载,包括群组名称/ ID,发送请求的用户以及正在添加的用户的电子邮件

  • 然后,服务器使用提供的电子邮件查找alovelace的用户ID并更新用户记录。

    admin.auth().getUserByEmail(alovelace_email)
      .then(function(userRecord) {
        // Add group to alovelace's groups.
        // Trigger a client-side notification using child_changed
        // Allow alovelace to approve or decline addition to group
      })
      .catch(function(error) {
        console.log("Error fetching user data:", error);
      });
    

上面的示例使用电子邮件作为公共/可共享的唯一标识符,但也有类似的getUserByPhoneNumber(phoneNumber)方法。