Is there a query I can run to show currently assigned privileges on a particular schema?
i.e. privileges that were assigned like so:
GRANT USAGE ON S
in console util psql:
\dn+
will show you
Name | Owner | Access privileges | Description
The privileges are stored in the nspacl field of pg_namespace. Since it's an array field, you have to do a little fancy coding to parse it. This query will give you the grant statements used for users and groups:
select
'grant ' || substring(
case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
, 2,10000)
|| ' on schema '||nspname||' to "'||pu.usename||'";'
from pg_namespace pn,pg_user pu
where array_to_string(nspacl,',') like '%'||pu.usename||'%' --and pu.usename='<username>'
and nspowner > 1
union
select
'grant ' || substring(
case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pg.groname,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pg.groname,2 ) ,'/',1)) > 0 then ',create ' else '' end
, 2,10000)
|| ' on schema '||nspname||' to group "'||pg.groname||'";'
from pg_namespace pn,pg_group pg
where array_to_string(nspacl,',') like '%'||pg.groname||'%' --and pg.groname='<username>'
and nspowner > 1
I know this post is old but I made another query based on the different answers to have one that is short and easy to use afterward :
select
nspname as schema_name
, r.rolname as role_name
, pg_catalog.has_schema_privilege(r.rolname, nspname, 'CREATE') as create_grant
, pg_catalog.has_schema_privilege(r.rolname, nspname, 'USAGE') as usage_grant
from pg_namespace pn,pg_catalog.pg_roles r
where array_to_string(nspacl,',') like '%'||r.rolname||'%'
and nspowner > 1
I keep thinking one day I will make a query to have all rights in only one view... One day. ;)
Try this one (works for PUBLIC role):
SELECT nspname,
coalesce(nullif(role.name,''), 'PUBLIC') AS name,
substring(
CASE WHEN position('U' in split_part(split_part((','||array_to_string(nspacl,',')), ','||role.name||'=',2 ) ,'/',1)) > 0 THEN ', USAGE' ELSE '' END
|| CASE WHEN position('C' in split_part(split_part((','||array_to_string(nspacl,',')), ','||role.name||'=',2 ) ,'/',1)) > 0 THEN ', CREATE' ELSE '' END
, 3,10000) AS privileges
FROM pg_namespace pn, (SELECT pg_roles.rolname AS name
FROM pg_roles UNION ALL SELECT '' AS name) AS role
WHERE (','||array_to_string(nspacl,',')) LIKE '%,'||role.name||'=%'
AND nspowner > 1;
Even more concisely, one can do:
SELECT
n.nspname AS schema_name
FROM pg_namespace n
WHERE has_schema_privilege('my_user',n.nspname, 'CREATE, USAGE');
Combined version (groups, users, PUBLIC) that works for AWS Redshift:
SELECT *
FROM (SELECT CASE
WHEN charindex ('U',SPLIT_PART(SPLIT_PART(ARRAY_TO_STRING(nspacl,'|'),pu.usename,2),'/',1)) > 0 THEN ' USAGE'
ELSE ''
END ||case WHEN charindex('C',SPLIT_PART(SPLIT_PART(ARRAY_TO_STRING(nspacl,'|'),pu.usename,2),'/',1)) > 0 THEN ' CREATE' ELSE '' END AS rights,
nspname AS schema,
'' AS role,
pu.usename AS user
FROM pg_namespace pn,
pg_user pu
WHERE ARRAY_TO_STRING(nspacl,',') LIKE '%' ||pu.usename|| '%'
--and pu.usename='<username>'
AND nspowner > 1
UNION
SELECT CASE
WHEN charindex ('U',SPLIT_PART(SPLIT_PART(ARRAY_TO_STRING(nspacl,'|'),pg.groname,2),'/',1)) > 0 THEN ' USAGE '
ELSE ''
END ||case WHEN charindex('C',SPLIT_PART(SPLIT_PART(ARRAY_TO_STRING(nspacl,'|'),pg.groname,2),'/',1)) > 0 THEN ' CREATE' ELSE '' END as rights,
nspname AS schema,
pg.groname AS role,
'' AS user
FROM pg_namespace pn,
pg_group pg
WHERE ARRAY_TO_STRING(nspacl,',') LIKE '%' ||pg.groname|| '%'
--and pg.groname='<username>'
AND nspowner > 1
UNION
SELECT CASE
WHEN POSITION('U' IN SPLIT_PART(SPLIT_PART((',' ||array_to_string (nspacl,',')),',' ||roles.name|| '=',2),'/',1)) > 0 THEN ' USAGE'
ELSE ''
END
|| CASE
WHEN POSITION('C' IN SPLIT_PART(SPLIT_PART((',' ||array_to_string (nspacl,',')),',' ||roles.name|| '=',2),'/',1)) > 0 THEN ' CREATE'
ELSE ''
END AS rights,
nspname AS schema,
COALESCE(NULLIF(roles.name,''),'PUBLIC') AS role,
'' AS user
FROM pg_namespace pn,
(SELECT pg_group.groname AS name
FROM pg_group
UNION ALL
SELECT '' AS name) AS roles
WHERE (',' ||array_to_string (nspacl,',')) LIKE '%,' ||roles.name|| '=%'
AND nspowner > 1) privs
ORDER BY schema,rights