firestore 安全规则:允许登录用户更新字段

firestore security rules: allow logged in user to update field

我有以下 Firestore 安全规则

match /users/{user} {
  allow read: if request.auth != null;
  allow create: if request.resource.id == request.auth.uid;            
    
  match /replies {
    allow update: if request.auth != null;
  }
}

我从 firestore 安全规则文档中了解到,这两个规则是相互独立的。但是,登录用户在尝试更新 /user/{user}/replies 字段时会收到权限被拒绝的消息。我是否嵌套规则并不重要。它仍然被拒绝。 (它在 Firebase 控制台的 Rules Playground 中也不起作用)

我做错了什么?

我的客户端代码如下:

const processNewMessage = async (evt, newMessage) => {
  myMessage.value = myMessage.value.trim();

  if (evt.srcElement.textContent === "send") {
    if (replying.value === true) {
      const message = {
        originalMessage: {
          text: props.selectedMessage.text,
          photoUrl: props.selectedMessage.photoUrl,
        },
        reply: {
          user: uid,
          userDisplayName: auth.currentUser.displayName,
          userName: userName.value,
          text: newMessage,
          createdAt: Timestamp.now(),
          g: { geohash: geohash.value, geopoint: myLocation },
          photoUrl: photoUrl,
        },
      };

      await updateDoc(doc(db, `users/${props.selectedMessage.user}`), {
        replies: arrayUnion(message),
      });
    }
  }
}

安全规则适用于 document-level。您的代码正在尝试更新 users 文档中的 replies array,您的任何规则都不允许这样做。

您的规则中的 match /replies 适用于 users 文档下的 replies 子集合。它对 users 文档中的 字段 没有影响。


如果您希望所有者更新他们的整个文档,而其他登录用户只更新 replies 字段,您必须在 users 的规则中允许这样做。

像这样:

match /users/{user} {
  allow read: if request.auth != null;
  allow create: if request.resource.id == request.auth.uid;            
  allow update: if request.auth != null && 
    request.resource.data.diff(resource.data).affectedKeys().hasOnly(["replies"])
  ;
}

有关其工作原理的更多信息,请参阅 map diff function 的发行说明。