Re: [PATCH] Implement (and document, and test) has_sequence_privilege() - Mailing list pgsql-hackers
From | Joe Conway |
---|---|
Subject | Re: [PATCH] Implement (and document, and test) has_sequence_privilege() |
Date | |
Msg-id | 4A775317.9080009@joeconway.com Whole thread Raw |
In response to | Re: [PATCH] Implement (and document, and test) has_sequence_privilege() (Joe Conway <mail@joeconway.com>) |
List | pgsql-hackers |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Joe Conway wrote: > If there are no objections, I'll commit in a day or two. Attached version committed. Only difference from the last is catversion. Joe -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org iQIcBAEBCAAGBQJKd1MXAAoJEDfy90M199hlz6IP/RvNrU3CQ0wUvipvR3sJi3wV Bis3TqPiSzGlKHDkV67Mh+sR0oQLJ2UG5yEgmSPM8yus+zd6rRzSIpS1Z+npE1sg CKJtYTzDjVby9szhKk9znn37dY/dyIOzW7S9AXCjwF1bM+60Pyavue3J8br3TnU7 yCCVH1wow4D7Pg0pO/kKEiOLAO+Qx9NUA5AGdUh47c0NLvz7XbmhkrG2Kt1KKrha 2qVgKUEqsi8Q6vahx5qczCM6TuYx33WFfwCLWT0HB0igtfuEp5Pp8D0C/5sRNer/ J10JqdWp/XPEv69rLkLNkdHns0pA+J0uPJLZkEcwi38a7YThwSzraDSw73gslcRX UdAlSe06tOuxUky4IlHNFZZnzaAaXwGNjJARmjKK+PtMozatfO0lUKU5QCeQhRx1 QgtlDC4MQuFcVsdDy5jFWLviP0PiMtiWtkKhAp9e0FZa5CHQQby5AuTKNHSfS3To XhE+abZfbwFTQFrGFGKJnNWPepbLnl1gm2sm6id175m/8FKXNQo++jr0SasqkEzA d52C6/WI7Ll6Zlo9smnc3ogt9ggnQ866AOdy1SXpkEDjFdGDsMxgxjI8rObNxYEL ew9VAgFI5lwnABKlRv7y2xIMxOEgdO6gduURJhQ2U20yhq1W8QlsjE+IE7UYURBL VXj6LlvceXdDFF2uUjMz =gAqc -----END PGP SIGNATURE----- ? GNUmakefile ? config.log ? config.status ? src/Makefile.global ? src/backend/bootstrap/bootstrap_tokens.h ? src/backend/parser/parse.h ? src/backend/snowball/libdict_snowball.so.0.0 ? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0 ? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0 ? src/bin/ipcclean/ipcclean ? src/include/pg_config.h ? src/include/stamp-h ? src/interfaces/ecpg/compatlib/libecpg_compat.so.2.3 ? src/interfaces/ecpg/ecpglib/libecpg.so.6.0 ? src/interfaces/ecpg/include/ecpg_config.h ? src/interfaces/ecpg/include/stamp-h ? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.2.3 ? src/interfaces/libpq/libpq.so.5.1 ? src/pl/plperl/libplperl.so.0.0 ? src/pl/plpgsql/src/libplpgsql.so.1.0 ? src/pl/plpgsql/src/pl.tab.h ? src/pl/tcl/libpltcl.so.2.0 ? src/test/regress/libregress.so.0.0 Index: doc/src/sgml/func.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.483 diff -c -r1.483 func.sgml *** doc/src/sgml/func.sgml 22 Jul 2009 18:07:26 -0000 1.483 --- doc/src/sgml/func.sgml 3 Aug 2009 21:10:21 -0000 *************** *** 11789,11794 **** --- 11789,11809 ---- <entry>does current user have privilege for foreign server</entry> </row> <row> + <entry><literal><function>has_sequence_privilege</function>(<parameter>user</parameter>, + <parameter>sequence</parameter>, + <parameter>privilege</parameter>)</literal> + </entry> + <entry><type>boolean</type></entry> + <entry>does user have privilege for sequence</entry> + </row> + <row> + <entry><literal><function>has_sequence_privilege</function>(<parameter>sequence</parameter>, + <parameter>privilege</parameter>)</literal> + </entry> + <entry><type>boolean</type></entry> + <entry>does current user have privilege for sequence</entry> + </row> + <row> <entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>, <parameter>table</parameter>, <parameter>privilege</parameter>)</literal> *************** *** 11862,11867 **** --- 11877,11885 ---- <primary>has_server_privilege</primary> </indexterm> <indexterm> + <primary>has_sequence_privilege</primary> + </indexterm> + <indexterm> <primary>has_table_privilege</primary> </indexterm> <indexterm> *************** *** 11901,11906 **** --- 11919,11934 ---- </para> <para> + <function>has_sequence_privilege</function> checks whether a user + can access a sequence in a particular way. The possibilities for its + arguments are analogous to <function>has_table_privilege</function>. + The desired access privilege type must evaluate to one of + <literal>USAGE</literal>, + <literal>SELECT</literal>, or + <literal>UPDATE</literal>. + </para> + + <para> <function>has_any_column_privilege</function> checks whether a user can access any column of a table in a particular way. Its argument possibilities Index: src/backend/utils/adt/acl.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v retrieving revision 1.148 diff -c -r1.148 acl.c *** src/backend/utils/adt/acl.c 11 Jun 2009 14:49:03 -0000 1.148 --- src/backend/utils/adt/acl.c 3 Aug 2009 21:10:22 -0000 *************** *** 20,25 **** --- 20,26 ---- #include "catalog/pg_authid.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_type.h" + #include "catalog/pg_class.h" #include "commands/dbcommands.h" #include "commands/tablespace.h" #include "foreign/foreign.h" *************** *** 88,93 **** --- 89,95 ---- static Oid convert_table_name(text *tablename); static AclMode convert_table_priv_string(text *priv_type_text); + static AclMode convert_sequence_priv_string(text *priv_type_text); static AttrNumber convert_column_name(Oid tableoid, text *column); static AclMode convert_column_priv_string(text *priv_type_text); static Oid convert_database_name(text *databasename); *************** *** 1704,1709 **** --- 1706,1921 ---- return convert_any_priv_string(priv_type_text, table_priv_map); } + /* + * has_sequence_privilege variants + * These are all named "has_sequence_privilege" at the SQL level. + * They take various combinations of relation name, relation OID, + * user name, user OID, or implicit user = current_user. + * + * The result is a boolean value: true if user has the indicated + * privilege, false if not. The variants that take a relation OID + * return NULL if the OID doesn't exist. + */ + + /* + * has_sequence_privilege_name_name + * Check user privileges on a sequence given + * name username, text sequencename, and text priv name. + */ + Datum + has_sequence_privilege_name_name(PG_FUNCTION_ARGS) + { + Name rolename = PG_GETARG_NAME(0); + text *sequencename = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid sequenceoid; + AclMode mode; + AclResult aclresult; + + roleid = get_roleid_checked(NameStr(*rolename)); + mode = convert_sequence_priv_string(priv_type_text); + sequenceoid = convert_table_name(sequencename); + if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + text_to_cstring(sequencename)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * has_sequence_privilege_name + * Check user privileges on a sequence given + * text sequencename and text priv name. + * current_user is assumed + */ + Datum + has_sequence_privilege_name(PG_FUNCTION_ARGS) + { + text *sequencename = PG_GETARG_TEXT_P(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + Oid sequenceoid; + AclMode mode; + AclResult aclresult; + + roleid = GetUserId(); + mode = convert_sequence_priv_string(priv_type_text); + sequenceoid = convert_table_name(sequencename); + if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + text_to_cstring(sequencename)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * has_sequence_privilege_name_id + * Check user privileges on a sequence given + * name usename, sequence oid, and text priv name. + */ + Datum + has_sequence_privilege_name_id(PG_FUNCTION_ARGS) + { + Name username = PG_GETARG_NAME(0); + Oid sequenceoid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AclMode mode; + AclResult aclresult; + char relkind; + + roleid = get_roleid_checked(NameStr(*username)); + mode = convert_sequence_priv_string(priv_type_text); + relkind = get_rel_relkind(sequenceoid); + if (relkind == '\0') + PG_RETURN_NULL(); + else if (relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + get_rel_name(sequenceoid)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * has_sequence_privilege_id + * Check user privileges on a sequence given + * sequence oid, and text priv name. + * current_user is assumed + */ + Datum + has_sequence_privilege_id(PG_FUNCTION_ARGS) + { + Oid sequenceoid = PG_GETARG_OID(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + AclMode mode; + AclResult aclresult; + char relkind; + + roleid = GetUserId(); + mode = convert_sequence_priv_string(priv_type_text); + relkind = get_rel_relkind(sequenceoid); + if (relkind == '\0') + PG_RETURN_NULL(); + else if (relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + get_rel_name(sequenceoid)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * has_sequence_privilege_id_name + * Check user privileges on a sequence given + * roleid, text sequencename, and text priv name. + */ + Datum + has_sequence_privilege_id_name(PG_FUNCTION_ARGS) + { + Oid roleid = PG_GETARG_OID(0); + text *sequencename = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid sequenceoid; + AclMode mode; + AclResult aclresult; + + mode = convert_sequence_priv_string(priv_type_text); + sequenceoid = convert_table_name(sequencename); + if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + text_to_cstring(sequencename)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * has_sequence_privilege_id_id + * Check user privileges on a sequence given + * roleid, sequence oid, and text priv name. + */ + Datum + has_sequence_privilege_id_id(PG_FUNCTION_ARGS) + { + Oid roleid = PG_GETARG_OID(0); + Oid sequenceoid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + AclMode mode; + AclResult aclresult; + char relkind; + + mode = convert_sequence_priv_string(priv_type_text); + relkind = get_rel_relkind(sequenceoid); + if (relkind == '\0') + PG_RETURN_NULL(); + else if (relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + get_rel_name(sequenceoid)))); + + aclresult = pg_class_aclcheck(sequenceoid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); + } + + /* + * convert_sequence_priv_string + * Convert text string to AclMode value. + */ + static AclMode + convert_sequence_priv_string(text *priv_type_text) + { + static const priv_map sequence_priv_map[] = { + { "USAGE", ACL_USAGE }, + { "SELECT", ACL_SELECT }, + { "UPDATE", ACL_UPDATE }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, sequence_priv_map); + } + /* * has_any_column_privilege variants Index: src/include/catalog/catversion.h =================================================================== RCS file: /cvsroot/pgsql/src/include/catalog/catversion.h,v retrieving revision 1.535 diff -c -r1.535 catversion.h *** src/include/catalog/catversion.h 2 Aug 2009 22:14:52 -0000 1.535 --- src/include/catalog/catversion.h 3 Aug 2009 21:10:22 -0000 *************** *** 53,58 **** */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200908021 #endif --- 53,58 ---- */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200908031 #endif Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.547 diff -c -r1.547 pg_proc.h *** src/include/catalog/pg_proc.h 29 Jul 2009 20:56:20 -0000 1.547 --- src/include/catalog/pg_proc.h 3 Aug 2009 21:10:24 -0000 *************** *** 2918,2923 **** --- 2918,2936 ---- DATA(insert OID = 1927 ( has_table_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "26 25" _null_ _null_ _null__null_ has_table_privilege_id _null_ _null_ _null_ )); DESCR("current user privilege on relation by rel oid"); + DATA(insert OID = 2181 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "19 25 25" _null_ _null__null_ _null_ has_sequence_privilege_name_name _null_ _null_ _null_ )); + DESCR("user privilege on sequence by username, seq name"); + DATA(insert OID = 2182 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "19 26 25" _null_ _null__null_ _null_ has_sequence_privilege_name_id _null_ _null_ _null_ )); + DESCR("user privilege on sequence by username, seq oid"); + DATA(insert OID = 2183 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 25 25" _null_ _null__null_ _null_ has_sequence_privilege_id_name _null_ _null_ _null_ )); + DESCR("user privilege on sequence by user oid, seq name"); + DATA(insert OID = 2184 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 26 25" _null_ _null__null_ _null_ has_sequence_privilege_id_id _null_ _null_ _null_ )); + DESCR("user privilege on sequence by user oid, seq oid"); + DATA(insert OID = 2185 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "25 25" _null_ _null__null_ _null_ has_sequence_privilege_name _null_ _null_ _null_ )); + DESCR("current user privilege on sequence by seq name"); + DATA(insert OID = 2186 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "26 25" _null_ _null__null_ _null_ has_sequence_privilege_id _null_ _null_ _null_ )); + DESCR("current user privilege on sequence by seq oid"); + DATA(insert OID = 3012 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 25 25" _null_ _null__null_ _null_ has_column_privilege_name_name_name _null_ _null_ _null_ )); DESCR("user privilege on column by username, rel name, col name"); DATA(insert OID = 3013 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 21 25" _null_ _null__null_ _null_ has_column_privilege_name_name_attnum _null_ _null_ _null_ )); Index: src/include/utils/builtins.h =================================================================== RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v retrieving revision 1.336 diff -c -r1.336 builtins.h *** src/include/utils/builtins.h 1 Aug 2009 19:59:41 -0000 1.336 --- src/include/utils/builtins.h 3 Aug 2009 21:10:25 -0000 *************** *** 46,51 **** --- 46,57 ---- extern Datum has_table_privilege_id_id(PG_FUNCTION_ARGS); extern Datum has_table_privilege_name(PG_FUNCTION_ARGS); extern Datum has_table_privilege_id(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_name_id(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_id_name(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_name(PG_FUNCTION_ARGS); + extern Datum has_sequence_privilege_id(PG_FUNCTION_ARGS); extern Datum has_database_privilege_name_name(PG_FUNCTION_ARGS); extern Datum has_database_privilege_name_id(PG_FUNCTION_ARGS); extern Datum has_database_privilege_id_name(PG_FUNCTION_ARGS); Index: src/test/regress/expected/privileges.out =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/expected/privileges.out,v retrieving revision 1.46 diff -c -r1.46 privileges.out *** src/test/regress/expected/privileges.out 5 Mar 2009 17:30:29 -0000 1.46 --- src/test/regress/expected/privileges.out 3 Aug 2009 21:10:25 -0000 *************** *** 815,822 **** --- 815,844 ---- t (1 row) + -- has_sequence_privilege tests + \c - + CREATE SEQUENCE x_seq; + GRANT USAGE on x_seq to regressuser2; + SELECT has_sequence_privilege('regressuser1', 'atest1', 'SELECT'); + ERROR: "atest1" is not a sequence + SELECT has_sequence_privilege('regressuser1', 'x_seq', 'INSERT'); + ERROR: unrecognized privilege type: "INSERT" + SELECT has_sequence_privilege('regressuser1', 'x_seq', 'SELECT'); + has_sequence_privilege + ------------------------ + f + (1 row) + + SET SESSION AUTHORIZATION regressuser2; + SELECT has_sequence_privilege('x_seq', 'USAGE'); + has_sequence_privilege + ------------------------ + t + (1 row) + -- clean up \c + drop sequence x_seq; DROP FUNCTION testfunc2(int); DROP FUNCTION testfunc4(boolean); DROP VIEW atestv1; Index: src/test/regress/sql/privileges.sql =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/sql/privileges.sql,v retrieving revision 1.25 diff -c -r1.25 privileges.sql *** src/test/regress/sql/privileges.sql 5 Mar 2009 17:30:29 -0000 1.25 --- src/test/regress/sql/privileges.sql 3 Aug 2009 21:10:25 -0000 *************** *** 469,478 **** --- 469,495 ---- SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true + -- has_sequence_privilege tests + \c - + + CREATE SEQUENCE x_seq; + + GRANT USAGE on x_seq to regressuser2; + + SELECT has_sequence_privilege('regressuser1', 'atest1', 'SELECT'); + SELECT has_sequence_privilege('regressuser1', 'x_seq', 'INSERT'); + SELECT has_sequence_privilege('regressuser1', 'x_seq', 'SELECT'); + + SET SESSION AUTHORIZATION regressuser2; + + SELECT has_sequence_privilege('x_seq', 'USAGE'); + -- clean up \c + drop sequence x_seq; + DROP FUNCTION testfunc2(int); DROP FUNCTION testfunc4(boolean);
pgsql-hackers by date: