postgresql 仅追加表的超级数据库行级安全性

dwthyt8l  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(2)|浏览(153)

我试图做的是有一个表,分配一个订阅给一个用户。到目前为止,我找到的所有示例都是通过以下方式实现的:

(auth.uid() = user_id)

不过,我想跟踪重新安排的工作。使用如下结构的表:

// assigments //

user_id | subscription_id | comment    | created_at
---------------------------------------------------
3       | 1001            | re-assign  | 2023-06-06
---------------------------------------------------
2       | 1002            | intial     | 2023-06-05
---------------------------------------------------
1       | 1001            | intial     | 2023-06-05
---------------------------------------------------

我很难理清我的思路来写这方面的政策。我觉得应该是

auth.uid() IN (SELECT DISTINCT ON (subscription_id) user_id FROM assignments ORDER BY created_at)

这是正确的轨道吗?auth.uid() IN (...)感觉超级低效。是否可以先查看是否有一行与user_id == auth.uid()匹配,并与结果subscription_id上的一个子查询匹配,然后以某种方式将结果用于auth.uid()比较?

crcmnpdw

crcmnpdw1#

如果用户和“活动”订阅具有一对一的关系,那么您应该能够执行以下操作

auth.uid() = (SELECT a.user_id
  FROM assignments a
  WHERE a.subscription_id = assignments.subscription_id
  ORDER BY a.created_at desc limit 1)

a.subscription_id = assignments.subscription_id中,a.subscription_id是来自子查询的订阅ID,assignments.subscription_id是在此RLS策略中正在评估的当前行。

gmxoilav

gmxoilav2#

在@dshukertjr的帮助下找到了解决方案。尝试在为其编写策略的表上运行子查询将导致infinite recursion detected in policy for relation "assignments" (Error: 42P17)。这样我就可以找到https://github.com/orgs/supabase/discussions/3328https://github.com/orgs/supabase/discussions/1138
答案是使用绕过RLS的函数来进行检查。

BEGIN
        RETURN _user_id IN (
            SELECT user_id
            FROM assignments
            WHERE subscription_id = _subscription_id
            ORDER BY created_at DESC
            LIMIT 1
        );
END;

并在策略中使用该函数,如:

is_subscription_owner(auth.uid(), subscription_id)

相关问题