newb ie в SQL из мира JS, которому нужен совет по триггерам.
У моего пользователя есть столбец id
, и мой GraphQL API всегда вызывает INSERT INTO .... RETURNING *
, а затем выполняет преобразования на слой GraphQL для возврата того, что я хочу.
Цель состоит в том, чтобы запрос типа INSERT INTO .... RETURNING *
работал с RLS на месте.
Политики:
CREATE POLICY USER_SELECT_RESTRICTIONS
ON "user"
FOR SELECT
USING ("id" = current_user_id() OR current_user_role() = 'admin' OR current_user_role() = 'partner');
CREATE POLICY USER_INSERT_RESTRICTIONS
ON "user"
FOR INSERT
WITH CHECK (true);
Это нарушает для гостевых пользователей (больше контекста внизу), потому что им разрешено INSERT
, но не может SELECT
(из-за ограничения, что только авторизованные пользователи могут выбирать свои собственные строки).
Поэтому у меня возникла идея каким-то образом установить пользовательские настройки вручную в триггере до / после вставки (не знаю, какие, потому что я не мог двигаться вперед из-за синтаксической ошибки).
Я пробовал это, но у меня есть синтаксис ошибка в NEW.id
? (он просто говорит мне «Синтаксическая ошибка»)
CREATE OR REPLACE FUNCTION after_user_insert()
RETURNS TRIGGER AS $$
BEGIN
SET LOCAL jwt.claims.userId NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER set_user_id_on_insert
AFTER INSERT ON "user"
FOR EACH ROW
EXECUTE PROCEDURE after_user_insert();
Много искал и, честно говоря, я думаю, что могу просто ничего не найти, потому что мне не хватает правильной терминологии, чтобы найти то, что мне нужно найти .
Буду признателен не только за помощь в решении этой конкретной проблемы c, но и за любые рекомендации по политикам для гостевых пользователей, которым требуются привилегии.
Контекст:
Эти являются соответствующими таблицами и функциями
CREATE TYPE "user_role" AS ENUM (
'customer',
'partner',
'admin'
);
CREATE TABLE "user" (
"id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
"first_name" varchar NOT NULL,
"last_name" varchar NOT NULL,
"email" text UNIQUE NOT NULL,
"role" user_role NOT NULL DEFAULT 'customer',
"created_at" timestamp NOT NULL DEFAULT NOW(),
"updated_at" timestamp NOT NULL DEFAULT NOW()
);
CREATE FUNCTION current_user_id() RETURNS uuid AS $$
SELECT nullif(current_setting('jwt.claims.userId', true), '')::uuid;
$$ LANGUAGE SQL stable;
CREATE FUNCTION current_user_role() RETURNS user_role AS $$
SELECT nullif(current_setting('jwt.claims.role', true), '')::user_role;
$$ LANGUAGE SQL stable
RLS ограничивает SELECT
строками, в которых столбец id
таблицы user
соответствует current_setting('jwt.claims.userId')
.
. Ранее он был установлен Postgraphile как видел здесь (https://www.graphile.org/postgraphile/security/).
Один из возможных вариантов обхода, о котором я подумал, был бы следующим, но я не знаю, приведет ли это к какой-либо уязвимости из-за очевидного повышения роли :
CREATE OR REPLACE FUNCTION after_user_insert()
RETURNS TRIGGER AS $$
BEGIN
SET LOCAL jwt.claims.role TO "customer";
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION before_user_insert()
RETURNS TRIGGER AS $$
BEGIN
SET LOCAL jwt.claims.role TO "admin";
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER before_insert
BEFORE INSERT ON "user"
FOR EACH ROW
EXECUTE PROCEDURE before_user_insert();
CREATE TRIGGER after_insert
AFTER INSERT ON "user"
FOR EACH ROW
EXECUTE PROCEDURE after_user_insert();