diff --git a/cmd/dashboard/controller/common_page.go b/cmd/dashboard/controller/common_page.go
deleted file mode 100644
index 3de8ecc..0000000
--- a/cmd/dashboard/controller/common_page.go
+++ /dev/null
@@ -1,257 +0,0 @@
-package controller
-
-import (
- "net/http"
- "strconv"
- "time"
-
- "github.com/gin-gonic/gin"
- "github.com/gorilla/websocket"
- "github.com/hashicorp/go-uuid"
-
- "github.com/naiba/nezha/model"
- "github.com/naiba/nezha/pkg/utils"
- "github.com/naiba/nezha/pkg/websocketx"
- "github.com/naiba/nezha/proto"
- "github.com/naiba/nezha/service/rpc"
- "github.com/naiba/nezha/service/singleton"
-)
-
-type commonPage struct {
- r *gin.Engine
-}
-
-func (cp *commonPage) serve() {
- cr := cp.r.Group("")
- // TODO: 界面直接跳转使用该接口
- cr.GET("/network/:id", cp.network)
- cr.GET("/network", cp.network)
- cr.GET("/file", cp.createFM)
- cr.GET("/file/:id", cp.fm)
-}
-
-func (cp *commonPage) network(c *gin.Context) {
- var (
- monitorHistory *model.ServiceHistory
- servers []model.Server
- serverIdsWithMonitor []uint64
- monitorInfos = []byte("{}")
- id uint64
- )
- if len(singleton.SortedServerList) > 0 {
- id = singleton.SortedServerList[0].ID
- }
- if err := singleton.DB.Model(&model.ServiceHistory{}).Select("monitor_id, server_id").
- Where("monitor_id != 0 and server_id != 0").Limit(1).First(&monitorHistory).Error; err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "请求参数有误:" + "server monitor history not found",
- // Link: "/",
- // Btn: "返回重试",
- // }, true)
- return
- } else {
- if monitorHistory == nil || monitorHistory.ServerID == 0 {
- if len(singleton.SortedServerList) > 0 {
- id = singleton.SortedServerList[0].ID
- }
- } else {
- id = monitorHistory.ServerID
- }
- }
-
- idStr := c.Param("id")
- if idStr != "" {
- var err error
- id, err = strconv.ParseUint(idStr, 10, 64)
- if err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "请求参数有误:" + err.Error(),
- // Link: "/",
- // Btn: "返回重试",
- // }, true)
- return
- }
- _, ok := singleton.ServerList[id]
- if !ok {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "请求参数有误:" + "server id not found",
- // Link: "/",
- // Btn: "返回重试",
- // }, true)
- return
- }
- }
- _, isMember := c.Get(model.CtxKeyAuthorizedUser)
- var isViewPasswordVerfied bool
-
- if err := singleton.DB.Model(&model.ServiceHistory{}).
- Select("distinct(server_id)").
- Where("server_id != 0").
- Find(&serverIdsWithMonitor).
- Error; err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "请求参数有误:" + "no server with monitor histories",
- // Link: "/",
- // Btn: "返回重试",
- // }, true)
- return
- }
- if isMember || isViewPasswordVerfied {
- for _, server := range singleton.SortedServerList {
- for _, id := range serverIdsWithMonitor {
- if server.ID == id {
- servers = append(servers, *server)
- }
- }
- }
- } else {
- for _, server := range singleton.SortedServerListForGuest {
- for _, id := range serverIdsWithMonitor {
- if server.ID == id {
- servers = append(servers, *server)
- }
- }
- }
- }
- serversBytes, _ := utils.Json.Marshal(model.StreamServerData{
- Now: time.Now().Unix() * 1000,
- // Servers: servers,
- })
-
- c.HTML(http.StatusOK, "", gin.H{
- "Servers": string(serversBytes),
- "MonitorInfos": string(monitorInfos),
- })
-}
-
-func (cp *commonPage) fm(c *gin.Context) {
- streamId := c.Param("id")
- if _, err := rpc.NezhaHandlerSingleton.GetStream(streamId); err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "无权访问",
- // Msg: "FM会话不存在",
- // Link: "/",
- // Btn: "返回首页",
- // }, true)
- return
- }
- defer rpc.NezhaHandlerSingleton.CloseStream(streamId)
-
- wsConn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
- if err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusInternalServerError,
- // // Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
- // // MessageID: "NetworkError",
- // // }),
- // Msg: "Websocket协议切换失败",
- // Link: "/",
- // Btn: "返回首页",
- // }, true)
- return
- }
- defer wsConn.Close()
- conn := websocketx.NewConn(wsConn)
-
- go func() {
- // PING 保活
- for {
- if err = conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
- return
- }
- time.Sleep(time.Second * 10)
- }
- }()
-
- if err = rpc.NezhaHandlerSingleton.UserConnected(streamId, conn); err != nil {
- return
- }
-
- rpc.NezhaHandlerSingleton.StartStream(streamId, time.Second*10)
-}
-
-func (cp *commonPage) createFM(c *gin.Context) {
- IdString := c.Query("id")
- if _, authorized := c.Get(model.CtxKeyAuthorizedUser); !authorized {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "无权访问",
- // Msg: "用户未登录",
- // Link: "/login",
- // Btn: "去登录",
- // }, true)
- return
- }
-
- streamId, err := uuid.GenerateUUID()
- if err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusInternalServerError,
- // // Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
- // // MessageID: "SystemError",
- // // }),
- // Msg: "生成会话ID失败",
- // Link: "/server",
- // Btn: "返回重试",
- // }, true)
- return
- }
-
- rpc.NezhaHandlerSingleton.CreateStream(streamId)
-
- serverId, err := strconv.Atoi(IdString)
- if err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "请求参数有误:" + err.Error(),
- // Link: "/server",
- // Btn: "返回重试",
- // }, true)
- return
- }
-
- singleton.ServerLock.RLock()
- server := singleton.ServerList[uint64(serverId)]
- singleton.ServerLock.RUnlock()
- if server == nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "服务器不存在或处于离线状态",
- // Link: "/server",
- // Btn: "返回重试",
- // }, true)
- return
- }
-
- fmData, _ := utils.Json.Marshal(&model.TaskFM{
- StreamID: streamId,
- })
- if err := server.TaskStream.Send(&proto.Task{
- Type: model.TaskTypeFM,
- Data: string(fmData),
- }); err != nil {
- // mygin.ShowErrorPage(c, mygin.ErrInfo{
- // Code: http.StatusForbidden,
- // Title: "请求失败",
- // Msg: "Agent信令下发失败",
- // Link: "/server",
- // Btn: "返回重试",
- // }, true)
- return
- }
-
- c.HTML(http.StatusOK, "dashboard-", gin.H{
- "SessionID": streamId,
- })
-}
diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go
deleted file mode 100644
index 13a7aba..0000000
--- a/cmd/dashboard/controller/member_api.go
+++ /dev/null
@@ -1,636 +0,0 @@
-package controller
-
-import (
- "bytes"
- "errors"
- "fmt"
- "net/http"
- "strconv"
- "strings"
- "time"
-
- "github.com/gin-gonic/gin"
- "github.com/jinzhu/copier"
- "golang.org/x/net/idna"
-
- "github.com/naiba/nezha/model"
- "github.com/naiba/nezha/pkg/utils"
- "github.com/naiba/nezha/proto"
- "github.com/naiba/nezha/service/singleton"
-)
-
-type memberAPI struct {
- r gin.IRouter
-}
-
-func (ma *memberAPI) serve() {
- mr := ma.r.Group("")
- // mr.Use(mygin.Authorize(mygin.AuthorizeOption{
- // MemberOnly: true,
- // IsPage: false,
- // Msg: "访问此接口需要登录",
- // Btn: "点此登录",
- // Redirect: "/login",
- // }))
- mr.POST("/cron", ma.addOrEditCron)
- mr.GET("/cron/:id/manual", ma.manualTrigger)
- mr.POST("/force-update", ma.forceUpdate)
- mr.POST("/batch-update-server-group", ma.batchUpdateServerGroup)
- mr.POST("/notification", ma.addOrEditNotification)
- mr.POST("/ddns", ma.addOrEditDDNS)
- mr.POST("/nat", ma.addOrEditNAT)
- mr.POST("/alert-rule", ma.addOrEditAlertRule)
- mr.POST("/setting", ma.updateSetting)
- mr.DELETE("/:model/:id", ma.delete)
- mr.POST("/logout", ma.logout)
-}
-
-func (ma *memberAPI) delete(c *gin.Context) {
- id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
- if id < 1 {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: "错误的 Server ID",
- })
- return
- }
-
- var err error
- switch c.Param("model") {
-
- case "cron":
- err = singleton.DB.Unscoped().Delete(&model.Cron{}, "id = ?", id).Error
- if err == nil {
- singleton.CronLock.RLock()
- defer singleton.CronLock.RUnlock()
- cr := singleton.Crons[id]
- if cr != nil && cr.CronJobID != 0 {
- singleton.Cron.Remove(cr.CronJobID)
- }
- delete(singleton.Crons, id)
- }
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("数据库错误:%s", err),
- })
- return
- }
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type cronForm struct {
- ID uint64
- TaskType uint8 // 0:计划任务 1:触发任务
- Name string
- Scheduler string
- Command string
- ServersRaw string
- Cover uint8
- PushSuccessful string
- NotificationTag string
-}
-
-func (ma *memberAPI) addOrEditCron(c *gin.Context) {
- var cf cronForm
- var cr model.Cron
- err := c.ShouldBindJSON(&cf)
- if err == nil {
- cr.TaskType = cf.TaskType
- cr.Name = cf.Name
- cr.Scheduler = cf.Scheduler
- cr.Command = cf.Command
- cr.ServersRaw = cf.ServersRaw
- cr.PushSuccessful = cf.PushSuccessful == "on"
- //cr.NotificationTag = cf.NotificationTag
- cr.ID = cf.ID
- cr.Cover = cf.Cover
- err = utils.Json.Unmarshal([]byte(cf.ServersRaw), &cr.Servers)
- }
-
- // 计划任务类型不得使用触发服务器执行方式
- if cr.TaskType == model.CronTypeCronTask && cr.Cover == model.CronCoverAlertTrigger {
- err = errors.New("计划任务类型不得使用触发服务器执行方式")
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
-
- tx := singleton.DB.Begin()
- if err == nil {
- // 保证NotificationTag不为空
- //if cr.NotificationTag == "" {
- // cr.NotificationTag = "default"
- //}
- if cf.ID == 0 {
- err = tx.Create(&cr).Error
- } else {
- err = tx.Save(&cr).Error
- }
- }
- if err == nil {
- err = tx.Commit().Error
- } else {
- tx.Rollback()
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
-
- singleton.CronLock.Lock()
- defer singleton.CronLock.Unlock()
- crOld := singleton.Crons[cr.ID]
- if crOld != nil && crOld.CronJobID != 0 {
- singleton.Cron.Remove(crOld.CronJobID)
- }
-
- delete(singleton.Crons, cr.ID)
- singleton.Crons[cr.ID] = &cr
-
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-func (ma *memberAPI) manualTrigger(c *gin.Context) {
- var cr model.Cron
- if err := singleton.DB.First(&cr, "id = ?", c.Param("id")).Error; err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: err.Error(),
- })
- return
- }
-
- //singleton.ManualTrigger(cr)
-
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type BatchUpdateServerGroupRequest struct {
- Servers []uint64
- Group string
-}
-
-func (ma *memberAPI) batchUpdateServerGroup(c *gin.Context) {
- var req BatchUpdateServerGroupRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: err.Error(),
- })
- return
- }
-
- if err := singleton.DB.Model(&model.Server{}).Where("id in (?)", req.Servers).Update("tag", req.Group).Error; err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: err.Error(),
- })
- return
- }
-
- singleton.ServerLock.Lock()
-
- for i := 0; i < len(req.Servers); i++ {
- serverId := req.Servers[i]
- var s model.Server
- copier.Copy(&s, singleton.ServerList[serverId])
- // s.Tag = req.Group
- // // 如果修改了Ta
- // oldTag := singleton.ServerList[serverId].Tag
- // newTag := s.Tag
- // if newTag != oldTag {
- // index := -1
- // for i := 0; i < len(singleton.ServerTagToIDList[oldTag]); i++ {
- // if singleton.ServerTagToIDList[oldTag][i] == s.ID {
- // index = i
- // break
- // }
- // }
- // if index > -1 {
- // // 删除旧 Tag-ID 绑定关系
- // singleton.ServerTagToIDList[oldTag] = append(singleton.ServerTagToIDList[oldTag][:index], singleton.ServerTagToIDList[oldTag][index+1:]...)
- // if len(singleton.ServerTagToIDList[oldTag]) == 0 {
- // delete(singleton.ServerTagToIDList, oldTag)
- // }
- // }
- // // 设置新的 Tag-ID 绑定关系
- // singleton.ServerTagToIDList[newTag] = append(singleton.ServerTagToIDList[newTag], s.ID)
- // }
- singleton.ServerList[s.ID] = &s
- }
-
- singleton.ServerLock.Unlock()
-
- singleton.ReSortServer()
-
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-func (ma *memberAPI) forceUpdate(c *gin.Context) {
- var forceUpdateServers []uint64
- if err := c.ShouldBindJSON(&forceUpdateServers); err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: err.Error(),
- })
- return
- }
-
- var executeResult bytes.Buffer
-
- for i := 0; i < len(forceUpdateServers); i++ {
- singleton.ServerLock.RLock()
- server := singleton.ServerList[forceUpdateServers[i]]
- singleton.ServerLock.RUnlock()
- if server != nil && server.TaskStream != nil {
- if err := server.TaskStream.Send(&proto.Task{
- Type: model.TaskTypeUpgrade,
- }); err != nil {
- executeResult.WriteString(fmt.Sprintf("%d 下发指令失败 %+v
", forceUpdateServers[i], err))
- } else {
- executeResult.WriteString(fmt.Sprintf("%d 下发指令成功
", forceUpdateServers[i]))
- }
- } else {
- executeResult.WriteString(fmt.Sprintf("%d 离线
", forceUpdateServers[i]))
- }
- }
-
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- Message: executeResult.String(),
- })
-}
-
-type notificationForm struct {
- ID uint64
- Name string
- URL string
- RequestMethod int
- RequestType int
- RequestHeader string
- RequestBody string
- VerifySSL string
- SkipCheck string
-}
-
-func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
- var nf notificationForm
- var n model.Notification
- err := c.ShouldBindJSON(&nf)
- if err == nil {
- n.Name = nf.Name
- n.RequestMethod = nf.RequestMethod
- n.RequestType = nf.RequestType
- n.RequestHeader = nf.RequestHeader
- n.RequestBody = nf.RequestBody
- n.URL = nf.URL
- //verifySSL := nf.VerifySSL == "on"
- //n.VerifySSL = &verifySSL
- n.ID = nf.ID
- ns := model.NotificationServerBundle{
- Notification: &n,
- Server: nil,
- Loc: singleton.Loc,
- }
- // 勾选了跳过检查
- if nf.SkipCheck != "on" {
- err = ns.Send("这是测试消息")
- }
- }
- if err == nil {
- if n.ID == 0 {
- err = singleton.DB.Create(&n).Error
- } else {
- err = singleton.DB.Save(&n).Error
- }
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
- singleton.OnRefreshOrAddNotification(&n)
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type ddnsForm struct {
- ID uint64
- MaxRetries uint64
- EnableIPv4 string
- EnableIPv6 string
- Name string
- Provider string
- DomainsRaw string
- AccessID string
- AccessSecret string
- WebhookURL string
- WebhookMethod uint8
- WebhookRequestType uint8
- WebhookRequestBody string
- WebhookHeaders string
-}
-
-func (ma *memberAPI) addOrEditDDNS(c *gin.Context) {
- var df ddnsForm
- var p model.DDNSProfile
- err := c.ShouldBindJSON(&df)
- if err == nil {
- if df.MaxRetries < 1 || df.MaxRetries > 10 {
- err = errors.New("重试次数必须为大于 1 且不超过 10 的整数")
- }
- }
- if err == nil {
- p.Name = df.Name
- p.ID = df.ID
- enableIPv4 := df.EnableIPv4 == "on"
- enableIPv6 := df.EnableIPv6 == "on"
- p.EnableIPv4 = &enableIPv4
- p.EnableIPv6 = &enableIPv6
- p.MaxRetries = df.MaxRetries
- p.Provider = df.Provider
- p.DomainsRaw = df.DomainsRaw
- p.Domains = strings.Split(p.DomainsRaw, ",")
- p.AccessID = df.AccessID
- p.AccessSecret = df.AccessSecret
- p.WebhookURL = df.WebhookURL
- p.WebhookMethod = df.WebhookMethod
- p.WebhookRequestType = df.WebhookRequestType
- p.WebhookRequestBody = df.WebhookRequestBody
- p.WebhookHeaders = df.WebhookHeaders
-
- for n, domain := range p.Domains {
- // IDN to ASCII
- domainValid, domainErr := idna.Lookup.ToASCII(domain)
- if domainErr != nil {
- err = fmt.Errorf("域名 %s 解析错误: %v", domain, domainErr)
- break
- }
- p.Domains[n] = domainValid
- }
- }
- if err == nil {
- if p.ID == 0 {
- err = singleton.DB.Create(&p).Error
- } else {
- err = singleton.DB.Save(&p).Error
- }
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
- //singleton.OnDDNSUpdate()
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type natForm struct {
- ID uint64
- Name string
- ServerID uint64
- Host string
- Domain string
-}
-
-func (ma *memberAPI) addOrEditNAT(c *gin.Context) {
- var nf natForm
- var n model.NAT
- err := c.ShouldBindJSON(&nf)
- if err == nil {
- n.Name = nf.Name
- n.ID = nf.ID
- n.Domain = nf.Domain
- n.Host = nf.Host
- n.ServerID = nf.ServerID
- }
- if err == nil {
- if n.ID == 0 {
- err = singleton.DB.Create(&n).Error
- } else {
- err = singleton.DB.Save(&n).Error
- }
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
- //singleton.OnNATUpdate()
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type alertRuleForm struct {
- ID uint64
- Name string
- RulesRaw string
- FailTriggerTasksRaw string // 失败时触发的任务id
- RecoverTriggerTasksRaw string // 恢复时触发的任务id
- NotificationTag string
- TriggerMode int
- Enable string
-}
-
-func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
- var arf alertRuleForm
- var r model.AlertRule
- err := c.ShouldBindJSON(&arf)
- if err == nil {
- err = utils.Json.Unmarshal([]byte(arf.RulesRaw), &r.Rules)
- }
- if err == nil {
- if len(r.Rules) == 0 {
- err = errors.New("至少定义一条规则")
- } else {
- for i := 0; i < len(r.Rules); i++ {
- if !r.Rules[i].IsTransferDurationRule() {
- if r.Rules[i].Duration < 3 {
- err = errors.New("错误:Duration 至少为 3")
- break
- }
- } else {
- if r.Rules[i].CycleInterval < 1 {
- err = errors.New("错误: cycle_interval 至少为 1")
- break
- }
- if r.Rules[i].CycleStart == nil {
- err = errors.New("错误: cycle_start 未设置")
- break
- }
- if r.Rules[i].CycleStart.After(time.Now()) {
- err = errors.New("错误: cycle_start 是个未来值")
- break
- }
- }
- }
- }
- }
- if err == nil {
- r.Name = arf.Name
- r.RulesRaw = arf.RulesRaw
- r.FailTriggerTasksRaw = arf.FailTriggerTasksRaw
- r.RecoverTriggerTasksRaw = arf.RecoverTriggerTasksRaw
- //r.NotificationTag = arf.NotificationTag
- enable := arf.Enable == "on"
- r.TriggerMode = arf.TriggerMode
- r.Enable = &enable
- r.ID = arf.ID
- }
- if err == nil {
- err = utils.Json.Unmarshal([]byte(arf.FailTriggerTasksRaw), &r.FailTriggerTasks)
- }
- if err == nil {
- err = utils.Json.Unmarshal([]byte(arf.RecoverTriggerTasksRaw), &r.RecoverTriggerTasks)
- }
- //保证NotificationTag不为空
- if err == nil {
- //if r.NotificationTag == "" {
- // r.NotificationTag = "default"
- //}
- if r.ID == 0 {
- err = singleton.DB.Create(&r).Error
- } else {
- err = singleton.DB.Save(&r).Error
- }
- }
- if err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
- //singleton.OnRefreshOrAddAlert(r)
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-}
-
-type logoutForm struct {
- ID uint64
-}
-
-func (ma *memberAPI) logout(c *gin.Context) {
- admin := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
- var lf logoutForm
- if err := c.ShouldBindJSON(&lf); err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
- if lf.ID != admin.ID {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", "用户ID不匹配"),
- })
- return
- }
- singleton.DB.Model(admin).UpdateColumns(model.User{
- // Token: "",
- // TokenExpired: time.Now(),
- })
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusOK,
- })
-
- // if oidcLogoutUrl := singleton.Conf.Oauth2.OidcLogoutURL; oidcLogoutUrl != "" {
- // // 重定向到 OIDC 退出登录地址。不知道为什么,这里的重定向不生效
- // c.Redirect(http.StatusOK, oidcLogoutUrl)
- // }
-}
-
-type settingForm struct {
- SiteName string
- Language string
- CustomNameservers string
- IgnoredIPNotification string
- IPChangeNotificationTag string // IP变更提醒的通知组
- InstallHost string
- Cover uint8
-
- EnableIPChangeNotification string
- EnablePlainIPInNotification string
-}
-
-func (ma *memberAPI) updateSetting(c *gin.Context) {
- var sf settingForm
- if err := c.ShouldBind(&sf); err != nil {
- c.JSON(http.StatusOK, model.Response{
- Code: http.StatusBadRequest,
- Message: fmt.Sprintf("请求错误:%s", err),
- })
- return
- }
-
- // if _, yes := model.Themes[sf.Theme]; !yes {
- // c.JSON(http.StatusOK, model.Response{
- // Code: http.StatusBadRequest,
- // Message: fmt.Sprintf("前台主题不存在:%s", sf.Theme),
- // })
- // return
- // }
-
- // if _, yes := model.DashboardThemes[sf.DashboardTheme]; !yes {
- // c.JSON(http.StatusOK, model.Response{
- // Code: http.StatusBadRequest,
- // Message: fmt.Sprintf("后台主题不存在:%s", sf.DashboardTheme),
- // })
- // 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 {
- 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.StatusOK,
- })
- */
-}
diff --git a/cmd/dashboard/controller/member_page.go b/cmd/dashboard/controller/member_page.go
deleted file mode 100644
index 110a069..0000000
--- a/cmd/dashboard/controller/member_page.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package controller
-
-import (
- "net/http"
-
- "github.com/gin-gonic/gin"
- "github.com/naiba/nezha/model"
- "github.com/naiba/nezha/service/singleton"
-)
-
-type memberPage struct {
- r *gin.Engine
-}
-
-func (mp *memberPage) serve() {
- mr := mp.r.Group("")
- // mr.Use(mygin.Authorize(mygin.AuthorizeOption{
- // MemberOnly: true,
- // IsPage: true,
- // // Msg: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "YouAreNotAuthorized"}),
- // // Btn: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
- // Redirect: "/login",
- // }))
- mr.GET("/cron", mp.cron)
- mr.GET("/notification", mp.notification)
- mr.GET("/ddns", mp.ddns)
- mr.GET("/nat", mp.nat)
- mr.GET("/setting", mp.setting)
-}
-
-func (mp *memberPage) cron(c *gin.Context) {
- var crons []model.Cron
- singleton.DB.Find(&crons)
- c.HTML(http.StatusOK, "dashboard-", gin.H{
- // "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ScheduledTasks"}),
- "Crons": crons,
- })
-}
-
-func (mp *memberPage) notification(c *gin.Context) {
- var nf []model.Notification
- singleton.DB.Find(&nf)
- var ar []model.AlertRule
- singleton.DB.Find(&ar)
- c.HTML(http.StatusOK, "dashboard-", gin.H{
- // "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Notification"}),
- "Notifications": nf,
- "AlertRules": ar,
- })
-}
-
-func (mp *memberPage) ddns(c *gin.Context) {
- var data []model.DDNSProfile
- singleton.DB.Find(&data)
- c.HTML(http.StatusOK, "dashboard-", gin.H{
- // "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "DDNS"}),
- "DDNS": data,
- //"ProviderMap": model.ProviderMap,
- //"ProviderList": model.ProviderList,
- })
-}
-
-func (mp *memberPage) nat(c *gin.Context) {
- var data []model.NAT
- singleton.DB.Find(&data)
- c.HTML(http.StatusOK, "dashboard-", gin.H{
- // "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "NAT"}),
- "NAT": data,
- })
-}
-
-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,
- })
-}