diff --git a/ddl/ddl.go b/ddl/ddl.go index 92aab675c5..c1e8002c3b 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -31,6 +31,7 @@ import ( "github.com/pingcap/tidb/model" "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/parser/coldef" + "github.com/pingcap/tidb/privilege" "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/util" @@ -576,6 +577,15 @@ func (d *ddl) DropTable(ctx context.Context, ti table.Ident) (err error) { if err != nil { return errors.Trace(err) } + // Check Privilege + privChecker := privilege.GetPrivilegeChecker(ctx) + hasPriv, err := privChecker.Check(ctx, schema, tb.Meta(), mysql.DropPriv) + if err != nil { + return errors.Trace(err) + } + if !hasPriv { + return errors.Errorf("You do not have the privilege to drop table %s.%s.", ti.Schema, ti.Name) + } err = kv.RunInNewTxn(d.store, false, func(txn kv.Transaction) error { t := meta.NewMeta(txn) diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 499d7e9ac6..e387e9ac70 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -166,6 +166,11 @@ func (p *UserPrivileges) Check(ctx context.Context, db *model.DBInfo, tbl *model if len(p.User) == 0 { // User current user p.User = variable.GetSessionVars(ctx).User + if len(p.User) == 0 { + // In embedded db mode, user does not need to login. So we do not have username. + // TODO: remove this check latter. + return true, nil + } } err := p.loadPrivileges(ctx) if err != nil { diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 37c74ddca5..23d8ff0912 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -233,6 +233,29 @@ func (t *testPrivilegeSuite) TestShowGrants(c *C) { c.Assert(testutil.CompareUnorderedStringSlice(gs, expected), IsTrue) } +func (t *testPrivilegeSuite) TestDropTablePriv(c *C) { + se := newSession(c, t.store, t.dbName) + ctx, _ := se.(context.Context) + mustExec(c, se, `CREATE TABLE todrop(c int);`) + variable.GetSessionVars(ctx).User = "root@localhost" + mustExec(c, se, `CREATE USER 'drop'@'localhost' identified by '123';`) + mustExec(c, se, `GRANT Select ON test.todrop TO 'drop'@'localhost';`) + + variable.GetSessionVars(ctx).User = "drop@localhost" + mustExec(c, se, `SELECT * FROM todrop;`) + + _, err := se.Execute("DROP TABLE todrop;") + c.Assert(err, NotNil) + + variable.GetSessionVars(ctx).User = "root@localhost" + mustExec(c, se, `GRANT Drop ON test.todrop TO 'drop'@'localhost';`) + + se1 := newSession(c, t.store, t.dbName) + ctx1, _ := se1.(context.Context) + variable.GetSessionVars(ctx1).User = "drop@localhost" + mustExec(c, se1, `DROP TABLE todrop;`) +} + func mustExec(c *C, se tidb.Session, sql string) { _, err := se.Execute(sql) c.Assert(err, IsNil)