swift 对象上未定义Firestore属性,for 'list' @L41

s4n0splo  于 2023-03-07  发布在  Swift
关注(0)|答案(1)|浏览(74)

我正在编写一些Firestore规则,当我尝试读取聊天集合中的聊天数据时,我看到一条错误消息。我看到过其他关于此错误的帖子,但没有一个与我的情况相符,我似乎无法找出问题所在。
以下是我的安全规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read: if userIsSignedIn();
      allow write: if request.auth.uid == uid;
    }

    match /users/{uid}/notifications/{notificationId} {
      allow read: if resource.data.recipientUid == request.auth.uid;
    }

    match /bands/{bandId} {
      allow read: if userIsSignedIn();
      allow delete: if request.auth.uid == resource.data.adminUid;
      allow list, update: if request.auth.uid in resource.data.memberUids;

      match /members/{memberId} {
        allow read: if userIsSignedIn();
        allow delete: if request.auth.uid == resource.data.uid;
      }

      match /links/{linkId} {
        allow read: if userIsSignedIn();
      }
    }

    match /shows/{showId} {
      allow read: if userIsSignedIn();

      match /backlineItems/{backlineItemId} {
        allow read: if userIsSignedIn();
      }

      match /participants/{participantId} {
        allow read: if userIsSignedIn();
      }
    }

    match /chats/{chatId} {
      allow read: if request.auth.uid in resource.data.participantUids;
      allow write: if true;
    }

    match /chats/{chatId}/messages/{messagesId} {
        allow read, write: if userIsSignedIn();
    }
  }

  function userIsSignedIn() {
    return request.auth != null;
  }
}

下面是触发错误消息的Swift查询(我知道这是导致错误的原因,我用断点缩小了范围):

func getChat(withShowId showId: String) async throws -> Chat? {
    do {
        let chat = try await db
            .collection("chats")
            .whereField("showId", isEqualTo: showId)
            .getDocuments()
        
        guard !chat.documents.isEmpty && chat.documents[0].exists && chat.documents.count == 1 else { return nil }
        
        let fetchedChat = try chat.documents[0].data(as: Chat.self)
        return fetchedChat
    } catch Swift.DecodingError.keyNotFound {
        throw FirebaseError.dataNotFound
    } catch {
        throw FirebaseError.connection(
            message: "Failed to fetch show chat.",
            systemError: error.localizedDescription
        )
    }
}

当我运行这个查询时,我收到这个错误消息:在对象上未定义"list "@L41的属性participantUids。
Here is a screenshot of the Chat document I'm trying to query, which clearly shows that the Chat type has a property called participantUids
我被卡住了,我不知道这里出了什么问题。这个错误同时发生在Firebase模拟器和我的实际数据库中。有什么想法吗?
编辑:我添加了一些调试语句到规则,它现在看起来像这样:第一个月第一次:第一个月第一次
以下是抛出异常时打印到firestore-debug.log文件中的内容:

string_value: "qvJ5tmKpih3mFkUCet5CPREg3qjZ" // The correct uid of the logged in user

map_value {
  fields {
    key: "showId" // The correct parameter that the query above is using to find the chat
    value {
      string_value: "Kk1NYjptTJITr0pjfVbe" // The correct value of the showId property for the chat that is to be fetched
    }
  }
}

让我感到奇怪的是,日志文件中打印的唯一属性是showId属性。我认为这是因为我的查询是基于showId属性过滤结果的。这是否意味着,因为我是基于showId属性进行查询的,所以我的规则也必须以showId属性为中心?我不认为是这种情况。但我真的被难住了。
编辑2:我发现了。我认为这个问题的根本原因是我没有理解"规则不是过滤器",就像Firestore规则文档中所说的那样。我试图查询基于showId属性的聊天,但是因为我的规则没有为聊天的showId属性提供任何读取指南,所以它们会完全拒绝请求。相反,我需要基于participantUids属性查询聊天,因为规则知道如何处理该属性,但不知道如何处理showId属性。
下面是另一个引用的文件,澄清了这一点给我:"如果查询可能返回客户端没有读取权限的文档,则整个请求将失败。"因为规则对showId一无所知,所以根据此属性批准查询可能会返回"客户端没有读取权限"的文档。因此,请求将被拒绝。

kxxlusnw

kxxlusnw1#

您的客户端查询必须与您的规则匹配。因此,在您的情况下,请将查询更改为:

let chat = try await db
  .collection("chats")
  .whereField("showId", isEqualTo: showId)
  .whereField("participantUids", arrayContains: {youruid})
  .getDocuments()

相关问题