mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Support default ACLs in get_object_address
In the spirit of 890192e99a, this time add support for the things
living in the pg_default_acl catalog. These are not really "objects",
but they show up as such in event triggers.
There is no "DROP DEFAULT PRIVILEGES" or similar command, so it doesn't
look like the new representation given would be useful anywhere else, so
I didn't try to use it outside objectaddress.c. (That might be a bug in
itself, but that would be material for another commit.)
Reviewed by Stephen Frost.
This commit is contained in:
@@ -522,7 +522,7 @@ ObjectTypeMap[] =
|
||||
/* OCLASS_USER_MAPPING */
|
||||
{ "user mapping", OBJECT_USER_MAPPING },
|
||||
/* OCLASS_DEFACL */
|
||||
{ "default acl", -1 }, /* unmapped */
|
||||
{ "default acl", OBJECT_DEFACL },
|
||||
/* OCLASS_EXTENSION */
|
||||
{ "extension", OBJECT_EXTENSION },
|
||||
/* OCLASS_EVENT_TRIGGER */
|
||||
@@ -557,6 +557,8 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
|
||||
List *objargs, bool missing_ok);
|
||||
static ObjectAddress get_object_address_usermapping(List *objname,
|
||||
List *objargs, bool missing_ok);
|
||||
static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
|
||||
bool missing_ok);
|
||||
static const ObjectPropertyType *get_object_property_data(Oid class_id);
|
||||
|
||||
static void getRelationDescription(StringInfo buffer, Oid relid);
|
||||
@@ -775,6 +777,10 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
|
||||
address = get_object_address_usermapping(objname, objargs,
|
||||
missing_ok);
|
||||
break;
|
||||
case OBJECT_DEFACL:
|
||||
address = get_object_address_defacl(objname, objargs,
|
||||
missing_ok);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
|
||||
/* placate compiler, in case it thinks elog might return */
|
||||
@@ -1447,6 +1453,113 @@ get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
|
||||
return address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the ObjectAddress for a default ACL.
|
||||
*/
|
||||
static ObjectAddress
|
||||
get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
|
||||
{
|
||||
HeapTuple tp;
|
||||
Oid userid;
|
||||
Oid schemaid;
|
||||
char *username;
|
||||
char *schema;
|
||||
char objtype;
|
||||
char *objtype_str;
|
||||
ObjectAddress address;
|
||||
|
||||
ObjectAddressSet(address, DefaultAclRelationId, InvalidOid);
|
||||
|
||||
/*
|
||||
* First figure out the textual attributes so that they can be used for
|
||||
* error reporting.
|
||||
*/
|
||||
username = strVal(linitial(objname));
|
||||
if (list_length(objname) >= 2)
|
||||
schema = (char *) strVal(lsecond(objname));
|
||||
else
|
||||
schema = NULL;
|
||||
|
||||
/*
|
||||
* Decode defaclobjtype. Only first char is considered; the rest of the
|
||||
* string, if any, is blissfully ignored.
|
||||
*/
|
||||
objtype = ((char *) strVal(linitial(objargs)))[0];
|
||||
switch (objtype)
|
||||
{
|
||||
case DEFACLOBJ_RELATION:
|
||||
objtype_str = "tables";
|
||||
break;
|
||||
case DEFACLOBJ_SEQUENCE:
|
||||
objtype_str = "sequences";
|
||||
break;
|
||||
case DEFACLOBJ_FUNCTION:
|
||||
objtype_str = "functions";
|
||||
break;
|
||||
case DEFACLOBJ_TYPE:
|
||||
objtype_str = "types";
|
||||
break;
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("unrecognized default ACL object type %c", objtype),
|
||||
errhint("Valid object types are 'r', 'S', 'f', and 'T'.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up user ID. Behave as "default ACL not found" if the user doesn't
|
||||
* exist.
|
||||
*/
|
||||
tp = SearchSysCache1(AUTHNAME,
|
||||
CStringGetDatum(username));
|
||||
if (!HeapTupleIsValid(tp))
|
||||
goto not_found;
|
||||
userid = HeapTupleGetOid(tp);
|
||||
ReleaseSysCache(tp);
|
||||
|
||||
/*
|
||||
* If a schema name was given, look up its OID. If it doesn't exist,
|
||||
* behave as "default ACL not found".
|
||||
*/
|
||||
if (schema)
|
||||
{
|
||||
schemaid = get_namespace_oid(schema, true);
|
||||
if (schemaid == InvalidOid)
|
||||
goto not_found;
|
||||
}
|
||||
else
|
||||
schemaid = InvalidOid;
|
||||
|
||||
/* Finally, look up the pg_default_acl object */
|
||||
tp = SearchSysCache3(DEFACLROLENSPOBJ,
|
||||
ObjectIdGetDatum(userid),
|
||||
ObjectIdGetDatum(schemaid),
|
||||
CharGetDatum(objtype));
|
||||
if (!HeapTupleIsValid(tp))
|
||||
goto not_found;
|
||||
|
||||
address.objectId = HeapTupleGetOid(tp);
|
||||
ReleaseSysCache(tp);
|
||||
|
||||
return address;
|
||||
|
||||
not_found:
|
||||
if (!missing_ok)
|
||||
{
|
||||
if (schema)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
|
||||
username, schema, objtype_str)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("default ACL for user \"%s\" on %s does not exist",
|
||||
username, objtype_str)));
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of TEXT into a List of string Values, as emitted by the
|
||||
* parser, which is what get_object_address uses as input.
|
||||
@@ -1599,6 +1712,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
|
||||
case OBJECT_OPFAMILY:
|
||||
case OBJECT_CAST:
|
||||
case OBJECT_USER_MAPPING:
|
||||
case OBJECT_DEFACL:
|
||||
if (list_length(args) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
@@ -4024,10 +4138,8 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
SysScanDesc rcscan;
|
||||
HeapTuple tup;
|
||||
Form_pg_default_acl defacl;
|
||||
|
||||
/* no objname support */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
char *schema;
|
||||
char *username;
|
||||
|
||||
defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
|
||||
|
||||
@@ -4047,19 +4159,20 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
|
||||
defacl = (Form_pg_default_acl) GETSTRUCT(tup);
|
||||
|
||||
username = GetUserNameFromId(defacl->defaclrole);
|
||||
appendStringInfo(&buffer,
|
||||
"for role %s",
|
||||
quote_identifier(GetUserNameFromId(defacl->defaclrole)));
|
||||
quote_identifier(username));
|
||||
|
||||
if (OidIsValid(defacl->defaclnamespace))
|
||||
{
|
||||
char *schema;
|
||||
|
||||
schema = get_namespace_name(defacl->defaclnamespace);
|
||||
appendStringInfo(&buffer,
|
||||
" in schema %s",
|
||||
quote_identifier(schema));
|
||||
}
|
||||
else
|
||||
schema = NULL;
|
||||
|
||||
switch (defacl->defaclobjtype)
|
||||
{
|
||||
@@ -4081,6 +4194,14 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
break;
|
||||
}
|
||||
|
||||
if (objname)
|
||||
{
|
||||
*objname = list_make1(username);
|
||||
if (schema)
|
||||
*objname = lappend(*objname, schema);
|
||||
*objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
|
||||
}
|
||||
|
||||
systable_endscan(rcscan);
|
||||
heap_close(defaclrel, AccessShareLock);
|
||||
break;
|
||||
|
||||
@@ -1065,6 +1065,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
|
||||
case OBJECT_COLUMN:
|
||||
case OBJECT_COLLATION:
|
||||
case OBJECT_CONVERSION:
|
||||
case OBJECT_DEFACL:
|
||||
case OBJECT_DEFAULT:
|
||||
case OBJECT_DOMAIN:
|
||||
case OBJECT_DOMCONSTRAINT:
|
||||
|
||||
Reference in New Issue
Block a user