Create a separate grantable privilege for TRUNCATE, rather than having it be

always owner-only.  The TRUNCATE privilege works identically to the DELETE
privilege so far as interactions with the rest of the system go.

Robert Haas
This commit is contained in:
Tom Lane 2008-09-08 00:47:41 +00:00
parent a26c7e3d71
commit a0b76dc662
22 changed files with 153 additions and 65 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.82 2008/05/09 23:32:03 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.83 2008/09/08 00:47:40 tgl Exp $ -->
<chapter id="ddl">
<title>Data Definition</title>
@ -1356,7 +1356,7 @@ ALTER TABLE products RENAME TO items;
<para>
There are several different privileges: <literal>SELECT</>,
<literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
<literal>REFERENCES</>, <literal>TRIGGER</>,
<literal>TRUNCATE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
<literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
<literal>EXECUTE</>, and <literal>USAGE</>.
The privileges applicable to a particular

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.445 2008/09/07 01:29:36 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.446 2008/09/08 00:47:40 tgl Exp $ -->
<chapter id="functions">
<title>Functions and Operators</title>
@ -11369,7 +11369,7 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
The desired access privilege type
is specified by a text string, which must evaluate to one of the
values <literal>SELECT</literal>, <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>DELETE</literal>,
<literal>UPDATE</literal>, <literal>DELETE</literal>, <literal>TRUNCATE</>,
<literal>REFERENCES</literal>, or <literal>TRIGGER</literal>.
(Case of the string is not significant, however.)
An example is:

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.33 2007/02/20 23:14:19 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.34 2008/09/08 00:47:40 tgl Exp $ -->
<chapter id="information-schema">
<title>The Information Schema</title>
@ -2820,9 +2820,9 @@ ORDER BY c.ordinal_position;
<entry><type>character_data</type></entry>
<entry>
Type of the privilege: <literal>SELECT</literal>,
<literal>DELETE</literal>, <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>REFERENCES</literal>,
or <literal>TRIGGER</literal>
<literal>INSERT</literal>, <literal>UPDATE</literal>,
<literal>DELETE</literal>, <literal>TRUNCATE</literal>,
<literal>REFERENCES</literal>, or <literal>TRIGGER</literal>
</entry>
</row>
@ -4406,9 +4406,9 @@ ORDER BY c.ordinal_position;
<entry><type>character_data</type></entry>
<entry>
Type of the privilege: <literal>SELECT</literal>,
<literal>DELETE</literal>, <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>REFERENCES</literal>,
or <literal>TRIGGER</literal>
<literal>INSERT</literal>, <literal>UPDATE</literal>,
<literal>DELETE</literal>, <literal>TRUNCATE</literal>,
<literal>REFERENCES</literal>, or <literal>TRIGGER</literal>
</entry>
</row>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.70 2008/07/03 15:59:55 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.71 2008/09/08 00:47:40 tgl Exp $
PostgreSQL documentation
-->
@ -20,7 +20,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
GRANT { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
@ -192,6 +192,16 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
</listitem>
</varlistentry>
<varlistentry>
<term>TRUNCATE</term>
<listitem>
<para>
Allows <xref linkend="sql-truncate" endterm="sql-truncate-title"> on
the specified table.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>REFERENCES</term>
<listitem>
@ -421,8 +431,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
=&gt; \z mytable
Access privileges
Schema | Name | Type | Access privileges
--------+---------+-------+----------------------
public | mytable | table | miriam=arwdxt/miriam
--------+---------+-------+-----------------------
public | mytable | table | miriam=arwdDxt/miriam
: =r/miriam
: admin=arw/miriam
(1 row)
@ -436,6 +446,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
w -- UPDATE ("write")
a -- INSERT ("append")
d -- DELETE
D -- TRUNCATE
x -- REFERENCES
t -- TRIGGER
X -- EXECUTE
@ -443,7 +454,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
C -- CREATE
c -- CONNECT
T -- TEMPORARY
arwdxt -- ALL PRIVILEGES (for tables)
arwdDxt -- ALL PRIVILEGES (for tables)
* -- grant option for preceding privilege
/yyyy -- role that granted this privilege
@ -466,7 +477,7 @@ GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
object type, as explained above. The first <command>GRANT</> or
<command>REVOKE</> on an object
will instantiate the default privileges (producing, for example,
<literal>{miriam=arwdxt/miriam}</>) and then modify them per the
<literal>{miriam=arwdDxt/miriam}</>) and then modify them per the
specified request.
</para>
@ -524,7 +535,8 @@ GRANT admins TO joe;
<para>
<productname>PostgreSQL</productname> allows an object owner to revoke his
own ordinary privileges: for example, a table owner can make the table
read-only to himself by revoking his own INSERT, UPDATE, and DELETE
read-only to himself by revoking his own <literal>INSERT</>,
<literal>UPDATE</>, <literal>DELETE</>, and <literal>TRUNCATE</>
privileges. This is not possible according to the SQL standard. The
reason is that <productname>PostgreSQL</productname> treats the owner's
privileges as having been granted by the owner to himself; therefore he

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.48 2006/09/16 00:30:19 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.49 2008/09/08 00:47:40 tgl Exp $
PostgreSQL documentation
-->
@ -155,7 +155,8 @@ where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
<para>
<literal>LOCK TABLE ... IN ACCESS SHARE MODE</> requires <literal>SELECT</>
privileges on the target table. All other forms of <command>LOCK</>
require <literal>UPDATE</> and/or <literal>DELETE</> privileges.
require at least one of <literal>UPDATE</>, <literal>DELETE</>, or
<literal>TRUNCATE</> privileges.
</para>
<para>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.47 2008/03/03 19:17:27 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.48 2008/09/08 00:47:40 tgl Exp $
PostgreSQL documentation
-->
@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.27 2008/05/17 23:36:27 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.28 2008/09/08 00:47:40 tgl Exp $
PostgreSQL documentation
-->
@ -97,7 +97,8 @@ TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ... ]
<title>Notes</title>
<para>
Only the owner of a table can <command>TRUNCATE</> it.
You must have the <literal>TRUNCATE</literal> privilege on a table
to truncate it.
</para>
<para>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.39 2007/02/01 00:28:18 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.40 2008/09/08 00:47:40 tgl Exp $ -->
<chapter id="user-manag">
<title>Database Roles and Privileges</title>
@ -293,7 +293,7 @@ ALTER ROLE myname SET enable_indexscan TO off;
granted.
There are several different kinds of privilege: <literal>SELECT</>,
<literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
<literal>REFERENCES</>, <literal>TRIGGER</>,
<literal>TRUNCATE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
<literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
<literal>EXECUTE</>, and <literal>USAGE</>.
For more information on the different types of privileges supported by

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.147 2008/06/19 00:46:03 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.148 2008/09/08 00:47:40 tgl Exp $
*
* NOTES
* See acl.h.
@ -1331,6 +1331,8 @@ string_to_privilege(const char *privname)
return ACL_UPDATE;
if (strcmp(privname, "delete") == 0)
return ACL_DELETE;
if (strcmp(privname, "truncate") == 0)
return ACL_TRUNCATE;
if (strcmp(privname, "references") == 0)
return ACL_REFERENCES;
if (strcmp(privname, "trigger") == 0)
@ -1368,6 +1370,8 @@ privilege_to_string(AclMode privilege)
return "UPDATE";
case ACL_DELETE:
return "DELETE";
case ACL_TRUNCATE:
return "TRUNCATE";
case ACL_REFERENCES:
return "REFERENCES";
case ACL_TRIGGER:
@ -1582,7 +1586,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
* protected in this way. Assume the view rules can take care of
* themselves. ACL_USAGE is if we ever have system sequences.
*/
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE)) &&
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
IsSystemClass(classForm) &&
classForm->relkind != RELKIND_VIEW &&
!has_rolcatupdate(roleid) &&
@ -1591,7 +1595,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
#ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update");
#endif
mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE);
mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
}
/*

View File

@ -4,7 +4,7 @@
*
* Copyright (c) 2003-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.45 2008/07/18 03:32:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.46 2008/09/08 00:47:40 tgl Exp $
*/
/*
@ -1214,9 +1214,10 @@ CREATE VIEW role_table_grants AS
pg_authid u_grantor,
pg_authid g_grantee,
(SELECT 'SELECT' UNION ALL
SELECT 'DELETE' UNION ALL
SELECT 'INSERT' UNION ALL
SELECT 'UPDATE' UNION ALL
SELECT 'DELETE' UNION ALL
SELECT 'TRUNCATE' UNION ALL
SELECT 'REFERENCES' UNION ALL
SELECT 'TRIGGER') AS pr (type)
@ -1728,6 +1729,7 @@ CREATE VIEW table_constraints AS
OR has_table_privilege(r.oid, 'INSERT')
OR has_table_privilege(r.oid, 'UPDATE')
OR has_table_privilege(r.oid, 'DELETE')
OR has_table_privilege(r.oid, 'TRUNCATE')
OR has_table_privilege(r.oid, 'REFERENCES')
OR has_table_privilege(r.oid, 'TRIGGER') )
@ -1761,6 +1763,7 @@ CREATE VIEW table_constraints AS
OR has_table_privilege(r.oid, 'INSERT')
OR has_table_privilege(r.oid, 'UPDATE')
OR has_table_privilege(r.oid, 'DELETE')
OR has_table_privilege(r.oid, 'TRUNCATE')
OR has_table_privilege(r.oid, 'REFERENCES')
OR has_table_privilege(r.oid, 'TRIGGER') );
@ -1802,9 +1805,10 @@ CREATE VIEW table_privileges AS
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname),
(SELECT 'SELECT' UNION ALL
SELECT 'DELETE' UNION ALL
SELECT 'INSERT' UNION ALL
SELECT 'UPDATE' UNION ALL
SELECT 'DELETE' UNION ALL
SELECT 'TRUNCATE' UNION ALL
SELECT 'REFERENCES' UNION ALL
SELECT 'TRIGGER') AS pr (type)
@ -1861,6 +1865,7 @@ CREATE VIEW tables AS
OR has_table_privilege(c.oid, 'INSERT')
OR has_table_privilege(c.oid, 'UPDATE')
OR has_table_privilege(c.oid, 'DELETE')
OR has_table_privilege(c.oid, 'TRUNCATE')
OR has_table_privilege(c.oid, 'REFERENCES')
OR has_table_privilege(c.oid, 'TRIGGER') );
@ -1982,6 +1987,7 @@ CREATE VIEW triggers AS
OR has_table_privilege(c.oid, 'INSERT')
OR has_table_privilege(c.oid, 'UPDATE')
OR has_table_privilege(c.oid, 'DELETE')
OR has_table_privilege(c.oid, 'TRUNCATE')
OR has_table_privilege(c.oid, 'REFERENCES')
OR has_table_privilege(c.oid, 'TRIGGER') );
@ -2180,6 +2186,7 @@ CREATE VIEW views AS
OR has_table_privilege(c.oid, 'INSERT')
OR has_table_privilege(c.oid, 'UPDATE')
OR has_table_privilege(c.oid, 'DELETE')
OR has_table_privilege(c.oid, 'TRUNCATE')
OR has_table_privilege(c.oid, 'REFERENCES')
OR has_table_privilege(c.oid, 'TRIGGER') );

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.18 2008/06/19 00:46:04 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.19 2008/09/08 00:47:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -54,7 +54,7 @@ LockTableCommand(LockStmt *lockstmt)
ACL_SELECT);
else
aclresult = pg_class_aclcheck(reloid, GetUserId(),
ACL_UPDATE | ACL_DELETE);
ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.265 2008/09/01 20:42:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.266 2008/09/08 00:47:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -989,6 +989,8 @@ ExecuteTruncate(TruncateStmt *stmt)
static void
truncate_check_rel(Relation rel)
{
AclResult aclresult;
/* Only allow truncate on regular tables */
if (rel->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
@ -997,8 +999,10 @@ truncate_check_rel(Relation rel)
RelationGetRelationName(rel))));
/* Permissions checks */
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_TRUNCATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelation(rel))

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.140 2008/03/25 22:42:43 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.141 2008/09/08 00:47:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -265,6 +265,9 @@ aclparse(const char *s, AclItem *aip)
case ACL_DELETE_CHR:
read = ACL_DELETE;
break;
case ACL_TRUNCATE_CHR:
read = ACL_TRUNCATE;
break;
case ACL_REFERENCES_CHR:
read = ACL_REFERENCES;
break;
@ -1323,6 +1326,8 @@ convert_priv_string(text *priv_type_text)
return ACL_UPDATE;
if (pg_strcasecmp(priv_type, "DELETE") == 0)
return ACL_DELETE;
if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
return ACL_TRUNCATE;
if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
return ACL_REFERENCES;
if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
@ -1548,6 +1553,11 @@ convert_table_priv_string(text *priv_type_text)
if (pg_strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_DELETE);
if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
return ACL_TRUNCATE;
if (pg_strcasecmp(priv_type, "TRUNCATE WITH GRANT OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_TRUNCATE);
if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
return ACL_REFERENCES;
if (pg_strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.40 2008/01/01 19:45:55 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.41 2008/09/08 00:47:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -659,6 +659,8 @@ do { \
CONVERT_PRIV('x', "REFERENCES");
CONVERT_PRIV('t', "TRIGGER");
}
if (remoteVersion >= 80400)
CONVERT_PRIV('D', "TRUNCATE");
}
/* UPDATE */

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.171 2008/08/16 01:36:35 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.172 2008/09/08 00:47:40 tgl Exp $
*/
/*----------------------------------------------------------------------
@ -1610,9 +1610,9 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev_wd, "REVOKE") == 0)
{
static const char *const list_privileg[] =
{"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES",
"TRIGGER", "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE",
"ALL", NULL};
{"SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES",
"TRIGGER", "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE",
"ALL", NULL};
COMPLETE_WITH_LIST(list_privileg);
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.483 2008/09/06 00:01:24 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.484 2008/09/08 00:47:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200809051
#define CATALOG_VERSION_NO 200809071
#endif

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.374 2008/09/01 20:42:45 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.375 2008/09/08 00:47:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -63,7 +63,7 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */
#define ACL_SELECT (1<<1)
#define ACL_UPDATE (1<<2)
#define ACL_DELETE (1<<3)
/* #define ACL_RULE (1<<4) unused, available */
#define ACL_TRUNCATE (1<<4)
#define ACL_REFERENCES (1<<5)
#define ACL_TRIGGER (1<<6)
#define ACL_EXECUTE (1<<7) /* for functions */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.103 2008/01/01 19:45:59 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.104 2008/09/08 00:47:41 tgl Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
@ -128,6 +128,7 @@ typedef ArrayType Acl;
#define ACL_SELECT_CHR 'r' /* formerly known as "read" */
#define ACL_UPDATE_CHR 'w' /* formerly known as "write" */
#define ACL_DELETE_CHR 'd'
#define ACL_TRUNCATE_CHR 'D' /* super-delete, as it were */
#define ACL_REFERENCES_CHR 'x'
#define ACL_TRIGGER_CHR 't'
#define ACL_EXECUTE_CHR 'X'
@ -137,12 +138,12 @@ typedef ArrayType Acl;
#define ACL_CONNECT_CHR 'c'
/* string holding all privilege code chars, in order by bitmask position */
#define ACL_ALL_RIGHTS_STR "arwdRxtXUCTc"
#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTc"
/*
* Bitmasks defining "all rights" for each supported object type
*/
#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_REFERENCES|ACL_TRIGGER)
#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|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_FUNCTION (ACL_EXECUTE)

View File

@ -21,7 +21,7 @@ DETAIL: access to table deptest
REVOKE SELECT ON deptest FROM GROUP regression_group;
DROP GROUP regression_group;
-- can't drop the user if we revoke the privileges partially
REVOKE SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES ON deptest FROM regression_user;
REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regression_user;
DROP USER regression_user;
ERROR: role "regression_user" cannot be dropped because some objects depend on it
DETAIL: access to table deptest
@ -68,21 +68,21 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" fo
GRANT ALL ON deptest1 TO regression_user2;
RESET SESSION AUTHORIZATION;
\z deptest1
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+------------------------------------------------
public | deptest1 | table | regression_user0=arwdxt/regression_user0
: regression_user1=a*r*w*d*x*t*/regression_user0
: regression_user2=arwdxt/regression_user1
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+--------------------------------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0
: regression_user1=a*r*w*d*D*x*t*/regression_user0
: regression_user2=arwdDxt/regression_user1
(1 row)
DROP OWNED BY regression_user1;
-- all grants revoked
\z deptest1
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+------------------------------------------
public | deptest1 | table | regression_user0=arwdxt/regression_user0
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+-------------------------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0
(1 row)
-- table was dropped

View File

@ -10,14 +10,16 @@ DROP ROLE IF EXISTS regressuser1;
DROP ROLE IF EXISTS regressuser2;
DROP ROLE IF EXISTS regressuser3;
DROP ROLE IF EXISTS regressuser4;
DROP ROLE IF EXISTS regressuser5;
RESET client_min_messages;
-- test proper begins here
CREATE USER regressuser1;
CREATE USER regressuser2;
CREATE USER regressuser3;
CREATE USER regressuser4;
CREATE USER regressuser4; -- duplicate
ERROR: role "regressuser4" already exists
CREATE USER regressuser5;
CREATE USER regressuser5; -- duplicate
ERROR: role "regressuser5" already exists
CREATE GROUP regressgroup1;
CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
ALTER GROUP regressgroup1 ADD USER regressuser4;
@ -42,6 +44,7 @@ SELECT * FROM atest1;
INSERT INTO atest1 VALUES (1, 'one');
DELETE FROM atest1;
UPDATE atest1 SET a = 1 WHERE b = 'blech';
TRUNCATE atest1;
LOCK atest1 IN ACCESS EXCLUSIVE MODE;
REVOKE ALL ON atest1 FROM PUBLIC;
SELECT * FROM atest1;
@ -60,6 +63,7 @@ CREATE TABLE atest2 (col1 varchar(10), col2 boolean);
GRANT SELECT ON atest2 TO regressuser2;
GRANT UPDATE ON atest2 TO regressuser3;
GRANT INSERT ON atest2 TO regressuser4;
GRANT TRUNCATE ON atest2 TO regressuser5;
SET SESSION AUTHORIZATION regressuser2;
SELECT session_user, current_user;
session_user | current_user
@ -96,6 +100,8 @@ SELECT * FROM atest2 FOR UPDATE; -- fail
ERROR: permission denied for relation atest2
DELETE FROM atest2; -- fail
ERROR: permission denied for relation atest2
TRUNCATE atest2; -- fail
ERROR: permission denied for relation atest2
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
ERROR: permission denied for relation atest2
COPY atest2 FROM stdin; -- fail
@ -147,6 +153,8 @@ SELECT * FROM atest2 FOR UPDATE; -- fail
ERROR: permission denied for relation atest2
DELETE FROM atest2; -- fail
ERROR: permission denied for relation atest2
TRUNCATE atest2; -- fail
ERROR: permission denied for relation atest2
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
COPY atest2 FROM stdin; -- fail
ERROR: permission denied for relation atest2
@ -285,6 +293,11 @@ ERROR: must be owner of function testfunc1
DROP FUNCTION testfunc1(int); -- ok
-- restore to sanity
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
-- truncate
SET SESSION AUTHORIZATION regressuser5;
TRUNCATE atest2; -- ok
TRUNCATE atest3; -- fail
ERROR: permission denied for relation atest3
-- has_table_privilege function
-- bad-input checks
select has_table_privilege(NULL,'pg_authid','select');
@ -375,6 +388,12 @@ select has_table_privilege('pg_authid','delete');
t
(1 row)
select has_table_privilege('pg_authid','truncate');
has_table_privilege
---------------------
t
(1 row)
select has_table_privilege(t1.oid,'select')
from (select oid from pg_class where relname = 'pg_authid') as t1;
has_table_privilege
@ -452,6 +471,12 @@ select has_table_privilege('pg_class','delete');
f
(1 row)
select has_table_privilege('pg_class','truncate');
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
@ -527,6 +552,12 @@ select has_table_privilege('atest1','delete');
f
(1 row)
select has_table_privilege('atest1','truncate');
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
@ -604,3 +635,4 @@ DROP USER regressuser1;
DROP USER regressuser2;
DROP USER regressuser3;
DROP USER regressuser4;
DROP USER regressuser5;

View File

@ -21,7 +21,7 @@ REVOKE SELECT ON deptest FROM GROUP regression_group;
DROP GROUP regression_group;
-- can't drop the user if we revoke the privileges partially
REVOKE SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES ON deptest FROM regression_user;
REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regression_user;
DROP USER regression_user;
-- now we are OK to drop him

View File

@ -14,6 +14,7 @@ DROP ROLE IF EXISTS regressuser1;
DROP ROLE IF EXISTS regressuser2;
DROP ROLE IF EXISTS regressuser3;
DROP ROLE IF EXISTS regressuser4;
DROP ROLE IF EXISTS regressuser5;
RESET client_min_messages;
@ -23,7 +24,8 @@ CREATE USER regressuser1;
CREATE USER regressuser2;
CREATE USER regressuser3;
CREATE USER regressuser4;
CREATE USER regressuser4; -- duplicate
CREATE USER regressuser5;
CREATE USER regressuser5; -- duplicate
CREATE GROUP regressgroup1;
CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
@ -45,6 +47,7 @@ SELECT * FROM atest1;
INSERT INTO atest1 VALUES (1, 'one');
DELETE FROM atest1;
UPDATE atest1 SET a = 1 WHERE b = 'blech';
TRUNCATE atest1;
LOCK atest1 IN ACCESS EXCLUSIVE MODE;
REVOKE ALL ON atest1 FROM PUBLIC;
@ -58,6 +61,7 @@ CREATE TABLE atest2 (col1 varchar(10), col2 boolean);
GRANT SELECT ON atest2 TO regressuser2;
GRANT UPDATE ON atest2 TO regressuser3;
GRANT INSERT ON atest2 TO regressuser4;
GRANT TRUNCATE ON atest2 TO regressuser5;
SET SESSION AUTHORIZATION regressuser2;
@ -75,6 +79,7 @@ UPDATE atest2 SET col2 = NOT col2; -- fail
SELECT * FROM atest1 FOR UPDATE; -- ok
SELECT * FROM atest2 FOR UPDATE; -- fail
DELETE FROM atest2; -- fail
TRUNCATE atest2; -- fail
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
COPY atest2 FROM stdin; -- fail
GRANT ALL ON atest1 TO PUBLIC; -- fail
@ -99,6 +104,7 @@ UPDATE atest2 SET col2 = true FROM atest1 WHERE atest1.a = 5; -- ok
SELECT * FROM atest1 FOR UPDATE; -- fail
SELECT * FROM atest2 FOR UPDATE; -- fail
DELETE FROM atest2; -- fail
TRUNCATE atest2; -- fail
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
COPY atest2 FROM stdin; -- fail
@ -205,6 +211,10 @@ DROP FUNCTION testfunc1(int); -- ok
-- restore to sanity
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
-- truncate
SET SESSION AUTHORIZATION regressuser5;
TRUNCATE atest2; -- ok
TRUNCATE atest3; -- fail
-- has_table_privilege function
@ -243,6 +253,7 @@ from (select oid from pg_class where relname = 'pg_authid') as t1,
select has_table_privilege('pg_authid','update');
select has_table_privilege('pg_authid','delete');
select has_table_privilege('pg_authid','truncate');
select has_table_privilege(t1.oid,'select')
from (select oid from pg_class where relname = 'pg_authid') as t1;
@ -272,6 +283,7 @@ from (select oid from pg_class where relname = 'pg_class') as t1,
select has_table_privilege('pg_class','update');
select has_table_privilege('pg_class','delete');
select has_table_privilege('pg_class','truncate');
select has_table_privilege(t1.oid,'select')
from (select oid from pg_class where relname = 'pg_class') as t1;
@ -298,6 +310,7 @@ from (select oid from pg_class where relname = 'atest1') as t1,
select has_table_privilege('atest1','update');
select has_table_privilege('atest1','delete');
select has_table_privilege('atest1','truncate');
select has_table_privilege(t1.oid,'select')
from (select oid from pg_class where relname = 'atest1') as t1;
@ -359,3 +372,4 @@ DROP USER regressuser1;
DROP USER regressuser2;
DROP USER regressuser3;
DROP USER regressuser4;
DROP USER regressuser5;