Ric*_*ard 3 postgresql privileges triggers database-design postgresql-9.2
我在表中有一个列A(类型int),在插入其他值时,该列的数据不可用。我不想拆分桌子,因为没有其他真正的理由这样做。我正在数据库级别实现权限分离。
只有某些用户(属于 A 类)才可以column A随时进行修改。但是其他用户(在类别 B 中,不一定与类别 A 互斥)应该能够更新该列(如果其值尚未设置),即。如果是NULL。
我正在使用 PostgreSQL 9.2.4。
我怎样才能做到这一点?触发器?规则?还有别的事吗?
只有某些用户应该能够修改列 A
...
其他用户应该能够更新该列,如果...它是 NULL。
撤销UPDATE(和DELETE?!?)public以及其他所有人不应该拥有该特权的人。
REVOKE UPDATE ON TABLE tbl FROM public;
REVOKE UPDATE ON TABLE tbl FROM ...
Run Code Online (Sandbox Code Playgroud)
创建一个some_users允许更新col_a(仅允许更新)的(组)角色:
CREATE ROLE some_users;
GRANT SELECT, UPDATE (col_a) ON TABLE tbl TO some_users;
Run Code Online (Sandbox Code Playgroud)
为什么SELECT?手册上GRANT:
实际上,任何重要的
UPDATE命令也都需要SELECT特权,因为它必须引用表列来确定要更新哪些行,和/或计算列的新值。
这样,您就可以在一个点上授予该列的权限。
创建另一个(组)角色certain_users,它可以做所有some_users可以做的事情(还有更多):
CREATE ROLE certain_users;
GRANT some_users TO certain_users;
Run Code Online (Sandbox Code Playgroud)
根据需要将这些角色的成员资格授予用户角色:
GRANT some_users TO lowly_user;
GRANT certain_users TO chief_user;
Run Code Online (Sandbox Code Playgroud)
创建一个条件触发器,类似于@Daniel 提供的,但使用另一个条件pg_has_role():
CREATE TRIGGER tbl_value_trigger
BEFORE UPDATE ON tbl
FOR EACH ROW
WHEN (OLD.col_a IS NOT NULL AND NOT pg_has_role('some_users', 'member'))
EXECUTE PROCEDURE always_fail();
Run Code Online (Sandbox Code Playgroud)
使用触发函数:
CREATE FUNCTION always_fail()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
-- To fail with exception, rolling back the whole transaction
-- use this instead:
-- RAISE EXCEPTION 'value is not null';
-- Do nothing instead, letting the rest of the transaction commit.
-- Requires BEFORE trigger.
RAISE WARNING 'col_a IS NOT NULL. User % is too ambitious!', current_user;
RETURN NULL; -- effectively aborts UPDATE
END
$func$;
Run Code Online (Sandbox Code Playgroud)
some_users并certain_users允许更新该列col_a(仅此而已),certain_users经历一次开始发生变化col_a is NOT NULL。请注意,超级用户自动成为任何组的成员。因此,该表单NOT pg_has_role(...) 支持超级用户,而逆逻辑可能会禁止超级用户更新列。
| 归档时间: |
|
| 查看次数: |
2000 次 |
| 最近记录: |