У меня сейчас база данных с двумя схемами app_private & app_publi c (в дополнение к схеме publi c по умолчанию). У меня также есть роль, которой предоставлено использование в схеме app_publi c, но не в схеме app_private . Я также использую две функции (одну функцию триггера и одну функцию проверки ограничений) в таблице.
См. Ниже код:
(1) Создание схем (и grants)
CREATE SCHEMA app_public;
CREATE SCHEMA app_private;
grant usage on schema public, app_public to "grant_test_role";
(2) Отменить гранты от пользователя PUBLI C
Тогда у меня есть специальное заявление DDL. Предполагается, что REVOKE разрешений для любой вновь добавленной функции из пользовательской роли publi c (от которой наследуются все другие роли).
alter default privileges revoke all on functions from public;
(3) Функция Определения (Trigger & Constraint)
-- Trigger Function
create OR replace function app_private.tg__timestamps() returns trigger as $$
begin
NEW.created_at = (case when TG_OP = 'INSERT' then NOW() else OLD.created_at end);
NEW.updated_at = (case when TG_OP = 'UPDATE' and OLD.updated_at >= NOW() then OLD.updated_at + interval '1 millisecond' else NOW() end);
return NEW;
end;
$$ language plpgsql volatile set search_path to pg_catalog, app_private, public, pg_temp;
-- Constraint Function
CREATE OR REPLACE FUNCTION app_private.constraint_max_length(
value text,
maxLength integer,
error_message text default 'The value "$1" is too long. It must be maximum $2 characters long.',
error_code text default 'MXLEN'
) RETURNS boolean
AS $$
begin
if length(value) > maxLength then
error_text = replace(replace(error_message, '$1', value), '$2', maxLength);
raise exception '%', error_text using errcode = error_code;
end if;
return true;
end;
$$ LANGUAGE plpgsql set search_path to pg_catalog, app_private, public, pg_temp;
(4) Таблица Definition (которая использует вышеуказанные функции Trigger & Constraint)
create table app_public.test_tab (
id INT not null primary key,
name text not null,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint name_length_check check (app_private.constraint_max_length(name, 5));
);
create trigger _100_timestamps
before insert or update on app_public.test_tab
for each row
execute procedure app_private.tg__timestamps();
-- Setting some restrictions on the test_tab for the "grant_test_role"
REVOKE ALL ON TABLE app_public.test_tab FROM "grant_test_role";
GRANT SELECT, DELETE ON app_public.test_tab TO "grant_test_role";
GRANT
INSERT(id, name),
UPDATE(id, name) ON app_public.test_tab TO "grant_test_role";
(5) Код (который работает как grant_test_role )
begin;
set local role to grant_test_role;
insert into app_public.test_tab (id, name) values (1, 'Very Long Name');
commit;
Я пытаюсь выполнить это в свободной sh БД каждый раз, чтобы я мог понять, как * Разрешения 1068 * работают в различных контекстах вызова (например, функция триггера, проверка ограничений, которая вызывает функцию автоматически, и т. Д. c.)
Когда у меня нет блока кода (2), который отзывает разрешения функций из Пользователь PUBLI C, блок кода (5) выполняется без ошибок. Событие, хотя роль пользователя не имеет прав доступа к схеме app_private , в которой существует функция триггера и функция ограничения. Но при наличии блока кода (2) код выполняет триггер просто отлично, но дает мне "permission denied for function constraint_max_length"
для ограничения проверки.
Итак, я пытаюсь понять,
- Каким образом функция триггера, которая существует в схеме, где роль пользователя не имеет разрешений на использование, всегда выполняется успешно?
- Если функция триггера выполняется, почему функция ограничения CHECK дает мне вышеуказанное ошибка отказа в разрешении?
- Что на самом деле делает блок кода (2)?
Я изо всех сил пытаюсь найти документацию о том, как разрешения применяются в этом виде "авто выполнил «сценарий ios (триггеры / ограничения)», поскольку пользователь не «явно» вызывает эти функции, скорее они автоматически вызываются БД. Поэтому я не уверен, какая роль выполняет их.