package clusters import ( "encoding/json" "fmt" "strconv" "strings" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils" "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/maps" "google.golang.org/grpc/metadata" ) type ClusterSettingsAction struct { actionutils.ParentAction } func (this *ClusterSettingsAction) Init() { this.Nav("httpdns", "cluster", "settings") } func (this *ClusterSettingsAction) RunGet(params struct { ClusterId int64 Section string }) { httpdnsutils.AddLeftMenu(this.Parent()) cluster, err := findClusterMap(this.Parent(), params.ClusterId) if err != nil { this.ErrorPage(err) return } httpdnsutils.AddClusterTabbar(this.Parent(), cluster.GetString("name"), params.ClusterId, "setting") section := strings.TrimSpace(params.Section) if len(section) == 0 { section = "basic" } settings := maps.Map{ "name": cluster.GetString("name"), "gatewayDomain": cluster.GetString("gatewayDomain"), "cacheTtl": cluster.GetInt("defaultTTL"), "fallbackTimeout": cluster.GetInt("fallbackTimeout"), "installDir": cluster.GetString("installDir"), "isOn": cluster.GetBool("isOn"), "autoRemoteStart": cluster.GetBool("autoRemoteStart"), "accessLogIsOn": cluster.GetBool("accessLogIsOn"), "timeZone": cluster.GetString("timeZone"), } if settings.GetInt("cacheTtl") <= 0 { settings["cacheTtl"] = 60 } if settings.GetInt("fallbackTimeout") <= 0 { settings["fallbackTimeout"] = 300 } if len(settings.GetString("installDir")) == 0 { settings["installDir"] = "/root/edge-httpdns" } if len(settings.GetString("timeZone")) == 0 { settings["timeZone"] = "Asia/Shanghai" } listenAddresses := []*serverconfigs.NetworkAddressConfig{ { Protocol: serverconfigs.ProtocolTLS, Host: "", PortRange: "443", }, } sslPolicy := &sslconfigs.SSLPolicy{ IsOn: true, MinVersion: "TLS 1.1", } if rawTLS := strings.TrimSpace(cluster.GetString("tlsPolicyJSON")); len(rawTLS) > 0 { tlsConfig := maps.Map{} if err := json.Unmarshal([]byte(rawTLS), &tlsConfig); err == nil { if listenRaw := tlsConfig.Get("listen"); listenRaw != nil { if data, err := json.Marshal(listenRaw); err == nil { _ = json.Unmarshal(data, &listenAddresses) } } if sslRaw := tlsConfig.Get("sslPolicy"); sslRaw != nil { if data, err := json.Marshal(sslRaw); err == nil { _ = json.Unmarshal(data, sslPolicy) } } } } this.Data["activeSection"] = section cid := strconv.FormatInt(params.ClusterId, 10) this.Data["leftMenuItems"] = []map[string]interface{}{ {"name": "基础设置", "url": "/httpdns/clusters/cluster/settings?clusterId=" + cid + "§ion=basic", "isActive": section == "basic"}, {"name": "TLS", "url": "/httpdns/clusters/cluster/settings?clusterId=" + cid + "§ion=tls", "isActive": section == "tls"}, } this.Data["cluster"] = cluster this.Data["settings"] = settings this.Data["tlsConfig"] = maps.Map{ "isOn": true, "listen": listenAddresses, "sslPolicy": sslPolicy, } this.Data["timeZoneGroups"] = nodeconfigs.FindAllTimeZoneGroups() this.Data["timeZoneLocations"] = nodeconfigs.FindAllTimeZoneLocations() timeZoneStr := settings.GetString("timeZone") if len(timeZoneStr) == 0 { timeZoneStr = nodeconfigs.DefaultTimeZoneLocation } this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(timeZoneStr) this.Show() } func (this *ClusterSettingsAction) RunPost(params struct { ClusterId int64 Name string GatewayDomain string CacheTtl int32 FallbackTimeout int32 InstallDir string IsOn bool AutoRemoteStart bool AccessLogIsOn bool TimeZone string Addresses []byte SslPolicyJSON []byte Must *actions.Must CSRF *actionutils.CSRF }) { params.Name = strings.TrimSpace(params.Name) params.GatewayDomain = strings.TrimSpace(params.GatewayDomain) params.InstallDir = strings.TrimSpace(params.InstallDir) params.Must.Field("clusterId", params.ClusterId).Gt(0, "请选择集群") params.Must.Field("name", params.Name).Require("请输入集群名称") params.Must.Field("gatewayDomain", params.GatewayDomain).Require("请输入服务域名") cluster, err := findClusterMap(this.Parent(), params.ClusterId) if err != nil { this.ErrorPage(err) return } // 开关项按请求值强制覆盖:未提交/空值都视为 false,支持取消勾选 autoRemoteStartRaw := strings.ToLower(strings.TrimSpace(this.ParamString("autoRemoteStart"))) params.AutoRemoteStart = autoRemoteStartRaw == "1" || autoRemoteStartRaw == "true" || autoRemoteStartRaw == "on" || autoRemoteStartRaw == "yes" || autoRemoteStartRaw == "enabled" accessLogIsOnRaw := strings.ToLower(strings.TrimSpace(this.ParamString("accessLogIsOn"))) params.AccessLogIsOn = accessLogIsOnRaw == "1" || accessLogIsOnRaw == "true" || accessLogIsOnRaw == "on" || accessLogIsOnRaw == "yes" || accessLogIsOnRaw == "enabled" isOnRaw := strings.ToLower(strings.TrimSpace(this.ParamString("isOn"))) params.IsOn = isOnRaw == "1" || isOnRaw == "true" || isOnRaw == "on" || isOnRaw == "yes" || isOnRaw == "enabled" // 时区为空时继承当前值,再兜底默认值 params.TimeZone = strings.TrimSpace(this.ParamString("timeZone")) if len(params.TimeZone) == 0 { params.TimeZone = strings.TrimSpace(cluster.GetString("timeZone")) } if len(params.TimeZone) == 0 { params.TimeZone = "Asia/Shanghai" } if params.CacheTtl <= 0 { params.CacheTtl = 60 } if params.FallbackTimeout <= 0 { params.FallbackTimeout = 300 } if len(params.InstallDir) == 0 { params.InstallDir = "/root/edge-httpdns" } tlsConfig := maps.Map{} if rawTLS := strings.TrimSpace(cluster.GetString("tlsPolicyJSON")); len(rawTLS) > 0 { _ = json.Unmarshal([]byte(rawTLS), &tlsConfig) } if len(params.Addresses) > 0 { var addresses []*serverconfigs.NetworkAddressConfig if err := json.Unmarshal(params.Addresses, &addresses); err != nil { this.Fail("监听端口配置格式不正确") return } tlsConfig["listen"] = addresses } if len(params.SslPolicyJSON) > 0 { sslPolicy := &sslconfigs.SSLPolicy{} if err := json.Unmarshal(params.SslPolicyJSON, sslPolicy); err != nil { this.Fail("TLS 配置格式不正确") return } tlsConfig["sslPolicy"] = sslPolicy } var tlsPolicyJSON []byte if len(tlsConfig) > 0 { tlsPolicyJSON, err = json.Marshal(tlsConfig) if err != nil { this.ErrorPage(err) return } } updateReq := &pb.UpdateHTTPDNSClusterRequest{ ClusterId: params.ClusterId, Name: params.Name, ServiceDomain: params.GatewayDomain, DefaultTTL: params.CacheTtl, FallbackTimeoutMs: params.FallbackTimeout, InstallDir: params.InstallDir, TlsPolicyJSON: tlsPolicyJSON, IsOn: params.IsOn, IsDefault: false, AutoRemoteStart: params.AutoRemoteStart, AccessLogIsOn: params.AccessLogIsOn, TimeZone: params.TimeZone, } updateCtx := metadata.AppendToOutgoingContext( this.AdminContext(), "x-httpdns-auto-remote-start", fmt.Sprintf("%t", updateReq.GetAutoRemoteStart()), "x-httpdns-access-log-is-on", fmt.Sprintf("%t", updateReq.GetAccessLogIsOn()), "x-httpdns-time-zone", updateReq.GetTimeZone(), ) _, err = this.RPC().HTTPDNSClusterRPC().UpdateHTTPDNSCluster(updateCtx, updateReq) if err != nil { this.ErrorPage(err) return } this.Success() }