Работа на postgres 10.4 (на RDS, если это имеет значение) Я пытаюсь обеспечить соблюдение прав пользователя приложения с помощью Row Level Security.
У меня есть таблица разрешений, которая выглядит примерно так:
user_group_id | entity1 | entity2 | entity3 | permission
==============|=========|=========|=========|============
1 |1 |null |null | write
1 |1 |1 |null | read
entity1 (root) -entity2-entity3 (leaf) - это иерархия элементов, хранящихся в разных таблицах. entity1 содержит элементы entity2, entity2 содержит элементы entity3.
разрешения наследуются, то есть entity3 наследует разрешения от entity2, entity2 наследует разрешения от entity1, если:
Строки с совпадающим entity3 переопределяют строки с совпадающим entity2, которые переопределяют строки с соответствующим entity1.
В приведенном выше примере пользовательская группа 1 имеет запись для всех entity2 / entity3 в entity1 = 1 (1-я строка), за исключением entity2 = 1 и всех entity3 в entity2 = 1, для которых она прочитала (2-я строка) и т. Д.
Я уже написал логику (я думаю, что она не относится к актуальному вопросу, следовательно, не вставляя ее) как отдельный запрос, используя dense_rank - which is a window function
.
Когда я использую эту логику напрямую с ОБНОВЛЕНИЕМ - она работает безупречно.
Когда я встраиваю ту же самую логику, что и WITH CHECK
политики безопасности на уровне строк - обновление отказывается обновлять строки (я включил БЕЗОПАСНОСТЬ УРОВНЯ СТРОКИ в соответствующих таблицах - так что это не так).
Я пытался встроить свою логику в функцию, а не прямо в политику, - но получил тот же результат, означающий, что это работает:
--not as table owner
update entity1
set col1=1
where entity1_id=10
and check_access(entity1_id); --updates 1 row
но это не так:
--as table owner
alter table entity1 enable row level security;
CREATE POLICY entity1_update
ON entity1
AS permissive
FOR UPDATE
TO some_role
WITH CHECK ( check_access(entity1_id) );
--not as table owner
update entity1
set col1=1
where entity1_id=10; --updates no rows
Чтение документации:
The conditional expression cannot contain any aggregate or window functions
- это причина? Если это так - я ожидал, что при попытке создать политику или при запуске обновления возникнет ошибка, но ничего не происходит.
Я также попытался переписать свою логику проверки доступа, используя подзапрос с ORDER BY и обернув его с помощью LIMIT - не помогло.
Я что-то упустил? Есть ли способ обойти это?