From 4c751e7c8a8fef0ae070aa43042d1a993c53a014 Mon Sep 17 00:00:00 2001 From: Hangjie Mo Date: Mon, 14 Apr 2025 18:05:46 +0800 Subject: [PATCH] planner: check drop privilege for `CREATE OR REPLACE VEIW` stmt (#60519) close pingcap/tidb#60469 --- pkg/planner/core/planbuilder.go | 13 ++++++++-- .../r/privilege/privileges.result | 13 ++++++++++ .../t/privilege/privileges.test | 24 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/pkg/planner/core/planbuilder.go b/pkg/planner/core/planbuilder.go index 6551f116b4..332bd25aec 100644 --- a/pkg/planner/core/planbuilder.go +++ b/pkg/planner/core/planbuilder.go @@ -5199,12 +5199,21 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (base.Plan if len(v.Cols) != schema.Len() { return nil, dbterror.ErrViewWrongList } + var authCreateErr, authDropErr error if user := b.ctx.GetSessionVars().User; user != nil { - authErr = plannererrors.ErrTableaccessDenied.GenWithStackByArgs("CREATE VIEW", user.AuthUsername, + authCreateErr = plannererrors.ErrTableaccessDenied.GenWithStackByArgs("CREATE VIEW", user.AuthUsername, user.AuthHostname, v.ViewName.Name.L) + if v.OrReplace { + authDropErr = plannererrors.ErrTableaccessDenied.GenWithStackByArgs("DROP", user.AuthUsername, + user.AuthHostname, v.ViewName.Name.L) + } } b.visitInfo = appendVisitInfo(b.visitInfo, mysql.CreateViewPriv, v.ViewName.Schema.L, - v.ViewName.Name.L, "", authErr) + v.ViewName.Name.L, "", authCreateErr) + if v.OrReplace { + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.DropPriv, v.ViewName.Schema.L, + v.ViewName.Name.L, "", authDropErr) + } if v.Definer.CurrentUser && b.ctx.GetSessionVars().User != nil { v.Definer = b.ctx.GetSessionVars().User } diff --git a/tests/integrationtest/r/privilege/privileges.result b/tests/integrationtest/r/privilege/privileges.result index 82d821f44b..9d72494e4d 100644 --- a/tests/integrationtest/r/privilege/privileges.result +++ b/tests/integrationtest/r/privilege/privileges.result @@ -732,3 +732,16 @@ Database INFORMATION_SCHEMA tmpdb create temporary table tmpdb.tmp(id int); +use privilege__privileges; +DROP USER IF EXISTS foo; +CREATE USER foo; +DROP VIEW IF EXISTS v, v1; +GRANT SELECT ON privilege__privileges.* TO foo; +CREATE OR REPLACE VIEW v AS SELECT 1; +Error 1142 (42000): CREATE VIEW command denied to user 'foo'@'%' for table 'v' +GRANT CREATE VIEW ON privilege__privileges.* TO foo; +CREATE VIEW v AS SELECT 1; +CREATE OR REPLACE VIEW v AS SELECT 1, 1; +Error 1142 (42000): DROP command denied to user 'foo'@'%' for table 'v' +CREATE OR REPLACE VIEW v1 AS SELECT 1, 1; +Error 1142 (42000): DROP command denied to user 'foo'@'%' for table 'v1' diff --git a/tests/integrationtest/t/privilege/privileges.test b/tests/integrationtest/t/privilege/privileges.test index bc6dc953bd..d0c5a41315 100644 --- a/tests/integrationtest/t/privilege/privileges.test +++ b/tests/integrationtest/t/privilege/privileges.test @@ -990,3 +990,27 @@ create temporary table tmpdb.tmp(id int); disconnect test_user; connection default; +# TestIssue60469 +use privilege__privileges; +DROP USER IF EXISTS foo; +CREATE USER foo; +DROP VIEW IF EXISTS v, v1; +GRANT SELECT ON privilege__privileges.* TO foo; + +connect (foo, localhost, foo,,privilege__privileges); +--error 1142 +CREATE OR REPLACE VIEW v AS SELECT 1; + +connection default; +GRANT CREATE VIEW ON privilege__privileges.* TO foo; + +connection foo; +CREATE VIEW v AS SELECT 1; +--error 1142 +CREATE OR REPLACE VIEW v AS SELECT 1, 1; +--error 1142 +CREATE OR REPLACE VIEW v1 AS SELECT 1, 1; + +disconnect foo; +connection default; +