From: Tom Lane Date: Thu, 14 Jun 2001 01:09:22 +0000 (+0000) Subject: has_table_privilege functions from Joe Conway (with some kibitzing from X-Git-Tag: REL7_2_BETA1~1036 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c9499e68daa5860368300f744337460e43f93865;p=postgresql has_table_privilege functions from Joe Conway (with some kibitzing from Tom Lane). For the moment, only the OID/name variants are provided. I didn't force initdb, but the additions to the 'privileges' regress test won't pass until you do one. --- diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 2a56a6573a..6a2bd7dc93 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.133 2001/06/12 05:55:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.134 2001/06/14 01:09:22 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -19,40 +19,36 @@ */ #include "postgres.h" +#include "access/genam.h" #include "access/tuptoaster.h" #include "catalog/catalog.h" #include "catalog/catname.h" +#include "catalog/heap.h" #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/pg_attrdef.h" +#include "catalog/pg_index.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_rewrite.h" +#include "catalog/pg_type.h" #include "commands/command.h" -#include "executor/spi.h" -#include "catalog/heap.h" +#include "commands/trigger.h" +#include "executor/execdefs.h" +#include "executor/executor.h" #include "miscadmin.h" +#include "optimizer/clauses.h" +#include "optimizer/planmain.h" #include "optimizer/prep.h" -#include "utils/acl.h" -#include "utils/fmgroids.h" -#include "commands/trigger.h" - +#include "parser/parse.h" #include "parser/parse_expr.h" -#include "parser/parse_clause.h" -#include "parser/parse_relation.h" #include "parser/parse_oper.h" -#include "nodes/makefuncs.h" -#include "optimizer/planmain.h" -#include "optimizer/clauses.h" -#include "rewrite/rewriteSupport.h" -#include "commands/view.h" -#include "utils/temprel.h" -#include "executor/spi_priv.h" -#include "catalog/pg_index.h" -#include "catalog/pg_shadow.h" +#include "parser/parse_relation.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" #include "utils/relcache.h" - -#include "parser/parse.h" -#include "access/genam.h" +#include "utils/temprel.h" static void drop_default(Oid relid, int16 attnum); @@ -1689,13 +1685,7 @@ AlterTableOwner(const char *relationName, const char *newOwnerName) /* * look up the new owner in pg_shadow and get the sysid */ - tuple = SearchSysCache(SHADOWNAME, - PointerGetDatum(newOwnerName), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "ALTER TABLE: user \"%s\" not found", newOwnerName); - newOwnerSysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; - ReleaseSysCache(tuple); + newOwnerSysid = get_usesysid(newOwnerName); /* * find the table's entry in pg_class and make a modifiable copy diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 74990ce1b9..3d003616c0 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.76 2001/06/12 05:55:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.77 2001/06/14 01:09:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -728,16 +729,9 @@ CreateGroup(CreateGroupStmt *stmt) const char *groupuser = strVal(lfirst(item)); Value *v; - tuple = SearchSysCache(SHADOWNAME, - PointerGetDatum(groupuser), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "CREATE GROUP: user \"%s\" does not exist", groupuser); - - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + v = makeInteger(get_usesysid(groupuser)); if (!member(v, newlist)) newlist = lcons(v, newlist); - ReleaseSysCache(tuple); } /* build an array to insert */ @@ -879,18 +873,10 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (strcmp(tag, "ALTER GROUP") == 0) { /* Get the uid of the proposed user to add. */ - tuple = SearchSysCache(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "%s: user \"%s\" does not exist", - tag, strVal(lfirst(item))); - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); - ReleaseSysCache(tuple); + v = makeInteger(get_usesysid(strVal(lfirst(item)))); } else if (strcmp(tag, "CREATE USER") == 0) { - /* * in this case we already know the uid and it wouldn't be * in the cache anyway yet @@ -906,12 +892,12 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (!member(v, newlist)) newlist = lcons(v, newlist); else - /* * we silently assume here that this error will only come * up in a ALTER GROUP statement */ - elog(NOTICE, "%s: user \"%s\" is already in group \"%s\"", tag, strVal(lfirst(item)), stmt->name); + elog(NOTICE, "%s: user \"%s\" is already in group \"%s\"", + tag, strVal(lfirst(item)), stmt->name); } newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); @@ -1001,13 +987,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (!is_dropuser) { /* Get the uid of the proposed user to drop. */ - tuple = SearchSysCache(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item))); - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); - ReleaseSysCache(tuple); + v = makeInteger(get_usesysid(strVal(lfirst(item)))); } else { diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 9b150d387f..4a21630b06 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.63 2001/06/12 16:34:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.64 2001/06/14 01:09:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,14 +25,25 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/memutils.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" + +#define ACL_IDTYPE_GID_KEYWORD "group" +#define ACL_IDTYPE_UID_KEYWORD "user" + static const char *getid(const char *s, char *n); static bool aclitemeq(const AclItem *a1, const AclItem *a2); static bool aclitemgt(const AclItem *a1, const AclItem *a2); -#define ACL_IDTYPE_GID_KEYWORD "group" -#define ACL_IDTYPE_UID_KEYWORD "user" +static AclMode convert_priv_string(text *priv_type_text); +static bool has_table_privilege_cname_cname(char *username, char *relname, + text *priv_type_text); +static bool has_table_privilege_cname_id(char *username, Oid reloid, + text *priv_type_text); +static bool has_table_privilege_id_cname(int32 usesysid, char *relname, + text *priv_type_text); + /* * getid @@ -106,7 +117,6 @@ getid(const char *s, char *n) const char * aclparse(const char *s, AclItem *aip, unsigned *modechg) { - HeapTuple htup; char name[NAMEDATALEN]; Assert(s && aip && modechg); @@ -183,13 +193,7 @@ aclparse(const char *s, AclItem *aip, unsigned *modechg) switch (aip->ai_idtype) { case ACL_IDTYPE_UID: - htup = SearchSysCache(SHADOWNAME, - PointerGetDatum(name), - 0, 0, 0); - if (!HeapTupleIsValid(htup)) - elog(ERROR, "aclparse: non-existent user \"%s\"", name); - aip->ai_id = ((Form_pg_shadow) GETSTRUCT(htup))->usesysid; - ReleaseSysCache(htup); + aip->ai_id = get_usesysid(name); break; case ACL_IDTYPE_GID: aip->ai_id = get_grosysid(name); @@ -710,3 +714,367 @@ makeAclString(const char *privileges, const char *grantee, char grant_or_revoke) pfree(str.data); return ret; } + + +/* + * has_table_privilege_name_name + * Check user privileges on a relation given + * name usename, name relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name_name(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Name relname = PG_GETARG_NAME(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + bool result; + + result = has_table_privilege_cname_cname(NameStr(*username), + NameStr(*relname), + priv_type_text); + + PG_RETURN_BOOL(result); +} + + +/* + * has_table_privilege_name + * Check user privileges on a relation given + * name relname and text priv name. + * current_user is assumed + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name(PG_FUNCTION_ARGS) +{ + Name relname = PG_GETARG_NAME(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + int32 usesysid; + bool result; + + usesysid = GetUserId(); + + result = has_table_privilege_id_cname(usesysid, + NameStr(*relname), + priv_type_text); + + PG_RETURN_BOOL(result); +} + + +/* + * has_table_privilege_name_id + * Check user privileges on a relation given + * name usename, rel oid, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name_id(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Oid reloid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + bool result; + + result = has_table_privilege_cname_id(NameStr(*username), + reloid, + priv_type_text); + + PG_RETURN_BOOL(result); +} + + +/* + * has_table_privilege_id + * Check user privileges on a relation given + * rel oid, and text priv name. + * current_user is assumed + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id(PG_FUNCTION_ARGS) +{ + Oid reloid = PG_GETARG_OID(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + char *relname; + int32 usesysid; + AclMode mode; + int32 result; + + usesysid = GetUserId(); + + /* + * Lookup relname based on rel oid + */ + relname = get_rel_name(reloid); + if (relname == NULL) + elog(ERROR, "has_table_privilege: invalid relation oid %u", + reloid); + + /* + * Convert priv_type_text to an AclMode + */ + mode = convert_priv_string(priv_type_text); + + /* + * Finally, check for the privilege + */ + result = pg_aclcheck(relname, usesysid, mode); + + if (result == ACLCHECK_OK) + PG_RETURN_BOOL(true); + else + PG_RETURN_BOOL(false); +} + + +/* + * has_table_privilege_id_name + * Check user privileges on a relation given + * usesysid, name relname, and priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id_name(PG_FUNCTION_ARGS) +{ + int32 usesysid = PG_GETARG_INT32(0); + Name relname = PG_GETARG_NAME(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + bool result; + + result = has_table_privilege_id_cname(usesysid, + NameStr(*relname), + priv_type_text); + + PG_RETURN_BOOL(result); +} + + +/* + * has_table_privilege_id_id + * Check user privileges on a relation given + * usesysid, rel oid, and priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id_id(PG_FUNCTION_ARGS) +{ + int32 usesysid = PG_GETARG_INT32(0); + Oid reloid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + char *relname; + AclMode mode; + int32 result; + + /* + * Lookup relname based on rel oid + */ + relname = get_rel_name(reloid); + if (relname == NULL) + elog(ERROR, "has_table_privilege: invalid relation oid %u", + reloid); + + /* + * Convert priv_type_text to an AclMode + */ + mode = convert_priv_string(priv_type_text); + + /* + * Finally, check for the privilege + */ + result = pg_aclcheck(relname, usesysid, mode); + + if (result == ACLCHECK_OK) + PG_RETURN_BOOL(true); + else + PG_RETURN_BOOL(false); +} + +/* + * Internal functions. + */ + +/* + * convert_priv_string + * Internal function. + * Return mode from priv_type string + * + * RETURNS + * AclMode + */ + +static AclMode +convert_priv_string(text *priv_type_text) +{ + char *priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text))); + + /* + * Return mode from priv_type string + */ + if (strcasecmp(priv_type, "SELECT") == 0) + return ACL_SELECT; + + if (strcasecmp(priv_type, "INSERT") == 0) + return ACL_INSERT; + + if (strcasecmp(priv_type, "UPDATE") == 0) + return ACL_UPDATE; + + if (strcasecmp(priv_type, "DELETE") == 0) + return ACL_DELETE; + + if (strcasecmp(priv_type, "RULE") == 0) + return ACL_RULE; + + if (strcasecmp(priv_type, "REFERENCES") == 0) + return ACL_REFERENCES; + + if (strcasecmp(priv_type, "TRIGGER") == 0) + return ACL_TRIGGER; + + elog(ERROR, "has_table_privilege: invalid privilege type %s", priv_type); + /* + * We should never get here, but stop the compiler from complaining + */ + return ACL_NO; +} + +/* + * has_table_privilege_cname_cname + * Check user privileges on a relation given + * char *usename, char *relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +static bool +has_table_privilege_cname_cname(char *username, char *relname, + text *priv_type_text) +{ + int32 usesysid; + + /* + * Lookup userid based on username + */ + usesysid = get_usesysid(username); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + return has_table_privilege_id_cname(usesysid, relname, priv_type_text); +} + + +/* + * has_table_privilege_cname_id + * Check user privileges on a relation given + * char *usename, rel oid, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +static bool +has_table_privilege_cname_id(char *username, Oid reloid, + text *priv_type_text) +{ + int32 usesysid; + char *relname; + + /* + * Lookup userid based on username + */ + usesysid = get_usesysid(username); + + /* + * Lookup relname based on rel oid + */ + relname = get_rel_name(reloid); + if (relname == NULL) + elog(ERROR, "has_table_privilege: invalid relation oid %u", + reloid); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + return has_table_privilege_id_cname(usesysid, relname, priv_type_text); +} + + +/* + * has_table_privilege_id_cname + * Check user privileges on a relation given + * usesysid, char *relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +static bool +has_table_privilege_id_cname(int32 usesysid, char *relname, + text *priv_type_text) +{ + HeapTuple tuple; + AclMode mode; + int32 result; + + /* + * Check relname is valid. + * This is needed to deal with the case when usename is a superuser + * in which case pg_aclcheck simply returns ACLCHECK_OK + * without validating relname + */ + tuple = SearchSysCache(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "has_table_privilege: relation \"%s\" does not exist", + relname); + ReleaseSysCache(tuple); + + /* + * Convert priv_type_text to an AclMode + */ + mode = convert_priv_string(priv_type_text); + + /* + * Finally, check for the privilege + */ + result = pg_aclcheck(relname, usesysid, mode); + + if (result == ACLCHECK_OK) + return true; + else + return false; +} diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 573c21afd8..587213d48f 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.55 2001/05/09 23:13:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.56 2001/06/14 01:09:22 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -18,6 +18,7 @@ #include "access/tupmacs.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" +#include "catalog/pg_shadow.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "utils/array.h" @@ -25,6 +26,7 @@ #include "utils/lsyscache.h" #include "utils/syscache.h" + /* ---------- AMOP CACHES ---------- */ /* @@ -537,7 +539,7 @@ get_relnatts(Oid relid) * * Returns the name of a given relation. * - * Note: returns a palloc'd copy of the string, or NULL if no such operator. + * Note: returns a palloc'd copy of the string, or NULL if no such relation. */ char * get_rel_name(Oid relid) @@ -1039,3 +1041,35 @@ free_attstatsslot(Oid atttype, if (numbers) pfree(numbers); } + +/* ---------- PG_SHADOW CACHE ---------- */ + +/* + * get_usesysid + * + * Given a user name, look up the user's sysid. + * Raises an error if no such user (rather than returning zero, + * which might possibly be a valid usesysid). + * + * Note: the type of usesysid is currently int4, but may change to Oid + * someday. It'd be reasonable to return zero on failure if we were + * using Oid ... + */ +int32 +get_usesysid(const char *username) +{ + int32 result; + HeapTuple userTup; + + userTup = SearchSysCache(SHADOWNAME, + PointerGetDatum(username), + 0, 0, 0); + if (!HeapTupleIsValid(userTup)) + elog(ERROR, "user \"%s\" does not exist", username); + + result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid; + + ReleaseSysCache(userTup); + + return result; +} diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 58bf546889..df46469f00 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.70 2001/06/13 19:52:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.71 2001/06/14 01:09:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,6 +30,7 @@ #include "catalog/pg_shadow.h" #include "miscadmin.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -442,24 +443,20 @@ InitializeSessionUserId(const char *username) } - +/* + * Change session auth ID while running + */ void SetSessionAuthorization(const char * username) { - HeapTuple userTup; + int32 userid; if (!AuthenticatedUserIsSuperuser) elog(ERROR, "permission denied"); - userTup = SearchSysCache(SHADOWNAME, - PointerGetDatum(username), - 0, 0, 0); - if (!HeapTupleIsValid(userTup)) - elog(ERROR, "user \"%s\" does not exist", username); + userid = get_usesysid(username); - SetSessionUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid); - SetUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid); - - ReleaseSysCache(userTup); + SetSessionUserId(userid); + SetUserId(userid); } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 71b3b545f1..415f3b0372 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.193 2001/06/13 21:12:43 momjian Exp $ + * $Id: pg_proc.h,v 1.194 2001/06/14 01:09:22 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -2633,6 +2633,20 @@ DESCR("unary plus"); DATA(insert OID = 1915 ( numeric_uplus PGUID 12 f t t t 1 f 1700 "1700" 100 0 0 100 numeric_uplus - )); DESCR("unary plus"); +DATA(insert OID = 1922 ( has_table_privilege PGUID 12 f t f t 3 f 16 "19 19 25" 100 0 0 100 has_table_privilege_name_name - )); +DESCR("user privilege on relation by username, relname"); +DATA(insert OID = 1923 ( has_table_privilege PGUID 12 f t f t 3 f 16 "19 26 25" 100 0 0 100 has_table_privilege_name_id - )); +DESCR("user privilege on relation by username, rel oid"); +DATA(insert OID = 1924 ( has_table_privilege PGUID 12 f t f t 3 f 16 "23 19 25" 100 0 0 100 has_table_privilege_id_name - )); +DESCR("user privilege on relation by usesysid, relname"); +DATA(insert OID = 1925 ( has_table_privilege PGUID 12 f t f t 3 f 16 "23 26 25" 100 0 0 100 has_table_privilege_id_id - )); +DESCR("user privilege on relation by usesysid, rel oid"); +DATA(insert OID = 1926 ( has_table_privilege PGUID 12 f t f t 2 f 16 "19 25" 100 0 0 100 has_table_privilege_name - )); +DESCR("current user privilege on relation by relname"); +DATA(insert OID = 1927 ( has_table_privilege PGUID 12 f t f t 2 f 16 "26 25" 100 0 0 100 has_table_privilege_id - )); +DESCR("current user privilege on relation by rel oid"); + + /* * prototypes for functions pg_proc.c */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index d739fd83d8..7ffde98abf 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.153 2001/06/13 21:08:59 momjian Exp $ + * $Id: builtins.h,v 1.154 2001/06/14 01:09:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,15 @@ /* * Defined in adt/ */ + +/* acl.c */ +extern Datum has_table_privilege_name_name(PG_FUNCTION_ARGS); +extern Datum has_table_privilege_name_id(PG_FUNCTION_ARGS); +extern Datum has_table_privilege_id_name(PG_FUNCTION_ARGS); +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); + /* bool.c */ extern Datum boolin(PG_FUNCTION_ARGS); extern Datum boolout(PG_FUNCTION_ARGS); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 719f68a873..d418e8a10d 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.33 2001/05/09 23:13:37 tgl Exp $ + * $Id: lsyscache.h,v 1.34 2001/06/14 01:09:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,6 +51,7 @@ extern bool get_attstatsslot(HeapTuple statstuple, extern void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers); +extern int32 get_usesysid(const char *username); #define TypeIsToastable(typid) (get_typstorage(typid) != 'p') diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index ea19667a16..4ada312755 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -188,6 +188,274 @@ SELECT * FROM atestv3; -- ok -----+-----+------- (0 rows) +-- has_table_privilege function +-- bad-input checks +select has_table_privilege(NULL,'pg_shadow','select'); + has_table_privilege +--------------------- + +(1 row) + +select has_table_privilege('pg_shad','select'); +ERROR: has_table_privilege: relation "pg_shad" does not exist +select has_table_privilege('nosuchuser','pg_shadow','select'); +ERROR: user "nosuchuser" does not exist +select has_table_privilege('pg_shadow','sel'); +ERROR: has_table_privilege: invalid privilege type sel +select has_table_privilege(-999999,'pg_shadow','update'); +ERROR: pg_aclcheck: invalid user id 4293967297 +select has_table_privilege(1,'rule'); +ERROR: has_table_privilege: invalid relation oid 1 +-- superuser +\c regression +select has_table_privilege(current_user,'pg_shadow','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'pg_shadow','insert'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,'pg_shadow','update') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,'pg_shadow','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_shadow') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_shadow') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege('pg_shadow','update'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege('pg_shadow','delete'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + has_table_privilege +--------------------- + t +(1 row) + +-- non-superuser +SET SESSION AUTHORIZATION regressuser3; +select has_table_privilege(current_user,'pg_class','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'pg_class','insert'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,'pg_class','update') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,'pg_class','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('pg_class','update'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('pg_class','delete'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,'atest1','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'atest1','insert'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,'atest1','update') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,'atest1','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'atest1') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('atest1','update'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('atest1','delete'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + f +(1 row) + -- clean up \c regression DROP TABLE atest1; diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 2a09666083..95e7b604d3 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -126,6 +126,106 @@ SELECT * FROM atestv1; -- ok SELECT * FROM atestv3; -- ok +-- has_table_privilege function + +-- bad-input checks +select has_table_privilege(NULL,'pg_shadow','select'); +select has_table_privilege('pg_shad','select'); +select has_table_privilege('nosuchuser','pg_shadow','select'); +select has_table_privilege('pg_shadow','sel'); +select has_table_privilege(-999999,'pg_shadow','update'); +select has_table_privilege(1,'rule'); + +-- superuser +\c regression +select has_table_privilege(current_user,'pg_shadow','select'); +select has_table_privilege(current_user,'pg_shadow','insert'); + +select has_table_privilege(t2.usesysid,'pg_shadow','update') +from (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,'pg_shadow','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'pg_shadow') as t1; +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_shadow') as t1, + (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_shadow') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege('pg_shadow','update'); +select has_table_privilege('pg_shadow','delete'); + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_shadow') as t1; +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_shadow') as t1; + +-- non-superuser +SET SESSION AUTHORIZATION regressuser3; + +select has_table_privilege(current_user,'pg_class','select'); +select has_table_privilege(current_user,'pg_class','insert'); + +select has_table_privilege(t2.usesysid,'pg_class','update') +from (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,'pg_class','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'pg_class') as t1; +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_class') as t1; + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege('pg_class','update'); +select has_table_privilege('pg_class','delete'); + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1; +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_class') as t1; + +select has_table_privilege(current_user,'atest1','select'); +select has_table_privilege(current_user,'atest1','insert'); + +select has_table_privilege(t2.usesysid,'atest1','update') +from (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,'atest1','delete') +from (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'atest1') as t1; +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'atest1') as t1; + +select has_table_privilege(t2.usesysid,t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1, + (select usesysid from pg_user where usename = current_user) as t2; +select has_table_privilege(t2.usesysid,t1.oid,'insert') +from (select oid from pg_class where relname = 'atest1') as t1, + (select usesysid from pg_user where usename = current_user) as t2; + +select has_table_privilege('atest1','update'); +select has_table_privilege('atest1','delete'); + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1; +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'atest1') as t1; + + -- clean up \c regression