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
List all schemas with their priveleges for current user:
WITH "names"("name") AS (
SELECT n.nspname AS "name"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_'
AND n.nspname <> 'information_schema'
) SELECT "name",
pg_catalog.has_schema_privilege(current_user, "name", 'CREATE') AS "create",
pg_catalog.has_schema_privilege(current_user, "name", 'USAGE') AS "usage"
FROM "names";
The response will be for example:
name | create | usage
---------+--------+-------
public | t | t
test | t | t
awesome | f | f
(3 rows)
In this example current user is not owner of the awesome
schema.
As you could guess, similar request for particular schema:
SELECT
pg_catalog.has_schema_privilege(
current_user, 'awesome', 'CREATE') AS "create",
pg_catalog.has_schema_privilege(
current_user, 'awesome', 'USAGE') AS "usage";
and response:
create | usage
--------+-------
f | f
As you know, it's possible to use pg_catalog.current_schema()
for current schema.
Of all the possible privileges
-- SELECT
-- INSERT
-- UPDATE
-- DELETE
-- TRUNCATE
-- REFERENCES
-- TRIGGER
-- CREATE
-- CONNECT
-- TEMP
-- EXECUTE
-- USAGE
the only CREATE
and USAGE
allowed for schemas.
Like the current_schema()
the current_user
can be replaced with particular role.
BONUS with current
column
WITH "names"("name") AS (
SELECT n.nspname AS "name"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_'
AND n.nspname <> 'information_schema'
) SELECT "name",
pg_catalog.has_schema_privilege(current_user, "name", 'CREATE') AS "create",
pg_catalog.has_schema_privilege(current_user, "name", 'USAGE') AS "usage",
"name" = pg_catalog.current_schema() AS "current"
FROM "names";
-- name | create | usage | current
-- ---------+--------+-------+---------
-- public | t | t | t
-- test | t | t | f
-- awesome | f | f | f
-- (3 rows)
WITH | System Information Functions | GRANT (privileges)
For current question can try this one:
SELECT r.rolname AS role_name,
n.nspname AS schema_name,
p.perm AS privilege
FROM pg_catalog.pg_namespace AS n
CROSS JOIN pg_catalog.pg_roles AS r
CROSS JOIN (VALUES ('USAGE'), ('CREATE')) AS p(perm)
WHERE has_schema_privilege(r.oid, n.oid, p.perm)
-- AND n.nspname <> 'information_schema'
-- AND n.nspname !~~ 'pg\_%'
-- AND NOT r.rolsuper
Could be pretty low in performance at database with a lot of objects and users with which I have come across. So i've got possible workaround using aclexplode() default function like this:
SELECT oid_to_rolname(a.grantee) AS role_name,
n.nspname AS schema_name,
a.privilege_type AS privilege_type
FROM pg_catalog.pg_namespace AS n,
aclexplode(nspacl) a
WHERE n.nspacl IS NOT NULL
AND oid_to_rolname(a.grantee) IS NOT NULL
-- AND n.nspname <> 'information_schema'
-- AND n.nspname !~~ 'pg\_%'
But, be careful, last one doesn't include privileges which users have obtained from PUBLIC
role.
Where oid_to_rolname()
is simple custom function SELECT rolname FROM pg_roles WHERE oid = $1
.
And, like @Jaisus, my task required to have all privileges which all users have. So i have similar to schema
privileges queries for table
, views
, columns
, sequences
, functions
, database
and even default
privileges.
Also, there is helpful extension pg_permission where I get logic for provided queries and just upgraded it for my purposes.
This is what psql uses internally :)
SELECT n.nspname AS "Name",
pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner",
pg_catalog.array_to_string(n.nspacl, E'\n') AS "Access privileges",
pg_catalog.obj_description(n.oid, 'pg_namespace') AS "Description"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
ORDER BY 1;