mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Extend ALTER DEFAULT PRIVILEGES to define default privileges for large objects.
Previously, ALTER DEFAULT PRIVILEGES did not support large objects. This meant that to grant privileges to users other than the owner, permissions had to be manually assigned each time a large object was created, which was inconvenient. This commit extends ALTER DEFAULT PRIVILEGES to allow defining default access privileges for large objects. With this change, specified privileges will automatically apply to newly created large objects, making privilege management more efficient. As a side effect, this commit introduces the new keyword OBJECTS since it's used in the syntax of ALTER DEFAULT PRIVILEGES. Original patch by Haruka Takatsuka, with some fixes and tests by Yugo Nagata, and rebased by Laurenz Albe. Author: Takatsuka Haruka <harukat@sraoss.co.jp> Co-authored-by: Yugo Nagata <nagata@sraoss.co.jp> Co-authored-by: Laurenz Albe <laurenz.albe@cybertec.at> Reviewed-by: Masao Fujii <masao.fujii@gmail.com> Discussion: https://postgr.es/m/20240424115242.236b499b2bed5b7a27f7a418@sraoss.co.jp
This commit is contained in:
@@ -1005,6 +1005,10 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
|
||||
all_privileges = ACL_ALL_RIGHTS_SCHEMA;
|
||||
errormsg = gettext_noop("invalid privilege type %s for schema");
|
||||
break;
|
||||
case OBJECT_LARGEOBJECT:
|
||||
all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
|
||||
errormsg = gettext_noop("invalid privilege type %s for large object");
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
|
||||
(int) action->objtype);
|
||||
@@ -1196,6 +1200,16 @@ SetDefaultACL(InternalDefaultACL *iacls)
|
||||
this_privileges = ACL_ALL_RIGHTS_SCHEMA;
|
||||
break;
|
||||
|
||||
case OBJECT_LARGEOBJECT:
|
||||
if (OidIsValid(iacls->nspid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
||||
errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON LARGE OBJECTS")));
|
||||
objtype = DEFACLOBJ_LARGEOBJECT;
|
||||
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
|
||||
this_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized object type: %d",
|
||||
(int) iacls->objtype);
|
||||
@@ -1439,6 +1453,9 @@ RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
|
||||
case DEFACLOBJ_NAMESPACE:
|
||||
iacls.objtype = OBJECT_SCHEMA;
|
||||
break;
|
||||
case DEFACLOBJ_LARGEOBJECT:
|
||||
iacls.objtype = OBJECT_LARGEOBJECT;
|
||||
break;
|
||||
default:
|
||||
/* Shouldn't get here */
|
||||
elog(ERROR, "unexpected default ACL type: %d",
|
||||
@@ -4250,6 +4267,10 @@ get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
|
||||
defaclobjtype = DEFACLOBJ_NAMESPACE;
|
||||
break;
|
||||
|
||||
case OBJECT_LARGEOBJECT:
|
||||
defaclobjtype = DEFACLOBJ_LARGEOBJECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2005,16 +2005,20 @@ get_object_address_defacl(List *object, bool missing_ok)
|
||||
case DEFACLOBJ_NAMESPACE:
|
||||
objtype_str = "schemas";
|
||||
break;
|
||||
case DEFACLOBJ_LARGEOBJECT:
|
||||
objtype_str = "large objects";
|
||||
break;
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("unrecognized default ACL object type \"%c\"", objtype),
|
||||
errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
|
||||
errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
|
||||
DEFACLOBJ_RELATION,
|
||||
DEFACLOBJ_SEQUENCE,
|
||||
DEFACLOBJ_FUNCTION,
|
||||
DEFACLOBJ_TYPE,
|
||||
DEFACLOBJ_NAMESPACE)));
|
||||
DEFACLOBJ_NAMESPACE,
|
||||
DEFACLOBJ_LARGEOBJECT)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3844,6 +3848,12 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
|
||||
_("default privileges on new schemas belonging to role %s"),
|
||||
rolename);
|
||||
break;
|
||||
case DEFACLOBJ_LARGEOBJECT:
|
||||
Assert(!nspname);
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges on new large objects belonging to role %s"),
|
||||
rolename);
|
||||
break;
|
||||
default:
|
||||
/* shouldn't get here */
|
||||
if (nspname)
|
||||
@@ -5766,6 +5776,10 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
appendStringInfoString(&buffer,
|
||||
" on schemas");
|
||||
break;
|
||||
case DEFACLOBJ_LARGEOBJECT:
|
||||
appendStringInfoString(&buffer,
|
||||
" on large objects");
|
||||
break;
|
||||
}
|
||||
|
||||
if (objname)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "catalog/pg_largeobject_metadata.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
@@ -39,6 +40,8 @@ LargeObjectCreate(Oid loid)
|
||||
Oid loid_new;
|
||||
Datum values[Natts_pg_largeobject_metadata];
|
||||
bool nulls[Natts_pg_largeobject_metadata];
|
||||
Oid ownerId;
|
||||
Acl *lomacl;
|
||||
|
||||
pg_lo_meta = table_open(LargeObjectMetadataRelationId,
|
||||
RowExclusiveLock);
|
||||
@@ -55,11 +58,18 @@ LargeObjectCreate(Oid loid)
|
||||
loid_new = GetNewOidWithIndex(pg_lo_meta,
|
||||
LargeObjectMetadataOidIndexId,
|
||||
Anum_pg_largeobject_metadata_oid);
|
||||
ownerId = GetUserId();
|
||||
lomacl = get_user_default_acl(OBJECT_LARGEOBJECT, ownerId, InvalidOid);
|
||||
|
||||
values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
|
||||
values[Anum_pg_largeobject_metadata_lomowner - 1]
|
||||
= ObjectIdGetDatum(GetUserId());
|
||||
nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
|
||||
= ObjectIdGetDatum(ownerId);
|
||||
|
||||
if (lomacl != NULL)
|
||||
values[Anum_pg_largeobject_metadata_lomacl - 1]
|
||||
= PointerGetDatum(lomacl);
|
||||
else
|
||||
nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
|
||||
|
||||
ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
|
||||
values, nulls);
|
||||
@@ -70,6 +80,10 @@ LargeObjectCreate(Oid loid)
|
||||
|
||||
table_close(pg_lo_meta, RowExclusiveLock);
|
||||
|
||||
/* dependencies on roles mentioned in default ACL */
|
||||
recordDependencyOnNewAcl(LargeObjectRelationId, loid_new, 0,
|
||||
ownerId, lomacl);
|
||||
|
||||
return loid_new;
|
||||
}
|
||||
|
||||
|
||||
@@ -752,7 +752,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
|
||||
NULLS_P NUMERIC
|
||||
|
||||
OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR
|
||||
OBJECT_P OBJECTS_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR
|
||||
ORDER ORDINALITY OTHERS OUT_P OUTER_P
|
||||
OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER
|
||||
|
||||
@@ -8177,6 +8177,7 @@ defacl_privilege_target:
|
||||
| SEQUENCES { $$ = OBJECT_SEQUENCE; }
|
||||
| TYPES_P { $$ = OBJECT_TYPE; }
|
||||
| SCHEMAS { $$ = OBJECT_SCHEMA; }
|
||||
| LARGE_P OBJECTS_P { $$ = OBJECT_LARGEOBJECT; }
|
||||
;
|
||||
|
||||
|
||||
@@ -17882,6 +17883,7 @@ unreserved_keyword:
|
||||
| NOWAIT
|
||||
| NULLS_P
|
||||
| OBJECT_P
|
||||
| OBJECTS_P
|
||||
| OF
|
||||
| OFF
|
||||
| OIDS
|
||||
@@ -18504,6 +18506,7 @@ bare_label_keyword:
|
||||
| NULLS_P
|
||||
| NUMERIC
|
||||
| OBJECT_P
|
||||
| OBJECTS_P
|
||||
| OF
|
||||
| OFF
|
||||
| OIDS
|
||||
|
||||
Reference in New Issue
Block a user