我需要撤销 test.persons 表中 uid 列的 INSERT 和 UPDATE 权限。
以下是我目前所做的:
CREATE TABLE test.persons (
uid UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name VARCHAR(255),
description TEXT
);
REVOKE INSERT (uid) ON test.persons FROM hasura;
GRANT INSERT (name, description) ON test.persons TO hasura;
REVOKE UPDATE (uid) ON test.persons FROM hasura;
GRANT UPDATE (name, description) ON test.persons TO hasura;
INSERT INTO test.persons (uid, name, description)
VALUES ('e7443661-f6c3-4448-8df7-c65e3f8243ca', 'John Doe', 'Some description');
//correct: ERROR: permission denied for table persons
INSERT INTO test.persons (uid)
VALUES (gen_random_uuid());
//correct: ERROR: permission denied for table persons
INSERT INTO test.persons (name, description)
VALUES ('John Doe', 'Some description');
//correct: Successfully inserted
INSERT INTO test.persons (name)
VALUES ('John Doe1');
//correct: Successfully inserted
到目前为止,一切都很好。
但是当我尝试执行以下更新时:
UPDATE test.persons SET uid = gen_random_uuid() WHERE name = 'John Doe';
它已成功更新,但实际上不应该更新,因为我撤销了 uid 列上的 UPDATE 权限。
我做错了什么以及我应该如何正确地撤销 uid 列上的 UPDATE 权限?
您走在正确的轨道上,但是 PostgreSQL不支持 INSERT/UPDATE 的列级 REVOKE。 撤销列权限仅适用于SELECT。
为什么 UPDATE
uid
仍然有效?即使您撤销了
UPDATE (uid)
,PostgreSQL 也会在表级别检查 UPDATE,因此如果hasura
可以更新表,它就可以更新任何列。解决方案:使用行级安全 (RLS) 策略
要强制执行此限制,您可以使用 RLS:
确保更新期间
uid
无法修改。替代方法:使用 BEFORE UPDATE 触发器
如果有人尝试更新
uid
,它将会抛出一个错误。为特定 RLS 添加了替代解决方案
RLS 政策
UPDATE
(防止uid
修改)为了防止用户更新该
uid
列,您可以使用如下 RLS 策略:USING (true)
:允许用户尝试更新。WITH CHECK (uid = old.uid)
:确保uid
保持不变,防止修改。RLS 策略
INSERT
(防止手动uid
插入)为了防止用户手动插入
uid
并强制执行默认的gen_random_uuid()
,请使用:WITH CHECK (uid IS NULL)
:仅当用户未指定时才可以插入uid
。uid
有DEFAULT gen_random_uuid()
,PostgreSQL 将自动生成它。启用 RLS
解决:
uid
但可以更新其他列。uid
,强制 PostgreSQL 生成一个。REVOKE
只会撤销已(隐式或显式)授予的权限。因此,以下语句无效:由于
hasura
已经拥有UPDATE
该表的权限,因此该用户对所有列都具有相同的权限。因此,您首先必须撤销该表的权限:
然后您仅在允许的列上授予权限:
现在它应该可以按您希望的方式工作了。
INSERT
工作方式完全一样。