在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对象,它将用户已知的标识符(如电子邮件)映射到组列表?
答案 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 添加为成员时,一个可能的事件序列将是:
向您的服务器发送请求,其中包含有效负载,包括群组名称/ 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)方法。