在postgres 10.4上工作(如果有区别,请在RDS上工作)我正在尝试使用行级安全性强制执行应用程序用户权限。
我有一个权限表,看起来像
user_group_id | entity1 | entity2 | entity3 | permission
==============|=========|=========|=========|============
1 |1 |null |null | write
1 |1 |1 |null | read
entity1(root)-entity2-entity3(leaf)是存储在不同表中的项目的层次结构。实体1包含实体2项,实体2包含实体3项。
权限被继承,这意味着entry3从entity2继承权限,entry2从entity1继承权限,除非:
具有匹配的entity3的行将覆盖具有匹配的entity2的行,这些行将覆盖具有匹配的entity1的行。
在上面的示例中,用户组1在实体1 = 1(第一行)下的所有实体2 /实体3上都有写入,除了实体2 = 1和实体2 = 1下的所有实体3(其已读取(第二行)等)。>
我已经使用dense_rank - which is a window function
作为单个查询编写了逻辑(我认为这与实际问题无关,因此不粘贴)。
当我直接将此逻辑与UPDATE一起使用时-它可以完美地工作。
当我嵌入与行级安全策略的WITH CHECK
完全相同的逻辑时-update拒绝更新行(我在相关表上启用了ROW LEVEL SECURITY-就是这样)。
我试图将逻辑嵌入函数中,而不是直接嵌入策略中-但是得到了相同的结果,这意味着有效:
--not as table owner
update entity1
set col1=1
where entity1_id=10
and check_access(entity1_id); --updates 1 row
但这不是:
--as table owner
alter table entity1 enable row level security;
CREATE POLICY entity1_update
ON entity1
AS permissive
FOR UPDATE
TO some_role
WITH CHECK ( check_access(entity1_id) );
--not as table owner
update entity1
set col1=1
where entity1_id=10; --updates no rows
阅读文档:
The conditional expression cannot contain any aggregate or window functions
-是这个原因吗?如果是这样,我希望在尝试创建策略或实际运行更新时会抛出错误-但什么都不会发生。
我还尝试使用带有ORDER BY的子查询重写我的访问检查逻辑,并用LIMIT包装它-没有帮助。
我想念什么吗?可以解决这个问题吗?
答案 0 :(得分:0)
我认为我发现了问题-我在同一个表上还有另一个FOR SELECT
策略,并且我认为它的USING
子句就足够了(不同FOR
类型的策略之间存在AND )-因此我没有在USING
策略中包含FOR UPDATE
子句。一旦我在USING (true)
策略上添加了FOR UPDATE
,事情就开始正常工作(至少现在-我需要做更多的实验)。
似乎与使用窗口函数无关。
我认为postgres允许我创建不带FOR UPDATE
子句的USING
策略,因为它允许多个相同类型的策略-但是文档中应注意在使用{strong>必须同时包含两个子句的单一FOR UPDATE
政策?
更新:我不是唯一出于相同原因而更新失败的人-
PostgreSQL, unable to update row ( with row level security )
这使我想问The conditional expression cannot contain any aggregate or window functions
限制是什么意思-如果使用dense_rank() over (order by...)
...引发Aggregate/Window functions restriction in Postgres Row Level Security Policy conditions