firebase - 理解 Firestore 安全规则 - 只允许更新某些字段

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

我正在尝试使用 Firestore 安全规则来编辑一些数据,如下所示,带有 交易在 flutter 中:

  Future sendRequest(uidSend, uidRec, pid, title) async {
    final crSend = ChatRequest(uid: uidRec, pid: pid, title: title);
    var _lsSend = List();
    _lsSend.add(crSend.toJson());

    final crRec = ChatRequest(uid: uidSend, pid: pid, title: title);
    var _lsRec = List();
    _lsRec.add(crRec.toJson());

    final uMSendDocref = userMetadataCollection.document(uidSend);
    final uMRecDocref = userMetadataCollection.document(uidRec);

    Firestore.instance.runTransaction((transaction) async {
      await transaction.update(uMSendDocref, <String, dynamic>{
        "sentRequests": FieldValue.arrayUnion(
          _lsSend,
        ),
      });
      await transaction.update(uMRecDocref, <String, dynamic>{
        "receivedRequests": FieldValue.arrayUnion(
          _lsRec,
        ),
      });
    });
  }

请注意,用户 1 正在尝试更新他/她自己的数据以及用户 2 的数据。但是,我只希望 user1 能够更新 user2 的这个单个字段。我制定了我的 Firestore 规则:
    match /userMetadata/{uid} {
      allow read: if uid == request.auth.uid || uid == 'PREVIEW';
      allow write: if uid == request.auth.uid && uid != 'PREVIEW';
      match /receivedRequests {
        allow read: if uid == request.auth.uid;
        allow write: if request.auth != null && request.auth.uid != 'PREVIEW';
      }
      match /sentRequests {
        allow read: if uid == request.auth.uid;
        allow write: if request.auth != null && request.auth.uid != 'PREVIEW';
      }
    }
receivedRequests (和 sentRequests )只要求用户具有非空的编辑权限,即任何用户都应该能够编辑。但是,在运行我的事务时出现权限错误。这是为什么?也许我误解了 Firestore 规则?也许事务正在尝试读取?有什么想法吗?

更新:

我尝试使用批处理:
  Future sendRequest(uidSend, uidRec, pid, title) async {
    //update own uM with post
    //update other uM with user

    final crSend = ChatRequest(uid: uidRec, pid: pid, title: title);
    var _lsSend = List();
    _lsSend.add(crSend.toJson());

    final crRec = ChatRequest(uid: uidSend, pid: pid, title: title);
    var _lsRec = List();
    _lsRec.add(crRec.toJson());

    final uMSendDocref = userMetadataCollection.document(uidSend);
    final uMRecDocref = userMetadataCollection.document(uidRec);

    var batch = Firestore.instance.batch();

    batch.updateData(uMSendDocref, <String, dynamic>{
      "sentRequests": FieldValue.arrayUnion(
        _lsSend,
      ),
    });

    batch.updateData(uMRecDocref, <String, dynamic>{
      "receivedRequests": FieldValue.arrayUnion(
        _lsRec,
      ),
    });

    return await batch.commit();
  }

仍然不起作用。 Firestore 的某些东西要么非常不直观,要么存在严重的错误。

另一件要注意的事情:一些 userMetadata 当前可能没有正在更新的字段。

最佳答案

I only want user1 to be able to update this single field of user2's.



允许仅更新某些字段的一般方法是检查 request.resource.data 的差异。与 resource.data .

需要更新的示例文档有 3 个字段:name、city、standingBalance。我们希望任何人都可以更改standingBalance,但只有相应的用户可以更改他的姓名和城市。

下面的例子考虑到 user1 应该有完整的 write访问 user1's sendRequest & 仅 single field update访问 user2's receivedRequests ,其他场景不会有太大变化。
match /userMetadata/{uid} {
  allow read: if uid == request.auth.uid || uid == 'PREVIEW';
  allow write: if uid == request.auth.uid && uid != 'PREVIEW';
  match /receivedRequests/{req} {
    allow read: if uid == request.auth.uid;
    allow write: if uid == request.auth.uid;
    allow update: if uid == request.auth.uid 
                 || (request.resource.data.keys().hasOnly(['name','city','standingBalance']) 
                     && request.resource.data.name == resource.data.name
                     && request.resource.data.city == resource.data.city
                     && request.resource.data.standingBalance != resource.data.standingBalance
                     && request.auth.uid != null
                    )
  }
  match /sentRequests/{req} {
    allow read: if uid == request.auth.uid;
    allow write: if request.auth != request.auth.uid || request.auth.uid != 'PREVIEW';
  }

hasOnly 核对确保没有其他 key 添加到文档中。另外,我不知道什么是“预览”,所以请自己验证规则。

有一个 fieldsChanged Firestore 规则中的变量将是一个很好的功能请求;)

关于firebase - 理解 Firestore 安全规则 - 只允许更新某些字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62110037/

相关文章:

ios - iPhone X 上未收到 Firebase 通知 FCM

Firebase:403 PERMISSION_DENIED(FirebaseError:安装):更新 SDK 后请求被阻止 (FirebaseInstallationsService)

dart - 如何禁用 Flutter Raw Chip 中的芯片选择图标?

android - Flutter:TextButton 中的 setState 不起作用

javascript - firestore 查询中的条件 where 子句

list - flutter 将项目添加到列表

firebase - 从第一张图片生成的缩略图在 Firebase 存储中为其他人复制

带有后退按钮的 Flutter 测试 WillPopScope

database - Cloud Firestore 等同于 AppEngine/Datastore Memcache 和 Keys-only 查询?

javascript - 注销后调用 Firebase getRedirectResult