flutter 用于验证仅更改单个阵列Map的Firestore安全规则

f87krz0w  于 2023-05-19  发布在  Flutter
关注(0)|答案(1)|浏览(135)

我的应用有一个用户集合,每个经过身份验证的用户在此集合中都有一个文档。

目标

我的安全规则应该允许经过身份验证的用户更新他们自己的文档(其中auth.uid匹配文档ID),并允许任何经过身份验证的用户更新任何其他用户文档中的 * 一个字段 *。
此字段“memberships”是一个数组,其中数组中的每个项都是两个字段的Map:“groupId”和“status”:

问题

我的问题是更新另一个用户的文档,但只是一个字段。其他多个问题建议我如何做到这一点,但这些都没有看到工作。
在这个例子中,有问题的项是一个带有多个键的Map值列表,我想知道这是否是导致这个不起作用的原因。

5月12日更新-清理现有代码

当前的安全规则是:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
        // Allow users to read their own user document
    match /users/{userId} {
      allow read: if request.auth != null;
    }
    
    // Allow authorized user to edit their own user document
    match /users/{userId} {
      allow update: if request.auth.uid == userId;
    }
    
    // Allow any user to update the 'memberships' field in any user document
    match /users/{userId} {
      allow update: if request.auth != null && request.resource.data.diff(resource.data).affectedKeys().hasOnly('memberships');
    }
  }
  }

这里是我遇到问题的函数-您可以跳到我尝试完成一个批处理的部分。

Future<FailureOrSuccess> _confirmUpdateValidityAndUpdate(
      User user, Group group) async {

    MemberOfGroup memberInUser = MemberOfGroup.invited(groupId: group.id);

    ValueResult<User> userResult =
        user.addOrUpdateMembership(memberInUser);

    if (userResult.isFailure) {
      return const GroupFailure.invalidMembershipUpdate();
    }

    User userForUpdate = userResult.value;

    List<Map<String, dynamic>> userMemberships = [
      for (var membership in userForUpdate.memberships)
        MemberOfGroupDto.fromDomain(membership).toJson()
    ];
    
    try {
      print(user.id);
      // I've tried both 'set' and 'update' - both still have this issue.
      await _firestore
          .collection('users')
          .doc(user.id)
          .set({'memberships': userMemberships});
      return const Success();
    } on FirebaseException catch (e) {
      return mapFirebaseExceptionToFailure(e);
    }
  }

另外,不知道这是否重要,但UserMembership字段是List<Map<String,dynamic>> -不确定这是否重要:

List<Map<String, dynamic>> userMemberships = [
      for (var membership in userForUpdate.memberships)
        MemberOfGroupDto.fromDomain(membership).toJson()
    ];

下面是我看到的错误:

r7knjye2

r7knjye21#

这并不符合您的要求:

request.resource.data.keys().size() == 1

request.resource包含文档,因为它将在操作成功后存在,所以它包含文档的所有字段。如果只允许用户修改某些字段,您需要查看map diff的affectedKeys。从那里:

// This rule only allows updates where "a" is the only field affected
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["a"]);

因此,您可以使用它来确保只有memberships受到用户的影响。

相关问题