snippetsqlCritical
How to get all roles that a user is a member of (including inherited roles)?
Viewed 0 times
inheritedallrolesusermembergetthatincludinghow
Problem
Let's say I have two Postgresql database groups, "authors" and "editors", and two users, "maxwell" and "ernest".
I would like to write a performant function that returns a list of the roles (preferably their oid's) that maxwell belongs to, something like this:
It should return the oids for maxwell, authors, and editors (but not ernest).
But I am not sure how to do it when there is inheritance.
create role authors;
create role editors;
create user maxwell;
create user ernest;
grant authors to editors; --editors can do what authors can do
grant editors to maxwell; --maxwell is an editor
grant authors to ernest; --ernest is an authorI would like to write a performant function that returns a list of the roles (preferably their oid's) that maxwell belongs to, something like this:
create or replace function get_all_roles() returns oid[] ...It should return the oids for maxwell, authors, and editors (but not ernest).
But I am not sure how to do it when there is inheritance.
Solution
You can query the system catalog with a recursive query, in particular
The manual about the cast to object identifier type
BTW 1:
BTW 2: circular dependencies are not possible. Postgres disallows that. So we don't have to check for that.
pg_auth_members:WITH RECURSIVE cte AS (
SELECT oid FROM pg_roles WHERE rolname = 'maxwell'
UNION ALL
SELECT m.roleid
FROM cte
JOIN pg_auth_members m ON m.member = cte.oid
)
SELECT oid, oid::regrole::text AS rolename FROM cte; -- oid & nameThe manual about the cast to object identifier type
regrole.BTW 1:
INHERIT is the default behavior of CREATE ROLE and doesn't have to be spelled out.BTW 2: circular dependencies are not possible. Postgres disallows that. So we don't have to check for that.
Code Snippets
WITH RECURSIVE cte AS (
SELECT oid FROM pg_roles WHERE rolname = 'maxwell'
UNION ALL
SELECT m.roleid
FROM cte
JOIN pg_auth_members m ON m.member = cte.oid
)
SELECT oid, oid::regrole::text AS rolename FROM cte; -- oid & nameContext
StackExchange Database Administrators Q#56096, answer score: 56
Revisions (0)
No revisions yet.