我想编写一个查询,该查询将每个用户的权限转储到覆盖率表中。进行此搜索的原因是,我可以快照表权限,然后在服务器之间或在运行大型GRANTS重置脚本之前和之后比较它们。我正在寻找易于比较的输出,因此如下所示:
schema_name table_name qualified_name owner_name privilege setting
api base4 api.base4 postgres delete TRUE
api bucket_test api.bucket_test postgres delete TRUE
我编写了一个查询,使我进入其中,但特权名称和设置作为列对。我可以通过在特权之后命名它们来将列切成两半,但是我使用的是上面的窄行格式。这使得我将对表+用户+特权进行比较。
schema_name table_name qualified_name owner_name privilege delete privilege insert privilege references privilege setting privilege trigger privilege truncate privilege update
api base4 api.base4 postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
api bucket_test api.bucket_test postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
有人可以建议正确的联接或取消嵌套+联接来重做我现在得到的查询吗?
而且,是的,此查询将生成很多结果行。没关系,这就是我的追求。
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
schemaname::text || '.' || tablename::text as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select table_list.schema_name,
table_list.table_name,
table_list.qualified_name,
table_list.owner_name,
'delete' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'delete') as delete,
'insert' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'insert') as insert,
'references' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'references') as references,
'select' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'select') as select,
'trigger' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'trigger') as trigger,
'truncate' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'truncate') as truncate,
'update' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'update') as update
from table_list
cross join user_list
我在RDS上使用Postgres 11.4。
对于以后发现此问题的人,以下是最终查询的版本:
DROP VIEW IF EXISTS data.table_grants;
CREATE OR REPLACE VIEW data.table_grants AS
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
schemaname::text || '.' || tablename::text as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select
table_list.*,
user_list.user_name,
privilege,
has_table_privilege(user_name, qualified_name, privilege) as setting
from
table_list
cross join user_list
cross join (values
('delete'), ('insert'), ('references'), ('select'), ('trigger'), ('truncate'), ('update')
) as p(privilege);
ALTER TABLE data.table_grants
OWNER TO user_change_structure;
[这使在表上的搜索授予更为简单,就像这样,以查看在名为item
的表上授予的权限
select *
from table_grants
where table_name = 'item'
order by user_name,
privilege;
或此查询以获取特定表上用户权限的摘要视图:
select qualified_name,
owner_name,
user_name,
array_agg(privilege) as rights
from table_grants
where table_name = 'item' and
setting = true
group by qualified_name,
owner_name,
user_name;
上面的查询不一定是最佳效率的,视图的产品是表*用户* 8 ...但是对于我来说,这是瞬时的,少于100个表并且大约有15个角色。
像评论中已经建议过的伊斯林格,您可以使用
select
table_list.*,
privilege,
has_table_privilege(user_name, qualified_name, privilege) as setting
from
table_list
cross join user_list
cross join (values
('delete'), ('insert'), ('references'), ('select'), ('trigger'), ('truncate'), ('update')
) as p(privilege)