我在 Postgres 函数上违反了 RLS 政策。我相信这是因为策略依赖于函数中创建的行。在SELECT
函数中运行命令。新行不可用,因为它们仍在事务中。
这是功能:
CREATE FUNCTION public.create_message(organization_id int, content text, tags Int[])
RETURNS setof public.message
AS $$
-- insert message, return PK
WITH moved_rows AS (
INSERT INTO public.message (organization_id, content)
VALUES($1, $2)
RETURNING *
),
-- many to many relation
moved_tags AS (
INSERT INTO public.message_tag (message_id, tag_id)
SELECT moved_rows.id, tagInput.tag_id
FROM moved_rows, UNNEST($3) as tagInput(tag_id)
RETURNING *
)
SELECT moved_rows.* FROM moved_rows LEFT JOIN moved_tags ON moved_rows.id = moved_tags.message_id
$$ LANGUAGE sql VOLATILE STRICT;
这是政策:
CREATE POLICY select_if_organization
on message_tag
for select
USING ( message_id IN (
SELECT message.id
FROM message
INNER JOIN organization_user ON (organization_user.organization_id = message.organization_id)
INNER JOIN sessions ON (sessions.user_id = organization_user.user_id)
WHERE sessions.session_token = current_user_id()));
想法:
- 向联接表添加字段以简化策略,但它违反了正常形式。
- 返回用户输入而不是运行 SELECT,但输入可能会被转义,我应该能够运行
SELECT
命令 - 分成两个功能。创建
message
行,然后添加message_tag
. 我正在运行 postgraphile,所以有两个突变。我在两者之间设置了外键关系。我不知道graphile是否会自动执行此操作。
错误信息:
ERROR: new row violates row-level security policy for table "message_tag"
CONTEXT: SQL function "create_message" statement 1
运行该功能时收到错误消息。我希望函数成功运行,在表中插入一行message
,并将输入数组转换为message_tag
表的行message_tag.message_id=message.id
,最后插入的 id。我需要一个适当的策略,以便来自该连接关系的用户只能看到他们自己组织的message_tag
行。
这是关于 INSERT 命令的另一个策略。如果用户登录,它允许 INSERT:
create policy insert_message_tag_if_author
on message_tag
for insert
with check (EXISTS (SELECT * FROM sessions WHERE sessions.session_token = current_user_id()));