Skip to content

Commit

Permalink
*: bind user to some resource group (#39561)
Browse files Browse the repository at this point in the history
ref #38825
  • Loading branch information
BornChanger committed Dec 7, 2022
1 parent edabc32 commit 8e3cbac
Show file tree
Hide file tree
Showing 12 changed files with 5,441 additions and 5,311 deletions.
29 changes: 22 additions & 7 deletions executor/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -946,14 +946,23 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm
passwdlockinfo.passwordExpired = "Y"
}

var userAttributes any = nil
var userAttributes []string

if s.CommentOrAttributeOption != nil {
if s.CommentOrAttributeOption.Type == ast.UserCommentType {
userAttributes = fmt.Sprintf("{\"metadata\": {\"comment\": \"%s\"}}", s.CommentOrAttributeOption.Value)
userAttributes = append(userAttributes, fmt.Sprintf("\"metadata\": {\"comment\": \"%s\"}", s.CommentOrAttributeOption.Value))
} else if s.CommentOrAttributeOption.Type == ast.UserAttributeType {
userAttributes = fmt.Sprintf("{\"metadata\": %s}", s.CommentOrAttributeOption.Value)
userAttributes = append(userAttributes, fmt.Sprintf("\"metadata\": %s", s.CommentOrAttributeOption.Value))
}
}
resourceGroupName := "default"
if s.ResourceGroupNameOption != nil {
if s.ResourceGroupNameOption.Type == ast.UserResourceGroupName {
resourceGroupName = s.ResourceGroupNameOption.Value
}
}
userAttributes = append(userAttributes, fmt.Sprintf("\"resource_group\": \"%s\"", resourceGroupName))
userAttributesStr := fmt.Sprintf("{%s}", strings.Join(userAttributes, ","))

tokenIssuer := ""
for _, authTokenOption := range s.AuthTokenOrTLSOptions {
Expand Down Expand Up @@ -1043,7 +1052,7 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm
}

hostName := strings.ToLower(spec.User.Hostname)
sqlexec.MustFormatSQL(sql, valueTemplate, hostName, spec.User.Username, pwd, authPlugin, userAttributes, passwdlockinfo.lockAccount, recordTokenIssuer, passwdlockinfo.passwordExpired, passwdlockinfo.passwordLifetime)
sqlexec.MustFormatSQL(sql, valueTemplate, hostName, spec.User.Username, pwd, authPlugin, userAttributesStr, passwdlockinfo.lockAccount, recordTokenIssuer, passwdlockinfo.passwordExpired, passwdlockinfo.passwordLifetime)
// add Password_reuse_time value.
if passwdlockinfo.passwordReuseInterval != notSpecified {
sqlexec.MustFormatSQL(sql, `, %?`, passwdlockinfo.passwordReuseInterval)
Expand Down Expand Up @@ -1583,13 +1592,19 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt)
fields = append(fields, alterField{"password_lifetime=%?", passwdlockinfo.passwordLifetime})
}

var newAttributes []string
if s.CommentOrAttributeOption != nil {
newAttributesStr := ""
if s.CommentOrAttributeOption.Type == ast.UserCommentType {
newAttributesStr = fmt.Sprintf(`{"metadata": {"comment": "%s"}}`, s.CommentOrAttributeOption.Value)
newAttributes = append(newAttributes, fmt.Sprintf(`"metadata": {"comment": "%s"}`, s.CommentOrAttributeOption.Value))
} else {
newAttributesStr = fmt.Sprintf(`{"metadata": %s}`, s.CommentOrAttributeOption.Value)
newAttributes = append(newAttributes, fmt.Sprintf(`"metadata": %s`, s.CommentOrAttributeOption.Value))
}
}
if s.ResourceGroupNameOption != nil && s.ResourceGroupNameOption.Type == ast.UserResourceGroupName {
newAttributes = append(newAttributes, fmt.Sprintf(`"resource_group": "%s"`, s.ResourceGroupNameOption.Value))
}
if len(newAttributes) > 0 {
newAttributesStr := fmt.Sprintf("{%s}", strings.Join(newAttributes, ","))
fields = append(fields, alterField{"user_attributes=json_merge_patch(coalesce(user_attributes, '{}'), %?)", newAttributesStr})
}

