From f7b7e0c68ea58d2f73a4b15817f00999064c6731 Mon Sep 17 00:00:00 2001 From: luozihao <1165977584@qq.com> Date: Sat, 25 Mar 2023 11:31:17 +0800 Subject: [PATCH] view definer bugfix --- src/bin/pg_dump/pg_dump.cpp | 8 +-- src/gausskernel/optimizer/commands/view.cpp | 22 ++++++ .../expected/view_definer_permission_test.out | 15 ++++ .../regress/input/view_definer_test.source | 18 ++--- .../regress/output/view_definer_test.source | 70 ++++++++----------- src/test/regress/parallel_schedule0 | 2 +- .../sql/view_definer_permission_test.sql | 10 +++ 7 files changed, 83 insertions(+), 62 deletions(-) create mode 100644 src/test/regress/expected/view_definer_permission_test.out create mode 100644 src/test/regress/sql/view_definer_permission_test.sql diff --git a/src/bin/pg_dump/pg_dump.cpp b/src/bin/pg_dump/pg_dump.cpp index 864880ad9b..c436983940 100644 --- a/src/bin/pg_dump/pg_dump.cpp +++ b/src/bin/pg_dump/pg_dump.cpp @@ -18543,13 +18543,7 @@ static void dumpViewSchema( appendPQExpBuffer(q, "%s CASCADE;\n", fmtId(tbinfo->dobj.name)); } - /* set definer for CREATE VIEW statement */ - appendPQExpBuffer(q, "CREATE "); - if ((gdatcompatibility != NULL) && strcmp(gdatcompatibility, B_FORMAT) == 0 && - tbinfo->rolname != NULL && strlen(tbinfo->rolname) > 0) { - appendPQExpBuffer(q, " DEFINER = \"%s\" ", tbinfo->rolname); - } - appendPQExpBuffer(q, " VIEW %s(%s)", fmtId(tbinfo->dobj.name), schemainfo); + appendPQExpBuffer(q, "CREATE VIEW %s(%s)", fmtId(tbinfo->dobj.name), schemainfo); if ((tbinfo->reloptions != NULL) && strlen(tbinfo->reloptions) > 0) appendPQExpBuffer(q, " WITH (%s)", tbinfo->reloptions); appendPQExpBuffer(q, " AS\n "); diff --git a/src/gausskernel/optimizer/commands/view.cpp b/src/gausskernel/optimizer/commands/view.cpp index 0e9f358967..ca191887b4 100644 --- a/src/gausskernel/optimizer/commands/view.cpp +++ b/src/gausskernel/optimizer/commands/view.cpp @@ -222,6 +222,28 @@ static ObjectAddress DefineVirtualRelation(RangeVar* relation, List* tlist, bool * set definer by AlterTameCmd */ if (definer != NULL) { + /* Get owner to check the permissions. */ + Oid ownerOid = get_role_oid(definer, false); + bool isOwnerChange = false; + if (!OidIsValid(ownerOid)) { + ownerOid = GetUserId(); + } else if (ownerOid != GetUserId()) { + isOwnerChange = true; + } + + if (isOwnerChange && !is_alter) { + /* Check namespace permissions. */ + AclResult aclresult; + Oid namespaceId = RangeVarGetAndCheckCreationNamespace(relation, NoLock, NULL, relkind); + aclresult = pg_namespace_aclcheck(namespaceId, ownerOid, ACL_CREATE); + bool anyResult = false; + if (aclresult != ACLCHECK_OK && !IsSysSchema(namespaceId)) { + anyResult = CheckRelationCreateAnyPrivilege(ownerOid, relkind); + } + if (aclresult != ACLCHECK_OK && !anyResult) { + aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceId)); + } + } atcmd = makeNode(AlterTableCmd); atcmd->subtype = AT_ChangeOwner; atcmd->name = definer; diff --git a/src/test/regress/expected/view_definer_permission_test.out b/src/test/regress/expected/view_definer_permission_test.out new file mode 100644 index 0000000000..87785ca790 --- /dev/null +++ b/src/test/regress/expected/view_definer_permission_test.out @@ -0,0 +1,15 @@ +create database db1 dbcompatibility='B'; +\c db1; +create user use_1136631 password 'Aa123456'; +create table tab_1136631(id int unique,a1 varchar(20)); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "tab_1136631_id_key" for table "tab_1136631" +create view v_1136631 as select * from tab_1136631; +create definer=use_1136631 view v_1136631 as select * from tab_1136631; +ERROR: permission denied for schema public +DETAIL: N/A +create or replace definer=use_1136631 view v_1136631 as select * from tab_1136631; +ERROR: permission denied for schema public +DETAIL: N/A +\c postgres +drop database db1; +drop user use_1136631 cascade; diff --git a/src/test/regress/input/view_definer_test.source b/src/test/regress/input/view_definer_test.source index cfb3785b0e..876cfa025e 100644 --- a/src/test/regress/input/view_definer_test.source +++ b/src/test/regress/input/view_definer_test.source @@ -33,21 +33,12 @@ end; SELECT c.relname as view_name, u.usename as rolname FROM pg_class c, pg_user u WHERE u.usesysid = c.relowner AND relname like '%definer_test_view%' order by view_name; -- dump all views -\! @abs_bindir@/gs_dump test_db -p @portstring@ --include-depend-objs --exclude-self | grep -vE '^SET|^REVOKE|^GRANT|^--|^gs_dump|^COMMENT|^ALTER|^DROP'| tr -s ‘'\n' > @abs_bindir@/definer_view_dump.sql 2>&1 +\! @abs_bindir@/gs_dump test_db -p @portstring@ --include-depend-objs --exclude-self | grep -vE '^SET|^REVOKE|^GRANT|^--|^gs_dump|^COMMENT|^DROP'| tr -s '\n' > @abs_bindir@/definer_view_dump.sql 2>&1 \! cat @abs_bindir@/definer_view_dump.sql +\! @abs_bindir@/gs_dump test_db -p @portstring@ -F c -f @abs_bindir@/definer_view_dump.dmp +CREATE DATABASE target DBCOMPATIBILITY 'B'; -DROP VIEW definer_test_view1; -DROP VIEW definer_test_view2; -DROP VIEW definer_test_view3; -DROP FUNCTION pro_1107262(n int); -DROP TABLE tab_1107262; - -DROP SCHEMA "Test_User"; -DROP SCHEMA test_user2; - -GRANT ALL PRIVILEGES TO test_user2; - -\i @abs_bindir@/definer_view_dump.sql +\! @abs_bindir@/gs_restore -d target -p @portstring@ @abs_bindir@/definer_view_dump.dmp SELECT * FROM definer_test_view1; SELECT * FROM definer_test_view2; @@ -72,6 +63,7 @@ create database test_2; drop database test_db; drop database test_1; drop database test_2; +drop database target; DROP USER "Test_User"; DROP USER test_user2; DROP USER "Root_Test" CASCADE; diff --git a/src/test/regress/output/view_definer_test.source b/src/test/regress/output/view_definer_test.source index 471e0ff215..aff9730f44 100755 --- a/src/test/regress/output/view_definer_test.source +++ b/src/test/regress/output/view_definer_test.source @@ -58,11 +58,13 @@ SELECT c.relname as view_name, u.usename as rolname FROM pg_class c, pg_user u W (3 rows) -- dump all views -\! @abs_bindir@/gs_dump test_db -p @portstring@ --include-depend-objs --exclude-self | grep -vE '^SET|^REVOKE|^GRANT|^--|^gs_dump|^COMMENT|^ALTER|^DROP'| tr -s ‘'\n' > @abs_bindir@/definer_view_dump.sql 2>&1 +\! @abs_bindir@/gs_dump test_db -p @portstring@ --include-depend-objs --exclude-self | grep -vE '^SET|^REVOKE|^GRANT|^--|^gs_dump|^COMMENT|^DROP'| tr -s '\n' > @abs_bindir@/definer_view_dump.sql 2>&1 \! cat @abs_bindir@/definer_view_dump.sql CREATE SCHEMA "Test_User"; +ALTER SCHEMA "Test_User" OWNER TO "Test_User"; CREATE SCHEMA test_user2; +ALTER SCHEMA test_user2 OWNER TO test_user2; CREATE DEFINER = "Root_Test" PROCEDURE pro_1107262(n int) NOT SHIPPABLE AS DECLARE begin @@ -72,53 +74,38 @@ n:=n+1; until n>10 end repeat; end; / -CREATE DEFINER = "Root_Test" VIEW definer_test_view1(log) AS +ALTER PROCEDURE public.pro_1107262(n integer) OWNER TO "Root_Test"; +CREATE VIEW definer_test_view1(log) AS SELECT log((10)::numeric, (1000)::numeric) AS log; -CREATE DEFINER = "test_user2" VIEW definer_test_view2(log) AS +ALTER VIEW public.definer_test_view1 OWNER TO "Root_Test"; +CREATE VIEW definer_test_view2(log) AS SELECT log((10)::numeric, (100)::numeric) AS log; -CREATE DEFINER = "Test_User" VIEW definer_test_view3(log) AS +ALTER VIEW public.definer_test_view2 OWNER TO test_user2; +CREATE VIEW definer_test_view3(log) AS SELECT log((10)::numeric, (100)::numeric) AS log; +ALTER VIEW public.definer_test_view3 OWNER TO "Test_User"; CREATE TABLE tab_1107262 ( id integer, c1 integer ) WITH (orientation=row, compression=no); +ALTER TABLE public.tab_1107262 OWNER TO "Root_Test"; COPY tab_1107262 (id, c1) FROM stdin; \. ; -DROP VIEW definer_test_view1; -DROP VIEW definer_test_view2; -DROP VIEW definer_test_view3; -DROP FUNCTION pro_1107262(n int); -DROP TABLE tab_1107262; -DROP SCHEMA "Test_User"; -DROP SCHEMA test_user2; -GRANT ALL PRIVILEGES TO test_user2; -\i @abs_bindir@/definer_view_dump.sql -CREATE SCHEMA "Test_User"; -CREATE SCHEMA test_user2; -CREATE DEFINER = "Root_Test" PROCEDURE pro_1107262(n int) NOT SHIPPABLE - AS DECLARE -begin -repeat -insert into tab_1107262 values(n,n*2); -n:=n+1; -until n>10 end repeat; -end; -/ -CREATE DEFINER = "Root_Test" VIEW definer_test_view1(log) AS - SELECT log((10)::numeric, (1000)::numeric) AS log; -CREATE DEFINER = "test_user2" VIEW definer_test_view2(log) AS - SELECT log((10)::numeric, (100)::numeric) AS log; -CREATE DEFINER = "Test_User" VIEW definer_test_view3(log) AS - SELECT log((10)::numeric, (100)::numeric) AS log; -CREATE TABLE tab_1107262 ( - id integer, - c1 integer -) -WITH (orientation=row, compression=no); -COPY tab_1107262 (id, c1) FROM stdin; -; +\! @abs_bindir@/gs_dump test_db -p @portstring@ -F c -f @abs_bindir@/definer_view_dump.dmp +--?gs_dump[port='@portstring@'][test_db].* +--?gs_dump[port='@portstring@'][test_db].* +--?gs_dump[port='@portstring@'][test_db].* +--?gs_dump[port='@portstring@'][test_db].* +CREATE DATABASE target DBCOMPATIBILITY 'B'; +\! @abs_bindir@/gs_restore -d target -p @portstring@ @abs_bindir@/definer_view_dump.dmp +start restore operation ... +table tab_1107262 complete data imported ! +Finish reading 12 SQL statements! +end restore operation ... +restore operation successful +--?.* SELECT * FROM definer_test_view1; log -------------------- @@ -151,10 +138,10 @@ create database test_1; create table startwith_t(id int, level int, connect_by_isleaf int, connect_by_iscycle int); create view startwith_v as select id, connect_by_isleaf as level, level as connect_by_isleaf from startwith_t; \! @abs_bindir@/gs_dump test_1 -p @portstring@ -f @abs_bindir@/dump_postgres.sql ---?.* ---?.* ---?.* ---?.* +--?gs_dump[port='@portstring@'][test_1].* +--?gs_dump[port='@portstring@'][test_1].* +--?gs_dump[port='@portstring@'][test_1].* +--?gs_dump[port='@portstring@'][test_1].* drop database if exists test_2; NOTICE: database "test_2" does not exist, skipping create database test_2; @@ -187,6 +174,7 @@ GRANT drop database test_db; drop database test_1; drop database test_2; +drop database target; DROP USER "Test_User"; DROP USER test_user2; DROP USER "Root_Test" CASCADE; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index aa14fd8f0e..82736e0628 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -66,7 +66,7 @@ test: pl_debugger_server pl_debugger_client test: update_for_wait_s1 update_for_wait_s2 test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt deserialize_func test: large_sequence int16 gs_dump_sequence -test: gs_dump_tableof view_definer_test +test: gs_dump_tableof view_definer_test view_definer_permission_test test: analyze_commands #test: single_node_job test: single_node_ddl diff --git a/src/test/regress/sql/view_definer_permission_test.sql b/src/test/regress/sql/view_definer_permission_test.sql new file mode 100644 index 0000000000..8eb1f4ae45 --- /dev/null +++ b/src/test/regress/sql/view_definer_permission_test.sql @@ -0,0 +1,10 @@ +create database db1 dbcompatibility='B'; +\c db1; +create user use_1136631 password 'Aa123456'; +create table tab_1136631(id int unique,a1 varchar(20)); +create view v_1136631 as select * from tab_1136631; +create definer=use_1136631 view v_1136631 as select * from tab_1136631; +create or replace definer=use_1136631 view v_1136631 as select * from tab_1136631; +\c postgres +drop database db1; +drop user use_1136631 cascade; \ No newline at end of file -- Gitee