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

Posted

技术标签:

【中文标题】Firebase 规则 - 如何检查用户是不是存在于子文档中【英文标题】:Firebase Rules - How to check if user exists in sub documentFirebase 规则 - 如何检查用户是否存在于子文档中 【发布时间】:2019-02-26 03:40:18 【问题描述】:

我正在使用 Firebase 商店/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");
     
 ];

非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

您的安全规则允许用户阅读特定主题(如果他们正在关注该主题)。您的代码尝试阅读您的规则不允许的所有主题。这就解释了为什么服务器拒绝读取操作。

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

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

您也可以尝试validate the query,但我不太确定这是否适合您的情况。

【讨论】:

感谢您的回复!我完全明白。我认为规则会检查每个主题,而不是检查整个 /Topics 的规则。我想我在某种程度上将规则视为过滤器,这很糟糕。我可能最终会按照建议创建一个单独的用户配置文件,以保留他们关注的主题列表。虽然......你提供的链接让我很感兴趣,而且我觉得这离我想要的更近了一步。我认为在该解决方案中我会遇到问题的地方是在 IOS 端编写“where”子句,但这是我可以玩的东西 =) 再次感谢 Frank!

以上是关于Firebase 规则 - 如何检查用户是不是存在于子文档中的主要内容,如果未能解决你的问题,请参考以下文章

如何检查用户是不是存在于 Firebase 中?

通过firebase规则检查数据库中是不是存在相同的数据

如何使用geofire查询检查10公里半径内是不是存在firebase用户

当用户在flutter中使用otp方法登录时,如何检查用户详细信息是不是已经存在于firebase中? [复制]

将 Apple Sign In 与 React Native Firebase 和 Firestore 一起使用时,如何检查用户是不是存在?

Flutter & Firebase:如何检查某个项目是不是存在于 Firebase 文档中的数组中