Cloud Firestore安全规则-仅允许写入文档中的特定密钥

时间:2019-06-19 21:40:32

标签: firebase google-cloud-firestore firebase-security-rules

我目前正在使用Firestore数据库为我的应用程序编写一些规则。 当前,每个人都可以读取数据,经过身份验证的用户可以写入。

  match /quizzes/{quizId} {
    allow read; 
    allow write: if request.auth != null;
  }

这很好,但是我还希望未经身份验证的用户只写文档中的特定键。

文档内容示例:

{
  title: 'title',
  plays: 12,
  playedBy: [//Filled with user id's],
  ...
}

是否有任何方法可以限制未经身份验证的用户仅具有对playBy数组的写入权限,而不能对该文档的其他键进行写入?

2 个答案:

答案 0 :(得分:3)

当然。但是,如果您有很多字段,可能会涉及到一些问题。

让我们从最简单的例子开始。这样的事情允许未经身份验证的用户编写playedBy,只要这是文档中的唯一字段即可。

if request.auth != null || request.resource.data.keys().hasOnly(['playedBy'])

如果未经身份验证的用户正在创建新文档或更新现有文档,则此方法有效。但是,一旦文档包含更多字段,该操作将立即停止,因为request.resource.data包含了写入成功后文档将拥有的所有字段。

因此,更好的选择是检查仅修改playedBy,并且所有其他字段都具有与以前相同的值。棘手的是处理字段的不存在,我通常使用一些辅助函数来处理这些字段:

function isUnmodified(key) {
  return request.resource.data[key] == resource.data[key]
}
function isNotExisting(key) {
  return !(key in request.resource.data) && (!exists(resource) || !(key in resource.data));
}

然后:

if request.auth != null &&
  request.resource.data.keys().hasOnly(['title', 'plays', 'playedBy']) &&
  isUnmodified('title') && 
  isUnmodified('plays')

确切的规则可能有点过时,但是我希望这足以让您自己完成。

答案 1 :(得分:1)

在较早的答案(我认为是2019年末)之后,Firebase带来了Map.diff

类似的东西:

match /quizzes/{quizId} {
    allow read; 
    allow write: if request.auth != null ||
      request.resource.data.diff(resource.data).affectedKeys() == ["playedBy"].toSet()
  }

可以在here上看到我使用过的经过测试的代码。