!2158 修复reassign时directory没有适配的问题
Merge pull request !2158 from 胡正超/directory
This commit is contained in:
@ -57,6 +57,7 @@
|
||||
#include "commands/sec_rls_cmds.h"
|
||||
#include "commands/tablecmds.h"
|
||||
#include "commands/typecmds.h"
|
||||
#include "commands/directory.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/acl.h"
|
||||
@ -1412,6 +1413,10 @@ void shdepReassignOwned(List* roleids, Oid newrole)
|
||||
AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case PgDirectoryRelationId:
|
||||
AlterPgDirectoryOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("unexpected classid %u", sdepForm->classid)));
|
||||
|
@ -389,6 +389,72 @@ void RemoveDirectoryById(Oid dirOid)
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
}
|
||||
|
||||
static void AlterPgDirectoryOwner_internal(Relation rel, HeapTuple tuple, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_directory dirForm = (Form_pg_directory)GETSTRUCT(tuple);
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is to be consistent with other
|
||||
* objects.
|
||||
*/
|
||||
if (dirForm->owner == newOwnerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
Datum repl_val[Natts_pg_directory];
|
||||
bool repl_null[Natts_pg_directory];
|
||||
bool repl_repl[Natts_pg_directory];
|
||||
Acl* newAcl = NULL;
|
||||
Datum aclDatum;
|
||||
bool isNull = false;
|
||||
HeapTuple newtuple;
|
||||
errno_t rc;
|
||||
|
||||
if (u_sess->attr.attr_storage.enable_access_server_directory) {
|
||||
/* must be sysadmin or owner of the existing object */
|
||||
if (!superuser() && !pg_directory_ownercheck(HeapTupleGetOid(tuple), GetUserId())) {
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DIRECTORY, NameStr(dirForm->dirname));
|
||||
}
|
||||
} else {
|
||||
if (!initialuser()) {
|
||||
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied to change owner of directory"),
|
||||
errhint("must be initial user to change owner of a directory")));
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
rc = memset_s(repl_null, sizeof(repl_null), false, sizeof(repl_null));
|
||||
securec_check(rc, "\0", "\0");
|
||||
rc = memset_s(repl_repl, sizeof(repl_repl), false, sizeof(repl_repl));
|
||||
securec_check(rc, "\0", "\0");
|
||||
|
||||
repl_repl[Anum_pg_directory_owner - 1] = true;
|
||||
repl_val[Anum_pg_directory_owner - 1] = ObjectIdGetDatum(newOwnerId);
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = tableam_tops_tuple_getattr(tuple, Anum_pg_directory_directory_acl, RelationGetDescr(rel), &isNull);
|
||||
if (!isNull) {
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum), dirForm->owner, newOwnerId);
|
||||
repl_repl[Anum_pg_directory_directory_acl - 1] = true;
|
||||
repl_val[Anum_pg_directory_directory_acl - 1] = PointerGetDatum(newAcl);
|
||||
}
|
||||
|
||||
newtuple = (HeapTuple) tableam_tops_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
|
||||
simple_heap_update(rel, &newtuple->t_self, newtuple);
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
tableam_tops_free_tuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(PgDirectoryRelationId, HeapTupleGetOid(tuple), newOwnerId);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER Directory name OWNER TO newowner
|
||||
*/
|
||||
@ -398,7 +464,6 @@ void AlterDirectoryOwner(const char* dirname, Oid newOwnerId)
|
||||
Relation rel;
|
||||
ScanKeyData scankey;
|
||||
SysScanDesc scan = NULL;
|
||||
Form_pg_directory dirForm = NULL;
|
||||
|
||||
/*
|
||||
* Get the old tuple. We don't need a lock on the directory per se,
|
||||
@ -413,69 +478,30 @@ void AlterDirectoryOwner(const char* dirname, Oid newOwnerId)
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("directory \"%s\" does not exist", dirname)));
|
||||
}
|
||||
dirForm = (Form_pg_directory)GETSTRUCT(tuple);
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is to be consistent with other
|
||||
* objects.
|
||||
*/
|
||||
if (dirForm->owner != newOwnerId) {
|
||||
Datum repl_val[Natts_pg_directory];
|
||||
bool repl_null[Natts_pg_directory];
|
||||
bool repl_repl[Natts_pg_directory];
|
||||
Acl* newAcl = NULL;
|
||||
Datum aclDatum;
|
||||
bool isNull = false;
|
||||
HeapTuple newtuple;
|
||||
errno_t rc;
|
||||
|
||||
if (u_sess->attr.attr_storage.enable_access_server_directory) {
|
||||
/* must be sysadmin or owner of the existing object */
|
||||
if (!superuser() && !pg_directory_ownercheck(HeapTupleGetOid(tuple), GetUserId())) {
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DIRECTORY, dirname);
|
||||
}
|
||||
} else {
|
||||
if (!initialuser()) {
|
||||
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied to change owner of directory"),
|
||||
errhint("must be initial user to change owner of a directory")));
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
rc = memset_s(repl_null, sizeof(repl_null), false, sizeof(repl_null));
|
||||
securec_check(rc, "\0", "\0");
|
||||
rc = memset_s(repl_repl, sizeof(repl_repl), false, sizeof(repl_repl));
|
||||
securec_check(rc, "\0", "\0");
|
||||
|
||||
repl_repl[Anum_pg_directory_owner - 1] = true;
|
||||
repl_val[Anum_pg_directory_owner - 1] = ObjectIdGetDatum(newOwnerId);
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = tableam_tops_tuple_getattr(tuple, Anum_pg_directory_directory_acl, RelationGetDescr(rel), &isNull);
|
||||
if (!isNull) {
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum), dirForm->owner, newOwnerId);
|
||||
repl_repl[Anum_pg_directory_directory_acl - 1] = true;
|
||||
repl_val[Anum_pg_directory_directory_acl - 1] = PointerGetDatum(newAcl);
|
||||
}
|
||||
|
||||
newtuple = (HeapTuple) tableam_tops_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
|
||||
simple_heap_update(rel, &newtuple->t_self, newtuple);
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
tableam_tops_free_tuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(PgDirectoryRelationId, HeapTupleGetOid(tuple), newOwnerId);
|
||||
}
|
||||
AlterPgDirectoryOwner_internal(rel, tuple, newOwnerId);
|
||||
|
||||
systable_endscan(scan);
|
||||
|
||||
/* Close pg_database, but keep lock till commit */
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
|
||||
void AlterPgDirectoryOwner_oid(Oid dirOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
HeapTuple tup = NULL;
|
||||
|
||||
rel = heap_open(PgDirectoryRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCacheCopy1(DIRECTORYOID, ObjectIdGetDatum(dirOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for directory %u", dirOid)));
|
||||
|
||||
AlterPgDirectoryOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
|
@ -35,5 +35,6 @@ extern Oid get_directory_oid(const char* directoryname, bool missing_ok);
|
||||
extern char* get_directory_name(Oid dir_oid);
|
||||
extern void RemoveDirectoryById(Oid dirOid);
|
||||
extern void AlterDirectoryOwner(const char* dirname, Oid newOwnerId);
|
||||
extern void AlterPgDirectoryOwner_oid(Oid dirOid, Oid newOwnerId);
|
||||
|
||||
#endif /* DIRECTORY_H*/
|
||||
|
@ -133,5 +133,19 @@ DROP DIRECTORY test_dir2;
|
||||
\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "enable_access_server_directory=off" >/dev/null 2>&1
|
||||
|
||||
RESET ROLE;
|
||||
|
||||
alter system set enable_access_server_directory=on;
|
||||
create user u_reassign_owned_0008_1 sysadmin password 'test@123';
|
||||
create user u_reassign_owned_0008_2 sysadmin password 'test@123';
|
||||
SET ROLE u_reassign_owned_0008_1 PASSWORD 'test@123';
|
||||
show enable_access_server_directory;
|
||||
create or replace directory dir_object_reassign_owned_0008 as '/tmp';
|
||||
select t1.dirname, t2.usename, t1.dirpath from pg_directory t1 inner join pg_user t2 on t2.usesysid=t1.owner where t1.dirname='dir_object_reassign_owned_0008';
|
||||
reassign owned by u_reassign_owned_0008_1 to u_reassign_owned_0008_2;
|
||||
|
||||
RESET ROLE;
|
||||
alter system set enable_access_server_directory=off;
|
||||
|
||||
DROP USER test_user1,test_user2,test_user3;
|
||||
DROP USER test_sysadmin,test_create,test_drop;
|
||||
DROP USER u_reassign_owned_0008_1, u_reassign_owned_0008_2 cascade;
|
||||
|
@ -265,5 +265,26 @@ DROP DIRECTORY test_dir2;
|
||||
\! rm -rf @testtablespace@/dir2
|
||||
\! @abs_bindir@/gs_guc reload -Z datanode -D @abs_srcdir@/tmp_check/datanode1 -c "enable_access_server_directory=off" >/dev/null 2>&1
|
||||
RESET ROLE;
|
||||
alter system set enable_access_server_directory=on;
|
||||
create user u_reassign_owned_0008_1 sysadmin password 'test@123';
|
||||
create user u_reassign_owned_0008_2 sysadmin password 'test@123';
|
||||
SET ROLE u_reassign_owned_0008_1 PASSWORD 'test@123';
|
||||
show enable_access_server_directory;
|
||||
enable_access_server_directory
|
||||
--------------------------------
|
||||
on
|
||||
(1 row)
|
||||
|
||||
create or replace directory dir_object_reassign_owned_0008 as '/tmp';
|
||||
select t1.dirname, t2.usename, t1.dirpath from pg_directory t1 inner join pg_user t2 on t2.usesysid=t1.owner where t1.dirname='dir_object_reassign_owned_0008';
|
||||
dirname | usename | dirpath
|
||||
--------------------------------+-------------------------+---------
|
||||
dir_object_reassign_owned_0008 | u_reassign_owned_0008_1 | /tmp
|
||||
(1 row)
|
||||
|
||||
reassign owned by u_reassign_owned_0008_1 to u_reassign_owned_0008_2;
|
||||
RESET ROLE;
|
||||
alter system set enable_access_server_directory=off;
|
||||
DROP USER test_user1,test_user2,test_user3;
|
||||
DROP USER test_sysadmin,test_create,test_drop;
|
||||
DROP USER u_reassign_owned_0008_1, u_reassign_owned_0008_2 cascade;
|
||||
|
Reference in New Issue
Block a user