fix: 数据源编辑密码保留 + Redis ACL 认证支持

后端:
- UpdateInstance: 空密码和'******'都不更新密码字段,防止编辑后丢失密码
- testRedis/getRedisClient/getRedisMetrics: 增加 Username 参数支持 Redis 6.0+ ACL 认证
- username 为 'default' 或空时走传统密码认证模式

前端:
- EditInstanceDialog: Redis 用户名字段提示'6.0+ ACL 可选',密码 placeholder 改为'不修改请留空'
- CreateInstanceForm: Redis 类型也显示用户名输入框(可选),创建/测试连接时 Redis username 为空则不传
- Redis 提示文案从'无需用户名'改为'6.0+ ACL 支持用户名+密码认证'
This commit is contained in:
logan committed 2026-05-31 23:55:18 +08:00
1 parent bfb64d4dce
commit 8af868b3ca
5 files changed
+59 -34

No files matched your search

+15 -3
View File
@@ -42,7 +42,7 @@ func testDBConnection(instance *model.Instance) (bool, string) {
}
return testPostgreSQL(ctx, instance.Host, instance.Port, instance.Username, password, dbname)
case "redis":
ok, msg, _ := testRedis(ctx, instance.Host, instance.Port, password)
ok, msg, _ := testRedis(ctx, instance.Host, instance.Port, instance.Username, password)
return ok, msg
default:
return false, fmt.Sprintf("Unsupported database type: %s", instance.DBType)
@@ -71,7 +71,7 @@ func testDBConnectionFull(instance *model.Instance) *ConnectionResult {
ok, msg := testPostgreSQL(ctx, instance.Host, instance.Port, instance.Username, password, dbname)
return &ConnectionResult{Success: ok, Message: msg, Version: extractVersion(msg, "version: ")}
case "redis":
ok, msg, isCluster := testRedis(ctx, instance.Host, instance.Port, password)
ok, msg, isCluster := testRedis(ctx, instance.Host, instance.Port, instance.Username, password)
return &ConnectionResult{Success: ok, Message: msg, Version: extractVersion(msg, "version: "), ClusterMode: isCluster}
default:
return &ConnectionResult{Success: false, Message: fmt.Sprintf("Unsupported database type: %s", instance.DBType)}
@@ -132,10 +132,16 @@ func testPostgreSQL(ctx context.Context, host string, port int, user, pass, dbna
return true, fmt.Sprintf("PostgreSQL connection successful (version: %s)", ver)
}
func testRedis(ctx context.Context, host string, port int, pass string) (bool, string, bool) {
func testRedis(ctx context.Context, host string, port int, username, pass string) (bool, string, bool) {
addr := fmt.Sprintf("%s:%d", host, port)
// Redis 6.0+ ACL: empty username = traditional password-only auth
redisUsername := username
if redisUsername == "default" {
redisUsername = ""
}
rdb := redis.NewClient(&redis.Options{
Addr: addr,
Username: redisUsername,
Password: pass,
DB: 0,
DialTimeout: 10 * time.Second,
@@ -199,11 +205,17 @@ func getRedisMetrics(instance *model.Instance) map[string]interface{} {
"cluster_mode": isCluster,
}
// Redis 6.0+ ACL support
redisUsername := instance.Username
if redisUsername == "default" {
redisUsername = ""
}
var info string
// For metrics collection, always use single-node connection even for clusters.
// ClusterClient does topology discovery which can timeout if some nodes are unreachable.
rdb := redis.NewClient(&redis.Options{
Addr: addr,
Username: redisUsername,
Password: password,
DB: 0,
DialTimeout: 5 * time.Second,