Expand Down
10 changes: 6 additions & 4 deletions executor/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ func TestUserAttributes(t *testing.T) {
_, err := rootTK.Exec(`CREATE USER testuser2 ATTRIBUTE '{"name": "Tom", age: 19}'`)
rootTK.MustExec(`CREATE USER testuser2`)
require.Error(t, err)
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser'`).Check(testkit.Rows(`{"metadata": {"comment": "1234"}}`))
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser1'`).Check(testkit.Rows(`{"metadata": {"age": 19, "name": "Tom"}}`))
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser2'`).Check(testkit.Rows(`<nil>`))
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser'`).Check(testkit.Rows(`{"metadata": {"comment": "1234"}, "resource_group": "default"}`))
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser1'`).Check(testkit.Rows(`{"metadata": {"age": 19, "name": "Tom"}, "resource_group": "default"}`))
rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser2'`).Check(testkit.Rows(`{"resource_group": "default"}`))
rootTK.MustQueryWithContext(ctx, `SELECT attribute FROM information_schema.user_attributes WHERE user = 'testuser'`).Check(testkit.Rows(`{"comment": "1234"}`))
rootTK.MustQueryWithContext(ctx, `SELECT attribute FROM information_schema.user_attributes WHERE user = 'testuser1'`).Check(testkit.Rows(`{"age": 19, "name": "Tom"}`))
rootTK.MustQueryWithContext(ctx, `SELECT attribute->>"$.age" AS age, attribute->>"$.name" AS name FROM information_schema.user_attributes WHERE user = 'testuser1'`).Check(testkit.Rows(`19 Tom`))
Expand Down Expand Up @@ -127,7 +127,9 @@ func TestUserAttributes(t *testing.T) {
// https://github.com/pingcap/tidb/issues/39207
rootTK.MustExec("create user usr1@'%' identified by 'passord'")
rootTK.MustExec("alter user usr1 comment 'comment1'")
rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}}`))
rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "default"}`))
rootTK.MustExec("alter user usr1 resource group 'rg1'")
rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "rg1"}`))
}

func TestValidatePassword(t *testing.T) {
Expand Down
29 changes: 29 additions & 0 deletions parser/ast/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,8 @@ const (

UserCommentType
UserAttributeType

UserResourceGroupName
)

type PasswordOrLockOption struct {
Expand Down Expand Up @@ -1573,6 +1575,19 @@ func (c *CommentOrAttributeOption) Restore(ctx *format.RestoreCtx) error {
return nil
}

type ResourceGroupNameOption struct {
Type int
Value string
}

func (c *ResourceGroupNameOption) Restore(ctx *format.RestoreCtx) error {
if c.Type == UserResourceGroupName {
ctx.WriteKeyWord(" RESOURCE GROUP ")
ctx.WriteString(c.Value)
}
return nil
}

// CreateUserStmt creates user account.
// See https://dev.mysql.com/doc/refman/8.0/en/create-user.html
type CreateUserStmt struct {
Expand All @@ -1585,6 +1600,7 @@ type CreateUserStmt struct {
ResourceOptions []*ResourceOption
PasswordOrLockOptions []*PasswordOrLockOption
CommentOrAttributeOption *CommentOrAttributeOption
ResourceGroupNameOption *ResourceGroupNameOption
}

// Restore implements Node interface.
Expand Down Expand Up @@ -1643,6 +1659,12 @@ func (n *CreateUserStmt) Restore(ctx *format.RestoreCtx) error {
}
}

if n.ResourceGroupNameOption != nil {
if err := n.ResourceGroupNameOption.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.ResourceGroupNameOption")
}
}

return nil
}

Expand Down Expand Up @@ -1679,6 +1701,7 @@ type AlterUserStmt struct {
ResourceOptions []*ResourceOption
PasswordOrLockOptions []*PasswordOrLockOption
CommentOrAttributeOption *CommentOrAttributeOption
ResourceGroupNameOption *ResourceGroupNameOption
}

// Restore implements Node interface.
Expand Down Expand Up @@ -1740,6 +1763,12 @@ func (n *AlterUserStmt) Restore(ctx *format.RestoreCtx) error {
}
}

if n.ResourceGroupNameOption != nil {
if err := n.ResourceGroupNameOption.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.ResourceGroupNameOption")
}
}

return nil
}

Expand Down
Loading

0 comments on commit 8e3cbac

Please sign in to comment.