From 82a2881c5b230d62bc811a374503625226be02ae Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sun, 30 Apr 2006 21:15:33 +0000 Subject: [PATCH] Code review for GRANT CONNECT patch. Spell the privilege as CONNECT not CONNECTION, fix a number of places that were missed (eg pg_dump support), avoid executing an extra search of pg_database during startup. --- doc/src/sgml/client-auth.sgml | 15 +++++-- doc/src/sgml/ddl.sgml | 7 +-- doc/src/sgml/func.sgml | 3 +- doc/src/sgml/ref/grant.sgml | 18 ++++---- doc/src/sgml/ref/revoke.sgml | 4 +- doc/src/sgml/user-manag.sgml | 8 ++-- src/backend/catalog/aclchk.c | 42 ++++++++++++------ src/backend/utils/adt/acl.c | 12 ++++- src/backend/utils/init/postinit.c | 74 +++++++++++++++---------------- src/bin/pg_dump/dumputils.c | 3 +- src/bin/psql/tab-complete.c | 5 ++- src/include/utils/acl.h | 8 +++- 12 files changed, 118 insertions(+), 81 deletions(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 2185eebeb05..22fe521bfb0 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.88 2006/04/30 02:09:06 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.89 2006/04/30 21:15:32 tgl Exp $ --> <chapter id="client-authentication"> <title>Client Authentication</title> @@ -206,8 +206,6 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> Multiple user names can be supplied by separating them with commas. A separate file containing user names can be specified by preceding the file name with <literal>@</>. - User and group connectivity can also be restricted by <command>GRANT - CONNECTION ON DATABASE</>. </para> </listitem> </varlistentry> @@ -436,6 +434,17 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> re-read the file. </para> + <tip> + <para> + To connect to a particular database, a user must not only pass the + <filename>pg_hba.conf</filename> checks, but must have the + <literal>CONNECT</> privilege for the database. If you wish to + restrict which users can connect to which databases, it's usually + easier to control this by granting/revoking <literal>CONNECT</> privilege + than to put the rules into <filename>pg_hba.conf</filename> entries. + </para> + </tip> + <para> Some examples of <filename>pg_hba.conf</filename> entries are shown in <xref linkend="example-pg-hba.conf">. See the next section for details on the diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 77bc1dd4970..a6fb4b3691f 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.56 2006/04/23 03:39:50 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.57 2006/04/30 21:15:32 tgl Exp $ --> <chapter id="ddl"> <title>Data Definition</title> @@ -1343,8 +1343,9 @@ ALTER TABLE products RENAME TO items; There are several different privileges: <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>, <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>, - <literal>CREATE</>, <literal>TEMPORARY</>, <literal>EXECUTE</>, and - <literal>USAGE</>. The privileges applicable to a particular + <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>, + <literal>EXECUTE</>, and <literal>USAGE</>. + The privileges applicable to a particular object vary depending on the object's type (table, function, etc). For complete information on the different types of privileges supported by <productname>PostgreSQL</productname>, refer to the diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index b53bdca6fc3..1c6738b8cb4 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.315 2006/04/25 00:25:15 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.316 2006/04/30 21:15:32 tgl Exp $ --> <chapter id="functions"> <title>Functions and Operators</title> @@ -9227,6 +9227,7 @@ SELECT has_table_privilege('myschema.mytable', 'select'); arguments are analogous to <function>has_table_privilege</function>. The desired access privilege type must evaluate to <literal>CREATE</literal>, + <literal>CONNECT</literal>, <literal>TEMPORARY</literal>, or <literal>TEMP</literal> (which is equivalent to <literal>TEMPORARY</literal>). diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index 03060f97212..c6073dc35e4 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.53 2006/04/30 02:09:06 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.54 2006/04/30 21:15:33 tgl Exp $ PostgreSQL documentation --> @@ -30,7 +30,7 @@ GRANT { { USAGE | SELECT | UPDATE } ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...] TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ] -GRANT { { CREATE | TEMPORARY | TEMP | CONNECTION } [,...] | ALL [ PRIVILEGES ] } +GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>dbname</replaceable> [, ...] TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ] @@ -118,7 +118,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] Depending on the type of object, the initial default privileges may include granting some privileges to <literal>PUBLIC</literal>. The default is no public access for tables, schemas, and tablespaces; - <literal>TEMP</> table creation privilege for databases; + <literal>CONNECT</> privilege and <literal>TEMP</> table creation privilege + for databases; <literal>EXECUTE</> privilege for functions; and <literal>USAGE</> privilege for languages. The object owner may of course revoke these privileges. (For maximum @@ -230,13 +231,12 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] </varlistentry> <varlistentry> - <term>CONNECTION</term> + <term>CONNECT</term> <listitem> <para> - Allows the ability to connect to the specified database. - By default, Grant permissions allow users to connect to any database, - though <filename>pg_hba.conf</> can add additional connection - restrictions. + Allows the user to connect to the specified database. This + privilege is checked at connection startup (in addition to checking + any restrictions imposed by <filename>pg_hba.conf</>). </para> </listitem> </varlistentry> @@ -429,7 +429,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] X -- EXECUTE U -- USAGE C -- CREATE - c -- CONNECTION + c -- CONNECT T -- TEMPORARY arwdRxt -- ALL PRIVILEGES (for tables) * -- grant option for preceding privilege diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index 034b946111c..bccb8010b5f 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.37 2006/04/30 02:09:06 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.38 2006/04/30 21:15:33 tgl Exp $ PostgreSQL documentation --> @@ -35,7 +35,7 @@ REVOKE [ GRANT OPTION FOR ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] - { { CREATE | TEMPORARY | TEMP | CONNECTION } [,...] | ALL [ PRIVILEGES ] } + { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>dbname</replaceable> [, ...] FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index d05a9d3b047..41e60200919 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.34 2006/03/10 19:10:49 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.35 2006/04/30 21:15:32 tgl Exp $ --> <chapter id="user-manag"> <title>Database Roles and Privileges</title> @@ -294,9 +294,9 @@ ALTER ROLE myname SET enable_indexscan TO off; There are several different kinds of privilege: <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>, <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>, - <literal>CREATE</>, <literal>TEMPORARY</>, <literal>EXECUTE</>, - and <literal>USAGE</>. For more - information on the different types of privileges supported by + <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>, + <literal>EXECUTE</>, and <literal>USAGE</>. + For more information on the different types of privileges supported by <productname>PostgreSQL</productname>, see the <xref linkend="sql-grant" endterm="sql-grant-title"> reference page. </para> diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 3b9701db077..a74c28e5b3d 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.126 2006/04/30 02:09:07 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $ * * NOTES * See acl.h. @@ -1368,7 +1368,7 @@ string_to_privilege(const char *privname) return ACL_CREATE_TEMP; if (strcmp(privname, "temp") == 0) return ACL_CREATE_TEMP; - if (strcmp(privname, "connection") == 0) + if (strcmp(privname, "connect") == 0) return ACL_CONNECT; ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -1404,7 +1404,7 @@ privilege_to_string(AclMode privilege) case ACL_CREATE_TEMP: return "TEMP"; case ACL_CONNECT: - return "CONNECTION"; + return "CONNECT"; default: elog(ERROR, "unrecognized privilege: %d", (int) privilege); } @@ -1661,10 +1661,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid, ScanKeyData entry[1]; SysScanDesc scan; HeapTuple tuple; - Datum aclDatum; - bool isNull; - Acl *acl; - Oid ownerId; /* Superusers bypass all permission checking. */ if (superuser_arg(roleid)) @@ -1688,10 +1684,33 @@ pg_database_aclmask(Oid db_oid, Oid roleid, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database with OID %u does not exist", db_oid))); - ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba; + result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database), + roleid, mask, how); + + systable_endscan(scan); + heap_close(pg_database, AccessShareLock); + + return result; +} + +/* + * This is split out so that ReverifyMyDatabase can perform an ACL check + * without a whole extra search of pg_database + */ +AclMode +pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc, + Oid roleid, AclMode mask, AclMaskHow how) +{ + AclMode result; + Datum aclDatum; + bool isNull; + Acl *acl; + Oid ownerId; + + ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba; - aclDatum = heap_getattr(tuple, Anum_pg_database_datacl, - RelationGetDescr(pg_database), &isNull); + aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl, + tupdesc, &isNull); if (isNull) { @@ -1711,9 +1730,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid, if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) pfree(acl); - systable_endscan(scan); - heap_close(pg_database, AccessShareLock); - return result; } diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 4f64104ad3d..0fa61196ea7 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.132 2006/04/30 02:09:07 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.133 2006/04/30 21:15:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -553,7 +553,8 @@ acldefault(GrantObjectType objtype, Oid ownerId) owner_default = ACL_ALL_RIGHTS_SEQUENCE; break; case ACL_OBJECT_DATABASE: - world_default = ACL_CREATE_TEMP | ACL_CONNECT; /* not NO_RIGHTS! */ + /* for backwards compatibility, grant some rights by default */ + world_default = ACL_CREATE_TEMP | ACL_CONNECT; owner_default = ACL_ALL_RIGHTS_DATABASE; break; case ACL_OBJECT_FUNCTION: @@ -1341,6 +1342,8 @@ convert_priv_string(text *priv_type_text) return ACL_CREATE_TEMP; if (pg_strcasecmp(priv_type, "TEMPORARY") == 0) return ACL_CREATE_TEMP; + if (pg_strcasecmp(priv_type, "CONNECT") == 0) + return ACL_CONNECT; ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -1778,6 +1781,11 @@ convert_database_priv_string(text *priv_type_text) if (pg_strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP); + if (pg_strcasecmp(priv_type, "CONNECT") == 0) + return ACL_CONNECT; + if (pg_strcasecmp(priv_type, "CONNECT WITH GRANT OPTION") == 0) + return ACL_GRANT_OPTION_FOR(ACL_CONNECT); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized privilege type: \"%s\"", priv_type))); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 63135d2d1e3..e89df5bb3af 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.163 2006/04/30 02:09:07 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.164 2006/04/30 21:15:33 tgl Exp $ * * *------------------------------------------------------------------------- @@ -51,7 +51,7 @@ static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace); -static void ReverifyMyDatabase(const char *name, const char *user_name); +static void ReverifyMyDatabase(const char *name, bool am_superuser); static void InitCommunication(void); static void ShutdownPostgres(int code, Datum arg); static bool ThereIsAtLeastOneRole(void); @@ -127,12 +127,11 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace) * of pg_database. * * To avoid having to read pg_database more times than necessary - * during session startup, this place is also fitting to set up any - * database-specific configuration variables. + * during session startup, this place is also fitting to check CONNECT + * privilege and set up any database-specific configuration variables. */ - static void -ReverifyMyDatabase(const char *name, const char *user_name) +ReverifyMyDatabase(const char *name, bool am_superuser) { Relation pgdbrel; SysScanDesc pgdbscan; @@ -195,6 +194,22 @@ ReverifyMyDatabase(const char *name, const char *user_name) errmsg("database \"%s\" is not currently accepting connections", name))); + /* + * Check privilege to connect to the database. To avoid making + * a whole extra search of pg_database here, we don't go through + * pg_database_aclcheck, but instead use a lower-level routine + * that we can pass the pg_database tuple to. + */ + if (!am_superuser && + pg_database_tuple_aclmask(tup, RelationGetDescr(pgdbrel), + GetUserId(), + ACL_CONNECT, ACLMASK_ANY) == 0) + ereport(FATAL, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied for database %s", + NameStr(dbform->datname)), + errdetail("User does not have CONNECT privilege."))); + /* * Check connection limit for this database. * @@ -206,29 +221,12 @@ ReverifyMyDatabase(const char *name, const char *user_name) * just document that the connection limit is approximate. */ if (dbform->datconnlimit >= 0 && - !superuser() && + !am_superuser && CountDBBackends(MyDatabaseId) > dbform->datconnlimit) ereport(FATAL, (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("too many connections for database \"%s\"", name))); - - /* - * Checking for privilege to connect to the database - * We want to bypass the test if we are running in bootstrap mode - */ - if (!IsBootstrapProcessingMode()) - { - if(pg_database_aclcheck(MyDatabaseId,GetUserId() - ,ACL_CONNECT) != ACLCHECK_OK ) - { - ereport(FATAL, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("couldn't connect to database %s", NameStr(dbform->datname)), - errdetail("User %s doesn't have the CONNECTION privilege for database %s.", - user_name, NameStr(dbform->datname)))); - } - } } /* @@ -476,15 +474,20 @@ InitPostgres(const char *dbname, const char *username) RelationCacheInitializePhase2(); /* - * Figure out our postgres user id. In standalone mode and in the - * autovacuum process, we use a fixed id, otherwise we figure it out from - * the authenticated user name. + * Figure out our postgres user id, and see if we are a superuser. + * + * In standalone mode and in the autovacuum process, we use a fixed id, + * otherwise we figure it out from the authenticated user name. */ if (bootstrap || autovacuum) + { InitializeSessionUserIdStandalone(); + am_superuser = true; + } else if (!IsUnderPostmaster) { InitializeSessionUserIdStandalone(); + am_superuser = true; if (!ThereIsAtLeastOneRole()) ereport(WARNING, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -496,8 +499,12 @@ InitPostgres(const char *dbname, const char *username) { /* normal multiuser case */ InitializeSessionUserId(username); + am_superuser = superuser(); } + /* set up ACL framework (so ReverifyMyDatabase can check permissions) */ + initialize_acl(); + /* * Unless we are bootstrapping, double-check that InitMyDatabaseInfo() got * a correct result. We can't do this until all the database-access @@ -505,7 +512,7 @@ InitPostgres(const char *dbname, const char *username) * superuser, so the above stuff has to happen first.) */ if (!bootstrap) - ReverifyMyDatabase(dbname,username); + ReverifyMyDatabase(dbname, am_superuser); /* * Final phase of relation cache startup: write a new cache file if @@ -514,14 +521,6 @@ InitPostgres(const char *dbname, const char *username) */ RelationCacheInitializePhase3(); - /* - * Check if user is a superuser. - */ - if (bootstrap || autovacuum) - am_superuser = true; - else - am_superuser = superuser(); - /* * Check a normal user hasn't connected to a superuser reserved slot. */ @@ -540,9 +539,6 @@ InitPostgres(const char *dbname, const char *username) /* set default namespace search path */ InitializeSearchPath(); - /* set up ACL framework (currently just sets RolMemCache callback) */ - initialize_acl(); - /* initialize client encoding */ InitializeClientEncoding(); diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 77e6d43fe02..86c930b8add 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.26 2006/03/05 15:58:50 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.27 2006/04/30 21:15:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -605,6 +605,7 @@ do { \ else if (strcmp(type, "DATABASE") == 0) { CONVERT_PRIV('C', "CREATE"); + CONVERT_PRIV('c', "CONNECT"); CONVERT_PRIV('T', "TEMPORARY"); } else if (strcmp(type, "TABLESPACE") == 0) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index a90d7eb72cf..ad8f0f841b2 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.150 2006/04/02 09:02:41 alvherre Exp $ + * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.151 2006/04/30 21:15:33 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -1373,7 +1373,8 @@ psql_completion(char *text, int start, int end) { static const char *const list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", - "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL}; + "TRIGGER", "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE", + "ALL", NULL}; COMPLETE_WITH_LIST(list_privileg); } diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index c329b6aab81..7651fba290c 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.94 2006/04/30 02:09:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.95 2006/04/30 21:15:33 tgl Exp $ * * NOTES * An ACL array is simply an array of AclItems, representing the union @@ -24,6 +24,8 @@ #ifndef ACL_H #define ACL_H +#include "access/htup.h" +#include "access/tupdesc.h" #include "nodes/parsenodes.h" #include "utils/array.h" @@ -145,7 +147,7 @@ typedef ArrayType Acl; */ #define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER) #define ACL_ALL_RIGHTS_SEQUENCE (ACL_USAGE|ACL_SELECT|ACL_UPDATE) -#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT ) +#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT) #define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE) #define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE) #define ACL_ALL_RIGHTS_NAMESPACE (ACL_USAGE|ACL_CREATE) @@ -250,6 +252,8 @@ extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how); +extern AclMode pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc, + Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, -- GitLab