我正在编写一些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
一无所知,所以根据此属性批准查询可能会返回"客户端没有读取权限"的文档。因此,请求将被拒绝。
1条答案
按热度按时间kxxlusnw1#
您的客户端查询必须与您的规则匹配。因此,在您的情况下,请将查询更改为: