Merge upstream monitoring features preserving domain extensions and require fixed Go toolchain

This commit is contained in:
Codex committed 2026-10-22 23:50:03 +08:00
commit 71dd21269b
92 files changed
+8557 -874

No files matched your search

+32
View File
@@ -66,6 +66,9 @@ type ConfigDashboard struct {
AdminTemplate string `koanf:"admin_template" json:"admin_template,omitempty"`
EnablePlainIPInNotification bool `koanf:"enable_plain_ip_in_notification" json:"enable_plain_ip_in_notification,omitempty"` // 通知信息IP不打码
// AllowJWTIPChange disables the IP binding check for browser login sessions.
// Keep this disabled by default so a stolen JWT remains bound to its issuing IP.
AllowJWTIPChange bool `koanf:"allow_jwt_ip_change" json:"allow_jwt_ip_change,omitempty"`
EnableMCP bool `koanf:"enable_mcp" json:"enable_mcp,omitempty"` // 是否启用 MCP 入口(默认关闭;启用前请审视 PAT scope/whitelist)
@@ -91,6 +94,10 @@ type ConfigDashboard struct {
AdminEmail string `koanf:"admin_email" json:"admin_email,omitempty"`
DomainExpiryNotificationDays string `koanf:"domain_expiry_notification_days" json:"domain_expiry_notification_days,omitempty"`
ServerExpiryNotificationDays string `koanf:"server_expiry_notification_days" json:"server_expiry_notification_days,omitempty"`
// OnlineStatsDays 设备在线时间段统计的保留与查询窗口(天)。
// 取值范围 [MinOnlineStatsDays, MaxOnlineStatsDays],默认 DefaultOnlineStatsDays。
OnlineStatsDays int `koanf:"online_stats_days" json:"online_stats_days,omitempty"`
}
type Config struct {
@@ -118,6 +125,10 @@ type Config struct {
// SettingResponse 按值拷贝 ConfigDashboard 触发 copylocks。
mcpEnabled atomic.Bool `koanf:"-" json:"-" yaml:"-"`
// jwtIPChangeAllowed mirrors AllowJWTIPChange for concurrent authentication
// and setting updates. Keep atomic fields outside ConfigDashboard.
jwtIPChangeAllowed atomic.Bool `koanf:"-" json:"-" yaml:"-"`
// oauth2 配置
Oauth2 map[string]*Oauth2Config `koanf:"oauth2" json:"oauth2,omitempty"`
@@ -240,6 +251,15 @@ func (c *Config) Read(path string, frontendTemplates []FrontendTemplate) error {
c.JWTTimeout = 1
}
if c.OnlineStatsDays == 0 {
c.OnlineStatsDays = DefaultOnlineStatsDays
} else if c.OnlineStatsDays < MinOnlineStatsDays || c.OnlineStatsDays > MaxOnlineStatsDays {
log.Printf("NEZHA>> online_stats_days %d out of range [%d, %d], reset to %d", c.OnlineStatsDays, MinOnlineStatsDays, MaxOnlineStatsDays, DefaultOnlineStatsDays)
c.OnlineStatsDays = DefaultOnlineStatsDays
}
c.jwtIPChangeAllowed.Store(c.AllowJWTIPChange)
if c.AgentSecretKey == "" {
c.AgentSecretKey, err = utils.GenerateRandomString(32)
if err != nil {
@@ -267,6 +287,17 @@ func (c *Config) SetMCPEnabled(v bool) {
c.mcpEnabled.Store(v)
}
// JWTIPChangeAllowed reports whether JWT sessions may change IP concurrently.
func (c *Config) JWTIPChangeAllowed() bool {
return c.jwtIPChangeAllowed.Load()
}
// SetJWTIPChangeAllowed updates only the atomic mirror. save() synchronizes
// the public field for persistence; authentication must use the accessor.
func (c *Config) SetJWTIPChangeAllowed(v bool) {
c.jwtIPChangeAllowed.Store(v)
}
// Save 保存配置文件
func (c *Config) Save() error {
return c.save()
@@ -335,6 +366,7 @@ func (c *Config) patchYAMLField(key string, value any) error {
func (c *Config) save() error {
c.EnableMCP = c.mcpEnabled.Load()
c.AllowJWTIPChange = c.jwtIPChangeAllowed.Load()
data, err := yaml.Marshal(c)
if err != nil {
return err