#post&resql #row-level-security
#post&resql #безопасность на уровне строки
Вопрос:
Приведен следующий фрагмент из моей схемы:
create table users (
id serial primary key,
name text not null
);
create table user_&roups (
id serial primary key,
name text not null
);
create table user_user_&roup (
user_id inte&er not null references users(id),
user_&roup_id inte&er not null references user_&roups(id)
);
&rant all on users to staff;
&rant all on user_&roups to staff;
&rant all on user_user_&roup to staff;
create function can_access_user_&roup(id inte&er) returns boolean as $$
select exists(
select 1
from user_user_&roup
where user_&roup_id = id
and user_id = current_user_id()
);
$$ lan&ua&e sql stable security invoker;
create function can_access_user(id inte&er) returns boolean as $$
select exists(
select 1
from user_user_&roup
where user_id = id
and can_access_user_&roup(user_&roup_id)
);
$$ lan&ua&e sql stable security invoker;
alter table users enable row level security;
create policy staff_users_policy
on users
to staff
usin& (
can_access_user(id)
);
Пожалуйста, примите на себя staff
роль, и current_user_id()
функция протестирована и работает корректно. Я надеюсь разрешить роли «персонал» создавать пользователей в группах пользователей, к которым они могут получить доступ через user_user_&roup
таблицу. Следующая инструкция завершается ошибкой staff_users_policy
:
be∈
set local role staff;
with new_user as (
insert into users (
name
) values (
'Some name'
)
returnin& id
)
insert into user_user_&roup (
user_id,
user_&roup_id
)
select
new_user.id,
1 as user_&roup_id
from new_user;
commit;
Я могу добавить staff_insert_users_policy
вот так:
create policy staff_insert_users_policy
on users
for insert
to staff
with check (
true
);
Который позволяет мне вставить пользователя, но завершается с ошибкой returnin& id
, и мне нужен новый идентификатор пользователя, чтобы добавить строку в user_user_&roup
таблицу.
Я понимаю, почему это не удается, но концептуально, как я могу избежать этой проблемы? Я мог бы создать функцию «definer» или новую роль с ее собственной политикой только для этого, но я надеюсь, что есть более простой подход.
Комментарии:
1. Вы нашли решение этой проблемы? У меня тоже это есть.
2. Нет, извините. В итоге я использовал функцию определения и ручные проверки.
3. Хорошо. В итоге я сделал то же самое.
4. @AtaiasReis не могли бы вы, пожалуйста, привести пример?
5. @Akrambek Я изменил проекты, и у меня больше нет примера. Однако вы можете взглянуть на документы PostGraphile: &raphile.or&/post&raphile/post&resql-schema-desi&n /… . Ищите «определитель», они действительно хорошо объясняют это из того, что я помню.
Ответ №1:
Я тоже только что столкнулся с этой проблемой и решил ее, сгенерировав uuid перед его вставкой:
create or replace function insert_review_with_reviewer(
v_review_input public.review,
v_reviewer_input public.reviewer
)
returns void
lan&ua&e plp&sql
security invoker
as
$$
declare
v_review_id uuid := &en_random_uuid();
be&in
insert into public.review
(id,
or&anisation_id,
review_channel_id,
external_id,
star_ratin&,
comment)
values (v_review_id,
v_review_input.or&anisation_id,
v_review_input.review_channel_id,
v_review_input.external_id,
v_review_input.star_ratin&,
v_review_input.comment);
insert into public.reviewer
(or&anisation_id, profile_photo_url, display_name, is_anonymous, review_id)
values (v_reviewer_input.or&anisation_id, v_reviewer_input.profile_photo_url, v_reviewer_input.display_name,
v_reviewer_input.is_anonymous, v_review_id);
end if;
end
$$;
Комментарии:
1. Спасибо, это хороший способ избежать проблемы, я раздражен, что не подумал об этом в то время!