如何为一对多关系设置PostgreSQL RLS更新策略?

7xzttuei  于 2023-01-13  发布在  PostgreSQL
关注(0)|答案(1)|浏览(87)

我刚刚开始接触PostgreSQL RLS,我很困惑,我有以下表:

users
| id|role          |email            |
|--:|:-------------|:----------------|
|  1|authenticated | bob@gmail.com   |
|  2|authenticated | alice@gmail.com |
|  3|authenticated | jane@gmail.com  |
|  4|authenticated | mark@gmail.com  |

profiles
| id|name  | company_id|
|--:|:-----|----------:|
|  1|Bob   |          1|
|  2|Alice |          1|
|  3|Jane  |          2|
|  4|Mark  |         NA|

companies
| id|name |
|--:|:----|
|  1|ABC  |
|  2|DEF  |

注意,我使用的是Supabase,它自动设置users表和角色。
我正在尝试为companies表设置更新策略。Supabase有一个如下所示的启动模板

CREATE POLICY "companies"
ON public.companies
FOR UPDATE USING (
  auth.email() = email
) WITH CHECK (
  auth.email() = email
);

有人能ELI5吗?在这个上下文中auth是什么?我如何修改它以适合我的模式?

lf5gs5x2

lf5gs5x21#

这里有一些东西要拆。

这里的auth是什么?

Auth是Supabase部署与身份验证相关的表和帮助器函数的模式。

函数auth.email()的作用是什么?

如果使用PSQL,则可以检查以下帮助函数的定义:
\df+ auth.email

select     
coalesce(     
nullif(current_setting('request.jwt.claim.email', true), ''),
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email')
)::text

所以,这是一个检查用户电子邮件是否与已验证用户相同的函数。这是为了确保用户正在尝试更新自己的行。请注意,此函数已被弃用。当前建议使用auth.jwt() ->> 'email'
以下是auth模式中列出的帮助器函数:

  • auth.email()
  • auth.jwt()
  • auth.role()
  • auth.uid()

进一步探索:

documentation还暗示了一个更复杂的场景,即只有具有定义的电子邮件结尾的用户才能更新某些内容:

create policy "Only Blizzard staff can update leaderboard"
  on my_scores
  for update using (
    right(auth.jwt() ->> 'email', 13) = '@blizzard.com'
  );

假设您在创建行级安全策略时希望涵盖更广泛和更复杂的情况,在这种情况下,我建议使用custom claims,因为它为您的平台创建更多的场景和不同的角色提供了更大的灵活性。

使用自定义声明创建公司更新策略:

通过在SQL Editor中运行SQL script来安装自定义声明:
为用户设置声明:

select set_claim('00000-0000-45c1-8dfb-6eeb7cf0b92e', 'company', '1');

然后,您可以将其用于RLS策略:

CREATE POLICY "User can update team details if they belong to the company."
ON public.companies
FOR UPDATE USING (
  get_my_claim('company') = id
);

另一种实现方法是在RLS中使用连接,但这会降低性能,因为您使用连接查询来检查每个更新。

相关问题