Merge branch 'upstream/master' into master and preserve domain extensions

This commit is contained in:
Bot
2026-08-31 02:46:42 +08:00
758 changed files with 89269 additions and 1366 deletions
+53 -1
View File
@@ -2,11 +2,13 @@ package controller
import (
"errors"
"log"
"strings"
"github.com/gin-gonic/gin"
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/service/rpc"
"github.com/nezhahq/nezha/service/singleton"
)
@@ -97,6 +99,8 @@ func updateConfig(c *gin.Context) (any, error) {
singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification
singleton.Conf.Cover = sf.Cover
singleton.Conf.InstallHost = sf.InstallHost
singleton.Conf.DashboardHost = sf.DashboardHost
singleton.Conf.ReservedHosts = sf.ReservedHosts
singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification
singleton.Conf.IPChangeNotificationGroupID = sf.IPChangeNotificationGroupID
singleton.Conf.ExpiryNotificationGroupID = sf.ExpiryNotificationGroupID
@@ -120,7 +124,16 @@ func updateConfig(c *gin.Context) (any, error) {
singleton.Conf.DomainExpiryNotificationDays = sf.DomainExpiryNotificationDays
singleton.Conf.ServerExpiryNotificationDays = sf.ServerExpiryNotificationDays
if err := singleton.Conf.Save(); err != nil {
mcpWasEnabled := singleton.Conf.MCPEnabled()
mcpNext := resolveSettingEnableMCP(sf.EnableMCP, mcpWasEnabled)
if err := applyEnableMCPTransition(
mcpWasEnabled, mcpNext,
singleton.Conf.SetMCPEnabled,
singleton.Conf.Save,
fireMCPKillSwitch,
); err != nil {
return nil, newGormError("%v", err)
}
@@ -128,6 +141,45 @@ func updateConfig(c *gin.Context) (any, error) {
return nil, nil
}
// applyEnableMCPTransition commits the new EnableMCP value and persists it,
// guaranteeing the in-memory flag and the kill-switch cleanup stay consistent
// with what actually reached durable storage:
// - setVal(next) is applied so Save serialises the new value.
// - If save fails, the flag is rolled back to prev and no cleanup runs, so a
// failed disable cannot leave the dashboard half-disabled (new requests
// rejected while in-flight RPC/streams/URLs are never revoked).
// - cleanup runs only on a persisted enabled->disabled transition.
func applyEnableMCPTransition(prev, next bool, setVal func(bool), save func() error, cleanup func()) error {
setVal(next)
if err := save(); err != nil {
setVal(prev)
return err
}
if prev && !next {
cleanup()
}
return nil
}
func fireMCPKillSwitch() {
purgedURLs := PurgeTransferEntries()
revokedStreams := rpc.NezhaHandlerSingleton.RevokeStreamsForPurpose(rpc.PurposeMCPTransfer)
cancelledRPC := rpc.CancelAllMCPInflight()
log.Printf("NEZHA>> MCP kill switch fired: purged=%d urls, revoked=%d streams, cancelled=%d rpc",
purgedURLs, revokedStreams, cancelledRPC)
}
// resolveSettingEnableMCP picks the effective EnableMCP value for the
// update. A nil form pointer means "field absent" so we MUST preserve
// the current config to avoid accidentally tripping the kill switch on
// partial PATCH calls that omit enable_mcp.
func resolveSettingEnableMCP(formValue *bool, current bool) bool {
if formValue == nil {
return current
}
return *formValue
}
// Perform maintenance
// @Summary Perform maintenance
// @Security BearerAuth