diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index a9a626db3c1..b571457be53 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -173,6 +173,7 @@ static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid tsql_has_linked_srv_permissions_hook_type tsql_has_linked_srv_permissions_hook = NULL; bbf_execute_grantstmt_as_dbsecadmin_hook_type bbf_execute_grantstmt_as_dbsecadmin_hook = NULL; +update_bbf_schema_permissions_catalog_hook_type update_bbf_schema_permissions_catalog_hook = NULL; pltsql_allow_storing_init_privs_hook_type pltsql_allow_storing_init_privs_hook = NULL; /* * If is_grant is true, adds the given privileges for the list of @@ -2052,6 +2053,25 @@ ExecGrant_Relation(InternalGrant *istmt) NameStr(pg_class_tuple->relname), 0, NULL); + /* + * Call the hook to add the permission in bbf_schema_permissions catalog + * If the hook returns false, indicates that object-level and schema-level grants both are present and schema-level grant is revoked. + * In such case we remove schema-level entry from the bbf_schema_permissions catalog but skip the execution of revoke as object-level grants exist. + */ + if (update_bbf_schema_permissions_catalog_hook && !(*update_bbf_schema_permissions_catalog_hook) (this_privileges, istmt->is_grant, istmt->grantees, + istmt->col_privs, pg_class_tuple->oid, GetUserNameFromId(grantorId, false), + istmt->grant_option, GetUserNameFromId(ownerId, false), istmt->objtype)) + { + pfree(old_rel_acl); + pfree(col_privileges); + if (!is_enr) + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); + ReleaseSysCache(tuple); + table_close(attRelation, RowExclusiveLock); + table_close(relation, RowExclusiveLock); + return; + } + /* * Generate new ACL. */ @@ -2272,6 +2292,22 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, NameStr(*DatumGetName(nameDatum)), 0, NULL); + /* + * Call the hook to add the permission in bbf_schema_permissions catalog + * If the hook returns false, indicates that object-level and schema-level grants both are present and schema-level grant is revoked. + * In such case we remove schema-level entry from the bbf_schema_permissions catalog but skip the execution of revoke as object-level grants exist. + */ + if (update_bbf_schema_permissions_catalog_hook && !(*update_bbf_schema_permissions_catalog_hook) (this_privileges, istmt->is_grant, istmt->grantees, + istmt->col_privs, objectid, GetUserNameFromId(grantorId, false), + istmt->grant_option, GetUserNameFromId(ownerId, false), istmt->objtype)) + { + if (!is_enr) + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); + ReleaseSysCache(tuple); + table_close(relation, RowExclusiveLock); + return; + } + /* * Generate new ACL. */ diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index b672a2f340d..73a5c378b0f 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -312,6 +312,9 @@ extern PGDLLEXPORT pltsql_allow_storing_init_privs_hook_type pltsql_allow_storin typedef bool (*bbf_check_member_has_direct_priv_to_grant_role_hook_type) (Oid, Oid); extern PGDLLEXPORT bbf_check_member_has_direct_priv_to_grant_role_hook_type bbf_check_member_has_direct_priv_to_grant_role_hook; +typedef bool (*update_bbf_schema_permissions_catalog_hook_type) (AclMode , bool, List*, List*, Oid, const char*, bool, const char*, ObjectType); +extern PGDLLEXPORT update_bbf_schema_permissions_catalog_hook_type update_bbf_schema_permissions_catalog_hook; + #define IS_BBF_DB_DDLADMIN(namespaceId) \ (is_bbf_db_ddladmin_operation_hook && \ is_bbf_db_ddladmin_operation_hook(namespaceId))