Firestore规则无需授权即可写入/更新一个特定字段

时间:2018-08-16 16:09:47

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

我想只对Firestore数据库集合中的一个字段提供写/更新访问权限,而无需请求auth服务。我对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

有什么建议吗?

5 个答案:

答案 0 :(得分:4)

我不知道该线程是否仍然有效,但是在寻找一个偶然发现的解决方案时,我偶然发现了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

答案 1 :(得分:1)

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

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

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

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

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

答案 2 :(得分:0)

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

home/claimsCollection
    bizABC123
        claim:true
    bizXYZ123
        claim:false

答案 3 :(得分:0)

如罗恩所说,firestore Rules中的

权限分配只能应用于整个文档。 尽管如此,仍然存在一种允许写入/更新/删除/创建特定文件的方法,即通过确保传入的更改对象仅具有您要授予权限的字段。 您可以通过以下方式做到这一点:

  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"]; 
         }
      }
}

希望它会有所帮助,尽管问题已经发布了一阵子了!

答案 4 :(得分:0)

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

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

此功能可以如下使用:

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