ERROR: permission denied for relation table_name
Что означает ошибка permission denied for relation?
Эта ошибка появляется, когда пользователь пытается выполнить действие (например, прочитать данные из таблицы или записать их), но у него нет на это прав.
Важно знать: «relation» — в PostgreSQL это не только таблицы, в этот термин входят и представления и другие объекты.
Основные причины
Причина одна — отсутствие нужных привилегий, но сценариев, в которых это происходит, несколько:
- нет прав USAGE на schema
- relation был создан другим пользователем и при этом не были выданы права текущему
- нет прав у вызывающего на таблицы, которые используются во view
- RLS (Row Level Security) - права на доступ к конкретным строкам
- search_path указывает в другую схему, где нет нужных прав
- запрос выполняется не от того пользователя
1. Не определили права при создании relation
При создании объекта в базе данных, права на этот объект присваиваются роли, которая создала объект. Если к
объекту обратиться от другой роли, то получим ошибку permission denied. Чтобы этого не
произошло после создания надо указать какими правами должны обладать другие роли.
-- Есть три пользователя: root, developer, user
-- От имени root выполняется запрос:
CREATE TABLE table_name (...);
-- Права на таблицу есть только у root
GRANT USAGE ON SCHEMA public TO developer; -- выдать права на использование схемы (если у пользователя нет прав на схему,
-- то получим ошибку даже если есть права на таблицу)
GRANT USAGE ON SCHEMA public TO user;
GRANT DELETE, INSERT, SELECT, UPDATE ON table_name to developer; -- выдать права на чтение, запись, удаление и обновление разработчику
GRANT SELECT ON table_name to user; -- выдать права только на чтение для пользователя (остальные операторы будут давать ошибку)
ALTER TABLE table_name OWNER TO developer; -- сделать владельцем таблицы
В PostgreSQL для столбцов id часто используют sequence (специальная сущность PostgreSQL, которая автоматически
увеличивает значение столбца, при вставке новой строки). В таком случае если нужно выдать права на
INSERT для таблицы с serial нужно выдать права и на саму sequence.
-- От имени root выполняется запрос:
CREATE TABLE table_name (
id serial,
...
);
GRANT DELETE, INSERT, SELECT, UPDATE ON table_name to developer; -- выдать права для таблицы
GRANT USAGE, SELECT ON SEQUENCE table_name_id_seq TO developer; -- выдать права для секвенции (USAGE нужен для возможности выполнить nextval())
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO developer; -- автоматически выдавать права для всех объектов
-- которые будут созданы текущим пользователем (для уже существующих не применится) в схеме public
2. Row Level Security
С помощью RLS можно добавить дополнительный слой для безопасности и ограничить с помощью политики доступ для пользователя только конкретными строками
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
SELECT * FROM table_name; -- может вернуть пустой результат, даже если есть права на таблицу
INSERT INTO table_name () VALUES (); -- ошибка "new row violates row-level security policy" (не permission denied, но тоже ошибка из-за отсутствия прав)
CREATE POLICY client_old_data_policy ON table_name
FOR SELECT
TO client
USING (created_at > '2026-01-01'::date); -- разрешает выборку для пользователя client только строк созданных после 2026-01-01
3. Запрос выполняется не от того пользователя
Фактически это та же проблема, но проявляется она уже на стороне приложения. Например, если у приложения есть админка, то можно настроить выполнение запросов от разных пользователей со стороны пользовательской части и со стороны админки. Однако при этом надо внимательно следить чтобы переключение происходило вовремя.
SELECT current_user;
Как проверить текущие права доступа для таблицы:
SELECT grantee, array_agg(privilege_type)
FROM information_schema.role_table_grants
WHERE table_name = 'goods'
GROUP BY grantee;
Заключение
Иметь несколько ролей (пользователей) с минимальными нужными им правами это хорошая практика, которая позволяет
повысить безопасность продукта. Ошибка permission denied for relation легко решить, если понимать,
как работают права в PostgreSQL. Главное — чётко определить, какие действия должен выполнять пользователь, и
назначить соответствующие привилегии.
Быстрое решение:
- Проверить пользователя
SELECT current_user; - Дать права на schema
GRANT USAGE ON SCHEMA public TO role; - Дать права на таблицу
GRANT SELECT ON table_name TO role; - Дать права на sequence
GRANT USAGE ON SEQUENCE ... TO role; - Проверить RLS
SELECT * FROM pg_policies WHERE tablename = 'table_name';