Firebase规则-如何检查子文档中是否存在用户

时间:2019-02-26 03:40:18

标签: ios firebase google-cloud-firestore firebase-security-rules

我正在使用Firebase商店/ Firebase规则构建类似论坛的结构。我的结构是这样的:

Collection --- Document ------ Collection --- Document
Topic1         CreationDate    UsersJoined    UserUID1
Topic2         Title                          UserUID2
Topic3         UpdatedDate                    UserUID3
...            ...                            ...

基本上,每个主题都有一个用户集合。我的目标是能够编写一个安全规则,其中只有“ UsersJoined”中的Users可以读/写相应的主题。这就是我现在的规则:

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;
      }
    }
  }
}

因此,当我使用内置的Simulator时,读取工作正常;但是,当我请求通过我的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");
     }
 }];

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您的安全规则允许用户阅读特定主题(如果他们遵循该主题)。您的代码尝试读取规则不允许的所有主题。因此可以解释为什么服务器拒绝读取操作。

这很容易记住,因为意识到规则本身不会过滤数据。相反,它们允许听众或不允许听众。而且由于您的规则不允许在所有/Topics上使用侦听器,因此该侦听器将被拒绝。

一种解决方案是只阅读您关注的特定主题。要确定主题,您可能需要将文档与用户的主题列表一起存储,例如存储在/Profiles集合中。这在NoSQL数据库上很常见:您实际上是在存储多对多关系的两端。

或者,您可以尝试validate the query,但是我不确定是否可以使它适合您的情况。