Firestore规则,用于限制对文档中特定字段的写入权限

ast*_*ms1 15 stripe-payments firebase firebase-security google-cloud-firestore

我使用Stripe付款.为此,我在Firestore中有以下数据模型:

Users/{userId}/payments/{document}
Run Code Online (Sandbox Code Playgroud)

每个{document}都是一个看起来像这样的对象:

{
  amount: 55
  token: {...}
  charge: {...}
}
Run Code Online (Sandbox Code Playgroud)

用户必须能够编写该token字段(这是传递给服务器的内容),但我不希望用户能够编写该charge字段.

目前我的规则允许任何用户读取和写入此文档:

match /payments/{documents} {
  allow read, write: if request.auth.uid == userId;
}
Run Code Online (Sandbox Code Playgroud)

什么Firestore规则将实现我所期望的安全性?

Dan*_*ath 22

我相信以下内容可行,它允许客户更新除收费之外的字段,以及创建没有收费字段的文档.

service cloud.firestore {
  match /databases/{database}/documents {
    function valid_create() {
        return !(request.resource.data.keys().hasAll(["charge"]));
    }

    function valid_update() {
        return request.resource.data.charge == resource.data.charge
               || (valid_create()
                  && !(resource.data.keys().hasAll(["charge"])))
    }

    match /payments/{userId} {
        allow read: if request.auth.uid == userId;
        allow create: if request.auth.uid == userId
                        && valid_create(); 
        allow update: if request.auth.uid == userId
                        && valid_update(); 
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 你指的是`userId`,但它没有定义.为清楚起见,您可能希望将`{database}`更改为`{userId}`. (3认同)

m.s*_*tos 6

宣布了套装类型,以及其他一些很酷的东西。


使用 Sets 确保文档只有字段“a”、“b”和“c”:

request.resource.data.keys().toSet() == ["a", "b", "c"].toSet()
Run Code Online (Sandbox Code Playgroud)

同样,您可以确保文档只有指定的键,而没有其他键:

(request.resource.data.keys().toSet() - ["required","and","opt","keys"].toSet()).size == 0?`
Run Code Online (Sandbox Code Playgroud)


Der*_*yen 5

接受的答案不适用于update,其中request.resource.data返回已与现有数据合并的新地图。因此,request.resource.data.keys().hasAll([<<field>>])总是 return true

无论如何,对我有用的是使用.diff()

function meta_is_modified() {
      return 'meta' in resource.data.diff(request.resource.data).affectedKeys();
    }
Run Code Online (Sandbox Code Playgroud)

这是具有多个受保护字段的另一个版本:

function invalid_modification() {
  return resource.data.diff(request.resource.data).affectedKeys().hasAny(['field1', 'field2'].toSet());
}
Run Code Online (Sandbox Code Playgroud)