From b4edb4cc953737e07546c184c4d6560cef3261ab Mon Sep 17 00:00:00 2001 From: UUBulb <35923940+uubulb@users.noreply.github.com> Date: Sun, 27 Oct 2024 13:10:07 +0800 Subject: [PATCH] add setting api (#461) --- cmd/dashboard/controller/controller.go | 4 ++ cmd/dashboard/controller/member_api.go | 48 +++++++++-------- cmd/dashboard/controller/member_page.go | 4 +- cmd/dashboard/controller/setting.go | 71 +++++++++++++++++++++++++ model/config.go | 53 ++++-------------- model/setting_api.go | 16 ++++++ service/rpc/nezha.go | 32 +++++------ service/singleton/servicesentinel.go | 5 +- 8 files changed, 143 insertions(+), 90 deletions(-) create mode 100644 cmd/dashboard/controller/setting.go create mode 100644 model/setting_api.go diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go index bf5c8cc..8f217cb 100644 --- a/cmd/dashboard/controller/controller.go +++ b/cmd/dashboard/controller/controller.go @@ -55,6 +55,8 @@ func routers(r *gin.Engine) { optionalAuth.GET("/ws/server", commonHandler(serverStream)) optionalAuth.GET("/server-group", commonHandler(listServerGroup)) + optionalAuth.GET("/setting", commonHandler(listConfig)) + auth := api.Group("", authMiddleware.MiddlewareFunc()) auth.GET("/refresh_token", authMiddleware.RefreshHandler) @@ -114,6 +116,8 @@ func routers(r *gin.Engine) { auth.PATCH("/nat/:id", commonHandler(updateNAT)) auth.POST("/batch-delete/nat", commonHandler(batchDeleteNAT)) + auth.PATCH("/setting", commonHandler(updateConfig)) + r.NoRoute(fallbackToFrontend) } diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index b3c0128..158fa7e 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -606,29 +606,31 @@ func (ma *memberAPI) updateSetting(c *gin.Context) { // return // } - singleton.Conf.Language = sf.Language - singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification == "on" - singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification == "on" - singleton.Conf.Cover = sf.Cover - singleton.Conf.InstallHost = sf.InstallHost - singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification - singleton.Conf.IPChangeNotificationTag = sf.IPChangeNotificationTag - singleton.Conf.SiteName = sf.SiteName - singleton.Conf.DNSServers = sf.CustomNameservers - // 保证NotificationTag不为空 - if singleton.Conf.IPChangeNotificationTag == "" { - singleton.Conf.IPChangeNotificationTag = "default" - } - if err := singleton.Conf.Save(); err != nil { + /* + singleton.Conf.Language = sf.Language + singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification == "on" + singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification == "on" + singleton.Conf.Cover = sf.Cover + singleton.Conf.InstallHost = sf.InstallHost + singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification + singleton.Conf.IPChangeNotificationTag = sf.IPChangeNotificationTag + singleton.Conf.SiteName = sf.SiteName + singleton.Conf.DNSServers = sf.CustomNameservers + // 保证NotificationTag不为空 + if singleton.Conf.IPChangeNotificationTag == "" { + singleton.Conf.IPChangeNotificationTag = "default" + } + if err := singleton.Conf.Save(); err != nil { + c.JSON(http.StatusOK, model.Response{ + Code: http.StatusBadRequest, + Message: fmt.Sprintf("请求错误:%s", err), + }) + return + } + // 更新DNS服务器 + singleton.OnNameserverUpdate() c.JSON(http.StatusOK, model.Response{ - Code: http.StatusBadRequest, - Message: fmt.Sprintf("请求错误:%s", err), + Code: http.StatusOK, }) - return - } - // 更新DNS服务器 - singleton.OnNameserverUpdate() - c.JSON(http.StatusOK, model.Response{ - Code: http.StatusOK, - }) + */ } diff --git a/cmd/dashboard/controller/member_page.go b/cmd/dashboard/controller/member_page.go index c73a810..110a069 100644 --- a/cmd/dashboard/controller/member_page.go +++ b/cmd/dashboard/controller/member_page.go @@ -72,7 +72,7 @@ func (mp *memberPage) nat(c *gin.Context) { func (mp *memberPage) setting(c *gin.Context) { c.HTML(http.StatusOK, "dashboard-", gin.H{ // "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}), - "Languages": model.Languages, - "DashboardThemes": model.DashboardThemes, + //"Languages": model.Languages, + //"DashboardThemes": model.DashboardThemes, }) } diff --git a/cmd/dashboard/controller/setting.go b/cmd/dashboard/controller/setting.go new file mode 100644 index 0000000..dc2a56f --- /dev/null +++ b/cmd/dashboard/controller/setting.go @@ -0,0 +1,71 @@ +package controller + +import ( + "github.com/gin-gonic/gin" + + "github.com/naiba/nezha/model" + "github.com/naiba/nezha/service/singleton" +) + +// List settings +// @Summary List settings +// @Schemes +// @Description List settings +// @Security BearerAuth +// @Tags common +// @Produce json +// @Success 200 {object} model.CommonResponse[model.Config] +// @Router /setting [get] +func listConfig(c *gin.Context) (model.Config, error) { + _, isMember := c.Get(model.CtxKeyAuthorizedUser) + authorized := isMember // TODO || isViewPasswordVerfied + + conf := *singleton.Conf + if !authorized { + conf = model.Config{ + SiteName: conf.SiteName, + Language: conf.Language, + CustomCode: conf.CustomCode, + CustomCodeDashboard: conf.CustomCodeDashboard, + } + } + + return conf, nil +} + +// Edit config +// @Summary Edit config +// @Security BearerAuth +// @Schemes +// @Description Edit config +// @Tags auth required +// @Accept json +// @Param body body model.SettingForm true "SettingForm" +// @Produce json +// @Success 200 {object} model.CommonResponse[any] +// @Router /setting [patch] +func updateConfig(c *gin.Context) (any, error) { + var sf model.SettingForm + if err := c.ShouldBindJSON(&sf); err != nil { + return nil, err + } + + singleton.Conf.Language = sf.Language + singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification + singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification + singleton.Conf.Cover = sf.Cover + singleton.Conf.InstallHost = sf.InstallHost + singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification + singleton.Conf.IPChangeNotificationGroupID = sf.IPChangeNotificationGroupID + singleton.Conf.SiteName = sf.SiteName + singleton.Conf.DNSServers = sf.CustomNameservers + singleton.Conf.CustomCode = sf.CustomCode + singleton.Conf.CustomCodeDashboard = sf.CustomCodeDashboard + + if err := singleton.Conf.Save(); err != nil { + return nil, err + } + + singleton.OnNameserverUpdate() + return nil, nil +} diff --git a/model/config.go b/model/config.go index 0c06bb1..c59d4c2 100644 --- a/model/config.go +++ b/model/config.go @@ -10,38 +10,6 @@ import ( "sigs.k8s.io/yaml" ) -var Languages = map[string]string{ - "zh-CN": "简体中文", - "zh-TW": "繁體中文", - "en-US": "English", - "es-ES": "Español", -} - -var Themes = map[string]string{ - "default": "Default", - "daynight": "JackieSung DayNight", - "mdui": "Neko Mdui", - "hotaru": "Hotaru", - "angel-kanade": "AngelKanade", - "server-status": "ServerStatus", - "custom": "Custom(local)", -} - -var DashboardThemes = map[string]string{ - "default": "Default", - "custom": "Custom(local)", -} - -const ( - ConfigTypeGitHub = "github" - ConfigTypeGitee = "gitee" - ConfigTypeGitlab = "gitlab" - ConfigTypeJihulab = "jihulab" - ConfigTypeGitea = "gitea" - ConfigTypeCloudflare = "cloudflare" - ConfigTypeOidc = "oidc" -) - const ( ConfigCoverAll = iota ConfigCoverIgnoreAll @@ -62,16 +30,19 @@ type Config struct { EnablePlainIPInNotification bool `mapstructure:"enable_plain_ip_in_notification" json:"enable_plain_ip_in_notification,omitempty"` // 通知信息IP不打码 // IP变更提醒 - EnableIPChangeNotification bool `mapstructure:"enable_ip_change_notification" json:"enable_ip_change_notification,omitempty"` - IPChangeNotificationTag string `mapstructure:"ip_change_notification_tag" json:"ip_change_notification_tag,omitempty"` - Cover uint8 `mapstructure:"cover" json:"cover,omitempty"` // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) - IgnoredIPNotification string `mapstructure:"ignored_ip_notification" json:"ignored_ip_notification,omitempty"` // 特定服务器IP(多个服务器用逗号分隔) + EnableIPChangeNotification bool `mapstructure:"enable_ip_change_notification" json:"enable_ip_change_notification,omitempty"` + IPChangeNotificationGroupID uint64 `mapstructure:"ip_change_notification_group_id" json:"ip_change_notification_group_id,omitempty"` + Cover uint8 `mapstructure:"cover" json:"cover,omitempty"` // 覆盖范围(0:提醒未被 IgnoredIPNotification 包含的所有服务器; 1:仅提醒被 IgnoredIPNotification 包含的服务器;) + IgnoredIPNotification string `mapstructure:"ignored_ip_notification" json:"ignored_ip_notification,omitempty"` // 特定服务器IP(多个服务器用逗号分隔) - IgnoredIPNotificationServerIDs map[uint64]bool `mapstructure:"ignored_ip_notification_server_i_ds" json:"ignored_ip_notification_server_i_ds,omitempty"` // [ServerID] -> bool(值为true代表当前ServerID在特定服务器列表内) + IgnoredIPNotificationServerIDs map[uint64]bool `mapstructure:"ignored_ip_notification_server_ids" json:"ignored_ip_notification_server_ids,omitempty"` // [ServerID] -> bool(值为true代表当前ServerID在特定服务器列表内) AvgPingCount int `mapstructure:"avg_ping_count" json:"avg_ping_count,omitempty"` DNSServers string `mapstructure:"dns_servers" json:"dns_servers,omitempty"` - v *viper.Viper + CustomCode string `mapstructure:"custom_code" json:"custom_code,omitempty"` + CustomCodeDashboard string `mapstructure:"custom_code_dashboard" json:"custom_code_dashboard,omitempty"` + + v *viper.Viper `json:"-"` } // Read 读取配置文件并应用 @@ -91,12 +62,6 @@ func (c *Config) Read(path string) error { if c.ListenPort == 0 { c.ListenPort = 8008 } - if c.Language == "" { - c.Language = "zh-CN" - } - if c.EnableIPChangeNotification && c.IPChangeNotificationTag == "" { - c.IPChangeNotificationTag = "default" - } if c.Location == "" { c.Location = "Asia/Shanghai" } diff --git a/model/setting_api.go b/model/setting_api.go new file mode 100644 index 0000000..a3cdf6d --- /dev/null +++ b/model/setting_api.go @@ -0,0 +1,16 @@ +package model + +type SettingForm struct { + CustomNameservers string `json:"custom_nameservers,omitempty"` + IgnoredIPNotification string `json:"ignored_ip_notification,omitempty"` + IPChangeNotificationGroupID uint64 `json:"ip_change_notification_group_id,omitempty"` // IP变更提醒的通知组 + Cover uint8 `json:"cover,omitempty"` + SiteName string `json:"site_name,omitempty"` + Language string `json:"language,omitempty"` + InstallHost string `json:"install_host,omitempty"` + CustomCode string `json:"custom_code,omitempty"` + CustomCodeDashboard string `json:"custom_code_dashboard,omitempty"` + + EnableIPChangeNotification bool `json:"enable_ip_change_notification,omitempty"` + EnablePlainIPInNotification bool `json:"enable_plain_ip_in_notification,omitempty"` +} diff --git a/service/rpc/nezha.go b/service/rpc/nezha.go index ed8619a..38adff0 100644 --- a/service/rpc/nezha.go +++ b/service/rpc/nezha.go @@ -54,18 +54,12 @@ func (s *NezhaHandler) ReportTask(c context.Context, r *pb.TaskResult) (*pb.Rece curServer := model.Server{} copier.Copy(&curServer, singleton.ServerList[clientID]) if cr.PushSuccessful && r.GetSuccessful() { - // singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[%s] %s, %s\n%s", singleton.Localizer.MustLocalize( - // &i18n.LocalizeConfig{ - // MessageID: "ScheduledTaskExecutedSuccessfully", - // }, - // ), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer) + singleton.SendNotification(cr.NotificationGroupID, fmt.Sprintf("[%s] %s, %s\n%s", "Scheduled Task Executed Successfully", + cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer) } if !r.GetSuccessful() { - // singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[%s] %s, %s\n%s", singleton.Localizer.MustLocalize( - // &i18n.LocalizeConfig{ - // MessageID: "ScheduledTaskExecutedFailed", - // }, - // ), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer) + singleton.SendNotification(cr.NotificationGroupID, fmt.Sprintf("[%s] %s, %s\n%s", "Scheduled Task Executed Failed", + cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer) } singleton.DB.Model(cr).Updates(model.Cron{ LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())), @@ -156,16 +150,14 @@ func (s *NezhaHandler) ReportSystemInfo(c context.Context, r *pb.Host) (*pb.Rece host.IP != "" && singleton.ServerList[clientID].Host.IP != host.IP { - // singleton.SendNotification(singleton.Conf.IPChangeNotificationTag, - // fmt.Sprintf( - // "[%s] %s, %s => %s", - // singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{ - // MessageID: "IPChanged", - // }), - // singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), - // singleton.IPDesensitize(host.IP), - // ), - // nil) + singleton.SendNotification(singleton.Conf.IPChangeNotificationGroupID, + fmt.Sprintf( + "[%s] %s, %s => %s", + "IPChanged", + singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), + singleton.IPDesensitize(host.IP), + ), + nil) } /** diff --git a/service/singleton/servicesentinel.go b/service/singleton/servicesentinel.go index db194d7..ef2f5f1 100644 --- a/service/singleton/servicesentinel.go +++ b/service/singleton/servicesentinel.go @@ -602,14 +602,17 @@ func StatusCodeToString(statusCode int) string { switch statusCode { case StatusNoData: // return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusNoData"}) + return "No Data" case StatusGood: // return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusGood"}) + return "Good" case StatusLowAvailability: // return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusLowAvailability"}) + return "Low Availability" case StatusDown: // return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusDown"}) + return "Down" default: return "" } - return "" }