1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +03:00

Create an ALTER DEFAULT PRIVILEGES command, which allows users to adjust

the privileges that will be applied to subsequently-created objects.

Such adjustments are always per owning role, and can be restricted to objects
created in particular schemas too.  A notable benefit is that users can
override the traditional default privilege settings, eg, the PUBLIC EXECUTE
privilege traditionally granted by default for functions.

Petr Jelinek
This commit is contained in:
Tom Lane
2009-10-05 19:24:49 +00:00
parent 41f89e3bbc
commit 249724cb01
48 changed files with 2240 additions and 180 deletions

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.48 2009/08/04 21:56:08 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.49 2009/10/05 19:24:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -490,18 +490,22 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems)
* acls: the ACL string fetched from the database
* owner: username of object owner (will be passed through fmtId); can be
* NULL or empty string to indicate "no owner known"
* prefix: string to prefix to each generated command; typically empty
* remoteVersion: version of database
*
* Returns TRUE if okay, FALSE if could not parse the acl string.
* The resulting commands (if any) are appended to the contents of 'sql'.
*
* Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES "
* or something similar, and name is an empty string.
*
* Note: beware of passing a fmtId() result directly as 'name' or 'subname',
* since this routine uses fmtId() internally.
*/
bool
buildACLCommands(const char *name, const char *subname,
const char *type, const char *acls, const char *owner,
int remoteVersion,
const char *prefix, int remoteVersion,
PQExpBuffer sql)
{
char **aclitems;
@ -549,7 +553,7 @@ buildACLCommands(const char *name, const char *subname,
* wire-in knowledge about the default public privileges for different
* kinds of objects.
*/
appendPQExpBuffer(firstsql, "REVOKE ALL");
appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name);
@ -564,8 +568,8 @@ buildACLCommands(const char *name, const char *subname,
if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0)
{
/* database CONNECT priv didn't exist before 8.2 */
appendPQExpBuffer(firstsql, "GRANT CONNECT ON %s %s TO PUBLIC;\n",
type, name);
appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n",
prefix, type, name);
}
/* Scan individual ACL items */
@ -594,20 +598,20 @@ buildACLCommands(const char *name, const char *subname,
? strcmp(privswgo->data, "ALL") != 0
: strcmp(privs->data, "ALL") != 0)
{
appendPQExpBuffer(firstsql, "REVOKE ALL");
appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
type, name, fmtId(grantee->data));
if (privs->len > 0)
appendPQExpBuffer(firstsql,
"GRANT %s ON %s %s TO %s;\n",
privs->data, type, name,
"%sGRANT %s ON %s %s TO %s;\n",
prefix, privs->data, type, name,
fmtId(grantee->data));
if (privswgo->len > 0)
appendPQExpBuffer(firstsql,
"GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
privswgo->data, type, name,
"%sGRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
prefix, privswgo->data, type, name,
fmtId(grantee->data));
}
}
@ -623,8 +627,8 @@ buildACLCommands(const char *name, const char *subname,
if (privs->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
privs->data, type, name);
appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
prefix, privs->data, type, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC;\n");
else if (strncmp(grantee->data, "group ",
@ -636,8 +640,8 @@ buildACLCommands(const char *name, const char *subname,
}
if (privswgo->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
privswgo->data, type, name);
appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
prefix, privswgo->data, type, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC");
else if (strncmp(grantee->data, "group ",
@ -661,7 +665,7 @@ buildACLCommands(const char *name, const char *subname,
*/
if (!found_owner_privs && owner)
{
appendPQExpBuffer(firstsql, "REVOKE ALL");
appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
@ -682,6 +686,50 @@ buildACLCommands(const char *name, const char *subname,
return true;
}
/*
* Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry.
*
* type: the object type (as seen in GRANT command)
* nspname: schema name, or NULL for global default privileges
* acls: the ACL string fetched from the database
* owner: username of privileges owner (will be passed through fmtId)
* remoteVersion: version of database
*
* Returns TRUE if okay, FALSE if could not parse the acl string.
* The resulting commands (if any) are appended to the contents of 'sql'.
*/
bool
buildDefaultACLCommands(const char *type, const char *nspname,
const char *acls, const char *owner,
int remoteVersion,
PQExpBuffer sql)
{
bool result;
PQExpBuffer prefix;
prefix = createPQExpBuffer();
/*
* We incorporate the target role directly into the command, rather than
* playing around with SET ROLE or anything like that. This is so that
* a permissions error leads to nothing happening, rather than
* changing default privileges for the wrong user.
*/
appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ",
fmtId(owner));
if (nspname)
appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
result = buildACLCommands("", NULL,
type, acls, owner,
prefix->data, remoteVersion,
sql);
destroyPQExpBuffer(prefix);
return result;
}
/*
* This will parse an aclitem string, having the general form
* username=privilegecodes/grantor