!4102 修复物化视图刷新权限检查的问题

Merge pull request !4102 from Cross-罗/privileges_mat
This commit is contained in:
opengauss_bot
2023-09-08 06:12:25 +00:00
committed by Gitee
6 changed files with 118 additions and 5 deletions

View File

@ -830,7 +830,7 @@ ObjectAddress ExecRefreshMatViewInc(RefreshMatViewStmt *stmt, const char *queryS
matviewOid = RangeVarGetRelidExtended(stmt->relation,
ExclusiveLock,
false, false, false, true,
RangeVarCallbackOwnsTable, NULL);
RangeVarCallbackOwnsMatView, NULL);
Oid mapid = DatumGetObjectId(get_matview_mapid(matviewOid));
Datum oldTime = get_matview_refreshtime(matviewOid, &isTimeNULL);
@ -946,7 +946,7 @@ ObjectAddress ExecRefreshIncMatViewAll(RefreshMatViewStmt *stmt, const char *que
matviewOid = RangeVarGetRelidExtended(stmt->relation,
AccessExclusiveLock,
false, false, false, true,
RangeVarCallbackOwnsTable, NULL);
RangeVarCallbackOwnsMatView, NULL);
mapid = DatumGetObjectId(get_matview_mapid(matviewOid));
matviewRel = heap_open(matviewOid, AccessExclusiveLock);
@ -1055,7 +1055,7 @@ ObjectAddress ExecRefreshCtasMatViewAll(RefreshMatViewStmt *stmt, const char *qu
*/
matviewOid = RangeVarGetRelidExtended(stmt->relation,
AccessExclusiveLock, false, false, false, true,
RangeVarCallbackOwnsTable, NULL);
RangeVarCallbackOwnsMatView, NULL);
matviewRel = heap_open(matviewOid, NoLock);
/*
@ -1168,7 +1168,7 @@ bool isIncMatView(RangeVar *rv)
Oid matviewOid = RangeVarGetRelidExtended(rv,
NoLock,
false, false, false, true,
RangeVarCallbackOwnsTable, NULL);
RangeVarCallbackOwnsMatView, NULL);
Relation matviewRel = heap_open(matviewOid, AccessShareLock);
/* Make sure it is a materialized view. */

View File

@ -21920,6 +21920,51 @@ void RangeVarCallbackOwnsTable(const RangeVar* relation, Oid relId, Oid oldRelId
}
}
/*
* This is intended as a callback for RangeVarGetRelidExtended(). It allows
* the relation to be locked only if (1) it's a materialized view and
* (2) the current user is the owner (or the superuser).
* This meets the permission-checking needs of and REFRESH MATERIALIZED VIEW;
* we expose it here so that it can be used by all.
*/
void RangeVarCallbackOwnsMatView(const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg)
{
char relkind;
/* Nothing to do if the relation was not found. */
if (!OidIsValid(relId)) {
return;
}
/*
* If the relation does exist, check whether it's an index. But note that
* the relation might have been dropped between the time we did the name
* lookup and now. In that case, there's nothing to do.
*/
relkind = get_rel_relkind(relId);
if (!relkind) {
return;
}
if (relkind != RELKIND_RELATION &&
relkind != RELKIND_TOASTVALUE &&
relkind != RELKIND_MATVIEW) {
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table or materialized view", relation->relname)));
}
/* Check permissions */
AclResult aclresult = pg_class_aclcheck(relId, GetUserId(), ACL_INSERT | ACL_DELETE);
if (aclresult != ACLCHECK_OK) {
aclcheck_error(aclresult, ACL_KIND_CLASS, relation->relname);
}
bool is_owner = pg_class_ownercheck(relId, GetUserId());
if (!is_owner) {
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, relation->relname);
}
}
/*
* Callback to RangeVarGetRelidExtended(), similar to
* RangeVarCallbackOwnsTable() but without checks on the type of the relation.

View File

@ -4974,7 +4974,7 @@ List *QueryRewriteRefresh(Query *parse_tree)
*/
matviewOid = RangeVarGetRelidExtended(stmt->relation,
AccessExclusiveLock, false, false, false, false,
RangeVarCallbackOwnsTable, NULL);
RangeVarCallbackOwnsMatView, NULL);
matviewRel = heap_open(matviewOid, NoLock);
/* Make sure it is a materialized view. */

View File

@ -181,6 +181,8 @@ extern void DropTableThrowErrorExternal(RangeVar* relation, ObjectType removeTyp
extern void RangeVarCallbackOwnsTable(
const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg);
extern void RangeVarCallbackOwnsMatView(
const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg);
extern void RangeVarCallbackOwnsRelation(
const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* noCatalogs);
extern void checkPartNotInUse(Partition part, const char* stmt);

View File

@ -141,5 +141,39 @@ drop table test_syn cascade;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to materialized view mv_test_syn
drop cascades to materialized view imv_test_syn
-- test about the privileges of refresh
create table t (id int);
insert into t select generate_series(1,10);
create materialized view mv_t as select * from t;
create user testuser with password 'Gauss@123';
grant usage on schema public to testuser;
grant select on t to testuser;
grant select on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
ERROR: permission denied for relation mv_t
DETAIL: N/A
reset role;
grant delete,insert on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
ERROR: must be owner of relation mv_t
DETAIL: N/A
reset role;
grant index on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
ERROR: must be owner of relation mv_t
DETAIL: N/A
reset role;
alter table mv_t owner to testuser;
set role testuser password 'Gauss@123';
-- success
refresh materialized view mv_t;
reset role;
drop user testuser cascade;
\c regression
drop database test_imv_db;

View File

@ -72,5 +72,37 @@ drop synonym s_mv_test_syn;
drop synonym s_imv_test_syn;
drop table test_syn cascade;
-- test about the privileges of refresh
create table t (id int);
insert into t select generate_series(1,10);
create materialized view mv_t as select * from t;
create user testuser with password 'Gauss@123';
grant usage on schema public to testuser;
grant select on t to testuser;
grant select on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
reset role;
grant delete,insert on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
reset role;
grant index on mv_t to testuser;
set role testuser password 'Gauss@123';
-- failed, permission denied
refresh materialized view mv_t;
reset role;
alter table mv_t owner to testuser;
set role testuser password 'Gauss@123';
-- success
refresh materialized view mv_t;
reset role;
drop user testuser cascade;
\c regression
drop database test_imv_db;