【问题标题】:Firestore Security Rules: get path as stringFirestore 安全规则:以字符串形式获取路径
【发布时间】:2021-04-05 16:53:17
【问题描述】:

使用 Firestore 安全规则(第 2 版),如何将 Path 对象转换为字符串?整个路径作为一个字符串,而不是单个段。

我正在尝试编写一个通用函数以在各种 Match 语句中使用。像这样的:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // "pathobj" is a rules.firestore.Path object
    function getPathAsString(pathobj) {
      // Does not work:
      return pathobj.toString();
    }

    // I would expect the following to evaluate to True:
    match /foo/{fooid} {
      allow read: if getPathAsString(path('one')) == 'one'
                  && getPathAsString(path('one/!two')) == 'one/!two';
    }
  }
}

有人知道这是否可能吗?我阅读了documentation on Path 并在Firestore Rules Simulator 中尝试了各种方法,但均未成功。

【问题讨论】:

  • 请编辑问题以解释 resourceee 到底是什么,以及您如何从实际规则中调用 getPath()。如果有来自文档的数据,请显示该文档的实际数据示例。问题需要明确您的输入是什么以及您的预期输出是什么。
  • 嗨@DougStevenson,我已经添加(希望足够)说明函数参数是什么,以及我希望它如何工作。
  • 我很困惑。如果您已经知道字符串是“一”,那么为什么要将它传递给path() 以转换回字符串?我不确定这个例子是否实用。或者您只是想从中消除实际文件及其内容?听起来您可能希望文档包含在规则评估期间显示为路径的引用类型对象?
  • @DougStevenson 该示例的存在只是为了说明函数应该返回什么,给定一个 Path 对象。我唯一的问题是“有人知道如何将路径转换为字符串”

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


【解决方案1】:

据我所知,没有直接的方法可以将路径转换为字符串。但是,在尝试了相当长的一段时间后,我想出了一些解决方法,具体取决于您想要做什么。

你知道应该有多少个路径段:

最完整的方法是访问每个路径段并用斜杠连接它们。

let originalPath = path('one/!two');
let pathString = originalPath[0] + '/' + originalPath[1];

不过,这只有在您知道路径段的数量时才有效。我尝试连接任意数量的路径段,希望超出路径长度的任何路径段都将被忽略,但它似乎不起作用(虽然很难说,因为 Firestore 安全规则模拟器在调试方面很糟糕) .

你只需要一个路径比较:

您可能根本不需要使用字符串。在您的示例中,如果您只是硬编码路径而不是字符串,则可以获得正确的结果,即 allow read: if path('one') == /one;allow read: if path('one/!two') == /one/!two;

有不同的方式来做你想做的事:

这些变通办法中最没有帮助的想法是,有一种完全不同的方式来做你想做的事,你只需要弄清楚那是什么。我无法就您的预期用途向您提供更多建议,但我可以告诉您在追求这个答案时发生了什么:我试图找到一种方法来确定用户是否正在尝试阅读或编写文档在专用于它们的文件位置中,起初,我试图按照正则表达式匹配的方式做一些事情,这需要一个字符串。然而,在花了很长时间试图弄清楚如何使它工作之后,我突然想到我只需要将通配符路径的第一段 ({docPath=**}) 与请求的 UID 进行比较,我的复杂函数就被替换了用一行简单的代码。即使看起来字符串是唯一的解决方案,可能还有其他方法可以做你想做的事情。不过,我确实同意,应该有一种简单的方法将路径转换为字符串。

【讨论】:

    【解决方案2】:

    这会将资源路径返回为rules.List,但有一些注意事项。

    // firestore.rules
    
    // Workaround for rules.Path not having size(). Assumes docs have
    // unique ids across collections and max n path segments.
    function resourcePathToList(rsc) {
      let p = rsc.__name__;
      let id = rsc.id;
      return
        p[0] == id ? [p[0]] :
        p[1] == id ? [p[0],p[1]] :
        p[2] == id ? [p[0],p[1],p[2]] :
        p[3] == id ? [p[0],p[1],p[2],p[3]] :
        p[4] == id ? [p[0],p[1],p[2],p[3],p[4]] :
        p[5] == id ? [p[0],p[1],p[2],p[3],p[4],p[5]] :
        p[6] == id ? [p[0],p[1],p[2],p[3],p[4],p[5],p[6]] :
        p[7] == id ? [p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]] :
        p[8] == id ? [p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]] :
        p[9] == id ? [p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]] :
                     []
    }
    

    Firestore 规则目前不支持将 rules.Path 转换为 rules.String(或 rules.List)。 rules.Path api 缺少 .size() 方法,因此无法安全地迭代 rules.Path 值。

    与其解析资源路径,不如将路径绑定显式传递给函数更自然,我更喜欢这种方法。

    match /a/{a}/b/{b} {
      allow read: if someTest([a,b]) || someOtherTest(a,b)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 2015-10-23
      • 2023-04-09
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多