我正在使用Firebase Store / Firebase规则开发类似论坛的结构。我的结构是这样的:
Collection --- Document ------ Collection --- Document
Topic1 CreationDate UsersJoined UserUID1
Topic2 Title UserUID2
Topic3 UpdatedDate UserUID3
... ... ...
基本上,每个主题都有一个用户集合。我的目标是能够编写一个安全规则,其中只有'UsersJoined'中的用户可以读/写相应的主题。这就是我现在的规则:
service cloud.firestore {
match /databases/{database}/documents {
match /Topics/{topicUID} {
allow read, create, update, delete: if exists(/databases/$(database)/documents/Topics/$(topicUID)/UsersJoined/$(request.auth.uid));
match /UsersJoined/{userUID=**} {
allow read, create, update, delete;
}
}
}
}
因此,当我使用内置的模拟器时,读取工作正常;但是,当我通过我的IOS代码请求阅读时,它告诉我我没有足够的权限。
我已经尝试过做allow read: if request.auth.uid != null;
,我能够阅读。我确信UserUID确实存在于UsersJoined集合中。
我也尝试创建一个“姐妹”集合,我将用户ID存储在其中,所以我的结构如下所示:
Collection ----------- Document
MyTestUserCollection UserUID1
Topic1 UserUID2
Topic2 ...
...
然后我使用了这个规则:if exists(/databases/$(database)/documents/MyTestUserCollection/$(request.auth.uid));
和读取也适用于模拟器和IOS代码。
当用户列表嵌套在主题中时,我的问题是无法读取。所以我的问题是......通过编写一个检查(“读取”)嵌套集合中数据的规则,我是否违反了“允许读取”规则(因为从技术上讲,它还没有确定我是否可以读取)?或者我是否过于复杂化了一些事情并且有更好的方法来构建我的收藏/文档?或者我只是不正确地编写规则?
我不相信我在IOS上的代码是问题,但是以防这是我正在做的请求从我的数据库中读取的内容:(用户通过Firebase Auth登录)
[[myFirestore collectionWithPath:@"Topics"]
getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
if (error != nil) {
NSLog(@"Error getting documents: %@", error);
} else {
NSLog(@"Read it");
}
}];
任何帮助是极大的赞赏!
您的安全规则允许用户阅读特定主题(如果他们正在关注该主题)。您的代码会尝试阅读您的规则不允许的所有主题。这就解释了服务器拒绝读取操作的原因。
通过意识到规则本身不过滤数据,这是最容易记住的。相反,他们要么允许听众,要么不允许听众。由于你的规则不允许所有/Topics
上的监听器,该听众被拒绝。
一种解决方案是只阅读您作为追随者的特定主题。要确定主题,您可能需要使用用户的主题列表存储文档,例如在/Profiles
集合中。这在NoSQL数据库中很常见:你实际上存储了多对多关系的两面。
或者你可以尝试validate the query,但我不太确定是否可以为你的情况工作。