PostGraphile 不推荐列级 SELECT grants,而是建议
将您的关注点拆分为多个表,并使用一对一的关系功能将它们链接起来。
现在我希望我的users
表有一个role
可以访问role_admin
但不能访问的字段role_consumer
。基于上述建议,我创建了两个表。users
表(在公共模式中)包含两个角色都可以看到的所有字段,并且user_accounts
(在私有模式中)包含role
只有role_admin
必须能够看到的字段。role
字段通过计算列添加到user
GraphQL 类型。
CREATE SCHEMA demo_public;
CREATE SCHEMA demo_private;
/* users table*/
CREATE TABLE demo_public.users (
user_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
);
/* user_accounts */
CREATE TABLE demo_private.user_accounts (
user_id INT PRIMARY KEY REFERENCES demo_public.users (user_id) ON DELETE CASCADE,
role text not null default 'role_consumer',
);
/* role as computed column */
CREATE FUNCTION demo_public.users_role
(
u demo_public.users
)
RETURNS TEXT as $$
<code>
$$ LANGUAGE SQL STRICT STABLE;
现在基本上我有两种药水来设置权限。
1)第一个选项是使用表级安全性。IOW 将表上的选择访问权限授予user_accounts
ONLY role_admin
。
GRANT SELECT ON TABLE demo_private.user_accounts TO role_admin;
GRANT EXECUTE ON FUNCTION demo_public.users_role(demo_public.users) TO role_admin;
ALTER TABLE demo_private.user_accounts ENABLE ROW LEVEL SECURITY;
CREATE POLICY select_any_user_accounts ON demo_private.user_accounts FOR SELECT TO role_admin using (true);
这种方法的问题在于,当role_consumer
运行包含role
字段的查询时
{
me {
firstname
role
}
}
上述查询返回错误。这不好,因为错误会影响隐藏其他同级字段结果的整个结果。
2) 另一个选项是使用除表级别之外的行级别安全性;IOW 在表级别,授予对表的选择访问权限user_accounts
,role_admin
但role_consumer
在行级别仅允许管理员访问user_accounts
.
GRANT USAGE ON SCHEMA demo_private TO role_consumer;
GRANT SELECT ON TABLE demo_private.user_accounts TO role_consumer;
GRANT EXECUTE ON FUNCTION demo_public.users_role(demo_public.users) TO role_consumer;
ALTER TABLE demo_private.user_accounts ENABLE ROW LEVEL SECURITY;
CREATE POLICY select_user_accounts ON demo_private.user_accounts FOR SELECT
USING ('role_admin' = nullif(current_setting('role', true), ''));
现在,如果用户consumer_role
运行上述查询,该role
字段将为空,不会影响其兄弟字段。但是有两个问题:
我们是否应该始终避免错误以防止它们影响兄弟姐妹?
如果是,我们是否应该始终在行级别而不是仅在表级别处理事情?