firebase Firestore安全规则:获取路径为字符串

sy5wg1nm  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(110)

使用Firestore安全规则(版本2),如何将Path对象转换为String?整个路径作为一个字符串,而不是单独的段。
我正在尝试编写一个泛型函数,用于各种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中尝试了各种各样的东西,都没有成功。

2w2cym1i

2w2cym1i1#

  • 我是火焰怪 *

由于这个问题,我们最近添加了对将路径转换为字符串的支持。
你现在可以使用string()的cast方法来执行比较,这个方法已经存在于其他类型(null,float,int,bool)中,比如:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    // Evaluates to true for the foo/fooid document:
    match /foo/{fooid} {
      allow read: if string(path('one')) == '/one'
                  && string(request.path) == '/databases/(default)/documents/foo/fooid';
    }
  }
}

请注意,有效路径将始终以/开头。如果您遇到此功能的任何问题,请发表评论。

pu3pd22g

pu3pd22g2#

据我所知,没有一种直接的方法可以将路径转换为字符串;然而,在尝试了很长一段时间之后,我提出了一些变通方法,具体取决于您想做什么。

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

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

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;

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

这些解决方法中最没有帮助的是这样一种想法,即有一种完全不同的方式来做你想做的事情,你只需要弄清楚那是什么。我不能再给予更多关于你的预期用途的建议,但我可以告诉你在我追求这个答案的过程中发生了什么:我试图找到一种方法来确定用户是否试图在专门用于它们的文件位置中读取或写入文档,起初,我试图沿着需要字符串的正则表达式匹配行做一些事情。然而,在花了太长时间试图弄清楚如何实现这一点之后,我突然想到,我只需要将HTTP路径的第一段({docPath=**})与请求的UID进行比较,我的复杂函数被一行简单的代码所取代。即使字符串似乎是唯一的解决方案,但仍然可能有其他方法来完成您想做的事情。然而,我同意应该有一种简单的方法将路径转换为字符串。

x759pob2

x759pob23#

这将返回资源路径为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)
}

相关问题