From 16a2de0ef4595d93af8152ee1b13ffefc989527e Mon Sep 17 00:00:00 2001 From: nancy_w <1527108510@qq.com> Date: Mon, 29 May 2023 14:35:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1CREATE/ALTE?= =?UTF-8?q?R/DROP=20EVENT=E6=9D=83=E9=99=90=E6=A0=A1=E9=AA=8C=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/catalog/gs_job_attribute.cpp | 5 +- src/common/backend/parser/gram.y | 4 +- .../optimizer/commands/eventcmds.cpp | 77 ++++++++++++---- src/test/regress/expected/event.out | 89 ++++++++++++++++++ src/test/regress/sql/event.sql | 90 +++++++++++++++++++ 5 files changed, 241 insertions(+), 24 deletions(-) diff --git a/src/common/backend/catalog/gs_job_attribute.cpp b/src/common/backend/catalog/gs_job_attribute.cpp index f2c6dc40ca..61b576b3eb 100644 --- a/src/common/backend/catalog/gs_job_attribute.cpp +++ b/src/common/backend/catalog/gs_job_attribute.cpp @@ -994,7 +994,6 @@ char *CreateEventInlineProgram(Datum job_name, Datum job_type, Datum job_action, check_program_name_valid(CStringGetTextDatum(program_name), true); } check_program_type_valid(job_type); - check_program_creation_privilege(job_type); check_program_type_argument(job_type, 0); check_program_action(job_action); check_if_arguments_defined(CStringGetTextDatum(program_name), 0); @@ -1140,10 +1139,10 @@ void create_job_raw(PG_FUNCTION_ARGS) Datum job_definer_oid = (PG_ARGISNULL(18)) ? Datum(0) : PG_GETARG_DATUM(18); /* Various checks */ - if (!(u_sess->attr.attr_sql.sql_compatibility == B_FORMAT)) { + if (PG_ARGISNULL(16)) { check_job_name_valid(job_name); + check_job_creation_privilege(job_type); } - check_job_creation_privilege(job_type); check_job_class_valid(job_class); /* gs_job_attribute */ diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 5000ecedf4..5431b0201d 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -15482,9 +15482,9 @@ preserve_opt: ON COMPLETION PRESERVE | /*EMPTY*/ { $$ = NULL; } ; -rename_opt: RENAME TO qualified_name +rename_opt: RENAME TO name { - $$ = makeDefElem("rename", (Node *)$3); + $$ = makeDefElem("rename", (Node *)makeString($3)); } | /*EMPTY*/ { $$ = NULL; } ; diff --git a/src/gausskernel/optimizer/commands/eventcmds.cpp b/src/gausskernel/optimizer/commands/eventcmds.cpp index b0bca9838d..6324eab3eb 100755 --- a/src/gausskernel/optimizer/commands/eventcmds.cpp +++ b/src/gausskernel/optimizer/commands/eventcmds.cpp @@ -274,8 +274,8 @@ Datum TranslateArg(char *act_name, Node *act_node) break; } case job_type::ARG_JOB_RENAME: { - RangeVar *name_var = (RangeVar *)act_node; - result = CStringGetTextDatum(name_var->relname); + Value *new_name_val = (Value *)act_node; + result = CStringGetTextDatum(new_name_val->val.str); break; } case job_type::ARG_JOB_DEFINER: { @@ -414,13 +414,53 @@ void PrepareFuncArg(CreateEventStmt *stmt, Datum ev_name, Datum schemaName, Func ev_arg->arg[ARG_18] = CStringGetTextDatum(job_definer_oid); } +void CheckEventPrivilege(char* schema_name, char* event_name, AclMode mode, bool is_create_or_alter) +{ + Oid user_oid = GetUserId(); + + /* Check whether user have the permission on the specified schema. */ + Oid schema_oid = get_namespace_oid(schema_name, true); + AclResult acl_result = pg_namespace_aclcheck(schema_oid, user_oid, mode); + if(acl_result != ACLCHECK_OK) { + aclcheck_error(acl_result, ACL_KIND_NAMESPACE, schema_name); + } + + /* Superusers bypass all permission checking. */ + if(superuser_arg(user_oid) || systemDBA_arg(user_oid)) { + return; + } + if(is_create_or_alter) { + return; + } + + /* The owner needs to be checked for the alter and drop operation. */ + HeapTuple tup = NULL; + tup = SearchSysCache2(JOBATTRIBUTENAME, CStringGetTextDatum(event_name), CStringGetTextDatum("owner")); + if(!HeapTupleIsValid(tup)) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("event \"%s\" does not exist", event_name))); + } + + bool isnull = false; + Datum owner_datum = SysCacheGetAttr(JOBATTRIBUTENAME, tup, Anum_gs_job_attribute_attribute_value, &isnull); + char* owner_id_str = TextDatumGetCString(owner_datum); + Oid owner_id = pg_atoi(owner_id_str, sizeof(int32), '\0'); + + if(owner_id != user_oid) { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("only event's owner have the permission to operate object \"%s\"", event_name))); + } + ReleaseSysCache(tup); +} + void CreateEventCommand(CreateEventStmt *stmt) { - Datum schema_name = (stmt->event_name->schemaname) - ? CStringGetDatum(stmt->event_name->schemaname) - : DirectFunctionCall1(namein, CStringGetDatum(get_real_search_schema())); - Datum ev_name = CStringGetTextDatum(stmt->event_name->relname); + char *event_name_str = stmt->event_name->relname; + char *schema_name_str = (stmt->event_name->schemaname) ? stmt->event_name->schemaname : get_real_search_schema(); + CheckEventPrivilege(schema_name_str, event_name_str, ACL_CREATE, true); + Datum schema_name = DirectFunctionCall1(namein, CStringGetDatum(schema_name_str)); + Datum ev_name = CStringGetTextDatum(event_name_str); FunctionCallInfoData ev_arg; const short nrgs_job = ARG_19; @@ -789,17 +829,8 @@ void UpdatePgJobParam(AlterEventStmt *stmt, Datum ev_name) replaces[Anum_pg_job_enable - 1] = true; } if (stmt->new_name) { - Datum schema_name; - Datum new_ev_name; - RangeVar *event_name_var = (RangeVar *)stmt->new_name->arg; - schema_name = (event_name_var->schemaname) - ? DirectFunctionCall1(namein, CStringGetDatum(event_name_var->schemaname)) - : DirectFunctionCall1(namein, CStringGetDatum(get_real_search_schema())); - new_ev_name = CStringGetTextDatum(event_name_var->relname); - values[Anum_pg_job_nspname - 1] = schema_name; - nulls[Anum_pg_job_nspname - 1] = false; - replaces[Anum_pg_job_nspname - 1] = true; - values[Anum_pg_job_job_name - 1] = new_ev_name; + arg_result = TranslateArg(stmt->new_name->defname, stmt->new_name->arg); + values[Anum_pg_job_job_name - 1] = arg_result; nulls[Anum_pg_job_job_name - 1] = false; replaces[Anum_pg_job_job_name - 1] = true; } @@ -808,7 +839,11 @@ void UpdatePgJobParam(AlterEventStmt *stmt, Datum ev_name) void AlterEventCommand(AlterEventStmt *stmt) { - Datum ev_name = CStringGetTextDatum(stmt->event_name->relname); + char *event_name_str = stmt->event_name->relname; + char *schema_name_str = (stmt->event_name->schemaname) ? stmt->event_name->schemaname : get_real_search_schema(); + + Datum ev_name = CStringGetTextDatum(event_name_str); + CheckEventPrivilege(schema_name_str, event_name_str, ACL_USAGE, false); /* Check if object is visible for current user. */ check_object_is_visible(ev_name, false); @@ -828,10 +863,14 @@ void AlterEventCommand(AlterEventStmt *stmt) void DropEventCommand(DropEventStmt *stmt) { - Datum ev_name = CStringGetTextDatum(stmt->event_name->relname); + char *event_name_str = stmt->event_name->relname; + char *schema_name_str = (stmt->event_name->schemaname) ? stmt->event_name->schemaname : get_real_search_schema(); + + Datum ev_name = CStringGetTextDatum(event_name_str); if (CheckEventNotExists(ev_name, stmt->missing_ok)) { return; } + CheckEventPrivilege(schema_name_str, event_name_str, ACL_USAGE, false); FunctionCallInfoData ev_arg; const short nrgs_job = ARG_3; diff --git a/src/test/regress/expected/event.out b/src/test/regress/expected/event.out index 40abb708f4..803e18a51c 100644 --- a/src/test/regress/expected/event.out +++ b/src/test/regress/expected/event.out @@ -884,6 +884,95 @@ drop user if exists event_se_a cascade; drop user if exists event_se_b cascade; drop user if exists event_se_c cascade; drop user if exists event_se_d cascade; +--test privilege +drop user if exists priv_a cascade; +NOTICE: role "priv_a" does not exist, skipping +drop user if exists priv_b cascade; +NOTICE: role "priv_b" does not exist, skipping +drop user if exists priv_c cascade; +NOTICE: role "priv_c" does not exist, skipping +create user priv_a password 'event_123'; +create user priv_b with sysadmin password 'event_123'; +create user priv_c password 'event_123'; +--test CREATE +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +NOTICE: event "priv_e_a" is not exists, skipping +--fail Non-administrator users do not have the permission +create event priv_b.priv_e_a on schedule at sysdate disable do select 1; +ERROR: permission denied for schema priv_b +DETAIL: N/A +\c event_b +grant create on schema priv_b to priv_a; +set role priv_a password 'event_123'; +--success +create event priv_b.priv_e_a on schedule at sysdate disable do select 1; +drop event if exists priv_e_a; +set role priv_b password 'event_123'; +--success +drop event if exists priv_e_b; +NOTICE: event "priv_e_b" is not exists, skipping +create event priv_a.priv_e_b on schedule at sysdate disable do select 1; +drop event if exists priv_e_b; +\c event_b +revoke all on schema priv_b from priv_a; +--test ALTER +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +NOTICE: event "priv_e_a" is not exists, skipping +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; +--fail Non-administrator users do not have the permission +set role priv_c password 'event_123'; +alter event priv_a.priv_e_a do select 2; +ERROR: permission denied for schema priv_a +DETAIL: N/A +\c event_b +grant usage on schema priv_a to priv_c; +set role priv_c password 'event_123'; +--fail only owner and sysadmin user have the permission +alter event priv_a.priv_e_a do select 2; +ERROR: only event's owner have the permission to operate object "priv_e_a" +\c event_b +alter definer = priv_c event priv_a.priv_e_a; +set role priv_c password 'event_123'; +--success +alter event priv_a.priv_e_a do select 2; +drop event if exists priv_e_a; +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +NOTICE: event "priv_e_a" is not exists, skipping +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; +set role priv_b password 'event_123'; +--success +alter event priv_a.priv_e_a do select 2; +drop event if exists priv_e_a; +revoke all on schema priv_a from priv_c; +--test DROP +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +NOTICE: event "priv_e_a" is not exists, skipping +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; +set role priv_c password 'event_123'; +--fail Non-administrator users do not have the permission +drop event if exists priv_e_a; +ERROR: only event's owner have the permission to operate object "priv_e_a" +\c event_b +grant usage on schema priv_a to priv_c; +set role priv_c password 'event_123'; +--fail only owner and sysadmin user have the permission +drop event if exists priv_e_a; +ERROR: only event's owner have the permission to operate object "priv_e_a" +--success +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; +set role priv_b password 'event_123'; +--success +drop event if exists priv_e_a; +\c event_b +drop user if exists priv_a cascade; +drop user if exists priv_b cascade; +drop user if exists priv_c cascade; --test sql help \h CREATE EVENT Command: CREATE EVENT diff --git a/src/test/regress/sql/event.sql b/src/test/regress/sql/event.sql index 677b027462..a4eb40878c 100644 --- a/src/test/regress/sql/event.sql +++ b/src/test/regress/sql/event.sql @@ -347,6 +347,96 @@ drop user if exists event_se_b cascade; drop user if exists event_se_c cascade; drop user if exists event_se_d cascade; +--test privilege +drop user if exists priv_a cascade; +drop user if exists priv_b cascade; +drop user if exists priv_c cascade; + +create user priv_a password 'event_123'; +create user priv_b with sysadmin password 'event_123'; +create user priv_c password 'event_123'; + +--test CREATE +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +--fail Non-administrator users do not have the permission +create event priv_b.priv_e_a on schedule at sysdate disable do select 1; + +\c event_b +grant create on schema priv_b to priv_a; +set role priv_a password 'event_123'; +--success +create event priv_b.priv_e_a on schedule at sysdate disable do select 1; +drop event if exists priv_e_a; + +set role priv_b password 'event_123'; +--success +drop event if exists priv_e_b; +create event priv_a.priv_e_b on schedule at sysdate disable do select 1; +drop event if exists priv_e_b; + +\c event_b +revoke all on schema priv_b from priv_a; + +--test ALTER +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; + +--fail Non-administrator users do not have the permission +set role priv_c password 'event_123'; +alter event priv_a.priv_e_a do select 2; + +\c event_b +grant usage on schema priv_a to priv_c; +set role priv_c password 'event_123'; +--fail only owner and sysadmin user have the permission +alter event priv_a.priv_e_a do select 2; +\c event_b +alter definer = priv_c event priv_a.priv_e_a; +set role priv_c password 'event_123'; +--success +alter event priv_a.priv_e_a do select 2; +drop event if exists priv_e_a; + +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; +set role priv_b password 'event_123'; +--success +alter event priv_a.priv_e_a do select 2; +drop event if exists priv_e_a; +revoke all on schema priv_a from priv_c; + +--test DROP +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; + +set role priv_c password 'event_123'; +--fail Non-administrator users do not have the permission +drop event if exists priv_e_a; + +\c event_b +grant usage on schema priv_a to priv_c; +set role priv_c password 'event_123'; +--fail only owner and sysadmin user have the permission +drop event if exists priv_e_a; + +--success +set role priv_a password 'event_123'; +drop event if exists priv_e_a; +create event priv_a.priv_e_a on schedule at sysdate disable do select 1; + +set role priv_b password 'event_123'; +--success +drop event if exists priv_e_a; + +\c event_b +drop user if exists priv_a cascade; +drop user if exists priv_b cascade; +drop user if exists priv_c cascade; + --test sql help \h CREATE EVENT \h ALTER EVENT -- Gitee