【问题标题】:Firestore rules to write/update one particular field without auth无需身份验证即可写入/更新一个特定字段的 Firestore 规则
【发布时间】:2019-01-23 15:58:04
【问题描述】:

我想只授予对我的 firestore 数据库集合中的一个字段的写入/更新访问权限,而无需请求身份验证服务。我的 Firestore 规则是:

service cloud.firestore {
  match /databases/{database}/documents {
    match /businesses/{businessId} {
      allow read;
      allow write: if request.auth.uid != null;
    }
  }
}

businesses 我的数据库结构是:

addedBy: string;
address: string;
category: string;
claim: boolean;
city: string;
email: string;
id: string;
likes: number;
location: {
    _lat: number,
    _long: number
};
name: string;
ocHours: [{
    day: string,
    from: string,
    status: string,
    to: string
}];
phone: number;
sponsored: boolean;
state: string;
status: string;
verificationCode: string;

我只想更新 claim 字段而不更新 request.auth.uid != null

有什么建议吗?

【问题讨论】:

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


【解决方案1】:

我不知道这个帖子是否仍然有效,但在寻找解决方案时我偶然发现了 rules.MapDiff 规范,这正是您正在寻找的:

// Compare two Map objects and return whether the key "a" has been
// affected; that is, key "a" was added or removed, or its value was updated.
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["a"]);

详情请看这里https://firebase.google.com/docs/reference/rules/rules.MapDiff

【讨论】:

    【解决方案2】:

    this blog post 中所述,request.resource.data 不仅包含更新的字段,还包含整个未来状态(如果写入成功)。

    因此,您可以简单地检查资源中的字段是否与请求中的字段不同,并且正如作者巧妙地建议的那样,创建如下函数:

    function notUpdating(field) {
     return !(field in request.resource.data) || resource.data[field] == request.resource.data[field]
    }
    

    在您的情况下,您可能希望将您的 write 分解为 create,update,delete 并且 update 可能看起来像这样:

    allow update: if
         notUpdating(addedBy)
      && notUpdating(address)
      && notUpdating(category)
      // ... put all fields here except 'claim'
      && notUpdating(status)
      && notUpdating(verificationCode) ;
    

    【讨论】:

      【解决方案3】:

      如 Ron 所说,firestore 规则中的权限分配只能应用于整个文档。 尽管如此,有一种方法可以允许写入/更新/删除/创建特定文件,即确保传入的更改对象仅具有您要授予权限的字段。 你可以这样做:

      1. 读取传入对象中的所有键:request.resource.data.keys()
      2. 确保对象中的唯一键是hasOnly(["claim"])

      service cloud.firestore {
          match /databases/{database}/documents {
              match /businesses/{businessId} {
                  allow read;
                  allow write: if request.resource.data.keys().hasOnly(["claim"]); 
              }
          }
      }
      

      希望对您有所帮助,尽管问题已经发布了一段时间!!

      【讨论】:

      • request.resource.data 似乎包含整个文档,而不仅仅是正在写入的属性。我错过了什么吗?
      • @MoeSalih 遇到同样的事情......有没有解决方案?谢谢!
      【解决方案4】:

      我编写了以下函数,用于只允许编辑一个字段:

      function onlyField(field) {
          return request.resource.data.keys().hasOnly([field]);
      }
      

      这个函数可以如下使用:

      match /someObject/{document=**} {
          allow update: if onlyField('someFieldOfYOurObject');
      }
      

      【讨论】:

        【解决方案5】:

        授权应用于整个文档。您可以创建由业务 uid 标识的文档的“声明”集合,并将其设置为 write,这样公众就无法阅读该列表,但他们可以更新 claim 属性。这些文档可以是布尔值

        home/claimsCollection
            bizABC123
                claim:true
            bizXYZ123
                claim:false
        

        【讨论】:

        • 但是,如果我采用这种解决方案,那么我必须至少拨打三个电话,而不是一个电话,而且如您所知,firebase 会向我收取更多费用。 ?
        • 如果您确实遇到了这些限制,您将成功创建一个突破性应用程序,此时计费将不再是问题 :-) Firebase 实际上是免费的,除非您的应用程序成功大量使用。
        猜你喜欢
        • 2020-07-16
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-21
        • 2019-02-13
        相关资源
        最近更新 更多