mirror of
https://github.com/postgres/postgres.git
synced 2025-10-16 17:07:43 +03:00
Add support for privileges on types
This adds support for the more or less SQL-conforming USAGE privilege on types and domains. The intent is to be able restrict which users can create dependencies on types, which restricts the way in which owners can alter types. reviewed by Yeb Havinga
This commit is contained in:
@@ -87,9 +87,11 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
{
|
||||
Oid rettype;
|
||||
Type typtup;
|
||||
AclResult aclresult;
|
||||
|
||||
typtup = LookupTypeName(NULL, returnType, NULL);
|
||||
|
||||
|
||||
if (typtup)
|
||||
{
|
||||
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
|
||||
@@ -150,6 +152,11 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
Assert(OidIsValid(rettype));
|
||||
}
|
||||
|
||||
aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(rettype));
|
||||
|
||||
*prorettype_p = rettype;
|
||||
*returnsSet_p = returnType->setof;
|
||||
}
|
||||
@@ -207,6 +214,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
||||
bool isinput = false;
|
||||
Oid toid;
|
||||
Type typtup;
|
||||
AclResult aclresult;
|
||||
|
||||
typtup = LookupTypeName(NULL, t, NULL);
|
||||
if (typtup)
|
||||
@@ -237,6 +245,11 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
||||
toid = InvalidOid; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(toid));
|
||||
|
||||
if (t->setof)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
@@ -1429,6 +1442,7 @@ CreateCast(CreateCastStmt *stmt)
|
||||
bool nulls[Natts_pg_cast];
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
AclResult aclresult;
|
||||
|
||||
sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
|
||||
targettypeid = typenameTypeId(NULL, stmt->targettype);
|
||||
@@ -1457,6 +1471,16 @@ CreateCast(CreateCastStmt *stmt)
|
||||
format_type_be(sourcetypeid),
|
||||
format_type_be(targettypeid))));
|
||||
|
||||
aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(sourcetypeid));
|
||||
|
||||
aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(targettypeid));
|
||||
|
||||
/* Detemine the cast method */
|
||||
if (stmt->func != NULL)
|
||||
castmethod = COERCION_METHOD_FUNCTION;
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "parser/parse_func.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
@@ -73,6 +74,7 @@ DefineOperator(List *names, List *parameters)
|
||||
TypeName *typeName2 = NULL; /* second type name */
|
||||
Oid typeId1 = InvalidOid; /* types converted to OID */
|
||||
Oid typeId2 = InvalidOid;
|
||||
Oid rettype;
|
||||
List *commutatorName = NIL; /* optional commutator operator name */
|
||||
List *negatorName = NIL; /* optional negator operator name */
|
||||
List *restrictionName = NIL; /* optional restrict. sel. procedure */
|
||||
@@ -175,6 +177,22 @@ DefineOperator(List *names, List *parameters)
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("at least one of leftarg or rightarg must be specified")));
|
||||
|
||||
if (typeName1)
|
||||
{
|
||||
aclresult = pg_type_aclcheck(typeId1, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(typeId1));
|
||||
}
|
||||
|
||||
if (typeName2)
|
||||
{
|
||||
aclresult = pg_type_aclcheck(typeId2, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(typeId2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the operator's underlying function.
|
||||
*/
|
||||
@@ -206,6 +224,12 @@ DefineOperator(List *names, List *parameters)
|
||||
aclcheck_error(aclresult, ACL_KIND_PROC,
|
||||
NameListToString(functionName));
|
||||
|
||||
rettype = get_func_rettype(functionOid);
|
||||
aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(rettype));
|
||||
|
||||
/*
|
||||
* Look up restriction estimator if specified
|
||||
*/
|
||||
|
@@ -506,7 +506,16 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
|
||||
(void) heap_reloptions(relkind, reloptions, true);
|
||||
|
||||
if (stmt->ofTypename)
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
|
||||
|
||||
aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(ofTypeId));
|
||||
}
|
||||
else
|
||||
ofTypeId = InvalidOid;
|
||||
|
||||
@@ -4326,6 +4335,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
Expr *defval;
|
||||
List *children;
|
||||
ListCell *child;
|
||||
AclResult aclresult;
|
||||
|
||||
/* At top level, permission check was done in ATPrepCmd, else do it */
|
||||
if (recursing)
|
||||
@@ -4429,6 +4439,12 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
typeTuple = typenameType(NULL, colDef->typeName, &typmod);
|
||||
tform = (Form_pg_type) GETSTRUCT(typeTuple);
|
||||
typeOid = HeapTupleGetOid(typeTuple);
|
||||
|
||||
aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(typeOid));
|
||||
|
||||
collOid = GetColumnDefCollation(NULL, colDef, typeOid);
|
||||
|
||||
/* make sure datatype is legal for a column */
|
||||
@@ -6973,6 +6989,7 @@ ATPrepAlterColumnType(List **wqueue,
|
||||
Oid targetcollid;
|
||||
NewColumnValue *newval;
|
||||
ParseState *pstate = make_parsestate(NULL);
|
||||
AclResult aclresult;
|
||||
|
||||
if (rel->rd_rel->reloftype && !recursing)
|
||||
ereport(ERROR,
|
||||
@@ -7006,6 +7023,11 @@ ATPrepAlterColumnType(List **wqueue,
|
||||
/* Look up the target type */
|
||||
typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
|
||||
|
||||
aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(targettype));
|
||||
|
||||
/* And the collation */
|
||||
targetcollid = GetColumnDefCollation(NULL, def, targettype);
|
||||
|
||||
|
@@ -756,6 +756,11 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
errmsg("\"%s\" is not a valid base type for a domain",
|
||||
TypeNameToString(stmt->typeName))));
|
||||
|
||||
aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_TYPE,
|
||||
format_type_be(basetypeoid));
|
||||
|
||||
/*
|
||||
* Identify the collation if any
|
||||
*/
|
||||
|
Reference in New Issue
Block a user