Cloud Firestore 安全规则 - 只允许写入文档中的特定键

Pee*_*Jee 3 firebase firebase-security google-cloud-firestore

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

  match /quizzes/{quizId} {
    allow read; 
    allow write: if request.auth != null;
  }
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我也希望未经身份验证的用户只写入文档中的特定键。

文档内容示例:

{
  title: 'title',
  plays: 12,
  playedBy: [//Filled with user id's],
  ...
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以限制未经身份验证的用户只能对playedBy 数组进行写访问,而不能对该文档的其他键进行写访问?

aka*_*ppi 6

在之前的回答之后(我相信是 2019 年末),Firebase 引入了Map.diff

就像是:

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

我使用它的测试代码可以在这里看到。


Fra*_*len 5

肯定的事。但是如果你有很多领域,它可能会变得有点复杂。

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

if request.auth != null || request.resource.data.keys().hasOnly(['playedBy'])
Run Code Online (Sandbox Code Playgroud)

如果未经身份验证的用户正在创建新文档或更新现有文档,则此方法有效。但是一旦文档包含更多字段,它就会停止,因为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));
}
Run Code Online (Sandbox Code Playgroud)

进而:

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

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