Firestore安全规则中的递归通配符无法按预期工作

pop*_*rap 7 firebase firebase-security google-cloud-firestore

我有一个这样的数据结构(集合文档,而不是JSON当然,但你明白了):

{
   users: {
      user1:{
         name: Alice,
         groups: {
            groupA:{subbed:true},
            groupB:{subbed:true}
         }
      },
      user2:{
         name: Bob,
         groups: {
            groupC:{subbed:true},
            groupD:{subbed:true}
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

基本上,这是注册用户ID和每个用户订阅的组ID.我想编写一个安全规则,只有当他们是当前的auth用户时才允许访问用户配置文件和子集合,并且根据我对文档的阅读,我认为通配符可以实现这一点......

match /users/{user=**}{
   allow read,write: if user == request.auth.uid;
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我可以正常阅读user文档,但是当我尝试阅读groups子集时,我收到权限错误.我只能通过明确匹配子集合来使其工作...

match /appUsers/{user}{
   allow read,write: if user == request.auth.uid;

   match /groups/{group}{
      allow read,write: if user == request.auth.uid;
   }
}
Run Code Online (Sandbox Code Playgroud)

...所以我的问题是,两个例子之间有什么区别,我对递归通配符有什么误解?我认为{user=**}第一个示例的部分应该user无限制地授予对文档及其所有子集合,子子集合等的访问权限(对于授权用户),并且应该不需要专门为存储的数据编写规则我在第二个例子中不得不这样做.

我只是在短时间内搞乱Firestore,所以这可能是一个真正愚蠢的问题:)

谢谢大家

use*_*169 8

在使用递归时卡时,firebase文档有点令人困惑.我在测试中发现的是我需要设置两个规则来授予用户写入用户文档和所有子集合(及其子文档)的权限,这是管理用户数据的最合理设置.

您必须设置两个规则.

  1. 授予/ users/{userId}文档用户权限
  2. 授予用户对从/ users/{userId}路径开始的所有子集及其子文档的权限.

    service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read, write: if request.auth.uid == userId; } match /users/{userId}/{document=**} { allow read, write: if request.auth.uid == userId; } } }

规则

抱歉包含图片.我无法正确格式化它们.


Han*_*rds 5

我认为问题在于,虽然您确实在使用子集合通配符=**,但当用户 == request.auth.uid时才允许权限,所以这就是发生的情况(伪代码):

(访问时users/aHt3vGtyggD5fgGHJ

user = 'aHt3vGtyggD5fgGHJ'
user == request.auth.uid? Yes
allow access
Run Code Online (Sandbox Code Playgroud)

(访问时users/aHt3vGtyggD5fgGHJ/groups/h1s5GDS53

user = 'aHt3vGtyggD5fgGHJ/groups/h1s5GDS53'
user == request.auth.uid? No
deny access
Run Code Online (Sandbox Code Playgroud)

您有两种选择:要么按照您的方式进行操作并明确匹配子集合,要么使用以下命令:

function checkAuthorization(usr) {
   return usr.split('/')[0] == request.auth.uid;
}
match /users/{user=**}{
   allow read,write: if checkAuthorization(user);
}
Run Code Online (Sandbox Code Playgroud)

(该功能必须在您的 内match /databases/{database}/documents,就像您的规则一样)

让我知道这个是否奏效 :)