我应该如何优化此行级安全策略以读取事件?
How should I go about optimizing this row level security policy for reading an event?
这是我用于此策略的表/实体的摘要(针对 SO 进行了简化)。
user
----
id (pk)
event
-----
uuid (pk)
host_id (fk -> user)
privacy: int
friendship
----------
user_id (pk, fk -> user)
friend_id (pk, fk -> user)
invitation
----------
user_id (pk, fk -> user)
event_uuid (pk, fk -> event)
ENUMS:
- Privacy (Public, Friends, Private) = (0, 1, 2)
在我的例子中,我想确保的是,使用 PostgreSQL 中的行级安全性或其他一些方法(可能是什么条件?),用户只能在满足以下条件之一的情况下看到事件:
- 如果他们是活动的主持人
- 如果活动的隐私是 public
- 如果活动的隐私是朋友并且他们是活动主持人的朋友
- 如果他们受邀参加活动
我知道这些条件很多,但我不确定检查所有这些条件的最佳格式是什么。目前,这是我用来检查所有内容的 RLS 策略,但它看起来很冗长,我想知道是否缺少可以优化它的东西:
create policy read_event
on event
for select
using (
-- is host
event.user_id = ?
or
-- is public
event.privacy = 0
or
-- is invited
exists (
select *
from invitation as i
where i.user_id = ? and i.party_uuid = event.uuid
)
or
-- is friends and party is friends-level privacy
exists (
select *
from friendship as f
where f.user_id = ? and f.friend_id = party.user_id
or f.user_id = party.user_id and f.friend_id = ?
)
and
event.privacy = 1
)
'?'可以替换为进行查询的当前用户的 ID(使用会话变量或其他替代方法)。总的来说,这是我正在尝试做的事情的简化版本,但我只是想看看我是否在正确的道路上,或者我是否遗漏了什么。
此外,这有点超出了这个 SO 问题的范围,但如果有人有洞察力的话仍然有用,从其他表加入时 RLS 策略是否级联(例如,如果我创建一个带有 fk 的事件邀请,它会检查 RLS 策略以在插入时读取事件吗?)
非常感谢您的帮助!
我没有检查条件是否符合您的要求,但策略定义看起来很正常。问题是
如果 ?
与用户无关,如何获取?使用占位符参数将起作用,但可以随时使用 SET
语句更改参数。也许这足以满足您的安全要求。
USING
子句中的条件将作为过滤器添加到查询中。它包含 OR
,因此它可能会严重影响查询性能。如果数据,您应该使用实际数量进行测试。
行级安全性按照 table 工作。因此,具有外键约束的行的可见性不受引用 table.
上的行级安全策略的影响
这是我用于此策略的表/实体的摘要(针对 SO 进行了简化)。
user
----
id (pk)
event
-----
uuid (pk)
host_id (fk -> user)
privacy: int
friendship
----------
user_id (pk, fk -> user)
friend_id (pk, fk -> user)
invitation
----------
user_id (pk, fk -> user)
event_uuid (pk, fk -> event)
ENUMS:
- Privacy (Public, Friends, Private) = (0, 1, 2)
在我的例子中,我想确保的是,使用 PostgreSQL 中的行级安全性或其他一些方法(可能是什么条件?),用户只能在满足以下条件之一的情况下看到事件:
- 如果他们是活动的主持人
- 如果活动的隐私是 public
- 如果活动的隐私是朋友并且他们是活动主持人的朋友
- 如果他们受邀参加活动
我知道这些条件很多,但我不确定检查所有这些条件的最佳格式是什么。目前,这是我用来检查所有内容的 RLS 策略,但它看起来很冗长,我想知道是否缺少可以优化它的东西:
create policy read_event
on event
for select
using (
-- is host
event.user_id = ?
or
-- is public
event.privacy = 0
or
-- is invited
exists (
select *
from invitation as i
where i.user_id = ? and i.party_uuid = event.uuid
)
or
-- is friends and party is friends-level privacy
exists (
select *
from friendship as f
where f.user_id = ? and f.friend_id = party.user_id
or f.user_id = party.user_id and f.friend_id = ?
)
and
event.privacy = 1
)
'?'可以替换为进行查询的当前用户的 ID(使用会话变量或其他替代方法)。总的来说,这是我正在尝试做的事情的简化版本,但我只是想看看我是否在正确的道路上,或者我是否遗漏了什么。
此外,这有点超出了这个 SO 问题的范围,但如果有人有洞察力的话仍然有用,从其他表加入时 RLS 策略是否级联(例如,如果我创建一个带有 fk 的事件邀请,它会检查 RLS 策略以在插入时读取事件吗?)
非常感谢您的帮助!
我没有检查条件是否符合您的要求,但策略定义看起来很正常。问题是
如果
?
与用户无关,如何获取?使用占位符参数将起作用,但可以随时使用SET
语句更改参数。也许这足以满足您的安全要求。USING
子句中的条件将作为过滤器添加到查询中。它包含OR
,因此它可能会严重影响查询性能。如果数据,您应该使用实际数量进行测试。
行级安全性按照 table 工作。因此,具有外键约束的行的可见性不受引用 table.
上的行级安全策略的影响