Firestore规则,仅允许更新某些字段

时间:2020-05-03 02:22:01

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

我有以下数据库集合'/player_profiles/{userId}'。我要使用仅request.auth.uid == userId的规则,除非它们仅更新匹配数组的字段。我试过了,但是它拒绝了权限

match /player_profiles/{userId}{
        allow write: if userId == request.auth.uid; 
      allow update: if (request.resource.data.keys().hasOnly(["matches"]) && request.auth != null);
    }

这是Flutter代码,用于运行更新以将项目添加到matchs数组:

await DatabaseProvider()
        .db
        .collection(PLAYER_COLLECTION)
        .document(widget.userProfile.userId)
        .updateData({
      'matches': FieldValue.arrayUnion([profile.userId])
    });

我是Firestore规则的新手,但我认为这会起作用

能够获得我想要的以下行为:

match /player_profiles/{userId}{
        allow write: if request.auth.uid == userId || (request.auth != null && request.resource.data.diff(resource.data).affectedKeys().hasOnly(["matches"]));
    }

看看@Doug Stevenson的答案,尽管我可以确保他们只被允许将自己的userId放入其他人的个人资料中。

1 个答案:

答案 0 :(得分:2)

request.resource.data.keys()始终包含正在编写的文档中的每个字段,无论它是否正在更新。您应该使用新的MapDiff API来比较正在编写的内容和当前存在的内容。

我想你会想做这样的事情:

if
  (request.resource.data.diff(request.resource.data).affectedKeys().hasOnly(["matches"]) &&
  (request.resource.data.matches.toSet().difference(resource.data.matches) == [userId].toSet()) ||
  request.auth == null;

我还没有测试过,但是我想你明白了。您将需要放宽使用链接的API文档来获得安全规则,以有效地使用地图,集合和列表。