前言
PostgreSQL 中可以使用角色来控制访问数据库对象的权限,在 PostgreSQL 中,角色在一定程度上可以等同为数据库用户或数据库用户组,同时 PostgreSQL 还允许将一个角色的权限赋予另外一个角色。本章内容将介绍如何查询用户所继承的权限。
问题复现
查看 auser 有具有对象级别的权限,可以看到用户 auser 具有表 t1 的 insert,update,delete,select 权限:
postgres=# select table_catalog,table_schema,table_name , privilege_type from information_schema.table_privileges where grantee='auser';
table_catalog | table_schema | table_name | privilege_type
---------------+--------------+------------+----------------
postgres | public | t1 | INSERT
postgres | public | t1 | SELECT
postgres | public | t1 | UPDATE
postgres | public | t1 | DELETE
(4 rows)
```
`
创建 buser,然后将 auser 具有的权限赋予 buser:
````undefined
postgres=# create user buser password 'RFVrfv@2022';
CREATE ROLE
postgres=# grant auser to buser;
GRANT ROLE
```
`
这里如果我们想查看 buser 有拥有的权限,使用上面的语句是查询不到的:
````undefined
postgres=# select table_catalog,table_schema,table_name, privilege_type from information_schema.table_privileges where grantee='buser';
table_catalog | table_schema | table_name | privilege_type
---------------+--------------+------------+----------------
(0 rows)
```
`
通过如下语句,我们可以定位到 buser 继承了 auser 的权限,不过我们还需要执行相应的查询来获取 auser 的查询,我们希望有快捷的方式来获取一个用户所继承的权限是什么。
````undefined
postgres=# SELECT r.rolname, r.rolinherit,
ARRAY(SELECT b.rolname
FROM pg_catalog.pg_auth_members m
JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
WHERE m.member = r.oid) as memberof
FROM pg_catalog.pg_roles r
WHERE r.rolname='buser';
rolname | rolinherit | memberof
---------+------------+----------
buser | t | {auser}
(1 row)
```
`
# 解决方案
PostgreSQL 提供了 **has_table_privilege()** [1] 方法来查看某个用户所继承的权限,查询语句如下:
````undefined
postgres=# SELECT
tmp.user_name,
tmp.TABLE_NAME,
tmp.privilege_type
FROM
(
SELECT
r.rolname AS user_name,
C.oid :: regclass AS TABLE_NAME,
P.perm AS privilege_type
FROM
pg_class
C CROSS JOIN pg_roles r
CROSS JOIN UNNEST ( ARRAY [ 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER' ] ) P ( perm )
WHERE
relkind = 'r'
AND relnamespace NOT IN ( SELECT oid FROM pg_namespace WHERE nspname IN ( 'pg_catalog', 'information_schema' ) )
AND has_table_privilege ( rolname, C.oid, P.perm )
) tmp
WHERE
tmp.user_name = 'buser';
user_name | table_name | privilege_type
-----------+------------+----------------
buser | t1 | SELECT
buser | t1 | INSERT
buser | t1 | UPDATE
buser | t1 | DELETE
(4 rows)
```
`
上述语句可以将用户所具有的对象级别的权限列出来,会方便许多。
关于 PostgreSQL 中更多关于用户权限查询语句,您可以参考文档[2]。
# 参考文档
[1] [https://www.postgresql.org/docs/current/functions-info.html](https://www.postgresql.org/docs/current/functions-info.html)
[2] [https://developer.volcengine.com/articles/7103837907202342919](https://developer.volcengine.com/articles/7103837907202342919)
**如果您有其他问题,欢迎您联系火山引擎**[技术支持服务](https://console.volcengine.com/ticket/createTicketV2/)