【问题标题】:Firestore rules: unable to verify role in subcollectionFirestore 规则:无法验证子集合中的角色
【发布时间】:2021-11-14 06:30:41
【问题描述】:

我在设置安全规则时遇到了困难

数据结构

-- books (collection)
   -- bookId (autogenerated Id - doc) 
      -- {chapter: text}, {chapter: text}, 

userBooks
   -- email (email of user logged in - doc)
      -- books (sub collection)
        -- bookId (referencing bookId doc on collection book)
           -- role: admin or read

用例如下,一个拥有管理员角色的用户是唯一被允许共享一本书的用户,允许他在另一个用户的书中添加一个条目。

创建了试图实现该功能但没有成功通过的函数

我使用电子邮件 userWantsToShare@gmail.com 以用户身份登录。当用户尝试将他的书分享给 addUser@gmail.com 我提出以下请求:

userWantsToShare@gmail.com 请求在 addUser@gmail.com 集合下写入。

final role = {'role': 'edit'};
await FirebaseFirestore.instance
        .collection('userBooks')
        .doc("addUser@gmail.com")
        .collection('books')
        .doc('9KHYZJVBY3BNAlYPYYoA')
        .set(role);

来到火力基地时

这应该翻译成 /userBooks/addUser@gmail.com/books/9KHYZJVBY3BNAlYPYYoA 数据 {'role': 'edit'}。

match /userBooks/{emailId}/books/{bookId} {
      allow write: if isSharedEmail(bookId);
}

//here im verifying the user that wants to share has admin role and therefore is authorised to write in another user book subcollection
function isSharedEmail(bookId){
//this should translate to /userBooks/userWantToShare@gmail.com/books/9KHYZJVBY3BNAlYPYYoA
   get(/databases/$(database)/documents/userBooks/$(request.auth.token.email)/books/$(bookId)).data.role == "admin" ;
}

由于 userWantToShare@gmail.com 具有该路径管理员角色,它应该允许插入。但很可能我忽略了一些东西,因为它根本不起作用。

我错过了什么?

提前致谢

【问题讨论】:

    标签: flutter dart google-cloud-firestore firebase-security


    【解决方案1】:

    好的,对于任何像我一样犯同样愚蠢错误的人。调用函数时 isSharedEmail 不在上下文中。

    意味着通过将函数移动到上下文中的作用域就足以使其工作

    之前:不工作

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        
        match /userBooks/{email} {
          allow write: if ( isAppShared())
          allow read: if true;
        }
      } 
    }
      
    function isAppShared() {
      return  get(/databases/$(database)/documents/userBooks/$(request.auth.token.email)).data.bookId == request.resource.data.bookId; 
    }
    

    之后:工作

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        
        match /userBooks/{email} {
          allow write: if ( isAppShared())
          allow read: if true;
        }
        
        function isAppShared() {
          return  get(/databases/$(database)/documents/userBooks/$(request.auth.token.email)).data.bookId == request.resource.data.bookId; 
        }
      } 
    }
     
    

    【讨论】:

    • 您好,您是否介意接受您自己的答案,以便这个问题看起来已解决?这样,任何有相同问题的人都可以看到这个问题并找到解决方案
    猜你喜欢
    • 2018-11-27
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 2017-03-02
    • 2020-11-28
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    相关资源
    最近更新 更多