fix: 创建 MySQL 数据库授权已有用户报错 1410

MySQL 8 起 GRANT 不再隐式创建用户,授权已有用户时改为按
mysql.user 中实际存在的 host 逐一授权,用户不存在时明确报错,
并统一空 host 参数回退为 %

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
耗子
2026-07-22 23:31:18 +08:00
parent 9c977c154b
commit d8d1e20c5a
2 changed files with 41 additions and 14 deletions
+29 -2
View File
@@ -123,8 +123,17 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
if req.Username != "" {
if err = operator.PrivilegesGrant(req.Username, req.Name, req.Host); err != nil {
return err
// 授权已有用户时按其实际 host 授权,MySQL 8 起 GRANT 不再隐式创建用户
hosts := []string{req.Host}
if !req.CreateUser {
if hosts = uc.mysqlUserHosts(operator, req.Username); len(hosts) == 0 {
return errors.New(uc.t.Get("database user %s does not exist", req.Username))
}
}
for _, host := range hosts {
if err = operator.PrivilegesGrant(req.Username, req.Name, host); err != nil {
return err
}
}
}
case DatabaseTypePostgresql:
@@ -175,6 +184,24 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return nil
}
// mysqlUserHosts 查询 MySQL 用户实际存在的 host 列表
func (uc *DatabaseUsecase) mysqlUserHosts(operator db.Operator, user string) []string {
rows, err := operator.Query("SELECT host FROM mysql.user WHERE user = ?", user)
if err != nil {
return nil
}
defer func() { _ = rows.Close() }()
var hosts []string
for rows.Next() {
var host string
if rows.Scan(&host) == nil {
hosts = append(hosts, host)
}
}
return hosts
}
func (uc *DatabaseUsecase) Delete(ctx context.Context, serverID uint, name string) error {
server, err := uc.server.Get(serverID)
if err != nil {
+12 -12
View File
@@ -98,8 +98,8 @@ func (r *MySQL) DatabaseSize(name string) (int64, error) {
}
func (r *MySQL) UserCreate(user, password string, host ...string) error {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("CREATE USER IF NOT EXISTS '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges()
@@ -107,8 +107,8 @@ func (r *MySQL) UserCreate(user, password string, host ...string) error {
}
func (r *MySQL) UserDrop(user string, host ...string) error {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("DROP USER IF EXISTS '%s'@'%s'", user, host[0]))
r.flushPrivileges()
@@ -116,8 +116,8 @@ func (r *MySQL) UserDrop(user string, host ...string) error {
}
func (r *MySQL) UserPassword(user, password string, host ...string) error {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges()
@@ -125,8 +125,8 @@ func (r *MySQL) UserPassword(user, password string, host ...string) error {
}
func (r *MySQL) UserPrivileges(user string, host ...string) ([]string, error) {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
rows, err := r.Query(fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host[0]))
@@ -162,8 +162,8 @@ func (r *MySQL) UserPrivileges(user string, host ...string) ([]string, error) {
}
func (r *MySQL) PrivilegesGrant(user, database string, host ...string) error {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("GRANT ALL PRIVILEGES ON %s.* TO '%s'@'%s'", database, user, host[0]))
r.flushPrivileges()
@@ -171,8 +171,8 @@ func (r *MySQL) PrivilegesGrant(user, database string, host ...string) error {
}
func (r *MySQL) PrivilegesRevoke(user, database string, host ...string) error {
if len(host) == 0 {
host = append(host, "%")
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("REVOKE ALL PRIVILEGES ON %s.* FROM '%s'@'%s'", database, user, host[0]))
r.flushPrivileges()