Firestore安全规则:获取字符串形式的路径



使用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';
}
}
}

有人知道这是否可能吗?我阅读了Path上的文档,并在Firestore规则模拟器中尝试了各种方法,但都没有成功。

此处的火焰发生器

由于这个问题,我们最近添加了对字符串强制转换路径的支持。

现在,您可以使用string()强制转换方法通过强制转换路径来执行比较,该方法已存在于其他类型(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';
}
}
}

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

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

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

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

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进行比较,我的复杂函数就被一行简单的代码所取代。即使字符串似乎是唯一的解决方案,也可能有其他方法来做你想做的事情。然而,我确实同意,应该有一种简单的方法将路径转换为字符串。

这将以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(。规则。Path api缺少.size()方法,因此无法安全地迭代rules.Path值。

与其解析资源路径,更自然的做法是将路径绑定显式传递到函数中,我更喜欢这种方法。

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

最新更新