Thread: Does the current user have UPDATE privilege on FOO?
Hi, I'm trying to understand the "clean" way to determine whether the current role has UPDATE (or SELECT or DELETE or UPDATE) privileges on a specific table (or column). If I can do it in a way that is portable across different DBMSs, even better :) I went through several iterations, 'CUR_USER' being replaced by the name of the current user (the one the application authenticated with to PostgreSQL): SELECT * FROM information_schema.table_privileges WHERE table_schema='foo' AND table_name='bar' AND grantee='CUR_USER' This misses the privileges given to a role (group) the current role is a member of (false negative). SELECT * FROM information_schema.table_privileges WHERE table_schema='foo' AND table_name='bar' Is also not OK, because it also contains privileges that the current user granted to other users, privileges it does not necessarily have itself, so false positives :-| I tried mucking around with enabled_roles, something like: SELECT * FROM information_schema.table_privileges WHERE table_schema='foo' AND table_name='bar' AND grantee IN (SELECT role_name FROM information_schema.enabled_roles); But as explained below, that is inconvenient in the general framework of the application because I can't do "a similar thing" when given only a JDBC/ODBC interface. I currently use something like (modulo a workaround for bug in PostgreSQL < 9.2 that the default ACL is not taken into account when no ACL on object): SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable FROM (SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name, grantor, grantee, privilege_type AS PRIVILEGE, is_grantable FROM information_schema.table_privileges ) dp, (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr WHERE table_schem LIKE ? AND table_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE')) ORDER BY table_schem, table_name, privilege (On Postgresql < 9.2, I add to the definition of dp a "UNION ALL" giving full permissions to the owner on all objects that don't have an ACL.) For reasons internal to the application, I execute this SQL and then filter (in the application) the entries that have grantee='CUR_USER'. Is there a better / cleaner / more canonical way? Full background: I'm taking care of the native PostgreSQL driver for LibreOffice, the successor to OpenOffice.org. The driver exposes a JDBC-like interface to the rest of the system, and the above is taken from its "getTablePrivileges" interface method. The filtering is done in the driver-agnostic part of LibreOffice, which has to also work with JDBC drivers and ODBC drivers. So the "direct" way with information_schema.enabled_roles is not feasible, since ODBC/JDBC don't give me an interface to (an equivalent of) enabled_roles :-| Do you have a better suggestion than what I do now, what to do in the PostgreSQL driver and what to do in the driver-agnostic part for maximum compatibility (across DMBSs, across different PostgreSQL versions, ...)? The reason we want see whether a user has a given privilege is to enable or disable the corresponding UI elements that allow the user to edit / delete / insert data in / from / into the table, in GUI forms and datasheets and such. -- Lionel
On Mon, Feb 27, 2012 at 11:00, Lionel Elie Mamane <lionel@mamane.lu> wrote:
Hi,
I'm trying to understand the "clean" way to determine whether the
current role has UPDATE (or SELECT or DELETE or UPDATE) privileges on
a specific table (or column). If I can do it in a way that is portable
across different DBMSs, even better :)
For PostgreSQL only, see http://www.postgresql.org/docs/9.1/interactive/functions-info.html for a list of functions for this.
Mike
On Mon, Feb 27, 2012 at 12:11:23PM -0600, Mike Blackwell wrote: > On Mon, Feb 27, 2012 at 11:00, Lionel Elie Mamane <lionel@mamane.lu> wrote: >> I'm trying to understand the "clean" way to determine whether the >> current role has UPDATE (or SELECT or DELETE or UPDATE) privileges on >> a specific table (or column). If I can do it in a way that is portable >> across different DBMSs, even better :) > For PostgreSQL only, see > http://www.postgresql.org/docs/9.1/interactive/functions-info.html for a > list of functions for this. Ah yes, so basically I can implement the JDBC-alike getTablePrivileges as something like: SELECT (...), tables.table_name, pr.rolname AS grantee, has_table_privilege(pr.oid, tables.table_schema, + '.' + tables.table_name, privilege.name), (...) FROM information_schema.tables, pg_catalog.pg_roles pr, VALUES ('SELECT', 'UPDATE', ...) AS privilege I'd be missing a sensible value for the grantor column, but at least it would be complete and robust for the rest of the information. Thanks for the pointer. -- Lionel